Make CallIntentBuilder parcelable

Multi-SIM and several other new features requires additional user input (ie. select the phone account to call with) or processing (ie. rewrite phone number for assisted dialing) before the call is actually made. The plan is to use a chain of pre-call actions to complete the dialing infomation,with the CallIntentBuilder holding the intermediate steps. For example, a pre-call action can examine the CallIntentBuilder and figure that the PhoneAccountHandle cannot be inferred, and show a dialog for the user the select it. Only after pre-call actions are completed, the intent is built and sent to telecom.

Since pre-call actions involves dialogs and the process can be interrupted, the CallIntentBuilder must be persistable so the state can be restored. This CL made it parcelable so it can be stored with onSaveInstanceState().

The AssistedDialingMediator in CallIntentBuilder is temporarily removed as it would be called using a pre-call action in a future CL.

Bug: 64216442
Test: CallIntentBuilderTest
PiperOrigin-RevId: 174902775
Change-Id: Icf2f8fae620868d1a2f5acf0d08ae0a6bec4fb76
diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java
index 12c191e..089ffd3 100644
--- a/java/com/android/dialer/app/DialtactsActivity.java
+++ b/java/com/android/dialer/app/DialtactsActivity.java
@@ -44,7 +44,6 @@
 import android.support.v4.view.ViewPager;
 import android.support.v7.app.ActionBar;
 import android.telecom.PhoneAccount;
-import android.telephony.TelephonyManager;
 import android.text.Editable;
 import android.text.TextUtils;
 import android.text.TextWatcher;
@@ -90,7 +89,6 @@
 import com.android.dialer.app.settings.DialerSettingsActivity;
 import com.android.dialer.app.widget.ActionBarController;
 import com.android.dialer.app.widget.SearchEditTextLayout;
-import com.android.dialer.assisteddialing.ConcreteCreator;
 import com.android.dialer.callcomposer.CallComposerActivity;
 import com.android.dialer.calldetails.CallDetailsActivity;
 import com.android.dialer.callintent.CallInitiationType;
@@ -1521,11 +1519,7 @@
     Intent intent =
         new CallIntentBuilder(phoneNumber, callSpecificAppData)
             .setIsVideoCall(isVideoCall)
-            .setAllowAssistedDial(
-                callSpecificAppData.getAllowAssistedDialing(),
-                ConcreteCreator.createNewAssistedDialingMediator(
-                    getApplication().getSystemService(TelephonyManager.class),
-                    getApplicationContext()))
+            .setAllowAssistedDial(callSpecificAppData.getAllowAssistedDialing())
             .build();
 
     DialerUtils.startActivityWithErrorToast(this, intent);
diff --git a/java/com/android/dialer/app/calllog/IntentProvider.java b/java/com/android/dialer/app/calllog/IntentProvider.java
index 36e62c3..5180651 100644
--- a/java/com/android/dialer/app/calllog/IntentProvider.java
+++ b/java/com/android/dialer/app/calllog/IntentProvider.java
@@ -26,7 +26,6 @@
 import android.telephony.TelephonyManager;
 import com.android.contacts.common.model.Contact;
 import com.android.contacts.common.model.ContactLoader;
-import com.android.dialer.assisteddialing.ConcreteCreator;
 import com.android.dialer.calldetails.CallDetailsActivity;
 import com.android.dialer.calldetails.CallDetailsEntries;
 import com.android.dialer.callintent.CallInitiationType;
@@ -67,8 +66,7 @@
       @Override
       public Intent getIntent(Context context) {
         return new CallIntentBuilder(number, CallInitiationType.Type.CALL_LOG)
-            .setAllowAssistedDial(
-                true, ConcreteCreator.createNewAssistedDialingMediator(telephonyManager, context))
+            .setAllowAssistedDial(true)
             .build();
       }
     };
diff --git a/java/com/android/dialer/calldetails/CallDetailsActivity.java b/java/com/android/dialer/calldetails/CallDetailsActivity.java
index 3a3c911..6ba31e6 100644
--- a/java/com/android/dialer/calldetails/CallDetailsActivity.java
+++ b/java/com/android/dialer/calldetails/CallDetailsActivity.java
@@ -30,10 +30,8 @@
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.Toolbar;
 import android.support.v7.widget.Toolbar.OnMenuItemClickListener;
-import android.telephony.TelephonyManager;
 import android.view.MenuItem;
 import android.widget.Toast;
-import com.android.dialer.assisteddialing.ConcreteCreator;
 import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry;
 import com.android.dialer.callintent.CallInitiationType;
 import com.android.dialer.callintent.CallIntentBuilder;
@@ -243,10 +241,7 @@
     CallIntentBuilder callIntentBuilder =
         new CallIntentBuilder(phoneNumber + postDialDigits, CallInitiationType.Type.CALL_DETAILS);
     if (canSupportedAssistedDialing) {
-      callIntentBuilder.setAllowAssistedDial(
-          true,
-          ConcreteCreator.createNewAssistedDialingMediator(
-              getSystemService(TelephonyManager.class), this));
+      callIntentBuilder.setAllowAssistedDial(true);
     }
 
     DialerUtils.startActivityWithErrorToast(this, callIntentBuilder.build());
