Add assisted dialing to outbound calls that qualify.

* Add missing assisted dialing to calls from contacts in the call log.
* Add missing assisted dialing to calls from dialpad and normal search.

Bug: 63995025,63995261
Test: unit test
PiperOrigin-RevId: 171593967
Change-Id: I4e63ef1dcd7ee1b2b5cbb8ecb4d8da744d90bd66
diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java
index 04f1431..5f3620b 100644
--- a/java/com/android/dialer/app/DialtactsActivity.java
+++ b/java/com/android/dialer/app/DialtactsActivity.java
@@ -43,7 +43,7 @@
 import android.support.v4.view.ViewPager;
 import android.support.v7.app.ActionBar;
 import android.telecom.PhoneAccount;
-import android.telecom.TelecomManager;
+import android.telephony.TelephonyManager;
 import android.text.Editable;
 import android.text.TextUtils;
 import android.text.TextWatcher;
@@ -90,6 +90,7 @@
 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;
@@ -97,7 +98,6 @@
 import com.android.dialer.callintent.CallSpecificAppData;
 import com.android.dialer.common.Assert;
 import com.android.dialer.common.LogUtil;
-import com.android.dialer.compat.telephony.TelephonyManagerCompat;
 import com.android.dialer.configprovider.ConfigProviderBindings;
 import com.android.dialer.constants.ActivityRequestCodes;
 import com.android.dialer.contactsfragment.ContactsFragment;
@@ -1488,13 +1488,14 @@
     }
 
     Intent intent =
-        new CallIntentBuilder(phoneNumber, callSpecificAppData).setIsVideoCall(isVideoCall).build();
-
-    if (callSpecificAppData.getAllowAssistedDialing()) {
-      Bundle extras = new Bundle();
-      extras.putBoolean(TelephonyManagerCompat.ALLOW_ASSISTED_DIAL, true);
-      intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
-    }
+        new CallIntentBuilder(phoneNumber, callSpecificAppData)
+            .setIsVideoCall(isVideoCall)
+            .setAllowAssistedDial(
+                callSpecificAppData.getAllowAssistedDialing(),
+                ConcreteCreator.createNewAssistedDialingMediator(
+                    getApplication().getSystemService(TelephonyManager.class),
+                    getApplicationContext()))
+            .build();
 
     DialerUtils.startActivityWithErrorToast(this, intent);
     mClearSearchOnPause = true;
diff --git a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
index 60acb55..f0eee11 100644
--- a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
+++ b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
@@ -23,7 +23,6 @@
 import android.content.res.Resources;
 import android.net.Uri;
 import android.os.AsyncTask;
-import android.os.Bundle;
 import android.provider.CallLog;
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -38,6 +37,7 @@
 import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
 import android.text.BidiFormatter;
 import android.text.TextDirectionHeuristics;
 import android.text.TextUtils;
@@ -69,7 +69,6 @@
 import com.android.dialer.common.Assert;
 import com.android.dialer.common.LogUtil;
 import com.android.dialer.compat.CompatUtils;
-import com.android.dialer.compat.telephony.TelephonyManagerCompat;
 import com.android.dialer.configprovider.ConfigProviderBindings;
 import com.android.dialer.constants.ActivityRequestCodes;
 import com.android.dialer.contactphoto.ContactPhotoManager;
@@ -532,8 +531,16 @@
           // Call to generic voicemail number, in case there are multiple accounts.
           primaryActionButtonView.setTag(IntentProvider.getReturnVoicemailCallIntentProvider());
         } else {
-          primaryActionButtonView.setTag(
-              IntentProvider.getReturnCallIntentProvider(number + postDialDigits));
+          if (this.info != null && this.info.lookupKey != null) {
+            primaryActionButtonView.setTag(
+                IntentProvider.getAssistedDialIntentProvider(
+                    number + postDialDigits,
+                    mContext,
+                    mContext.getSystemService(TelephonyManager.class)));
+          } else {
+            primaryActionButtonView.setTag(
+                IntentProvider.getReturnCallIntentProvider(number + postDialDigits));
+          }
         }
 
         primaryActionButtonView.setContentDescription(
@@ -592,8 +599,14 @@
         ((TextView) callButtonView.findViewById(R.id.call_type_or_location_text));
 
     if (canPlaceCallToNumber) {
-      callButtonView.setTag(IntentProvider.getReturnCallIntentProvider(number));
-      callTypeOrLocationView.setVisibility(View.GONE);
+      if (this.info != null && this.info.lookupKey != null) {
+        callButtonView.setTag(
+            IntentProvider.getAssistedDialIntentProvider(
+                number, mContext, mContext.getSystemService(TelephonyManager.class)));
+      } else {
+        callButtonView.setTag(IntentProvider.getReturnCallIntentProvider(number));
+        callTypeOrLocationView.setVisibility(View.GONE);
+      }
     }
 
     if (!TextUtils.isEmpty(voicemailUri) && canPlaceCallToNumber) {
@@ -911,15 +924,6 @@
         return;
       }
 
-      if (info != null && info.lookupKey != null) {
-        Bundle extras = new Bundle();
-        if (intent.hasExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS)) {
-          extras = intent.getParcelableExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS);
-        }
-        extras.putBoolean(TelephonyManagerCompat.ALLOW_ASSISTED_DIAL, true);
-        intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
-      }
-
       // We check to see if we are starting a Lightbringer intent. The reason is Lightbringer
       // intents need to be started using startActivityForResult instead of the usual startActivity
       String packageName = intent.getPackage();
