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