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       @Nullable PhoneAccountHandle phoneAccountHandle) {
166     return new IntentProvider() {
167       @Override
168       public Intent getIntent(Context context) {
169         return PreCall.getIntent(
170             context,
171             CallIntentBuilder.forVoicemail(phoneAccountHandle, CallInitiationType.Type.CALL_LOG));
172       }
173     };
174   }
175 
176   public static IntentProvider getSendSmsIntentProvider(final String number) {
177     return new IntentProvider() {
178       @Override
179       public Intent getIntent(Context context) {
180         return IntentUtil.getSendSmsIntent(number);
181       }
182     };
183   }
184 
185   /**
186    * Retrieves the call details intent provider for an entry in the call log.
187    *
188    * @param callDetailsEntries The call details of the other calls grouped together with the call.
189    * @param contact The contact with which this call details intent pertains to.
190    * @param canReportCallerId Whether reporting a caller ID is supported.
191    * @param canSupportAssistedDialing Whether assisted dialing is supported.
192    * @return The call details intent provider.
193    */
194   public static IntentProvider getCallDetailIntentProvider(
195       CallDetailsEntries callDetailsEntries,
196       DialerContact contact,
197       boolean canReportCallerId,
198       boolean canSupportAssistedDialing) {
199     return new IntentProvider() {
200       @Override
201       public Intent getIntent(Context context) {
202         return OldCallDetailsActivity.newInstance(
203             context, callDetailsEntries, contact, canReportCallerId, canSupportAssistedDialing);
204       }
205     };
206   }
207 
208   /** Retrieves an add contact intent for the given contact and phone call details. */
209   public static IntentProvider getAddContactIntentProvider(
210       final Uri lookupUri,
211       final CharSequence name,
212       final CharSequence number,
213       final int numberType,
214       final boolean isNewContact) {
215     return new IntentProvider() {
216       @Override
217       public Intent getIntent(Context context) {
218         Contact contactToSave = null;
219 
220         if (lookupUri != null) {
221           contactToSave = ContactLoader.parseEncodedContactEntity(lookupUri);
222         }
223 
224         if (contactToSave != null) {
225           // Populate the intent with contact information stored in the lookup URI.
226           // Note: This code mirrors code in Contacts/QuickContactsActivity.
227           final Intent intent;
228           if (isNewContact) {
229             intent = IntentUtil.getNewContactIntent();
230           } else {
231             intent = IntentUtil.getAddToExistingContactIntent();
232           }
233 
234           ArrayList<ContentValues> values = contactToSave.getContentValues();
235           // Only pre-fill the name field if the provided display name is an nickname
236           // or better (e.g. structured name, nickname)
237           if (contactToSave.getDisplayNameSource()
238               >= ContactsContract.DisplayNameSources.NICKNAME) {
239             intent.putExtra(ContactsContract.Intents.Insert.NAME, contactToSave.getDisplayName());
240           } else if (contactToSave.getDisplayNameSource()
241               == ContactsContract.DisplayNameSources.ORGANIZATION) {
242             // This is probably an organization. Instead of copying the organization
243             // name into a name entry, copy it into the organization entry. This
244             // way we will still consider the contact an organization.
245             final ContentValues organization = new ContentValues();
246             organization.put(
247                 ContactsContract.CommonDataKinds.Organization.COMPANY,
248                 contactToSave.getDisplayName());
249             organization.put(
250                 ContactsContract.Data.MIMETYPE,
251                 ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
252             values.add(organization);
253           }
254 
255           // Last time used and times used are aggregated values from the usage stat
256           // table. They need to be removed from data values so the SQL table can insert
257           // properly
258           for (ContentValues value : values) {
259             value.remove(ContactsContract.Data.LAST_TIME_USED);
260             value.remove(ContactsContract.Data.TIMES_USED);
261           }
262 
263           intent.putExtra(ContactsContract.Intents.Insert.DATA, values);
264 
265           return intent;
266         } else {
267           // If no lookup uri is provided, rely on the available phone number and name.
268           if (isNewContact) {
269             return IntentUtil.getNewContactIntent(name, number, numberType);
270           } else {
271             return IntentUtil.getAddToExistingContactIntent(name, number, numberType);
272           }
273         }
274       }
275     };
276   }
277 
278   public abstract Intent getIntent(Context context);
279 
280   public void logInteraction(Context context) {}
281 }
282