diff --git a/java/com/android/dialer/app/calllog/IntentProvider.java b/java/com/android/dialer/app/calllog/IntentProvider.java
index 55fdbba..52a7b0f 100644
--- a/java/com/android/dialer/app/calllog/IntentProvider.java
+++ b/java/com/android/dialer/app/calllog/IntentProvider.java
@@ -22,8 +22,10 @@
 import android.net.Uri;
 import android.provider.ContactsContract;
 import android.telecom.PhoneAccountHandle;
+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;
@@ -59,6 +61,19 @@
     };
   }
 
+  public static IntentProvider getAssistedDialIntentProvider(
+      final String number, final Context context, final TelephonyManager telephonyManager) {
+    return new IntentProvider() {
+      @Override
+      public Intent getIntent(Context context) {
+        return new CallIntentBuilder(number, CallInitiationType.Type.CALL_LOG)
+            .setAllowAssistedDial(
+                true, ConcreteCreator.createNewAssistedDialingMediator(telephonyManager, context))
+            .build();
+      }
+    };
+  }
+
   public static IntentProvider getReturnVideoCallIntentProvider(final String number) {
     return getReturnVideoCallIntentProvider(number, null);
   }
diff --git a/java/com/android/dialer/assisteddialing/AssistedDialingMediator.java b/java/com/android/dialer/assisteddialing/AssistedDialingMediator.java
index 3d02729..4dc87a7 100644
--- a/java/com/android/dialer/assisteddialing/AssistedDialingMediator.java
+++ b/java/com/android/dialer/assisteddialing/AssistedDialingMediator.java
@@ -19,63 +19,12 @@
 import android.annotation.TargetApi;
 import android.os.Build.VERSION_CODES;
 import android.support.annotation.NonNull;
-import com.android.dialer.common.LogUtil;
 import java.util.Optional;
 
