• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.support.v7.widget.RecyclerView;
22 import android.telecom.PhoneAccount;
23 import android.text.TextUtils;
24 import android.view.View;
25 import android.view.View.OnClickListener;
26 import android.widget.ImageView;
27 import android.widget.QuickContactBadge;
28 import android.widget.RelativeLayout;
29 import android.widget.TextView;
30 import com.android.dialer.calldetails.CallDetailsActivityCommon.AssistedDialingNumberParseWorker;
31 import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry;
32 import com.android.dialer.calllogutils.CallbackActionHelper.CallbackAction;
33 import com.android.dialer.common.Assert;
34 import com.android.dialer.common.LogUtil;
35 import com.android.dialer.common.concurrent.DialerExecutor.FailureListener;
36 import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener;
37 import com.android.dialer.compat.telephony.TelephonyManagerCompat;
38 import com.android.dialer.contactphoto.ContactPhotoManager;
39 import com.android.dialer.dialercontact.DialerContact;
40 import com.android.dialer.glidephotomanager.GlidePhotoManagerComponent;
41 import com.android.dialer.logging.InteractionEvent;
42 import com.android.dialer.logging.Logger;
43 import com.android.dialer.phonenumberutil.PhoneNumberHelper;
44 import com.android.dialer.widget.BidiTextView;
45 
46 /**
47  * ViewHolder for the header in {@link OldCallDetailsActivity} or {@link CallDetailsActivity}.
48  *
49  * <p>The header contains contact info and the primary callback button.
50  */
51 public class CallDetailsHeaderViewHolder extends RecyclerView.ViewHolder
52     implements OnClickListener, FailureListener {
53 
54   private final CallDetailsHeaderListener callDetailsHeaderListener;
55   private final ImageView callbackButton;
56   private final BidiTextView nameView;
57   private final BidiTextView numberView;
58   private final TextView networkView;
59   private final QuickContactBadge contactPhoto;
60   private final Context context;
61   private final TextView assistedDialingInternationalDirectDialCodeAndCountryCodeText;
62   private final RelativeLayout assistedDialingContainer;
63 
64   private final String number;
65   private final String postDialDigits;
66 
67   private @CallbackAction int callbackAction;
68 
CallDetailsHeaderViewHolder( View container, String number, String postDialDigits, CallDetailsHeaderListener callDetailsHeaderListener)69   CallDetailsHeaderViewHolder(
70       View container,
71       String number,
72       String postDialDigits,
73       CallDetailsHeaderListener callDetailsHeaderListener) {
74     super(container);
75     context = container.getContext();
76     callbackButton = container.findViewById(R.id.call_back_button);
77     nameView = container.findViewById(R.id.contact_name);
78     numberView = container.findViewById(R.id.phone_number);
79     networkView = container.findViewById(R.id.network);
80     contactPhoto = container.findViewById(R.id.quick_contact_photo);
81     assistedDialingInternationalDirectDialCodeAndCountryCodeText =
82         container.findViewById(R.id.assisted_dialing_text);
83     assistedDialingContainer = container.findViewById(R.id.assisted_dialing_container);
84 
85     assistedDialingContainer.setOnClickListener(
86         callDetailsHeaderListener::openAssistedDialingSettings);
87 
88     callbackButton.setOnClickListener(this);
89 
90     this.number = number;
91     this.postDialDigits = postDialDigits;
92     this.callDetailsHeaderListener = callDetailsHeaderListener;
93 
94     Logger.get(context)
95         .logQuickContactOnTouch(
96             contactPhoto, InteractionEvent.Type.OPEN_QUICK_CONTACT_FROM_CALL_DETAILS, true);
97   }
98 
hasAssistedDialingFeature(Integer features)99   private boolean hasAssistedDialingFeature(Integer features) {
100     return (features & TelephonyManagerCompat.FEATURES_ASSISTED_DIALING)
101         == TelephonyManagerCompat.FEATURES_ASSISTED_DIALING;
102   }
103 
updateAssistedDialingInfo(CallDetailsEntry callDetailsEntry)104   void updateAssistedDialingInfo(CallDetailsEntry callDetailsEntry) {
105 
106     if (callDetailsEntry != null && hasAssistedDialingFeature(callDetailsEntry.getFeatures())) {
107       showAssistedDialingContainer(true);
108       callDetailsHeaderListener.createAssistedDialerNumberParserTask(
109           new CallDetailsActivityCommon.AssistedDialingNumberParseWorker(),
110           this::updateAssistedDialingText,
111           this::onFailure);
112 
113     } else {
114       showAssistedDialingContainer(false);
115     }
116   }
117 
showAssistedDialingContainer(boolean shouldShowContainer)118   private void showAssistedDialingContainer(boolean shouldShowContainer) {
119     if (shouldShowContainer) {
120       assistedDialingContainer.setVisibility(View.VISIBLE);
121     } else {
122       LogUtil.i(
123           "CallDetailsHeaderViewHolder.updateAssistedDialingInfo",
124           "hiding assisted dialing ui elements");
125       assistedDialingContainer.setVisibility(View.GONE);
126     }
127   }
128 
updateAssistedDialingText(Integer countryCode)129   private void updateAssistedDialingText(Integer countryCode) {
130 
131     // Try and handle any poorly formed inputs.
132     if (countryCode <= 0) {
133       onFailure(new IllegalStateException());
134       return;
135     }
136 
137     LogUtil.i(
138         "CallDetailsHeaderViewHolder.updateAssistedDialingText", "Updating Assisted Dialing Text");
139     assistedDialingInternationalDirectDialCodeAndCountryCodeText.setText(
140         context.getString(
141             R.string.assisted_dialing_country_code_entry, String.valueOf(countryCode)));
142   }
143 
144   @Override
onFailure(Throwable unused)145   public void onFailure(Throwable unused) {
146     assistedDialingInternationalDirectDialCodeAndCountryCodeText.setText(
147         R.string.assisted_dialing_country_code_entry_failure);
148   }
149 
150   /** Populates the contact info fields based on the current contact information. */
updateContactInfo(DialerContact contact, @CallbackAction int callbackAction)151   void updateContactInfo(DialerContact contact, @CallbackAction int callbackAction) {
152     ContactPhotoManager.getInstance(context)
153         .loadDialerThumbnailOrPhoto(
154             contactPhoto,
155             contact.getContactUri().isEmpty() ? null : Uri.parse(contact.getContactUri()),
156             contact.getPhotoId(),
157             contact.getPhotoUri().isEmpty() ? null : Uri.parse(contact.getPhotoUri()),
158             contact.getNameOrNumber(),
159             contact.getContactType());
160 
161     // Hide the secondary text of the header by default.
162     // We will show it if needed (see below).
163     numberView.setVisibility(View.GONE);
164     numberView.setText(null);
165 
166     if (PhoneNumberHelper.isLocalEmergencyNumber(context, contact.getNumber())) {
167       nameView.setText(context.getResources().getString(R.string.emergency_number));
168     } else {
169       nameView.setText(contact.getNameOrNumber());
170       if (!TextUtils.isEmpty(contact.getDisplayNumber())) {
171         numberView.setVisibility(View.VISIBLE);
172         String secondaryInfo =
173             TextUtils.isEmpty(contact.getNumberLabel())
174                 ? contact.getDisplayNumber()
175                 : context.getString(
176                     com.android.dialer.contacts.resources.R.string.call_subject_type_and_number,
177                     contact.getNumberLabel(),
178                     contact.getDisplayNumber());
179         numberView.setText(secondaryInfo);
180       }
181     }
182 
183     if (!TextUtils.isEmpty(contact.getSimDetails().getNetwork())) {
184       networkView.setVisibility(View.VISIBLE);
185       networkView.setText(contact.getSimDetails().getNetwork());
186       if (contact.getSimDetails().getColor() != PhoneAccount.NO_HIGHLIGHT_COLOR) {
187         networkView.setTextColor(contact.getSimDetails().getColor());
188       }
189     }
190 
191     setCallbackAction(callbackAction);
192   }
193 
updateContactInfo(CallDetailsHeaderInfo headerInfo, @CallbackAction int callbackAction)194   void updateContactInfo(CallDetailsHeaderInfo headerInfo, @CallbackAction int callbackAction) {
195     GlidePhotoManagerComponent.get(context)
196         .glidePhotoManager()
197         .loadQuickContactBadge(contactPhoto, headerInfo.getPhotoInfo());
198 
199     nameView.setText(headerInfo.getPrimaryText());
200     if (!headerInfo.getSecondaryText().isEmpty()) {
201       numberView.setVisibility(View.VISIBLE);
202       numberView.setText(headerInfo.getSecondaryText());
203     } else {
204       numberView.setVisibility(View.GONE);
205       numberView.setText(null);
206     }
207 
208     setCallbackAction(callbackAction);
209   }
210 
setCallbackAction(@allbackAction int callbackAction)211   private void setCallbackAction(@CallbackAction int callbackAction) {
212     this.callbackAction = callbackAction;
213     switch (callbackAction) {
214       case CallbackAction.DUO:
215       case CallbackAction.IMS_VIDEO:
216         callbackButton.setVisibility(View.VISIBLE);
217         callbackButton.setImageResource(R.drawable.quantum_ic_videocam_vd_theme_24);
218         break;
219       case CallbackAction.VOICE:
220         callbackButton.setVisibility(View.VISIBLE);
221         callbackButton.setImageResource(R.drawable.quantum_ic_call_vd_theme_24);
222         break;
223       case CallbackAction.NONE:
224         callbackButton.setVisibility(View.GONE);
225         break;
226       default:
227         throw Assert.createIllegalStateFailException("Invalid action: " + callbackAction);
228     }
229   }
230 
231   @Override
onClick(View view)232   public void onClick(View view) {
233     if (view == callbackButton) {
234       switch (callbackAction) {
235         case CallbackAction.IMS_VIDEO:
236           callDetailsHeaderListener.placeImsVideoCall(number);
237           break;
238         case CallbackAction.DUO:
239           callDetailsHeaderListener.placeDuoVideoCall(number);
240           break;
241         case CallbackAction.VOICE:
242           callDetailsHeaderListener.placeVoiceCall(number, postDialDigits);
243           break;
244         case CallbackAction.NONE:
245         default:
246           throw Assert.createIllegalStateFailException("Invalid action: " + callbackAction);
247       }
248     } else {
249       throw Assert.createIllegalStateFailException("View OnClickListener not implemented: " + view);
250     }
251   }
252 
253   /** Listener for the call details header */
254   interface CallDetailsHeaderListener {
255 
256     /** Places an IMS video call. */
placeImsVideoCall(String phoneNumber)257     void placeImsVideoCall(String phoneNumber);
258 
259     /** Places a Duo video call. */
placeDuoVideoCall(String phoneNumber)260     void placeDuoVideoCall(String phoneNumber);
261 
262     /** Place a traditional voice call. */
placeVoiceCall(String phoneNumber, String postDialDigits)263     void placeVoiceCall(String phoneNumber, String postDialDigits);
264 
265     /** Access the Assisted Dialing settings * */
openAssistedDialingSettings(View view)266     void openAssistedDialingSettings(View view);
267 
createAssistedDialerNumberParserTask( AssistedDialingNumberParseWorker worker, SuccessListener<Integer> onSuccess, FailureListener onFailure)268     void createAssistedDialerNumberParserTask(
269         AssistedDialingNumberParseWorker worker,
270         SuccessListener<Integer> onSuccess,
271         FailureListener onFailure);
272   }
273 }
274