Merge "Post Connection Events to handler."
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index fdb131b..c9eac3b 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -751,7 +751,8 @@
     <string name="call_barring_deactivate_success" msgid="8014685598632000936">"S\'ha desactivat la restricció de trucades"</string>
     <string name="call_barring_change_pwd" msgid="6887420609726284232">"Canvia la contrasenya"</string>
     <string name="call_barring_change_pwd_description" msgid="5505087790260233953">"Canvia la contrasenya de restricció de trucades"</string>
-    <string name="call_barring_change_pwd_description_disabled" msgid="7630770327645349957">"No es pot canviar la contrasenya de restricció de trucades."</string>
+    <!-- no translation found for call_barring_change_pwd_description_disabled (4040168949678570166) -->
+    <skip />
     <string name="call_barring_pwd_not_match" msgid="6716711689350314525">"Les contrasenyes no coincideixen"</string>
     <string name="call_barring_right_pwd_number" msgid="2902966502520410446">"Escriu una contrasenya amb quatre números"</string>
     <string name="call_barring_change_pwd_success" msgid="3278310763742760321">"S\'ha canviat la contrasenya"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 10a309e..1e8df19 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -751,7 +751,8 @@
     <string name="call_barring_deactivate_success" msgid="8014685598632000936">"Desactivouse a restrición de chamadas"</string>
     <string name="call_barring_change_pwd" msgid="6887420609726284232">"Cambiar contrasinal"</string>
     <string name="call_barring_change_pwd_description" msgid="5505087790260233953">"Cambiar contrasinal de restrición de chamadas"</string>
-    <string name="call_barring_change_pwd_description_disabled" msgid="7630770327645349957">"Non se puido cambiar o contrasinal de restrición de chamadas."</string>
+    <!-- no translation found for call_barring_change_pwd_description_disabled (4040168949678570166) -->
+    <skip />
     <string name="call_barring_pwd_not_match" msgid="6716711689350314525">"Os contrasinais non coinciden"</string>
     <string name="call_barring_right_pwd_number" msgid="2902966502520410446">"Introducir un contrasinal con 4 números"</string>
     <string name="call_barring_change_pwd_success" msgid="3278310763742760321">"Cambiouse o contrasinal"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b046c3a..7b3af07 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1773,7 +1773,7 @@
     <!-- Call barring settings screen, change password -->
     <string name="call_barring_change_pwd_description">Change call barring password</string>
     <!-- Call barring settings screen, not possible to change call barring password -->
-    <string name="call_barring_change_pwd_description_disabled">Cannot change call barring password.</string>
+    <string name="call_barring_change_pwd_description_disabled">Cannot change call barring password</string>
     <!-- Call barring settings screen, change password -->
     <string name="call_barring_pwd_not_match">Passwords do not match</string>
     <!-- Call barring settings screen, change password -->
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 2199a9f..345d7ec 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -4789,6 +4789,52 @@
         }
     }
 