-/**
- * The Mediator for Assisted Dialing.
- *
- * <p>This class is responsible for mediating location discovery of the user, determining if the
- * call is eligible for assisted dialing, and performing the transformation of numbers eligible for
- * assisted dialing.
- */
-public final class AssistedDialingMediator {
+/** The core interface for the AssistedDialingMediator. */
+public interface AssistedDialingMediator {
 
-  private final LocationDetector locationDetector;
-  private final NumberTransformer numberTransformer;
-
-  protected AssistedDialingMediator(
-      @NonNull LocationDetector locationDetector, @NonNull NumberTransformer numberTransformer) {
-    if (locationDetector == null) {
-      throw new NullPointerException("locationDetector was null");
-    }
-
-    if (numberTransformer == null) {
-      throw new NullPointerException("numberTransformer was null");
-    }
-    this.locationDetector = locationDetector;
-    this.numberTransformer = numberTransformer;
-  }
-
-  /**
-   * Returns a boolean for callers to quickly determine whether or not the AssistedDialingMediator
-   * thinks an attempt at assisted dialing is likely to succeed.
-   */
-  public boolean conditionsEligibleForAssistedDialing(
-      @NonNull String numberToCheck,
-      @NonNull String userHomeCountryCode,
-      @NonNull String userRoamingCountryCode) {
-    return numberTransformer.canDoAssistedDialingTransformation(
-        numberToCheck, userHomeCountryCode, userRoamingCountryCode);
-  }
-
-  /**
-   * Returns an Optional of type String containing the transformed number that was provided. The
-   * transformed number should be capable of dialing out of the User's current country and
-   * successfully connecting with a contact in the User's home country.
-   */
   @SuppressWarnings("AndroidApiChecker") // Use of optional
   @TargetApi(VERSION_CODES.N)
-  public Optional<TransformationInfo> attemptAssistedDial(@NonNull String numberToTransform) {
-    Optional<String> userHomeCountryCode = locationDetector.getUpperCaseUserHomeCountry();
-    Optional<String> userRoamingCountryCode = locationDetector.getUpperCaseUserRoamingCountry();
-
-    if (!userHomeCountryCode.isPresent() || !userRoamingCountryCode.isPresent()) {
-      LogUtil.i("AssistedDialingMediator.attemptAssistedDial", "Unable to determine country codes");
-      return Optional.empty();
-    }
-
-    return numberTransformer.doAssistedDialingTransformation(
-        numberToTransform, userHomeCountryCode.get(), userRoamingCountryCode.get());
-  }
+  public Optional<TransformationInfo> attemptAssistedDial(@NonNull String numberToTransform);
 }
diff --git a/java/com/android/dialer/assisteddialing/AssistedDialingMediatorImpl.java b/java/com/android/dialer/assisteddialing/AssistedDialingMediatorImpl.java
new file mode 100644
index 0000000..1692614
--- /dev/null
+++ b/java/com/android/dialer/assisteddialing/AssistedDialingMediatorImpl.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 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.assisteddialing;
+
+import android.annotation.TargetApi;
+import android.os.Build.VERSION_CODES;
+import android.support.annotation.NonNull;
+import com.android.dialer.common.LogUtil;
+import java.util.Optional;
+
+/**
+ * The Mediator for Assisted Dialing.
+ *
+ * <p>This class is responsible for mediating location discovery of the user, determining if the
+ * call is eligible for assisted dialing, and performing the transformation of numbers eligible for
+ * assisted dialing.
+ */
+final class AssistedDialingMediatorImpl implements AssistedDialingMediator {
+
+  private final LocationDetector locationDetector;
+  private final NumberTransformer numberTransformer;
+
+  AssistedDialingMediatorImpl(
+      @NonNull LocationDetector locationDetector, @NonNull NumberTransformer numberTransformer) {
+    if (locationDetector == null) {
+      throw new NullPointerException("locationDetector was null");
+    }
+
+    if (numberTransformer == null) {
+      throw new NullPointerException("numberTransformer was null");
+    }
+    this.locationDetector = locationDetector;
+    this.numberTransformer = numberTransformer;
+  }
+
+  /**
+   * Returns an Optional of type String containing the transformed number that was provided. The
+   * transformed number should be capable of dialing out of the User's current country and
+   * successfully connecting with a contact in the User's home country.
+   */
+  @SuppressWarnings("AndroidApiChecker") // Use of optional
+  @TargetApi(VERSION_CODES.N)
+  @Override
+  public Optional<TransformationInfo> attemptAssistedDial(@NonNull String numberToTransform) {
+    Optional<String> userHomeCountryCode = locationDetector.getUpperCaseUserHomeCountry();
+    Optional<String> userRoamingCountryCode = locationDetector.getUpperCaseUserRoamingCountry();
+
+    if (!userHomeCountryCode.isPresent() || !userRoamingCountryCode.isPresent()) {
+      LogUtil.i("AssistedDialingMediator.attemptAssistedDial", "Unable to determine country codes");
+      return Optional.empty();
+    }
+
+    return numberTransformer.doAssistedDialingTransformation(
+        numberToTransform, userHomeCountryCode.get(), userRoamingCountryCode.get());
+  }
+}
diff --git a/java/com/android/dialer/assisteddialing/AssistedDialingMediatorStub.java b/java/com/android/dialer/assisteddialing/AssistedDialingMediatorStub.java
new file mode 100644
index 0000000..c7a8212
--- /dev/null
+++ b/java/com/android/dialer/assisteddialing/AssistedDialingMediatorStub.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 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.assisteddialing;
+
+import android.annotation.TargetApi;
+import android.os.Build.VERSION_CODES;
+import android.support.annotation.NonNull;
+import java.util.Optional;
+
+/** A stub assisted dialing implementation. */
+public final class AssistedDialingMediatorStub implements AssistedDialingMediator {
+
+  /** Always returns an empty Optional. */
+  @Override
+  @SuppressWarnings("AndroidApiChecker") // Use of optional
+  @TargetApi(VERSION_CODES.N)
+  public Optional<TransformationInfo> attemptAssistedDial(@NonNull String numberToTransform) {
+    return Optional.empty();
+  }
+}
diff --git a/java/com/android/dialer/assisteddialing/ConcreteCreator.java b/java/com/android/dialer/assisteddialing/ConcreteCreator.java
index f51216a..49d3b1f 100644
--- a/java/com/android/dialer/assisteddialing/ConcreteCreator.java
+++ b/java/com/android/dialer/assisteddialing/ConcreteCreator.java
@@ -18,10 +18,12 @@
 
 import android.annotation.TargetApi;
 import android.content.Context;
+import android.os.Build;
 import android.os.Build.VERSION_CODES;
 import android.support.annotation.NonNull;
 import android.telephony.TelephonyManager;
 import com.android.dialer.common.LogUtil;
+import com.android.dialer.configprovider.ConfigProviderBindings;
 
 /**
  * A Creator for AssistedDialingMediators.
@@ -32,6 +34,11 @@
 @TargetApi(VERSION_CODES.N)
 public final class ConcreteCreator {
 
+  // Floor set at N due to use of Optional.
+  protected static final int BUILD_CODE_FLOOR = Build.VERSION_CODES.N;
+  // Ceiling set at O because this feature will ship as part of the framework in P.
+  protected static final int BUILD_CODE_CEILING = Build.VERSION_CODES.O;
+
   /**
    * Creates a new AssistedDialingMediator
    *
@@ -42,6 +49,7 @@
    */
   public static AssistedDialingMediator createNewAssistedDialingMediator(
       @NonNull TelephonyManager telephonyManager, @NonNull Context context) {
+
     if (telephonyManager == null) {
       LogUtil.i(
           "ConcreteCreator.createNewAssistedDialingMediator", "provided TelephonyManager was null");
@@ -51,8 +59,14 @@
       LogUtil.i("ConcreteCreator.createNewAssistedDialingMediator", "provided context was null");
       throw new NullPointerException("Provided context was null");
     }
+
+    if ((Build.VERSION.SDK_INT < BUILD_CODE_FLOOR || Build.VERSION.SDK_INT > BUILD_CODE_CEILING)
+        || !ConfigProviderBindings.get(context).getBoolean("assisted_dialing_enabled", false)) {
+      return new AssistedDialingMediatorStub();
+    }
+
     Constraints constraints = new Constraints(context);
-    return new AssistedDialingMediator(
+    return new AssistedDialingMediatorImpl(
         new LocationDetector(telephonyManager), new NumberTransformer(constraints));
   }
 }
diff --git a/java/com/android/dialer/assisteddialing/Constraints.java b/java/com/android/dialer/assisteddialing/Constraints.java
index 6bcab99..023be1c 100644
--- a/java/com/android/dialer/assisteddialing/Constraints.java
+++ b/java/com/android/dialer/assisteddialing/Constraints.java
@@ -62,7 +62,7 @@
         "GB" /* United Kingdom */,
         "JP" /* Japan */,
         "MX" /* Mexico */,
-        "US" /* United States*/,
+        "US" /* United States */,
       };
 
   private final Set<String> supportedCountryCodes =
