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.DialerUtils; 40 import com.android.dialer.util.IntentUtil; 41 42 /** ViewHolder for call entries in {@link CallDetailsActivity}. */ 43 public class CallDetailsEntryViewHolder extends ViewHolder { 44 45 private final CallTypeIconsView callTypeIcon; 46 private final TextView callTypeText; 47 private final TextView callTime; 48 private final TextView callDuration; 49 50 private final View multimediaImageContainer; 51 private final View multimediaDetailsContainer; 52 private final View multimediaDivider; 53 54 private final TextView multimediaDetails; 55 private final TextView postCallNote; 56 57 private final ImageView multimediaImage; 58 59 // TODO: Display this when location is stored - b/36160042 60 @SuppressWarnings("unused") 61 private final TextView multimediaAttachmentsNumber; 62 63 private final Context context; 64 65 public CallDetailsEntryViewHolder(View container) { 66 super(container); 67 context = container.getContext(); 68 69 callTypeIcon = (CallTypeIconsView) container.findViewById(R.id.call_direction); 70 callTypeText = (TextView) container.findViewById(R.id.call_type); 71 callTime = (TextView) container.findViewById(R.id.call_time); 72 callDuration = (TextView) container.findViewById(R.id.call_duration); 73 74 multimediaImageContainer = container.findViewById(R.id.multimedia_image_container); 75 multimediaDetailsContainer = container.findViewById(R.id.ec_container); 76 multimediaDivider = container.findViewById(R.id.divider); 77 multimediaDetails = (TextView) container.findViewById(R.id.multimedia_details); 78 postCallNote = (TextView) container.findViewById(R.id.post_call_note); 79 multimediaImage = (ImageView) container.findViewById(R.id.multimedia_image); 80 multimediaAttachmentsNumber = 81 (TextView) container.findViewById(R.id.multimedia_attachments_number); 82 } 83 84 void setCallDetails( 85 String number, 86 CallDetailsEntry entry, 87 CallTypeHelper callTypeHelper, 88 boolean showMultimediaDivider) { 89 int callType = entry.getCallType(); 90 boolean isVideoCall = (entry.getFeatures() & Calls.FEATURES_VIDEO) == Calls.FEATURES_VIDEO; 91 boolean isPulledCall = 92 (entry.getFeatures() & Calls.FEATURES_PULLED_EXTERNALLY) 93 == Calls.FEATURES_PULLED_EXTERNALLY; 94 95 callTime.setTextColor(getColorForCallType(context, callType)); 96 callTypeIcon.clear(); 97 callTypeIcon.add(callType); 98 callTypeIcon.setShowVideo(isVideoCall); 99 callTypeIcon.setShowHd(MotorolaUtils.shouldShowHdIconInCallLog(context, entry.getFeatures())); 100 callTypeIcon.setShowWifi( 101 MotorolaUtils.shouldShowWifiIconInCallLog(context, entry.getFeatures())); 102 103 callTypeText.setText(callTypeHelper.getCallTypeText(callType, isVideoCall, isPulledCall)); 104 callTime.setText(CallEntryFormatter.formatDate(context, entry.getDate())); 105 if (CallTypeHelper.isMissedCallType(callType)) { 106 callDuration.setVisibility(View.GONE); 107 } else { 108 callDuration.setVisibility(View.VISIBLE); 109 callDuration.setText( 110 CallEntryFormatter.formatDurationAndDataUsage( 111 context, entry.getDuration(), entry.getDataUsage())); 112 callDuration.setContentDescription( 113 CallEntryFormatter.formatDurationAndDataUsageA11y( 114 context, entry.getDuration(), entry.getDataUsage())); 115 } 116 setMultimediaDetails(number, entry, showMultimediaDivider); 117 } 118 119 private void setMultimediaDetails(String number, CallDetailsEntry entry, boolean showDivider) { 120 multimediaDivider.setVisibility(showDivider ? View.VISIBLE : View.GONE); 121 if (entry.getHistoryResultsList().isEmpty()) { 122 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "no data, hiding UI"); 123 multimediaDetailsContainer.setVisibility(View.GONE); 124 } else { 125 126 HistoryResult historyResult = entry.getHistoryResults(0); 127 multimediaDetailsContainer.setVisibility(View.VISIBLE); 128 multimediaDetailsContainer.setOnClickListener((v) -> startSmsIntent(context, number)); 129 multimediaImageContainer.setClipToOutline(true); 130 131 if (!TextUtils.isEmpty(historyResult.getImageUri())) { 132 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "setting image"); 133 multimediaImageContainer.setVisibility(View.VISIBLE); 134 multimediaImage.setImageURI(Uri.parse(historyResult.getImageUri())); 135 multimediaDetails.setText( 136 isIncoming(historyResult) ? R.string.received_a_photo : R.string.sent_a_photo); 137 } else { 138 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "no image"); 139 } 140 141 // Set text after image to overwrite the received/sent a photo text 142 if (!TextUtils.isEmpty(historyResult.getText())) { 143 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "showing text"); 144 multimediaDetails.setText( 145 context.getString(R.string.message_in_quotes, historyResult.getText())); 146 } else { 147 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "no text"); 148 } 149 150 if (entry.getHistoryResultsList().size() > 1 151 && !TextUtils.isEmpty(entry.getHistoryResults(1).getText())) { 152 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "showing post call note"); 153 postCallNote.setVisibility(View.VISIBLE); 154 postCallNote.setText( 155 context.getString(R.string.message_in_quotes, entry.getHistoryResults(1).getText())); 156 postCallNote.setOnClickListener((v) -> startSmsIntent(context, number)); 157 } else { 158 LogUtil.i("CallDetailsEntryViewHolder.setMultimediaDetails", "no post call note"); 159 } 160 } 161 } 162 163 private void startSmsIntent(Context context, String number) { 164 DialerUtils.startActivityWithErrorToast(context, IntentUtil.getSendSmsIntent(number)); 165 } 166 167 private static boolean isIncoming(@NonNull HistoryResult historyResult) { 168 return historyResult.getType() == Type.INCOMING_POST_CALL 169 || historyResult.getType() == Type.INCOMING_CALL_COMPOSER; 170 } 171 172 private static @ColorInt int getColorForCallType(Context context, int callType) { 173 switch (callType) { 174 case AppCompatConstants.CALLS_OUTGOING_TYPE: 175 case AppCompatConstants.CALLS_VOICEMAIL_TYPE: 176 case AppCompatConstants.CALLS_BLOCKED_TYPE: 177 case AppCompatConstants.CALLS_INCOMING_TYPE: 178 case AppCompatConstants.CALLS_ANSWERED_EXTERNALLY_TYPE: 179 case AppCompatConstants.CALLS_REJECTED_TYPE: 180 return ContextCompat.getColor(context, R.color.dialer_secondary_text_color); 181 case AppCompatConstants.CALLS_MISSED_TYPE: 182 default: 183 // It is possible for users to end up with calls with unknown call types in their 184 // call history, possibly due to 3rd party call log implementations (e.g. to 185 // distinguish between rejected and missed calls). Instead of crashing, just 186 // assume that all unknown call types are missed calls. 187 return ContextCompat.getColor(context, R.color.missed_call); 188 } 189 } 190 } 191