1 /*
2  * Copyright (C) 2011 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.app.calllog;
18 
19 import android.content.ContentValues;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.net.Uri;
23 import android.provider.ContactsContract;
24 import android.support.annotation.Nullable;
25 import android.telecom.PhoneAccountHandle;
26 import android.telephony.TelephonyManager;
27 import com.android.contacts.common.model.Contact;
28 import com.android.contacts.common.model.ContactLoader;
29 import com.android.dialer.calldetails.CallDetailsEntries;
30 import com.android.dialer.calldetails.OldCallDetailsActivity;
31 import com.android.dialer.callintent.CallInitiationType;
32 import com.android.dialer.callintent.CallIntentBuilder;
33 import com.android.dialer.dialercontact.DialerContact;
34 import com.android.dialer.duo.DuoComponent;
35 import com.android.dialer.logging.DialerImpression;
36 import com.android.dialer.logging.Logger;
37 import com.android.dialer.precall.PreCall;
38 import com.android.dialer.util.IntentUtil;
39 import java.util.ArrayList;
40 
41 /**
42  * Used to create an intent to attach to an action in the call log.
43  *
44  * <p>The intent is constructed lazily with the given information.
45  */
46 public abstract class IntentProvider {
47 
48   private static final String TAG = IntentProvider.class.getSimpleName();
49 
getReturnCallIntentProvider(final String number)50   public static IntentProvider getReturnCallIntentProvider(final String number) {
51     return getReturnCallIntentProvider(number, null);
52   }
53 
getReturnCallIntentProvider( final String number, final PhoneAccountHandle accountHandle)54   public static IntentProvider getReturnCallIntentProvider(
55       final String number, final PhoneAccountHandle accountHandle) {
56     return new IntentProvider() {
57       @Override
58       public Intent getIntent(Context context) {
59         return PreCall.getIntent(
60             context,
61             new CallIntentBuilder(number, CallInitiationType.Type.CALL_LOG)
62                 .setPhoneAccountHandle(accountHandle));
63       }
64     };
65   }
66 
67   public static IntentProvider getAssistedDialIntentProvider(
68       final String number, final Context context, final TelephonyManager telephonyManager) {
69     return new IntentProvider() {
70       @Override
71       public Intent getIntent(Context context) {
72         return PreCall.getIntent(
73             context,
74             new CallIntentBuilder(number, CallInitiationType.Type.CALL_LOG)
75                 .setAllowAssistedDial(true));
76       }
77     };
78   }
79 
80   public static IntentProvider getReturnVideoCallIntentProvider(final String number) {
81     return getReturnVideoCallIntentProvider(number, null);
82   }
83 
84   public static IntentProvider getReturnVideoCallIntentProvider(
85       final String number, final PhoneAccountHandle accountHandle) {
86     return new IntentProvider() {
87       @Override
88       public Intent getIntent(Context context) {
89         return PreCall.getIntent(
90             context,
91             new CallIntentBuilder(number, CallInitiationType.Type.CALL_LOG)
92                 .setPhoneAccountHandle(accountHandle)
93                 .setIsVideoCall(true));
94       }
95     };
96   }
97 
98   public static IntentProvider getDuoVideoIntentProvider(String number, boolean isNonContact) {
99     return new IntentProvider() {
100       @Override
101       public Intent getIntent(Context context) {
102         return PreCall.getIntent(
103             context,
104             new CallIntentBuilder(number, CallInitiationType.Type.CALL_LOG)
105                 .setIsDuoCall(true)
106                 .setIsVideoCall(true));
107       }
108 
109       @Override
110       public void logInteraction(Context context) {
111         Logger.get(context)
112             .logImpression(DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FROM_CALL_LOG);
113         if (isNonContact) {
114           Logger.get(context)
115               .logImpression(
116                   DialerImpression.Type.LIGHTBRINGER_NON_CONTACT_VIDEO_REQUESTED_FROM_CALL_LOG);
117         }
118       }
119     };
120   }
121 
122   public static IntentProvider getInstallDuoIntentProvider() {
123     return new IntentProvider() {
124       @Override
125       public Intent getIntent(Context context) {
126         return DuoComponent.get(context).getDuo().getInstallDuoIntent().orNull();
127       }
128 
129       @Override
130       public void logInteraction(Context context) {
131         Logger.get(context).logImpression(DialerImpression.Type.DUO_CALL_LOG_SET_UP_INSTALL);
132       }
133     };
134   }
135 
136   public static IntentProvider getSetUpDuoIntentProvider() {
137     return new IntentProvider() {
138       @Override
139       public Intent getIntent(Context context) {
140         return DuoComponent.get(context).getDuo().getActivateIntent().orNull();
141       }
142 
143       @Override
144       public void logInteraction(Context context) {
145         Logger.get(context).logImpression(DialerImpression.Type.DUO_CALL_LOG_SET_UP_ACTIVATE);
146       }
147     };
148   }
149 
150   public static IntentProvider getDuoInviteIntentProvider(String number) {
151     return new IntentProvider() {
152       @Override
153       public Intent getIntent(Context context) {
154         return DuoComponent.get(context).getDuo().getInviteIntent(number).orNull();
155       }
156 
157       @Override
158       public void logInteraction(Context context) {
159         Logger.get(context).logImpression(DialerImpression.Type.DUO_CALL_LOG_INVITE);
160       }
161     };
162   }
163 
164   public static IntentProvider getReturnVoicemailCallIntentProvider() {
165     return new IntentProvider() {
166       @Override
167       public Intent getIntent(Context context) {
168         return PreCall.getIntent(
169             context,
170             CallIntentBuilder.forVoicemail(CallInitiationType.Type.CALL_LOG));
171       }
172     };
173   }
174 
175   public static IntentProvider getSendSmsIntentProvider(final String number) {
176     return new IntentProvider() {
177       @Override
178       public Intent getIntent(Context context) {
179         return IntentUtil.getSendSmsIntent(number);
180       }
181     };
182   }
183 
184   /**
185    * Retrieves the call details intent provider for an entry in the call log.
186    *
187    * @param callDetailsEntries The call details of the other calls grouped together with the call.
188    * @param contact The contact with which this call details intent pertains to.
189    * @param canReportCallerId Whether reporting a caller ID is supported.
190    * @param canSupportAssistedDialing Whether assisted dialing is supported.
191    * @return The call details intent provider.
192    */
193   public static IntentProvider getCallDetailIntentProvider(
194       CallDetailsEntries callDetailsEntries,
195       DialerContact contact,
196       boolean canReportCallerId,
197       boolean canSupportAssistedDialing) {
198     return new IntentProvider() {
199       @Override
200       public Intent getIntent(Context context) {
201         return OldCallDetailsActivity.newInstance(
202             context, callDetailsEntries, contact, canReportCallerId, canSupportAssistedDialing);
203       }
204     };
205   }
206 
207   /** Retrieves an add contact intent for the given contact and phone call details. */
208   public static IntentProvider getAddContactIntentProvider(
209       final Uri lookupUri,
210       final CharSequence name,
211       final CharSequence number,
212       final int numberType,
213       final boolean isNewContact) {
214     return new IntentProvider() {
215       @Override
216       public Intent getIntent(Context context) {
217         Contact contactToSave = null;
218 
219         if (lookupUri != null) {
220           contactToSave = ContactLoader.parseEncodedContactEntity(lookupUri);
221         }
222 
223         if (contactToSave != null) {
224           // Populate the intent with contact information stored in the lookup URI.
225           // Note: This code mirrors code in Contacts/QuickContactsActivity.
226           final Intent intent;
227           if (isNewContact) {
228             intent = IntentUtil.getNewContactIntent();
229           } else {
230             intent = IntentUtil.getAddToExistingContactIntent();
231           }
232 
233           ArrayList<ContentValues> values = contactToSave.getContentValues();
234           // Only pre-fill the name field if the provided display name is an nickname
235           // or better (e.g. structured name, nickname)
236           if (contactToSave.getDisplayNameSource()
237               >= ContactsContract.DisplayNameSources.NICKNAME) {
238             intent.putExtra(ContactsContract.Intents.Insert.NAME, contactToSave.getDisplayName());
239           } else if (contactToSave.getDisplayNameSource()
240               == ContactsContract.DisplayNameSources.ORGANIZATION) {
241             // This is probably an organization. Instead of copying the organization
242             // name into a name entry, copy it into the organization entry. This
243             // way we will still consider the contact an organization.
244             final ContentValues organization = new ContentValues();
245             organization.put(
246                 ContactsContract.CommonDataKinds.Organization.COMPANY,
247                 contactToSave.getDisplayName());
248             organization.put(
249                 ContactsContract.Data.MIMETYPE,
250                 ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
251             values.add(organization);
252           }
253 
254           // Last time used and times used are aggregated values from the usage stat
255           // table. They need to be removed from data values so the SQL table can insert
256           // properly
257           for (ContentValues value : values) {
258             value.remove(ContactsContract.Data.LAST_TIME_USED);
259             value.remove(ContactsContract.Data.TIMES_USED);
260           }
261 
262           intent.putExtra(ContactsContract.Intents.Insert.DATA, values);
263 
264           return intent;
265         } else {
266           // If no lookup uri is provided, rely on the available phone number and name.
267           if (isNewContact) {
268             return IntentUtil.getNewContactIntent(name, number, numberType);
269           } else {
270             return IntentUtil.getAddToExistingContactIntent(name, number, numberType);
271           }
272         }
273       }
274     };
275   }
276 
277   public abstract Intent getIntent(Context context);
278 
279   public void logInteraction(Context context) {}
280 }
281