diff --git a/java/com/android/dialer/callintent/CallIntentBuilder.java b/java/com/android/dialer/callintent/CallIntentBuilder.java
index 25a5803..aabeabd 100644
--- a/java/com/android/dialer/callintent/CallIntentBuilder.java
+++ b/java/com/android/dialer/callintent/CallIntentBuilder.java
@@ -16,11 +16,11 @@
 
 package com.android.dialer.callintent;
 
-import android.annotation.TargetApi;
 import android.content.Intent;
 import android.net.Uri;
-import android.os.Build;
 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;
@@ -30,23 +30,22 @@
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.text.TextUtils;
-import com.android.dialer.assisteddialing.AssistedDialingMediator;
-import com.android.dialer.assisteddialing.TransformationInfo;
+import com.android.dialer.callintent.CallInitiationType.Type;
 import com.android.dialer.common.Assert;
-import com.android.dialer.compat.telephony.TelephonyManagerCompat;
 import com.android.dialer.performancereport.PerformanceReport;
 import com.android.dialer.util.CallUtil;
-import java.util.Optional;
+import com.google.protobuf.InvalidProtocolBufferException;
 
 /** Creates an intent to start a new outgoing call. */
-public class CallIntentBuilder {
-  private final Uri uri;
+public class CallIntentBuilder implements Parcelable {
+  private Uri uri;
   private final CallSpecificAppData callSpecificAppData;
   @Nullable private PhoneAccountHandle phoneAccountHandle;
   private boolean isVideoCall;
   private String callSubject;
   private boolean allowAssistedDial;
-  private AssistedDialingMediator assistedDialingMediator;
+
+  private final Bundle outgoingCallExtras = new Bundle();
 
   private static int lightbringerButtonAppearInExpandedCallLogItemCount = 0;
   private static int lightbringerButtonAppearInCollapsedCallLogItemCount = 0;
@@ -96,6 +95,23 @@
     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;
+    callSubject = parcel.readString();
+    allowAssistedDial = parcel.readInt() != 0;
+    outgoingCallExtras.putAll(parcel.readBundle(classLoader));
+  }
+
   public static CallIntentBuilder forVoicemail(
       @Nullable PhoneAccountHandle phoneAccountHandle, CallInitiationType.Type callInitiationType) {
     return new CallIntentBuilder(
@@ -103,6 +119,14 @@
         .setPhoneAccountHandle(phoneAccountHandle);
   }
 
+  public void setUri(@NonNull Uri uri) {
+    this.uri = Assert.isNotNull(uri);
+  }
+
+  public Uri getUri() {
+    return uri;
+  }
+
   public CallSpecificAppData getCallSpecificAppData() {
     return callSpecificAppData;
   }
@@ -112,40 +136,54 @@
     return this;
   }
 
+  @Nullable
+  public PhoneAccountHandle getPhoneAccountHandle() {
+    return phoneAccountHandle;
+  }
+
   public CallIntentBuilder setIsVideoCall(boolean isVideoCall) {
     this.isVideoCall = isVideoCall;
     return this;
   }
 
-  public CallIntentBuilder setAllowAssistedDial(
-      boolean allowAssistedDial, @NonNull AssistedDialingMediator assistedDialingMediator) {
-    this.assistedDialingMediator = Assert.isNotNull(assistedDialingMediator);
+  public boolean isVideoCall() {
+    return isVideoCall;
+  }
+
+  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;
+  }
+
+  public Bundle getOutgoingCallExtras() {
+    return outgoingCallExtras;
+  }
+
   public Intent build() {
     Intent intent = new Intent(Intent.ACTION_CALL, uri);
-    Bundle extras = new Bundle();
 
-    if (allowAssistedDial
-        && this.assistedDialingMediator != null
-        && this.assistedDialingMediator.isPlatformEligible()) {
-      intent = buildAssistedDialingParameters(intent, extras);
-    }
     intent.putExtra(
         TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
         isVideoCall ? VideoProfile.STATE_BIDIRECTIONAL : VideoProfile.STATE_AUDIO_ONLY);
 
-    extras.putLong(Constants.EXTRA_CALL_CREATED_TIME_MILLIS, SystemClock.elapsedRealtime());
-    CallIntentParser.putCallSpecificAppData(extras, callSpecificAppData);
+    outgoingCallExtras.putLong(
+        Constants.EXTRA_CALL_CREATED_TIME_MILLIS, SystemClock.elapsedRealtime());
+    CallIntentParser.putCallSpecificAppData(outgoingCallExtras, callSpecificAppData);
 
-    intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
+    intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, outgoingCallExtras);
 
     if (phoneAccountHandle != null) {
       intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
@@ -158,26 +196,6 @@
     return intent;
   }
 
-  @SuppressWarnings("AndroidApiChecker") // Use of optional
-  @TargetApi(Build.VERSION_CODES.N)
-  private Intent buildAssistedDialingParameters(Intent intent, Bundle extras) {
-    extras.putBoolean(TelephonyManagerCompat.ALLOW_ASSISTED_DIAL, true);
-    String phoneNumber =
-        uri.getScheme().equals(PhoneAccount.SCHEME_TEL) ? uri.getSchemeSpecificPart() : "";
-    Optional<TransformationInfo> transformedNumber =
-        assistedDialingMediator.attemptAssistedDial(phoneNumber);
-    if (transformedNumber.isPresent()) {
-      Bundle assistedDialingExtras = transformedNumber.get().toBundle();
-      extras.putBoolean(TelephonyManagerCompat.IS_ASSISTED_DIALED, true);
-      extras.putBundle(TelephonyManagerCompat.ASSISTED_DIALING_EXTRAS, assistedDialingExtras);
-      intent =
-          new Intent(
-              Intent.ACTION_CALL,
-              CallUtil.getCallUri(Assert.isNotNull(transformedNumber.get().transformedNumber())));
-    }
-    return intent;
-  }
-
   private static @NonNull CallSpecificAppData createCallSpecificAppData(
       CallInitiationType.Type callInitiationType) {
     CallSpecificAppData callSpecificAppData =
@@ -218,4 +236,33 @@
     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.writeString(callSubject);
+    dest.writeInt(allowAssistedDial ? 1 : 0);
+    dest.writeBundle(outgoingCallExtras);
+  }
+
+  public static final Creator<CallIntentBuilder> CREATOR =
+      new Creator<CallIntentBuilder>() {
+        @Override
+        public CallIntentBuilder createFromParcel(Parcel source) {
+          return new CallIntentBuilder(source);
+        }
+
+        @Override
+        public CallIntentBuilder[] newArray(int size) {
+          return new CallIntentBuilder[0];
+        }
+      };
 }
