• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.callintent;
18 
19 import android.content.Intent;
20 import android.net.Uri;
21 import android.os.Bundle;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.os.SystemClock;
25 import android.support.annotation.NonNull;
26 import android.support.annotation.Nullable;
27 import android.support.annotation.VisibleForTesting;
28 import android.telecom.Call.Details;
29 import android.telecom.PhoneAccount;
30 import android.telecom.PhoneAccountHandle;
31 import android.telecom.TelecomManager;
32 import android.telecom.VideoProfile;
33 import android.text.TextUtils;
34 import com.android.dialer.callintent.CallInitiationType.Type;
35 import com.android.dialer.common.Assert;
36 import com.android.dialer.performancereport.PerformanceReport;
37 import com.android.dialer.util.CallUtil;
38 import com.google.protobuf.InvalidProtocolBufferException;
39 
40 /** Creates an intent to start a new outgoing call. */
41 public class CallIntentBuilder implements Parcelable {
42   private Uri uri;
43   private final CallSpecificAppData callSpecificAppData;
44   @Nullable private PhoneAccountHandle phoneAccountHandle;
45   private boolean isVideoCall;
46   private boolean isDuoCall;
47   private String callSubject;
48   private boolean allowAssistedDial;
49 
50   private final Bundle inCallUiIntentExtras = new Bundle();
51   private final Bundle placeCallExtras = new Bundle();
52 
53   private static int lightbringerButtonAppearInExpandedCallLogItemCount = 0;
54   private static int lightbringerButtonAppearInCollapsedCallLogItemCount = 0;
55   private static int lightbringerButtonAppearInSearchCount = 0;
56 
CallIntentBuilder(@onNull Uri uri, @NonNull CallSpecificAppData callSpecificAppData)57   public CallIntentBuilder(@NonNull Uri uri, @NonNull CallSpecificAppData callSpecificAppData) {
58     this.uri = Assert.isNotNull(uri);
59     Assert.isNotNull(callSpecificAppData);
60     Assert.checkArgument(
61         callSpecificAppData.getCallInitiationType() != CallInitiationType.Type.UNKNOWN_INITIATION);
62 
63     CallSpecificAppData.Builder builder =
64         CallSpecificAppData.newBuilder(callSpecificAppData)
65             .setLightbringerButtonAppearInExpandedCallLogItemCount(
66                 lightbringerButtonAppearInExpandedCallLogItemCount)
67             .setLightbringerButtonAppearInCollapsedCallLogItemCount(
68                 lightbringerButtonAppearInCollapsedCallLogItemCount)
69             .setLightbringerButtonAppearInSearchCount(lightbringerButtonAppearInSearchCount);
70     lightbringerButtonAppearInExpandedCallLogItemCount = 0;
71     lightbringerButtonAppearInCollapsedCallLogItemCount = 0;
72     lightbringerButtonAppearInSearchCount = 0;
73 
74     if (PerformanceReport.isRecording()) {
75       builder
76           .setTimeSinceAppLaunch(PerformanceReport.getTimeSinceAppLaunch())
77           .setTimeSinceFirstClick(PerformanceReport.getTimeSinceFirstClick())
78           .addAllUiActionsSinceAppLaunch(PerformanceReport.getActions())
79           .addAllUiActionTimestampsSinceAppLaunch(PerformanceReport.getActionTimestamps())
80           .setStartingTabIndex(PerformanceReport.getStartingTabIndex())
81           .build();
82       PerformanceReport.stopRecording();
83     }
84 
85     this.callSpecificAppData = builder.build();
86   }
87 
CallIntentBuilder(@onNull Uri uri, CallInitiationType.Type callInitiationType)88   public CallIntentBuilder(@NonNull Uri uri, CallInitiationType.Type callInitiationType) {
89     this(uri, createCallSpecificAppData(callInitiationType));
90   }
91 
CallIntentBuilder( @onNull String number, @NonNull CallSpecificAppData callSpecificAppData)92   public CallIntentBuilder(
93       @NonNull String number, @NonNull CallSpecificAppData callSpecificAppData) {
94     this(CallUtil.getCallUri(Assert.isNotNull(number)), callSpecificAppData);
95   }
96 
CallIntentBuilder(@onNull String number, CallInitiationType.Type callInitiationType)97   public CallIntentBuilder(@NonNull String number, CallInitiationType.Type callInitiationType) {
98     this(CallUtil.getCallUri(Assert.isNotNull(number)), callInitiationType);
99   }
100 
CallIntentBuilder(@onNull Parcel parcel)101   public CallIntentBuilder(@NonNull Parcel parcel) {
102     ClassLoader classLoader = CallIntentBuilder.class.getClassLoader();
103     uri = parcel.readParcelable(classLoader);
104     CallSpecificAppData data;
105     try {
106       data = CallSpecificAppData.parseFrom(parcel.createByteArray());
107     } catch (InvalidProtocolBufferException e) {
108       data = createCallSpecificAppData(Type.UNKNOWN_INITIATION);
109     }
110     callSpecificAppData = data;
111     phoneAccountHandle = parcel.readParcelable(classLoader);
112     isVideoCall = parcel.readInt() != 0;
113     isDuoCall = parcel.readInt() != 0;
114     callSubject = parcel.readString();
115     allowAssistedDial = parcel.readInt() != 0;
116     inCallUiIntentExtras.putAll(parcel.readBundle(classLoader));
117   }
118 
forVoicemail( @ullable PhoneAccountHandle phoneAccountHandle, CallInitiationType.Type callInitiationType)119   public static CallIntentBuilder forVoicemail(
120       @Nullable PhoneAccountHandle phoneAccountHandle, CallInitiationType.Type callInitiationType) {
121     return new CallIntentBuilder(
122             Uri.fromParts(PhoneAccount.SCHEME_VOICEMAIL, "", null), callInitiationType)
123         .setPhoneAccountHandle(phoneAccountHandle);
124   }
125 
setUri(@onNull Uri uri)126   public void setUri(@NonNull Uri uri) {
127     this.uri = Assert.isNotNull(uri);
128   }
129 
getUri()130   public Uri getUri() {
131     return uri;
132   }
133 
getCallSpecificAppData()134   public CallSpecificAppData getCallSpecificAppData() {
135     return callSpecificAppData;
136   }
137 
setPhoneAccountHandle(@ullable PhoneAccountHandle accountHandle)138   public CallIntentBuilder setPhoneAccountHandle(@Nullable PhoneAccountHandle accountHandle) {
139     this.phoneAccountHandle = accountHandle;
140     return this;
141   }
142 
143   @Nullable
getPhoneAccountHandle()144   public PhoneAccountHandle getPhoneAccountHandle() {
145     return phoneAccountHandle;
146   }
147 
setIsVideoCall(boolean isVideoCall)148   public CallIntentBuilder setIsVideoCall(boolean isVideoCall) {
149     this.isVideoCall = isVideoCall;
150     return this;
151   }
152 
isVideoCall()153   public boolean isVideoCall() {
154     return isVideoCall;
155   }
156 
setIsDuoCall(boolean isDuoCall)157   public CallIntentBuilder setIsDuoCall(boolean isDuoCall) {
158     this.isDuoCall = isDuoCall;
159     return this;
160   }
161 
isDuoCall()162   public boolean isDuoCall() {
163     return isDuoCall;
164   }
165 
166   /** Default false. Should only be set to true if the number has a lookup URI. */
setAllowAssistedDial(boolean allowAssistedDial)167   public CallIntentBuilder setAllowAssistedDial(boolean allowAssistedDial) {
168     this.allowAssistedDial = allowAssistedDial;
169     return this;
170   }
171 
isAssistedDialAllowed()172   public boolean isAssistedDialAllowed() {
173     return allowAssistedDial;
174   }
175 
setCallSubject(String callSubject)176   public CallIntentBuilder setCallSubject(String callSubject) {
177     this.callSubject = callSubject;
178     return this;
179   }
180 
getCallSubject()181   public String getCallSubject() {
182     return callSubject;
183   }
184 
185   /** Additional data the in call UI can read with {@link Details#getIntentExtras()} */
getInCallUiIntentExtras()186   public Bundle getInCallUiIntentExtras() {
187     return inCallUiIntentExtras;
188   }
189 
190   /**
191    * Other extras that should be used with {@link TelecomManager#placeCall(Uri, Bundle)}. This will
192    * override everything set by the CallIntentBuilder
193    */
getPlaceCallExtras()194   public Bundle getPlaceCallExtras() {
195     return placeCallExtras;
196   }
197 
198   /**
199    * @deprecated Use {@link com.android.dialer.precall.PreCall#getIntent(android.content.Context,
200    *     CallIntentBuilder)} instead.
201    */
202   @Deprecated
build()203   public Intent build() {
204     Intent intent = new Intent(Intent.ACTION_CALL, uri);
205 
206     intent.putExtra(
207         TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
208         isVideoCall ? VideoProfile.STATE_BIDIRECTIONAL : VideoProfile.STATE_AUDIO_ONLY);
209 
210     inCallUiIntentExtras.putLong(
211         Constants.EXTRA_CALL_CREATED_TIME_MILLIS, SystemClock.elapsedRealtime());
212     CallIntentParser.putCallSpecificAppData(inCallUiIntentExtras, callSpecificAppData);
213 
214     intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, inCallUiIntentExtras);
215 
216     if (phoneAccountHandle != null) {
217       intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
218     }
219 
220     if (!TextUtils.isEmpty(callSubject)) {
221       intent.putExtra(TelecomManager.EXTRA_CALL_SUBJECT, callSubject);
222     }
223 
224     intent.putExtras(placeCallExtras);
225 
226     return intent;
227   }
228 
createCallSpecificAppData( CallInitiationType.Type callInitiationType)229   private static @NonNull CallSpecificAppData createCallSpecificAppData(
230       CallInitiationType.Type callInitiationType) {
231     CallSpecificAppData callSpecificAppData =
232         CallSpecificAppData.newBuilder().setCallInitiationType(callInitiationType).build();
233     return callSpecificAppData;
234   }
235 
increaseLightbringerCallButtonAppearInExpandedCallLogItemCount()236   public static void increaseLightbringerCallButtonAppearInExpandedCallLogItemCount() {
237     CallIntentBuilder.lightbringerButtonAppearInExpandedCallLogItemCount++;
238   }
239 
increaseLightbringerCallButtonAppearInCollapsedCallLogItemCount()240   public static void increaseLightbringerCallButtonAppearInCollapsedCallLogItemCount() {
241     CallIntentBuilder.lightbringerButtonAppearInCollapsedCallLogItemCount++;
242   }
243 
increaseLightbringerCallButtonAppearInSearchCount()244   public static void increaseLightbringerCallButtonAppearInSearchCount() {
245     CallIntentBuilder.lightbringerButtonAppearInSearchCount++;
246   }
247 
248   @VisibleForTesting
getLightbringerButtonAppearInExpandedCallLogItemCount()249   public static int getLightbringerButtonAppearInExpandedCallLogItemCount() {
250     return lightbringerButtonAppearInExpandedCallLogItemCount;
251   }
252 
253   @VisibleForTesting
getLightbringerButtonAppearInCollapsedCallLogItemCount()254   public static int getLightbringerButtonAppearInCollapsedCallLogItemCount() {
255     return lightbringerButtonAppearInCollapsedCallLogItemCount;
256   }
257 
258   @VisibleForTesting
getLightbringerButtonAppearInSearchCount()259   public static int getLightbringerButtonAppearInSearchCount() {
260     return lightbringerButtonAppearInSearchCount;
261   }
262 
263   @VisibleForTesting(otherwise = VisibleForTesting.NONE)
clearLightbringerCounts()264   public static void clearLightbringerCounts() {
265     lightbringerButtonAppearInCollapsedCallLogItemCount = 0;
266     lightbringerButtonAppearInExpandedCallLogItemCount = 0;
267     lightbringerButtonAppearInSearchCount = 0;
268   }
269 
270   @Override
describeContents()271   public int describeContents() {
272     return 0;
273   }
274 
275   @Override
writeToParcel(Parcel dest, int flags)276   public void writeToParcel(Parcel dest, int flags) {
277     dest.writeParcelable(uri, flags);
278     dest.writeByteArray(callSpecificAppData.toByteArray());
279     dest.writeParcelable(phoneAccountHandle, flags);
280     dest.writeInt(isVideoCall ? 1 : 0);
281     dest.writeInt(isDuoCall ? 1 : 0);
282     dest.writeString(callSubject);
283     dest.writeInt(allowAssistedDial ? 1 : 0);
284     dest.writeBundle(inCallUiIntentExtras);
285   }
286 
287   public static final Creator<CallIntentBuilder> CREATOR =
288       new Creator<CallIntentBuilder>() {
289         @Override
290         public CallIntentBuilder createFromParcel(Parcel source) {
291           return new CallIntentBuilder(source);
292         }
293 
294         @Override
295         public CallIntentBuilder[] newArray(int size) {
296           return new CallIntentBuilder[0];
297         }
298       };
299 }
300