+    private int getCarrierPrivilegeStatusFromCarrierConfigRules(int privilegeFromSim,
+            Phone phone) {
+        //load access rules from carrier configs, and check those as well: b/139133814
+        SubscriptionController subController = SubscriptionController.getInstance();
+        if (privilegeFromSim == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
+                || subController == null) return privilegeFromSim;
+
+        int uid = Binder.getCallingUid();
+        PackageManager pkgMgr = phone.getContext().getPackageManager();
+        String[] packages = pkgMgr.getPackagesForUid(uid);
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
+            SubscriptionManager subManager = (SubscriptionManager)
+                    phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+            for (String pkg : packages) {
+                if (subManager.canManageSubscription(subInfo, pkg)) {
+                    return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+                }
+            }
+            return privilegeFromSim;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    private int getCarrierPrivilegeStatusFromCarrierConfigRules(int privilegeFromSim, Phone phone,
+            String pkgName) {
+        //load access rules from carrier configs, and check those as well: b/139133814
+        SubscriptionController subController = SubscriptionController.getInstance();
+        if (privilegeFromSim == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
+                || subController == null) return privilegeFromSim;
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
+            SubscriptionManager subManager = (SubscriptionManager)
+                    phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+            return subManager.canManageSubscription(subInfo, pkgName)
+                ? TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS : privilegeFromSim;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     @Override
     public int getCarrierPrivilegeStatus(int subId) {
         final Phone phone = getPhone(subId);
@@ -4801,8 +4847,10 @@
             loge("getCarrierPrivilegeStatus: No UICC");
             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
         }
-        return card.getCarrierPrivilegeStatusForCurrentTransaction(
-                phone.getContext().getPackageManager());
+
+        return getCarrierPrivilegeStatusFromCarrierConfigRules(
+            card.getCarrierPrivilegeStatusForCurrentTransaction(
+                phone.getContext().getPackageManager()), phone);
     }
 
     @Override
@@ -4818,7 +4866,9 @@
             loge("getCarrierPrivilegeStatus: No UICC");
             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
         }
-        return profile.getCarrierPrivilegeStatusForUid(phone.getContext().getPackageManager(), uid);
+        return getCarrierPrivilegeStatusFromCarrierConfigRules(
+            profile.getCarrierPrivilegeStatusForUid(
+                phone.getContext().getPackageManager(), uid), phone);
     }
 
     @Override
@@ -4833,8 +4883,9 @@
             loge("checkCarrierPrivilegesForPackage: No UICC on subId " + subId);
             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
         }
-
-        return card.getCarrierPrivilegeStatus(mApp.getPackageManager(), pkgName);
+        return getCarrierPrivilegeStatusFromCarrierConfigRules(
+            card.getCarrierPrivilegeStatus(mApp.getPackageManager(), pkgName),
+            getPhone(phoneId), pkgName);
     }
 
     @Override
@@ -4849,7 +4900,9 @@
               continue;
             }
 
-            result = card.getCarrierPrivilegeStatus(mApp.getPackageManager(), pkgName);
+            result = getCarrierPrivilegeStatusFromCarrierConfigRules(
+                card.getCarrierPrivilegeStatus(mApp.getPackageManager(), pkgName),
+                getPhone(i), pkgName);
             if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
                 break;
             }
