diff options
Diffstat (limited to 'java/com/android/dialer/callintent/CallIntent.java')
-rw-r--r-- | java/com/android/dialer/callintent/CallIntent.java | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/java/com/android/dialer/callintent/CallIntent.java b/java/com/android/dialer/callintent/CallIntent.java new file mode 100644 index 000000000..ba61d5619 --- /dev/null +++ b/java/com/android/dialer/callintent/CallIntent.java @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2018 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.PhoneAccount; +import android.telecom.PhoneAccountHandle; +import android.telecom.TelecomManager; +import android.telecom.VideoProfile; +import android.text.TextUtils; +import com.android.dialer.common.Assert; +import com.android.dialer.performancereport.PerformanceReport; +import com.android.dialer.util.CallUtil; +import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableMap; +import com.google.protobuf.InvalidProtocolBufferException; + +/** Creates an intent to start a new outgoing call. */ +@AutoValue +public abstract class CallIntent implements Parcelable { + private static int lightbringerButtonAppearInExpandedCallLogItemCount = 0; + private static int lightbringerButtonAppearInCollapsedCallLogItemCount = 0; + private static int lightbringerButtonAppearInSearchCount = 0; + + abstract Uri number(); + + abstract CallSpecificAppData callSpecificAppData(); + + @Nullable + abstract PhoneAccountHandle phoneAccountHandle(); + + abstract boolean isVideoCall(); + + @Nullable + abstract String callSubject(); + + abstract boolean allowAssistedDial(); + + abstract ImmutableMap<String, String> stringInCallUiIntentExtras(); + + abstract ImmutableMap<String, Long> longInCallUiIntentExtras(); + + abstract ImmutableMap<String, String> stringPlaceCallExtras(); + + abstract ImmutableMap<String, Long> longPlaceCallExtras(); + + public static Builder builder() { + return new AutoValue_CallIntent.Builder().setIsVideoCall(false).setAllowAssistedDial(false); + } + + public abstract Builder toBuilder(); + + /** Builder class for CallIntent info. */ + @AutoValue.Builder + public abstract static class Builder { + public Builder setTelNumber(String number) { + return setNumber(CallUtil.getCallUri(Assert.isNotNull(number))); + } + + public Builder setVoicemailNumber(@Nullable PhoneAccountHandle phoneAccountHandle) { + return setNumber(Uri.fromParts(PhoneAccount.SCHEME_VOICEMAIL, "", null)) + .setPhoneAccountHandle(phoneAccountHandle); + } + + public abstract Builder setNumber(@NonNull Uri number); + + public Builder setCallInitiationType(CallInitiationType.Type callInitiationType) { + return setCallSpecificAppData( + CallSpecificAppData.newBuilder().setCallInitiationType(callInitiationType).build()); + } + + abstract CallSpecificAppData callSpecificAppData(); + + public abstract Builder setCallSpecificAppData( + @NonNull CallSpecificAppData callSpecificAppData); + + public abstract Builder setPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle); + + public abstract Builder setIsVideoCall(boolean isVideoCall); + + public abstract Builder setCallSubject(String callSubject); + + public abstract Builder setAllowAssistedDial(boolean allowAssistedDial); + + abstract ImmutableMap.Builder<String, String> stringInCallUiIntentExtrasBuilder(); + + abstract ImmutableMap.Builder<String, Long> longInCallUiIntentExtrasBuilder(); + + public Builder addInCallUiIntentExtra(String key, String value) { + stringInCallUiIntentExtrasBuilder().put(key, value); + return this; + } + + public Builder addInCallUiIntentExtra(String key, Long value) { + longInCallUiIntentExtrasBuilder().put(key, value); + return this; + } + + abstract ImmutableMap.Builder<String, String> stringPlaceCallExtrasBuilder(); + + abstract ImmutableMap.Builder<String, Long> longPlaceCallExtrasBuilder(); + + public Builder addPlaceCallExtra(String key, String value) { + stringPlaceCallExtrasBuilder().put(key, value); + return this; + } + + public Builder addPlaceCallExtra(String key, Long value) { + longPlaceCallExtrasBuilder().put(key, value); + return this; + } + + abstract CallIntent autoBuild(); + + public Intent build() { + 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(); + } + + setCallSpecificAppData(builder.build()); + + // Validate CallIntent. + CallIntent callIntent = autoBuild(); + Assert.isNotNull(callIntent.number()); + Assert.isNotNull(callIntent.callSpecificAppData()); + Assert.checkArgument( + callIntent.callSpecificAppData().getCallInitiationType() + != CallInitiationType.Type.UNKNOWN_INITIATION); + + return autoBuild().newIntent(); + } + } + + // Creates the intent which can start a call + private Intent newIntent() { + Intent intent = new Intent(Intent.ACTION_CALL, number()); + + intent.putExtra( + TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, + isVideoCall() ? VideoProfile.STATE_BIDIRECTIONAL : VideoProfile.STATE_AUDIO_ONLY); + + Bundle inCallUiIntentExtras = createInCallUiIntentExtras(); + inCallUiIntentExtras.putLong( + Constants.EXTRA_CALL_CREATED_TIME_MILLIS, SystemClock.elapsedRealtime()); + + 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(createPlaceCallExtras()); + + return intent; + } + + @SuppressWarnings("AndroidApiChecker") // Use of Java 8 APIs. + private Bundle createInCallUiIntentExtras() { + Bundle bundle = new Bundle(); + stringInCallUiIntentExtras().forEach(bundle::putString); + longInCallUiIntentExtras().forEach(bundle::putLong); + CallIntentParser.putCallSpecificAppData(bundle, callSpecificAppData()); + return bundle; + } + + @SuppressWarnings("AndroidApiChecker") // Use of Java 8 APIs. + private Bundle createPlaceCallExtras() { + Bundle bundle = new Bundle(); + stringPlaceCallExtras().forEach(bundle::putString); + longPlaceCallExtras().forEach(bundle::putLong); + CallIntentParser.putCallSpecificAppData(bundle, callSpecificAppData()); + return bundle; + } + + public static void increaseLightbringerCallButtonAppearInExpandedCallLogItemCount() { + CallIntent.lightbringerButtonAppearInExpandedCallLogItemCount++; + } + + public static void increaseLightbringerCallButtonAppearInCollapsedCallLogItemCount() { + CallIntent.lightbringerButtonAppearInCollapsedCallLogItemCount++; + } + + public static void increaseLightbringerCallButtonAppearInSearchCount() { + CallIntent.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; + } + + @SuppressWarnings("AndroidApiChecker") // Use of Java 8 APIs. + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(number(), flags); + dest.writeByteArray(callSpecificAppData().toByteArray()); + dest.writeParcelable(phoneAccountHandle(), flags); + dest.writeInt(isVideoCall() ? 1 : 0); + dest.writeString(callSubject()); + dest.writeInt(allowAssistedDial() ? 1 : 0); + Bundle stringInCallUiIntentExtrasBundle = new Bundle(); + stringInCallUiIntentExtras().forEach(stringInCallUiIntentExtrasBundle::putString); + dest.writeBundle(stringInCallUiIntentExtrasBundle); + Bundle longInCallUiIntentExtrasBundle = new Bundle(); + longInCallUiIntentExtras().forEach(longInCallUiIntentExtrasBundle::putLong); + dest.writeBundle(longInCallUiIntentExtrasBundle); + } + + // @TODO(justinmcclain): Investigate deleting the parcelable logic and instead switching + // to using an internal proto for serialization. + public static final Creator<CallIntent> CREATOR = + new Creator<CallIntent>() { + @Override + public CallIntent createFromParcel(Parcel source) { + CallIntent.Builder callIntentBuilder = builder(); + ClassLoader classLoader = CallIntent.class.getClassLoader(); + callIntentBuilder.setNumber(source.readParcelable(classLoader)); + CallSpecificAppData data; + try { + data = CallSpecificAppData.parseFrom(source.createByteArray()); + } catch (InvalidProtocolBufferException e) { + data = CallSpecificAppData.getDefaultInstance(); + } + callIntentBuilder + .setCallSpecificAppData(data) + .setPhoneAccountHandle(source.readParcelable(classLoader)) + .setIsVideoCall(source.readInt() != 0) + .setCallSubject(source.readString()) + .setAllowAssistedDial(source.readInt() != 0); + Bundle stringInCallUiIntentExtrasBundle = source.readBundle(classLoader); + for (String key : stringInCallUiIntentExtrasBundle.keySet()) { + callIntentBuilder.addInCallUiIntentExtra( + key, stringInCallUiIntentExtrasBundle.getString(key)); + } + Bundle longInCallUiIntentExtrasBundle = source.readBundle(classLoader); + for (String key : longInCallUiIntentExtrasBundle.keySet()) { + callIntentBuilder.addInCallUiIntentExtra( + key, longInCallUiIntentExtrasBundle.getLong(key)); + } + return callIntentBuilder.autoBuild(); + } + + @Override + public CallIntent[] newArray(int size) { + return new CallIntent[0]; + } + }; +} |