diff --git a/java/com/android/dialer/interactions/PhoneNumberInteraction.java b/java/com/android/dialer/interactions/PhoneNumberInteraction.java
index ac744cc..255f6c3 100644
--- a/java/com/android/dialer/interactions/PhoneNumberInteraction.java
+++ b/java/com/android/dialer/interactions/PhoneNumberInteraction.java
@@ -41,7 +41,6 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.VisibleForTesting;
 import android.support.v4.app.ActivityCompat;
-import android.telephony.TelephonyManager;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -53,7 +52,6 @@
 import com.android.contacts.common.Collapser.Collapsible;
 import com.android.contacts.common.MoreContactUtils;
 import com.android.contacts.common.util.ContactDisplayUtils;
-import com.android.dialer.assisteddialing.ConcreteCreator;
 import com.android.dialer.callintent.CallInitiationType;
 import com.android.dialer.callintent.CallIntentBuilder;
 import com.android.dialer.callintent.CallIntentParser;
@@ -187,10 +185,7 @@
         intent =
             new CallIntentBuilder(phoneNumber, callSpecificAppData)
                 .setIsVideoCall(isVideoCall)
-                .setAllowAssistedDial(
-                    callSpecificAppData.getAllowAssistedDialing(),
-                    ConcreteCreator.createNewAssistedDialingMediator(
-                        context.getSystemService(TelephonyManager.class), context))
+                .setAllowAssistedDial(callSpecificAppData.getAllowAssistedDialing())
                 .build();
         break;
     }
diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
index cd42a74..c0a6700 100644
--- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
+++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
@@ -32,7 +32,6 @@
 import android.support.v13.app.FragmentCompat;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
-import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -44,7 +43,6 @@
 import android.widget.FrameLayout.LayoutParams;
 import com.android.contacts.common.extensions.PhoneDirectoryExtenderAccessor;
 import com.android.dialer.animation.AnimUtils;
-import com.android.dialer.assisteddialing.ConcreteCreator;
 import com.android.dialer.callcomposer.CallComposerActivity;
 import com.android.dialer.callintent.CallInitiationType;
 import com.android.dialer.callintent.CallIntentBuilder;
@@ -488,11 +486,7 @@
     Intent intent =
         new CallIntentBuilder(phoneNumber, callSpecificAppData)
             .setIsVideoCall(isVideoCall)
-            .setAllowAssistedDial(
-                allowAssistedDial,
-                ConcreteCreator.createNewAssistedDialingMediator(
-                    getContext().getSystemService(TelephonyManager.class),
-                    getContext().getApplicationContext()))
+            .setAllowAssistedDial(allowAssistedDial)
             .build();
     DialerUtils.startActivityWithErrorToast(getActivity(), intent);
     FragmentUtils.getParentUnsafe(this, SearchFragmentListener.class).onCallPlaced();