@@ -115,7 +115,8 @@
         && isUserRoaming(userHomeCountryCode, userRoamingCountryCode)
         && isNotInternationalNumber(parsedPhoneNumber)
         && isNotEmergencyNumber(numberToCheck, context)
-        && isValidNumber(parsedPhoneNumber);
+        && isValidNumber(parsedPhoneNumber)
+        && doesNotHaveExtension(parsedPhoneNumber);
   }
 
   /** Returns a boolean indicating the value equivalence of the provided country codes. */
@@ -165,10 +166,7 @@
     }
   }
 
-  /**
-   * Returns a boolean indicating if the provided number and home country code are already
-   * internationally formatted.
-   */
+  /** Returns a boolean indicating if the provided number is already internationally formatted. */
   private boolean isNotInternationalNumber(@NonNull Optional<PhoneNumber> parsedPhoneNumber) {
 
     if (parsedPhoneNumber.get().hasCountryCode()
@@ -181,6 +179,22 @@
     return true;
   }
 
+  /**
+   * Returns a boolean indicating if the provided number has an extension.
+   *
+   * <p>Extensions are currently stripped when formatting a number for mobile dialing, so we don't
+   * want to purposefully truncate a number.
+   */
+  private boolean doesNotHaveExtension(@NonNull Optional<PhoneNumber> parsedPhoneNumber) {
+
+    if (parsedPhoneNumber.get().hasExtension()
+        && !TextUtils.isEmpty(parsedPhoneNumber.get().getExtension())) {
+      LogUtil.i("Constraints.doesNotHaveExtension", "phone number has an extension");
+      return false;
+    }
+    return true;
+  }
+
   /** Returns a boolean indicating if the provided number is considered to be a valid number. */
   private boolean isValidNumber(@NonNull Optional<PhoneNumber> parsedPhoneNumber) {
     boolean result = PhoneNumberUtil.getInstance().isValidNumber(parsedPhoneNumber.get());
diff --git a/java/com/android/dialer/assisteddialing/TransformationInfo.java b/java/com/android/dialer/assisteddialing/TransformationInfo.java
index 7149d71..03e565c 100644
--- a/java/com/android/dialer/assisteddialing/TransformationInfo.java
+++ b/java/com/android/dialer/assisteddialing/TransformationInfo.java
@@ -43,15 +43,15 @@
   private static final String TRANSFORMED_NUMBER_COUNTRY_CALLING_CODE_KEY =
       "TRANSFORMED_NUMBER_COUNTRY_CALLING_CODE";
 
-  abstract String originalNumber();
+  public abstract String originalNumber();
 
-  abstract String transformedNumber();
+  public abstract String transformedNumber();
 
-  abstract String userHomeCountryCode();
+  public abstract String userHomeCountryCode();
 
-  abstract String userRoamingCountryCode();
+  public abstract String userRoamingCountryCode();
 
-  abstract int transformedNumberCountryCallingCode();
+  public abstract int transformedNumberCountryCallingCode();
 
   public static Builder builder() {
     return new AutoValue_TransformationInfo.Builder();
diff --git a/java/com/android/dialer/callintent/CallIntentBuilder.java b/java/com/android/dialer/callintent/CallIntentBuilder.java
index b5b680e..dc239dc 100644
--- a/java/com/android/dialer/callintent/CallIntentBuilder.java
+++ b/java/com/android/dialer/callintent/CallIntentBuilder.java
@@ -16,21 +16,27 @@
 
 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.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.assisteddialing.AssistedDialingMediator;
+import com.android.dialer.assisteddialing.TransformationInfo;
 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;
 
 /** Creates an intent to start a new outgoing call. */
 public class CallIntentBuilder {
@@ -40,6 +46,7 @@
   private boolean isVideoCall;
   private String callSubject;
   private boolean allowAssistedDial;
+  private AssistedDialingMediator assistedDialingMediator;
 
   private static int lightbringerButtonAppearInExpandedCallLogItemCount = 0;
   private static int lightbringerButtonAppearInCollapsedCallLogItemCount = 0;
@@ -103,7 +110,9 @@
     return this;
   }
 
-  public CallIntentBuilder setAllowAssistedDial(boolean allowAssistedDial) {
+  public CallIntentBuilder setAllowAssistedDial(
+      boolean allowAssistedDial, @NonNull AssistedDialingMediator assistedDialingMediator) {
+    this.assistedDialingMediator = Assert.isNotNull(assistedDialingMediator);
     this.allowAssistedDial = allowAssistedDial;
     return this;
   }
@@ -115,18 +124,18 @@
 
   public Intent build() {
     Intent intent = new Intent(Intent.ACTION_CALL, uri);
+    Bundle extras = new Bundle();
+
+    if (allowAssistedDial && this.assistedDialingMediator != null) {
+      intent = buildAssistedDialingParameters(intent, extras);
+    }
     intent.putExtra(
         TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
         isVideoCall ? VideoProfile.STATE_BIDIRECTIONAL : VideoProfile.STATE_AUDIO_ONLY);
 
-    Bundle extras = new Bundle();
     extras.putLong(Constants.EXTRA_CALL_CREATED_TIME_MILLIS, SystemClock.elapsedRealtime());
     CallIntentParser.putCallSpecificAppData(extras, callSpecificAppData);
 
-    if (allowAssistedDial) {
-      extras.putBoolean(TelephonyManagerCompat.ALLOW_ASSISTED_DIAL, true);
-    }
-
     intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
 
     if (phoneAccountHandle != null) {
@@ -140,6 +149,26 @@
     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 =
diff --git a/java/com/android/dialer/compat/telephony/TelephonyManagerCompat.java b/java/com/android/dialer/compat/telephony/TelephonyManagerCompat.java
index ecd36d3..61c44b9 100644
--- a/java/com/android/dialer/compat/telephony/TelephonyManagerCompat.java
+++ b/java/com/android/dialer/compat/telephony/TelephonyManagerCompat.java
@@ -68,6 +68,11 @@
    */
   public static final String IS_ASSISTED_DIALED = "android.telecom.extra.IS_ASSISTED_DIALED";
 
+  // TODO(erfanian): b/63995261 Replace with the platform/telecom API when available.
+  /** Additional information relating to the assisted dialing transformation. */
+  public static final String ASSISTED_DIALING_EXTRAS =
+      "android.telecom.extra.ASSISTED_DIALING_EXTRAS";
+
   /**
    * Returns the number of phones available. Returns 1 for Single standby mode (Single SIM
    * functionality) Returns 2 for Dual standby mode.(Dual SIM functionality)
diff --git a/java/com/android/dialer/interactions/PhoneNumberInteraction.java b/java/com/android/dialer/interactions/PhoneNumberInteraction.java
index c42be42..9692dae 100644
--- a/java/com/android/dialer/interactions/PhoneNumberInteraction.java
+++ b/java/com/android/dialer/interactions/PhoneNumberInteraction.java
@@ -40,6 +40,7 @@
 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;
@@ -51,6 +52,7 @@
 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;
@@ -83,6 +85,7 @@
   private static final String TAG = PhoneNumberInteraction.class.getSimpleName();
   /** The identifier for a permissions request if one is generated. */
   public static final int REQUEST_READ_CONTACTS = 1;
+
   public static final int REQUEST_CALL_PHONE = 2;
 
   @VisibleForTesting
@@ -183,7 +186,10 @@
         intent =
             new CallIntentBuilder(phoneNumber, callSpecificAppData)
                 .setIsVideoCall(isVideoCall)
-                .setAllowAssistedDial(callSpecificAppData.getAllowAssistedDialing())
+                .setAllowAssistedDial(
+                    callSpecificAppData.getAllowAssistedDialing(),
+                    ConcreteCreator.createNewAssistedDialingMediator(
+                        context.getSystemService(TelephonyManager.class), context))
                 .build();
         break;
     }
diff --git a/java/com/android/dialer/searchfragment/list/SearchAdapter.java b/java/com/android/dialer/searchfragment/list/SearchAdapter.java
index 22bfa6d..1ca29e0 100644
--- a/java/com/android/dialer/searchfragment/list/SearchAdapter.java
+++ b/java/com/android/dialer/searchfragment/list/SearchAdapter.java
@@ -21,11 +21,13 @@
 import android.support.annotation.VisibleForTesting;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
+import com.android.dialer.assisteddialing.ConcreteCreator;
 import com.android.dialer.callcomposer.CallComposerActivity;
 import com.android.dialer.callintent.CallInitiationType;
 import com.android.dialer.callintent.CallIntentBuilder;
@@ -209,23 +211,32 @@
 
   @Override
   public void placeVoiceCall(String phoneNumber, int ranking) {
-    placeCall(phoneNumber, ranking, false);
+    placeCall(phoneNumber, ranking, false, true);
   }
 
   @Override
   public void placeVideoCall(String phoneNumber, int ranking) {
-    placeCall(phoneNumber, ranking, true);
+    placeCall(phoneNumber, ranking, true, false);
   }
 
-  private void placeCall(String phoneNumber, int position, boolean isVideoCall) {
+  private void placeCall(
+      String phoneNumber, int position, boolean isVideoCall, boolean allowAssistedDial) {
     CallSpecificAppData callSpecificAppData =
         CallSpecificAppData.newBuilder()
             .setCallInitiationType(callInitiationType)
             .setPositionOfSelectedSearchResult(position)
             .setCharactersInSearchString(query == null ? 0 : query.length())
+            .setAllowAssistedDialing(allowAssistedDial)
             .build();
     Intent intent =
-        new CallIntentBuilder(phoneNumber, callSpecificAppData).setIsVideoCall(isVideoCall).build();
+        new CallIntentBuilder(phoneNumber, callSpecificAppData)
+            .setIsVideoCall(isVideoCall)
+            .setAllowAssistedDial(
+                allowAssistedDial,
+                ConcreteCreator.createNewAssistedDialingMediator(
+                    activity.getSystemService(TelephonyManager.class),
+                    activity.getApplicationContext()))
+            .build();
     DialerUtils.startActivityWithErrorToast(activity, intent);
   }