1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.dialer.calldetails; 18 19 import android.content.Context; 20 import android.net.Uri; 21 import android.provider.CallLog.Calls; 22 import android.support.annotation.ColorInt; 23 import android.support.annotation.NonNull; 24 import android.support.v4.content.ContextCompat; 25 import android.support.v7.widget.RecyclerView.ViewHolder; 26 import android.text.TextUtils; 27 import android.view.View; 28 import android.widget.ImageView; 29 import android.widget.TextView; 30 import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry; 31 import com.android.dialer.calllogutils.CallLogDates; 32 import com.android.dialer.calllogutils.CallLogDurations; 33 import com.android.dialer.calllogutils.CallTypeHelper; 34 import com.android.dialer.calllogutils.CallTypeIconsView; 35 import com.android.dialer.common.LogUtil; 36 import com.android.dialer.compat.AppCompatConstants; 37 import com.android.dialer.enrichedcall.historyquery.proto.HistoryResult; 38 import com.android.dialer.enrichedcall.historyquery.proto.HistoryResult.Type; 39 import com.android.dialer.oem.MotorolaUtils; 40 import com.android.dialer.util.DialerUtils; 41 import com.android.dialer.util.IntentUtil; 42 43 /** ViewHolder for call entries in {@link CallDetailsActivity}. */ 44 public class CallDetailsEntryViewHolder extends ViewHolder { 45 46 private final CallTypeIconsView callTypeIcon; 47 private final TextView callTypeText; 48 private final TextView callTime; 49 private final TextView callDuration; 50 51 private final View multimediaImageContainer; 52 private final View multimediaDetailsContainer; 53 private final View multimediaDivider; 54 55 private final TextView multimediaDetails; 56 private final TextView postCallNote; 57 58 private final ImageView multimediaImage; 59 60 // TODO(maxwelb): Display this when location is stored - a bug 61 @SuppressWarnings("unused") 62 private final TextView multimediaAttachmentsNumber; 63 64 private final Context context; 65 66 public CallDetailsEntryViewHolder(View container) { 67 super(container); 68 context = container.getContext(); 69 70 callTypeIcon = (CallTypeIconsView) container.findViewById(R.id.call_direction); 71 callTypeText = (TextView) container.findViewById(R.id.call_type); 72 callTime = (TextView) container.findViewById(R.id.call_time); 73 callDuration = (TextView) container.findViewById(R.id.call_duration); 74 75 multimediaImageContainer = container.findViewById(R.id.multimedia_image_container); 76 multimediaDetailsContainer = container.findViewById(R.id.ec_container); 77 multimediaDivider = container.findViewById(R.id.divider); 78 multimediaDetails = (TextView) container.findViewById(R.id.multimedia_details); 79 postCallNote = (TextView) container.findViewById(R.id.post_call_note); 80 multimediaImage = (ImageView) container.findViewById(R.id.multimedia_image); 81 multimediaAttachmentsNumber = 82 (TextView) container.findViewById(R.id.multimedia_attachments_number); 83 } 84 85 void setCallDetails( 86 String number, 87 CallDetailsEntry entry, 88 CallTypeHelper callTypeHelper, 89 boolean showMultimediaDivider) { 90 int callType = entry.getCallType(); 91 boolean isVideoCall = (entry.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO; 92 boolean isPulledCall = 93 (entry.getFeatures() & Calls.FEATURES_PULLED_EXTERNALLY) 94 == Calls.FEATURES_PULLED_EXTERNALLY; 95 boolean isDuoCall = entry.getIsDuoCall(); 96 97 callTime.setTextColor(getColorForCallType(context, callType)); 98 callTypeIcon.clear(); 99 callTypeIcon.add(callType); 100 callTypeIcon.setShowVideo(isVideoCall); 101 callTypeIcon.setShowHd( 102 (entry.getFeatures() & Calls.FEATURES_HD_CALL) == Calls.FEATURES_HD_CALL); 103 callTypeIcon.setShowWifi( 104 MotorolaUtils.shouldShowWifiIconInCallLog(context, entry.getFeatures())); 105 106 callTypeText.setText( 107 callTypeHelper.getCallTypeText(callType, isVideoCall, isPulledCall, isDuoCall)); 108 callTime.setText(CallLogDates.formatDate(context, entry.getDate())); 109 110 if (CallTypeHelper.isMissedCallType(callType)) { 111 callDuration.setVisibility(View.GONE); 112 } else { 113 callDuration.setVisibility(View.VISIBLE); 114 callDuration.setText( 115 CallLogDurations.formatDurationAndDataUsage( 116 context, entry.getDuration(), entry.getDataUsage())); 117 callDuration.setContentDescription( 118 CallLogDurations.formatDurationAndDataUsageA11y( 119 context, entry.getDuration(), entry.getDataUsage())); 120 } 121 setMultimediaDetails(number, entry, showMultimediaDivider); 122 } 123 124 private void setMultimediaDetails(String number, CallDetailsEntry entry, boolean showDivider) { 125 multimediaDivider.setVisibility(showDivider ? View.VISIBLE : View.GONE); 126 if (entry.getHistoryResultsList().isEmpty()) { 127 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "no data, hiding UI"); 128 multimediaDetailsContainer.setVisibility(View.GONE); 129 } else { 130 131 HistoryResult historyResult = entry.getHistoryResults(0); 132 multimediaDetailsContainer.setVisibility(View.VISIBLE); 133 multimediaDetailsContainer.setOnClickListener((v) -> startSmsIntent(context, number)); 134 multimediaImageContainer.setOnClickListener((v) -> startSmsIntent(context, number)); 135 multimediaImageContainer.setClipToOutline(true); 136 137 if (!TextUtils.isEmpty(historyResult.getImageUri())) { 138 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "setting image"); 139 multimediaImageContainer.setVisibility(View.VISIBLE); 140 multimediaImage.setImageURI(Uri.parse(historyResult.getImageUri())); 141 multimediaDetails.setText( 142 isIncoming(historyResult) ? R.string.received_a_photo : R.string.sent_a_photo); 143 } else { 144 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "no image"); 145 } 146 147 // Set text after image to overwrite the received/sent a photo text 148 if (!TextUtils.isEmpty(historyResult.getText())) { 149 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "showing text"); 150 multimediaDetails.setText( 151 context.getString(R.string.message_in_quotes, historyResult.getText())); 152 } else { 153 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "no text"); 154 } 155 156 if (entry.getHistoryResultsList().size() > 1 157 && !TextUtils.isEmpty(entry.getHistoryResults(1).getText())) { 158 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "showing post call note"); 159 postCallNote.setVisibility(View.VISIBLE); 160 postCallNote.setText( 161 context.getString(R.string.message_in_quotes, entry.getHistoryResults(1).getText())); 162 postCallNote.setOnClickListener((v) -> startSmsIntent(context, number)); 163 } else { 164 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "no post call note"); 165 } 166 } 167 } 168 169 private void startSmsIntent(Context context, String number) { 170 DialerUtils.startActivityWithErrorToast(context, IntentUtil.getSendSmsIntent(number)); 171 } 172 173 private static boolean isIncoming(@NonNull HistoryResult historyResult) { 174 return historyResult.getType() == Type.INCOMING_POST_CALL 175 || historyResult.getType() == Type.INCOMING_CALL_COMPOSER; 176 } 177 178 private static @ColorInt int getColorForCallType(Context context, int callType) { 179 switch (callType) { 180 case AppCompatConstants.CALLS_OUTGOING_TYPE: 181 case AppCompatConstants.CALLS_VOICEMAIL_TYPE: 182 case AppCompatConstants.CALLS_BLOCKED_TYPE: 183 case AppCompatConstants.CALLS_INCOMING_TYPE: 184 case AppCompatConstants.CALLS_ANSWERED_EXTERNALLY_TYPE: 185 case AppCompatConstants.CALLS_REJECTED_TYPE: 186 return ContextCompat.getColor(context, R.color.dialer_secondary_text_color); 187 case AppCompatConstants.CALLS_MISSED_TYPE: 188 default: 189 // It is possible for users to end up with calls with unknown call types in their 190 // call history, possibly due to 3rd party call log implementations (e.g. to 191 // distinguish between rejected and missed calls). Instead of crashing, just 192 // assume that all unknown call types are missed calls. 193 return ContextCompat.getColor(context, R.color.missed_call); 194 } 195 } 196 } 197