/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.dialer.callintent; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.telecom.Call.Details; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telecom.VideoProfile; import android.text.TextUtils; import com.android.dialer.callintent.CallInitiationType.Type; import com.android.dialer.common.Assert; import com.android.dialer.performancereport.PerformanceReport; import com.android.dialer.util.CallUtil; import com.google.protobuf.InvalidProtocolBufferException; /** Creates an intent to start a new outgoing call. */ public class CallIntentBuilder implements Parcelable { private Uri uri; private final CallSpecificAppData callSpecificAppData; @Nullable private PhoneAccountHandle phoneAccountHandle; private boolean isVideoCall; private boolean isDuoCall; private String callSubject; private boolean allowAssistedDial; private final Bundle inCallUiIntentExtras = new Bundle(); private final Bundle placeCallExtras = new Bundle(); private static int lightbringerButtonAppearInExpandedCallLogItemCount = 0; private static int lightbringerButtonAppearInCollapsedCallLogItemCount = 0; private static int lightbringerButtonAppearInSearchCount = 0; public CallIntentBuilder(@NonNull Uri uri, @NonNull CallSpecificAppData callSpecificAppData) { this.uri = Assert.isNotNull(uri); Assert.isNotNull(callSpecificAppData); Assert.checkArgument( callSpecificAppData.getCallInitiationType() != CallInitiationType.Type.UNKNOWN_INITIATION); CallSpecificAppData.Builder builder = CallSpecificAppData.newBuilder(callSpecificAppData) .setLightbringerButtonAppearInExpandedCallLogItemCount( lightbringerButtonAppearInExpandedCallLogItemCount) .setLightbringerButtonAppearInCollapsedCallLogItemCount( lightbringerButtonAppearInCollapsedCallLogItemCount) .setLightbringerButtonAppearInSearchCount(lightbringerButtonAppearInSearchCount); lightbringerButtonAppearInExpandedCallLogItemCount = 0; lightbringerButtonAppearInCollapsedCallLogItemCount = 0; lightbringerButtonAppearInSearchCount = 0; if (PerformanceReport.isRecording()) { builder .setTimeSinceAppLaunch(PerformanceReport.getTimeSinceAppLaunch()) .setTimeSinceFirstClick(PerformanceReport.getTimeSinceFirstClick()) .addAllUiActionsSinceAppLaunch(PerformanceReport.getActions()) .addAllUiActionTimestampsSinceAppLaunch(PerformanceReport.getActionTimestamps()) .setStartingTabIndex(PerformanceReport.getStartingTabIndex()) .build(); PerformanceReport.stopRecording(); } this.callSpecificAppData = builder.build(); } public CallIntentBuilder(@NonNull Uri uri, CallInitiationType.Type callInitiationType) { this(uri, createCallSpecificAppData(callInitiationType)); } public CallIntentBuilder( @NonNull String number, @NonNull CallSpecificAppData callSpecificAppData) { this(CallUtil.getCallUri(Assert.isNotNull(number)), callSpecificAppData); } public CallIntentBuilder(@NonNull String number, CallInitiationType.Type callInitiationType) { this(CallUtil.getCallUri(Assert.isNotNull(number)), callInitiationType); } public CallIntentBuilder(@NonNull Parcel parcel) { ClassLoader classLoader = CallIntentBuilder.class.getClassLoader(); uri = parcel.readParcelable(classLoader); CallSpecificAppData data; try { data = CallSpecificAppData.parseFrom(parcel.createByteArray()); } catch (InvalidProtocolBufferException e) { data = createCallSpecificAppData(Type.UNKNOWN_INITIATION); } callSpecificAppData = data; phoneAccountHandle = parcel.readParcelable(classLoader); isVideoCall = parcel.readInt() != 0; isDuoCall = parcel.readInt() != 0; callSubject = parcel.readString(); allowAssistedDial = parcel.readInt() != 0; inCallUiIntentExtras.putAll(parcel.readBundle(classLoader)); } public static CallIntentBuilder forVoicemail( @Nullable PhoneAccountHandle phoneAccountHandle, CallInitiationType.Type callInitiationType) { return new CallIntentBuilder( Uri.fromParts(PhoneAccount.SCHEME_VOICEMAIL, "", null), callInitiationType) .setPhoneAccountHandle(phoneAccountHandle); } public void setUri(@NonNull Uri uri) { this.uri = Assert.isNotNull(uri); } public Uri getUri() { return uri; } public CallSpecificAppData getCallSpecificAppData() { return callSpecificAppData; } public CallIntentBuilder setPhoneAccountHandle(@Nullable PhoneAccountHandle accountHandle) { this.phoneAccountHandle = accountHandle; return this; } @Nullable public PhoneAccountHandle getPhoneAccountHandle() { return phoneAccountHandle; } public CallIntentBuilder setIsVideoCall(boolean isVideoCall) { this.isVideoCall = isVideoCall; return this; } public boolean isVideoCall() { return isVideoCall; } public CallIntentBuilder setIsDuoCall(boolean isDuoCall) { this.isDuoCall = isDuoCall; return this; } public boolean isDuoCall() { return isDuoCall; } /** Default false. Should only be set to true if the number has a lookup URI. */ public CallIntentBuilder setAllowAssistedDial(boolean allowAssistedDial) { this.allowAssistedDial = allowAssistedDial; return this; } public boolean isAssistedDialAllowed() { return allowAssistedDial; } public CallIntentBuilder setCallSubject(String callSubject) { this.callSubject = callSubject; return this; } public String getCallSubject() { return callSubject; } /** Additional data the in call UI can read with {@link Details#getIntentExtras()} */ public Bundle getInCallUiIntentExtras() { return inCallUiIntentExtras; } /** * Other extras that should be used with {@link TelecomManager#placeCall(Uri, Bundle)}. This will * override everything set by the CallIntentBuilder */ public Bundle getPlaceCallExtras() { return placeCallExtras; } /** * @deprecated Use {@link com.android.dialer.precall.PreCall#getIntent(android.content.Context, * CallIntentBuilder)} instead. */ @Deprecated public Intent build() { Intent intent = new Intent(Intent.ACTION_CALL, uri); intent.putExtra( TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, isVideoCall ? VideoProfile.STATE_BIDIRECTIONAL : VideoProfile.STATE_AUDIO_ONLY); inCallUiIntentExtras.putLong( Constants.EXTRA_CALL_CREATED_TIME_MILLIS, SystemClock.elapsedRealtime()); CallIntentParser.putCallSpecificAppData(inCallUiIntentExtras, callSpecificAppData); intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, inCallUiIntentExtras); if (phoneAccountHandle != null) { intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); } if (!TextUtils.isEmpty(callSubject)) { intent.putExtra(TelecomManager.EXTRA_CALL_SUBJECT, callSubject); } intent.putExtras(placeCallExtras); return intent; } private static @NonNull CallSpecificAppData createCallSpecificAppData( CallInitiationType.Type callInitiationType) { CallSpecificAppData callSpecificAppData = CallSpecificAppData.newBuilder().setCallInitiationType(callInitiationType).build(); return callSpecificAppData; } public static void increaseLightbringerCallButtonAppearInExpandedCallLogItemCount() { CallIntentBuilder.lightbringerButtonAppearInExpandedCallLogItemCount++; } public static void increaseLightbringerCallButtonAppearInCollapsedCallLogItemCount() { CallIntentBuilder.lightbringerButtonAppearInCollapsedCallLogItemCount++; } public static void increaseLightbringerCallButtonAppearInSearchCount() { CallIntentBuilder.lightbringerButtonAppearInSearchCount++; } @VisibleForTesting public static int getLightbringerButtonAppearInExpandedCallLogItemCount() { return lightbringerButtonAppearInExpandedCallLogItemCount; } @VisibleForTesting public static int getLightbringerButtonAppearInCollapsedCallLogItemCount() { return lightbringerButtonAppearInCollapsedCallLogItemCount; } @VisibleForTesting public static int getLightbringerButtonAppearInSearchCount() { return lightbringerButtonAppearInSearchCount; } @VisibleForTesting(otherwise = VisibleForTesting.NONE) public static void clearLightbringerCounts() { lightbringerButtonAppearInCollapsedCallLogItemCount = 0; lightbringerButtonAppearInExpandedCallLogItemCount = 0; lightbringerButtonAppearInSearchCount = 0; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeParcelable(uri, flags); dest.writeByteArray(callSpecificAppData.toByteArray()); dest.writeParcelable(phoneAccountHandle, flags); dest.writeInt(isVideoCall ? 1 : 0); dest.writeInt(isDuoCall ? 1 : 0); dest.writeString(callSubject); dest.writeInt(allowAssistedDial ? 1 : 0); dest.writeBundle(inCallUiIntentExtras); } public static final Creator CREATOR = new Creator() { @Override public CallIntentBuilder createFromParcel(Parcel source) { return new CallIntentBuilder(source); } @Override public CallIntentBuilder[] newArray(int size) { return new CallIntentBuilder[0]; } }; }