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.CallEntryFormatter; 32 import com.android.dialer.calllogutils.CallTypeHelper; 33 import com.android.dialer.calllogutils.CallTypeIconsView; 34 import com.android.dialer.common.LogUtil; 35 import com.android.dialer.compat.AppCompatConstants; 36 import com.android.dialer.enrichedcall.historyquery.proto.HistoryResult; 37 import com.android.dialer.enrichedcall.historyquery.proto.HistoryResult.Type; 38 import com.android.dialer.oem.MotorolaUtils; 39 import com.android.dialer.util.CallUtil; 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: Display this when location is stored - b/36160042 61 @SuppressWarnings("unused") 62 private final TextView multimediaAttachmentsNumber; 63 64 private final Context context; 65 CallDetailsEntryViewHolder(View container)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 setCallDetails( String number, CallDetailsEntry entry, CallTypeHelper callTypeHelper, boolean showMultimediaDivider)85 void setCallDetails( 86 String number, 87 CallDetailsEntry entry, 88 CallTypeHelper callTypeHelper, 89 boolean showMultimediaDivider) { 90 int callType = entry.getCallType(); 91 boolean isVideoCall = 92 (entry.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO 93 && CallUtil.isVideoEnabled(context); 94 boolean isPulledCall = 95 (entry.getFeatures() & Calls.FEATURES_PULLED_EXTERNALLY) 96 == Calls.FEATURES_PULLED_EXTERNALLY; 97 98 callTime.setTextColor(getColorForCallType(context, callType)); 99 callTypeIcon.clear(); 100 callTypeIcon.add(callType); 101 callTypeIcon.setShowVideo((entry.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO); 102 callTypeIcon.setShowHd(MotorolaUtils.shouldShowHdIconInCallLog(context, entry.getFeatures())); 103 callTypeIcon.setShowWifi( 104 MotorolaUtils.shouldShowWifiIconInCallLog(context, entry.getFeatures())); 105 106 callTypeText.setText(callTypeHelper.getCallTypeText(callType, isVideoCall, isPulledCall)); 107 callTime.setText(CallEntryFormatter.formatDate(context, entry.getDate())); 108 if (CallTypeHelper.isMissedCallType(callType)) { 109 callDuration.setVisibility(View.GONE); 110 } else { 111 callDuration.setVisibility(View.VISIBLE); 112 callDuration.setText( 113 CallEntryFormatter.formatDurationAndDataUsage( 114 context, entry.getDuration(), entry.getDataUsage())); 115 callDuration.setContentDescription( 116 CallEntryFormatter.formatDurationAndDataUsageA11y( 117 context, entry.getDuration(), entry.getDataUsage())); 118 } 119 setMultimediaDetails(number, entry, showMultimediaDivider); 120 } 121 setMultimediaDetails(String number, CallDetailsEntry entry, boolean showDivider)122 private void setMultimediaDetails(String number, CallDetailsEntry entry, boolean showDivider) { 123 multimediaDivider.setVisibility(showDivider ? View.VISIBLE : View.GONE); 124 if (entry.getHistoryResultsList().isEmpty()) { 125 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "no data, hiding UI"); 126 multimediaDetailsContainer.setVisibility(View.GONE); 127 } else { 128 129 HistoryResult historyResult = entry.getHistoryResults(0); 130 multimediaDetailsContainer.setVisibility(View.VISIBLE); 131 multimediaDetailsContainer.setOnClickListener((v) -> startSmsIntent(context, number)); 132 multimediaImageContainer.setClipToOutline(true); 133 134 if (!TextUtils.isEmpty(historyResult.getImageUri())) { 135 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "setting image"); 136 multimediaImageContainer.setVisibility(View.VISIBLE); 137 multimediaImage.setImageURI(Uri.parse(historyResult.getImageUri())); 138 multimediaDetails.setText( 139 isIncoming(historyResult) ? R.string.received_a_photo : R.string.sent_a_photo); 140 } else { 141 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "no image"); 142 } 143 144 // Set text after image to overwrite the received/sent a photo text 145 if (!TextUtils.isEmpty(historyResult.getText())) { 146 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "showing text"); 147 multimediaDetails.setText( 148 context.getString(R.string.message_in_quotes, historyResult.getText())); 149 } else { 150 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "no text"); 151 } 152 153 if (entry.getHistoryResultsList().size() > 1 154 && !TextUtils.isEmpty(entry.getHistoryResults(1).getText())) { 155 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "showing post call note"); 156 postCallNote.setVisibility(View.VISIBLE); 157 postCallNote.setText( 158 context.getString(R.string.message_in_quotes, entry.getHistoryResults(1).getText())); 159 postCallNote.setOnClickListener((v) -> startSmsIntent(context, number)); 160 } else { 161 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "no post call note"); 162 } 163 } 164 } 165 startSmsIntent(Context context, String number)166 private void startSmsIntent(Context context, String number) { 167 DialerUtils.startActivityWithErrorToast(context, IntentUtil.getSendSmsIntent(number)); 168 } 169 isIncoming(@onNull HistoryResult historyResult)170 private static boolean isIncoming(@NonNull HistoryResult historyResult) { 171 return historyResult.getType() == Type.INCOMING_POST_CALL 172 || historyResult.getType() == Type.INCOMING_CALL_COMPOSER; 173 } 174 getColorForCallType(Context context, int callType)175 private static @ColorInt int getColorForCallType(Context context, int callType) { 176 switch (callType) { 177 case AppCompatConstants.CALLS_OUTGOING_TYPE: 178 case AppCompatConstants.CALLS_VOICEMAIL_TYPE: 179 case AppCompatConstants.CALLS_BLOCKED_TYPE: 180 case AppCompatConstants.CALLS_INCOMING_TYPE: 181 case AppCompatConstants.CALLS_ANSWERED_EXTERNALLY_TYPE: 182 case AppCompatConstants.CALLS_REJECTED_TYPE: 183 return ContextCompat.getColor(context, R.color.dialer_secondary_text_color); 184 case AppCompatConstants.CALLS_MISSED_TYPE: 185 default: 186 // It is possible for users to end up with calls with unknown call types in their 187 // call history, possibly due to 3rd party call log implementations (e.g. to 188 // distinguish between rejected and missed calls). Instead of crashing, just 189 // assume that all unknown call types are missed calls. 190 return ContextCompat.getColor(context, R.color.missed_call); 191 } 192 } 193 } 194