@@ -4884,9 +4937,9 @@
                 if (packages == null) {
                     // Only check packages in user 0 for now
                     packages = pm.getInstalledPackagesAsUser(
-                            PackageManager.MATCH_DISABLED_COMPONENTS
-                                    | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
-                                    | PackageManager.GET_SIGNATURES, UserHandle.USER_SYSTEM);
+                        PackageManager.MATCH_DISABLED_COMPONENTS
+                            | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+                            | PackageManager.GET_SIGNATURES, UserHandle.USER_SYSTEM);
                 }
                 for (int p = packages.size() - 1; p >= 0; p--) {
                     PackageInfo pkgInfo = packages.get(p);
@@ -5360,14 +5413,19 @@
     }
 
     /**
-     * Determines whether the user has turned on RTT. Only returns true if the device and carrier
-     * both also support RTT.
+     * Determines whether the user has turned on RTT. If the carrier wants to ignore the user-set
+     * RTT setting, will return true if the device and carrier both support RTT.
+     * Otherwise. only returns true if the device and carrier both also support RTT.
      */
     public boolean isRttEnabled(int subscriptionId) {
         final long identity = Binder.clearCallingIdentity();
         try {
-            return isRttSupported(subscriptionId) && Settings.Secure.getInt(
+            boolean isRttSupported = isRttSupported(subscriptionId);
+            boolean isUserRttSettingOn = Settings.Secure.getInt(
                     mApp.getContentResolver(), Settings.Secure.RTT_CALLING_MODE, 0) != 0;
+            boolean shouldIgnoreUserRttSetting = mApp.getCarrierConfigForSubId(subscriptionId)
+                    .getBoolean(CarrierConfigManager.KEY_IGNORE_RTT_MODE_SETTING_BOOL);
+            return isRttSupported && (isUserRttSettingOn || shouldIgnoreUserRttSetting);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/src/com/android/phone/settings/AccessibilitySettingsFragment.java b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
index 3069091..092dd4c 100644
--- a/src/com/android/phone/settings/AccessibilitySettingsFragment.java
+++ b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
@@ -166,10 +166,16 @@
             int rttMode = mButtonRtt.isChecked() ? 1 : 0;
             Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.RTT_CALLING_MODE,
                     rttMode);
-            // Update RTT config with IMS Manager
-            ImsManager imsManager = ImsManager.getInstance(getContext(),
-                    SubscriptionManager.getDefaultVoicePhoneId());
-            imsManager.setRttEnabled(mButtonRtt.isChecked());
+            // Update RTT config with IMS Manager if the always-on carrier config isn't set to true.
+            CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(
+                            Context.CARRIER_CONFIG_SERVICE);
+            for (int subId : SubscriptionController.getInstance().getActiveSubIdList(true)) {
+                if (!configManager.getConfigForSubId(subId).getBoolean(
+                        CarrierConfigManager.KEY_IGNORE_RTT_MODE_SETTING_BOOL, false)) {
+                    ImsManager imsManager = ImsManager.getInstance(getContext(), subId);
+                    imsManager.setRttEnabled(mButtonRtt.isChecked());
+                }
+            }
             return true;
         }
 
@@ -199,18 +205,23 @@
     }
 
     private boolean shouldShowRttSetting() {
-        int subscriptionId = SubscriptionManager.getDefaultVoiceSubscriptionId();
-        if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
-                || subscriptionId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
-            for (int subId : SubscriptionController.getInstance().getActiveSubIdList(true)) {
-                if (PhoneGlobals.getInstance().phoneMgr.isRttSupported(subId)) {
+        CarrierConfigManager configManager =
+                (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+        // Go through all the subs -- if we want to display the RTT setting for any of them, do
+        // display it.
+        for (int subId : SubscriptionController.getInstance().getActiveSubIdList(true)) {
+            // In order to display the setting, we want:
+            // 1. The subscription supports RTT
+            // 2. The subscription isn't configured by the carrier to have the setting always-on
+            //    (see the documentation for the carrier config key)
+            if (PhoneGlobals.getInstance().phoneMgr.isRttSupported(subId)) {
+                if (!configManager.getConfigForSubId(subId).getBoolean(
+                        CarrierConfigManager.KEY_IGNORE_RTT_MODE_SETTING_BOOL, false)) {
                     return true;
                 }
             }
-            return false;
-        } else {
-            return PhoneGlobals.getInstance().phoneMgr.isRttSupported(subscriptionId);
         }
+        return false;
     }
 
     /**
diff --git a/src/com/android/services/telephony/GsmConnection.java b/src/com/android/services/telephony/GsmConnection.java
index 999c6f5..47434c0 100644
--- a/src/com/android/services/telephony/GsmConnection.java
+++ b/src/com/android/services/telephony/GsmConnection.java
@@ -72,9 +72,8 @@
         int capabilities = super.buildConnectionCapabilities();
         capabilities |= CAPABILITY_MUTE;
         // Overwrites TelephonyConnection.buildConnectionCapabilities() and resets the hold options
-        // because all GSM calls should hold, even if the carrier config option is set to not show
-        // hold for IMS calls.
-        if (!shouldTreatAsEmergencyCall()) {
+        // because all GSM calls should hold.
+        if (!shouldTreatAsEmergencyCall() && !isImsConnection()) {
             capabilities |= CAPABILITY_SUPPORT_HOLD;
             if (isHoldable() && (getState() == STATE_ACTIVE || getState() == STATE_HOLDING)) {
                 capabilities |= CAPABILITY_HOLD;