Merge "Add myself as an owner"
diff --git a/res/values/config.xml b/res/values/config.xml
index b1c1607..b1f8ae8 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -253,4 +253,7 @@
 
     <!-- Intent action to launch target emergency app. -->
     <string name="config_emergency_app_intent" translatable="false"></string>
+
+    <!-- Flag indicating whether shortcut view of promoted emergency numbers should be enabled. -->
+    <bool name="config_emergency_shortcut_view_enabled">false</bool>
 </resources>
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index cb12cbb..c89ddc6 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -96,10 +96,9 @@
  *
  * It's a simplified version of the regular dialer (i.e. the TwelveKeyDialer
  * activity from apps/Contacts) that:
- *   1. Allows ONLY emergency calls to be dialed
- *   2. Disallows voicemail functionality
- *   3. Uses the FLAG_SHOW_WHEN_LOCKED window manager flag to allow this
- *      activity to stay in front of the keyguard.
+ * 1. Allows ONLY emergency calls to be dialed
+ * 2. Disallows voicemail functionality
+ * 3. Allows this activity to stay in front of the keyguard.
  *
  * TODO: Even though this is an ultra-simplified version of the normal
  * dialer, there's still lots of code duplication between this class and
@@ -140,6 +139,10 @@
         private MetricsLogger mMetricsLogger = new MetricsLogger();
 
         public void writeMetricsForEnter() {
+            if (!mIsShortcutViewEnabled) {
+                return;
+            }
+
             int entryType = getIntent().getIntExtra(EXTRA_ENTRY_TYPE, ENTRY_TYPE_UNKNOWN);
             KeyguardManager keyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
             mMetricsLogger.write(new LogMaker(MetricsEvent.EMERGENCY_DIALER)
@@ -150,6 +153,10 @@
         }
 
         public void writeMetricsForExit() {
+            if (!mIsShortcutViewEnabled) {
+                return;
+            }
+
             int entryType = getIntent().getIntExtra(EXTRA_ENTRY_TYPE, ENTRY_TYPE_UNKNOWN);
             long userStayDuration = SystemClock.elapsedRealtime() - mUserEnterTimeMillis;
             mMetricsLogger.write(new LogMaker(MetricsEvent.EMERGENCY_DIALER)
@@ -162,6 +169,10 @@
 
         public void writeMetricsForMakingCall(int callSource, int phoneNumberType,
                 boolean hasShortcut) {
+            if (!mIsShortcutViewEnabled) {
+                return;
+            }
+
             mMetricsLogger.write(new LogMaker(MetricsEvent.EMERGENCY_DIALER_MAKE_CALL)
                     .setType(MetricsEvent.TYPE_ACTION)
                     .setSubtype(callSource)
@@ -188,11 +199,11 @@
             "com.android.phone.EmergencyDialer.extra.ENTRY_TYPE";
 
     // List of dialer button IDs.
-    private static final int[] DIALER_KEYS = new int[] {
+    private static final int[] DIALER_KEYS = new int[]{
             R.id.one, R.id.two, R.id.three,
             R.id.four, R.id.five, R.id.six,
             R.id.seven, R.id.eight, R.id.nine,
-            R.id.star, R.id.zero, R.id.pound };
+            R.id.star, R.id.zero, R.id.pound};
 
     // Debug constants.
     private static final boolean DBG = false;
@@ -284,7 +295,7 @@
     private boolean mIsWfcEmergencyCallingWarningEnabled;
     private float mDefaultDigitsTextSize;
 
-    private boolean mAreEmergencyDialerShortcutsEnabled;
+    private boolean mIsShortcutViewEnabled;
 
     private MetricsWriter mMetricsWriter;
     private SensorManager mSensorManager;
@@ -351,29 +362,25 @@
         PersistableBundle carrierConfig =
                 configMgr.getConfigForSubId(SubscriptionManager.getDefaultVoiceSubscriptionId());
 
-        // Disable emergency dialer shortcut when can't get the location information or inserting
-        // the SIM of the blacklisted carrier.
-        boolean isSupport = carrierConfig.getBoolean(
-                CarrierConfigManager.KEY_SUPPORT_EMERGENCY_DIALER_SHORTCUT_BOOL);
-        Log.d(LOG_TAG, "Is the carrier supported: " + isSupport);
-        TelephonyManager tm = getSystemService(TelephonyManager.class);
-        String countryIso = tm.getNetworkCountryIso();
-        mAreEmergencyDialerShortcutsEnabled = false;
-        if (isSupport && !TextUtils.isEmpty(countryIso)) {
-            if (EccInfoHelper.isCountryEccInfoAvailable(this, countryIso)) {
-                mAreEmergencyDialerShortcutsEnabled = true;
+        mIsShortcutViewEnabled = false;
+        if (canEnableShortcutView(carrierConfig)) {
+            TelephonyManager tm = getSystemService(TelephonyManager.class);
+            String countryIso = tm.getNetworkCountryIso();
+            if (TextUtils.isEmpty(countryIso)) {
+                Log.d(LOG_TAG, "Unable to determine the country of current network.");
+            } else if (!EccInfoHelper.isCountryEccInfoAvailable(this, countryIso)) {
+                Log.d(LOG_TAG, "ECC info is unavailable.");
             } else {
-                Log.d(LOG_TAG, "ECC info is unavailable. Disable emergency dialer shortcut.");
+                mIsShortcutViewEnabled = true;
             }
         }
         Log.d(LOG_TAG, "Enable emergency dialer shortcut: "
-                + mAreEmergencyDialerShortcutsEnabled);
+                + mIsShortcutViewEnabled);
 
         mColorExtractor = new ColorExtractor(this);
 
-        // It does not support dark text theme, when emergency dialer shortcuts are enabled.
-        // And the background color is black with 85% opacity.
-        if (mAreEmergencyDialerShortcutsEnabled) {
+        if (mIsShortcutViewEnabled) {
+            // Shortcut view doesn't support dark text theme.
             updateTheme(false);
         } else {
             GradientColors lockScreenColors = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK,
@@ -397,7 +404,7 @@
         ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
                 .getDefaultDisplay().getSize(displaySize);
         mBackgroundGradient.setScreenSize(displaySize.x, displaySize.y);
-        mBackgroundGradient.setAlpha(mAreEmergencyDialerShortcutsEnabled
+        mBackgroundGradient.setAlpha(mIsShortcutViewEnabled
                 ? BLACK_BACKGROUND_GRADIENT_ALPHA : BACKGROUND_GRADIENT_ALPHA);
         getWindow().setBackgroundDrawable(mBackgroundGradient);
 
@@ -461,7 +468,7 @@
 
         mEmergencyInfoGroup = (EmergencyInfoGroup) findViewById(R.id.emergency_info_button);
 
-        if (mAreEmergencyDialerShortcutsEnabled) {
+        if (mIsShortcutViewEnabled) {
             mEccInfoHelper = new EccInfoHelper(IsoToEccProtobufRepository.getInstance());
             setupEmergencyShortcutsView();
         }
@@ -526,10 +533,9 @@
 
     @Override
     public void onBackPressed() {
-        // If emergency dialer shortcut is enabled and Dialpad view is visible, pressing the
-        // back key will back to display EmergencyShortcutView view.
-        // Otherwise, it would finish the activity.
-        if (mAreEmergencyDialerShortcutsEnabled && mDialpadView != null
+        // If shortcut view is enabled and Dialpad view is visible, pressing the back key will
+        // back to display EmergencyShortcutView view. Otherwise, it would finish the activity.
+        if (mIsShortcutViewEnabled && mDialpadView != null
                 && mDialpadView.getVisibility() == View.VISIBLE) {
             switchView(mEmergencyShortcutView, mDialpadView, true);
             return;
@@ -750,9 +756,8 @@
         mUserActions = MetricsWriter.USER_ACTION_NONE;
         mMetricsWriter.writeMetricsForEnter();
 
-        // It does not support dark text theme, when emergency dialer shortcuts are enabled.
-        // And set background color to black.
-        if (mAreEmergencyDialerShortcutsEnabled) {
+        if (mIsShortcutViewEnabled) {
+            // Shortcut view doesn't support dark text theme.
             mBackgroundGradient.setColors(Color.BLACK, Color.BLACK, false);
             updateTheme(false);
         } else {
@@ -764,7 +769,7 @@
             updateTheme(lockScreenColors.supportsDarkText());
         }
 
-        if (mAreEmergencyDialerShortcutsEnabled && mEccInfoHelper != null) {
+        if (mIsShortcutViewEnabled && mEccInfoHelper != null) {
             final Context context = this;
             mEccInfoHelper.getCountryEccInfoAsync(context,
                     new EccInfoHelper.CountryEccInfoResultCallback() {
@@ -836,8 +841,22 @@
         mColorExtractor.removeOnColorsChangedListener(this);
     }
 
+    private boolean canEnableShortcutView(PersistableBundle carrierConfig) {
+        if (!getResources().getBoolean(R.bool.config_emergency_shortcut_view_enabled)) {
+            // Disables shortcut view by project.
+            return false;
+        }
+        if (!carrierConfig.getBoolean(
+                CarrierConfigManager.KEY_SUPPORT_EMERGENCY_DIALER_SHORTCUT_BOOL)) {
+            Log.d(LOG_TAG, "Disables shortcut view by carrier requirement");
+            return false;
+        }
+        return true;
+    }
+
     /**
      * Sets theme based on gradient colors
+     *
      * @param supportsDarkText true if gradient supports dark text
      */
     private void updateTheme(boolean supportsDarkText) {
@@ -1248,8 +1267,8 @@
     /**
      * Switch two view.
      *
-     * @param displayView the view would be displayed.
-     * @param hideView the view would be hidden.
+     * @param displayView  the view would be displayed.
+     * @param hideView     the view would be hidden.
      * @param hasAnimation is {@code true} when the view should be displayed with animation.
      */
     private void switchView(View displayView, View hideView, boolean hasAnimation) {
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 7b7eb0f..d3fd16d 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -1039,13 +1039,12 @@
                     ICellInfoCallback cb = (ICellInfoCallback) request.argument;
                     try {
                         if (ar.exception != null) {
-                            // something went wrong... the response is null
                             Log.e(LOG_TAG, "Exception retrieving CellInfo=" + ar.exception);
-                            cb.onCellInfo(null);
+                            cb.onError(TelephonyManager.CellInfoCallback.ERROR_MODEM_ERROR,
+                                    new android.os.ParcelableException(ar.exception));
                         } else if (ar.result == null) {
-                            // timeout occurred, so force the result to non-null "empty"
                             Log.w(LOG_TAG, "Timeout Waiting for CellInfo!");
-                            cb.onCellInfo(new ArrayList<CellInfo>());
+                            cb.onError(TelephonyManager.CellInfoCallback.ERROR_TIMEOUT, null);
                         } else {
                             // use the result as returned
                             cb.onCellInfo((List<CellInfo>) ar.result);
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index a0e5530..228eed1 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -46,6 +46,9 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
+import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.feature.MmTelFeature;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.text.TextUtils;
 
 import com.android.ims.ImsManager;
@@ -78,7 +81,10 @@
         private final PstnIncomingCallNotifier mIncomingCallNotifier;
         private final PstnPhoneCapabilitiesNotifier mPhoneCapabilitiesNotifier;
         private boolean mIsEmergency;
-        private boolean mIsDummy;
+        private boolean mIsRttCapable;
+        private MmTelFeature.MmTelCapabilities mMmTelCapabilities;
+        private ImsMmTelManager.CapabilityCallback mMmtelCapabilityCallback;
+        private final boolean mIsDummy;
         private boolean mIsVideoCapable;
         private boolean mIsVideoPresenceSupported;
         private boolean mIsVideoPauseSupported;
@@ -99,11 +105,53 @@
             mIncomingCallNotifier = new PstnIncomingCallNotifier((Phone) mPhone);
             mPhoneCapabilitiesNotifier = new PstnPhoneCapabilitiesNotifier((Phone) mPhone,
                     this);
+
+            if (!mIsDummy) {
+                ImsMmTelManager manager;
+                try {
+                    manager = ImsMmTelManager.createForSubscriptionId(mContext, getSubId());
+                } catch (IllegalArgumentException e) {
+                    Log.i(this, "Not registering Mmtel listener because the subid is invalid");
+                    return;
+                }
+
+                boolean isImsVoiceCapable = manager.isCapable(
+                        ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+                        MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE)
+                        || manager.isCapable(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
+                        MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE);
+
+                if (!isImsVoiceCapable) {
+                    Log.i(this, "Not registering MmTel listener because"
+                            + " voice over IMS isn't supported");
+                    return;
+                }
+
+                mMmtelCapabilityCallback =
+                        new ImsMmTelManager.CapabilityCallback() {
+                            @Override
+                            public void onCapabilitiesStatusChanged(
+                                    MmTelFeature.MmTelCapabilities capabilities) {
+                                mMmTelCapabilities = capabilities;
+                                updateRttCapability();
+                            }
+                        };
+                manager.registerMmTelCapabilityCallback(mContext.getMainExecutor(),
+                                mMmtelCapabilityCallback);
+            }
         }
 
         void teardown() {
             mIncomingCallNotifier.teardown();
             mPhoneCapabilitiesNotifier.teardown();
+            if (mMmtelCapabilityCallback != null) {
+                try {
+                    ImsMmTelManager.createForSubscriptionId(mContext, getSubId())
+                            .unregisterMmTelCapabilityCallback(mMmtelCapabilityCallback);
+                } catch (IllegalArgumentException e) {
+                    // TODO (breadley): Tearing down may fail if the sim has been removed.
+                }
+            }
         }
 
         /**
@@ -260,8 +308,10 @@
                 extras.putBoolean(PhoneAccount.EXTRA_PLAY_CALL_RECORDING_TONE, true);
             }
 
-            if (PhoneGlobals.getInstance().phoneMgr.isRttEnabled(subId)) {
+            if (PhoneGlobals.getInstance().phoneMgr.isRttEnabled(subId)
+                    && isImsVoiceAvailable()) {
                 capabilities |= PhoneAccount.CAPABILITY_RTT;
+                mIsRttCapable = true;
             }
 
             extras.putBoolean(PhoneAccount.EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK,
@@ -525,10 +575,21 @@
         }
 
         public void updateRttCapability() {
-            boolean isRttEnabled = PhoneGlobals.getInstance().phoneMgr
+            // In the rare case that mMmTelCapabilities hasn't been set yet, try fetching it
+            // directly.
+            boolean hasVoiceAvailability;
+            if (mMmTelCapabilities != null) {
+                hasVoiceAvailability = mMmTelCapabilities.isCapable(
+                        MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE);
+            } else {
+                hasVoiceAvailability = isImsVoiceAvailable();
+            }
+
+            boolean isRttSupported = PhoneGlobals.getInstance().phoneMgr
                     .isRttEnabled(mPhone.getSubId());
-            boolean oldRttEnabled = mAccount.hasCapabilities(PhoneAccount.CAPABILITY_RTT);
-            if (isRttEnabled != oldRttEnabled) {
+
+            boolean isRttEnabled = hasVoiceAvailability && isRttSupported;
+            if (isRttEnabled != mIsRttCapable) {
                 mAccount = registerPstnPhoneAccount(mIsEmergency, mIsDummy);
             }
         }
@@ -591,6 +652,20 @@
         public boolean isShowPreciseFailedCause() {
             return mIsShowPreciseFailedCause;
         }
+
+        private boolean isImsVoiceAvailable() {
+            if (mMmTelCapabilities != null) {
+                return mMmTelCapabilities.isCapable(
+                        MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE);
+            }
+
+            ImsMmTelManager manager = ImsMmTelManager.createForSubscriptionId(
+                    mContext, getSubId());
+            return manager.isAvailable(ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+                    MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE)
+                    || manager.isAvailable(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
+                    MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE);
+        }
     }
 
     private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 8f46ecf..d2ba8f1 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -2266,6 +2266,8 @@
                 android.telecom.Connection.EXTRA_CHILD_ADDRESS);
         result.put(ImsCallProfile.EXTRA_DISPLAY_TEXT,
                 android.telecom.Connection.EXTRA_CALL_SUBJECT);
+        result.put(ImsCallProfile.EXTRA_ADDITIONAL_SIP_INVITE_FIELDS,
+                android.telecom.Connection.EXTRA_SIP_INVITE);
         return Collections.unmodifiableMap(result);
     }