Merge "Start using CarrierConfig for 4G/LTE icon"
diff --git a/res/values/config.xml b/res/values/config.xml
index 855fa92..5ad369f 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -137,7 +137,7 @@
     <!-- DEPRECATED: Use CarrierConfigManager#KEY_PREFER_2G_BOOL -->
     <bool name="config_prefer_2g" translatable="false">true</bool>
     <!-- Show enabled lte option for lte device -->
-    <bool name="config_enabled_lte" translatable="false">false</bool>
+    <bool name="config_enabled_lte" translatable="false">true</bool>
     <!-- Show enabled tdscdma option for device -->
     <bool name="config_support_tdscdma" translatable="false">false</bool>
     <!-- Show enabled tdscdma option for device when connect roaming network -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9e55501..7fe534c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1119,8 +1119,10 @@
     <string name="incall_error_supp_service_separate">Can\'t separate call.</string>
     <!-- In-call screen: message displayed in an error dialog -->
     <string name="incall_error_supp_service_transfer">Can\'t transfer.</string>
-    <!-- In-call screen: message displayed in an error dialog -->
-    <string name="incall_error_supp_service_conference">Unable to conference calls.</string>
+    <!-- In-call screen: message displayed in an error dialog.  Shown when the user attempts to
+        merge calls to form a conference call, but there was an error which prevented this from
+        occurring. -->
+    <string name="incall_error_supp_service_conference">Unable to merge calls.</string>
     <!-- In-call screen: message displayed in an error dialog -->
     <string name="incall_error_supp_service_reject">Can\'t reject call.</string>
     <!-- In-call screen: message displayed in an error dialog -->
diff --git a/src/com/android/phone/GsmUmtsOptions.java b/src/com/android/phone/GsmUmtsOptions.java
index 3e45173..35aab34 100644
--- a/src/com/android/phone/GsmUmtsOptions.java
+++ b/src/com/android/phone/GsmUmtsOptions.java
@@ -28,7 +28,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.settingslib.RestrictedLockUtils;
 
@@ -79,8 +78,6 @@
         boolean addCarrierSettings = true;
         final TelephonyManager telephonyManager = TelephonyManager.from(mPrefFragment.getContext())
                 .createForSubscriptionId(subId);
-        Phone phone = PhoneGlobals.getPhone(subId);
-        if (phone == null) return;
         if (telephonyManager.getPhoneType() != PhoneConstants.PHONE_TYPE_GSM) {
             log("Not a GSM phone");
             addAPNExpand = false;
@@ -104,7 +101,7 @@
             }
 
             if (carrierConfig.getBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL)) {
-                if (phone.isCspPlmnEnabled()) {
+                if (telephonyManager.isManualNetworkSelectionAllowed()) {
                     log("[CSP] Enabling Operator Selection menu.");
                     mNetworkOperator.setEnabled(true);
                 } else {
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index 67f6992..28b6497 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -245,7 +245,8 @@
         // active subscriptions.
         if (sil != null) {
             for (SubscriptionInfo subInfo : sil) {
-                ImsManager imsManager = ImsManager.getInstance(context, subInfo.getSimSlotIndex());
+                int phoneId = SubscriptionManager.getPhoneId(subInfo.getSubscriptionId());
+                ImsManager imsManager = ImsManager.getInstance(context, phoneId);
                 PersistableBundle carrierConfig = carrierConfigManager.getConfigForSubId(
                         subInfo.getSubscriptionId());
                 if ((imsManager.isVolteEnabledByPlatform()
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index cef0e53..6eba28d 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -25,6 +25,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -288,12 +289,23 @@
         // SubscriptionManager.INVALID_SUBSCRIPTION_ID
         public Integer subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
+        // In cases where subId is unavailable, the caller needs to specify the phone.
+        public Phone phone;
+
         public WorkSource workSource;
 
         public MainThreadRequest(Object argument) {
             this.argument = argument;
         }
 
+        MainThreadRequest(Object argument, Phone phone, WorkSource workSource) {
+            this.argument = argument;
+            if (phone != null) {
+                this.phone = phone;
+            }
+            this.workSource = workSource;
+        }
+
         MainThreadRequest(Object argument, Integer subId, WorkSource workSource) {
             this.argument = argument;
             if (subId != null) {
@@ -982,9 +994,8 @@
 
                 case CMD_GET_ALL_CELL_INFO:
                     request = (MainThreadRequest) msg.obj;
-                    Pair<Phone, WorkSource> args = (Pair<Phone, WorkSource>) request.argument;
                     onCompleted = obtainMessage(EVENT_GET_ALL_CELL_INFO_DONE, request);
-                    ((Phone) args.first).getAllCellInfo(args.second, onCompleted);
+                    request.phone.requestCellInfoUpdate(request.workSource, onCompleted);
                     break;
 
                 case EVENT_GET_ALL_CELL_INFO_DONE:
@@ -1058,7 +1069,8 @@
      * @see #sendRequestAsync
      */
     private Object sendRequest(int command, Object argument) {
-        return sendRequest(command, argument,  SubscriptionManager.INVALID_SUBSCRIPTION_ID, null);
+        return sendRequest(
+                command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID, null, null);
     }
 
     /**
@@ -1068,7 +1080,7 @@
      */
     private Object sendRequest(int command, Object argument, WorkSource workSource) {
         return sendRequest(command, argument,  SubscriptionManager.INVALID_SUBSCRIPTION_ID,
-                workSource);
+                null, workSource);
     }
 
     /**
@@ -1077,7 +1089,7 @@
      * @see #sendRequestAsync
      */
     private Object sendRequest(int command, Object argument, Integer subId) {
-        return sendRequest(command, argument, subId, null);
+        return sendRequest(command, argument, subId, null, null);
     }
 
     /**
@@ -1085,12 +1097,40 @@
      * waits for the request to complete, and returns the result.
      * @see #sendRequestAsync
      */
-    private Object sendRequest(int command, Object argument, Integer subId, WorkSource workSource) {
+    private Object sendRequest(int command, Object argument, int subId, WorkSource workSource) {
+        return sendRequest(command, argument, subId, null, workSource);
+    }
+
+    /**
+     * Posts the specified command to be executed on the main thread,
+     * waits for the request to complete, and returns the result.
+     * @see #sendRequestAsync
+     */
+    private Object sendRequest(int command, Object argument, Phone phone, WorkSource workSource) {
+        return sendRequest(
+                command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phone, workSource);
+    }
+
+    /**
+     * Posts the specified command to be executed on the main thread,
+     * waits for the request to complete, and returns the result.
+     * @see #sendRequestAsync
+     */
+    private Object sendRequest(
+            int command, Object argument, Integer subId, Phone phone, WorkSource workSource) {
         if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
             throw new RuntimeException("This method will deadlock if called from the main thread.");
         }
 
-        MainThreadRequest request = new MainThreadRequest(argument, subId, workSource);
+        MainThreadRequest request = null;
+        if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID && phone != null) {
+            throw new IllegalArgumentException("subId and phone cannot both be specified!");
+        } else if (phone != null) {
+            request = new MainThreadRequest(argument, phone, workSource);
+        } else {
+            request = new MainThreadRequest(argument, subId, workSource);
+        }
+
         Message msg = mMainThreadHandler.obtainMessage(command, request);
         msg.sendToTarget();
 
@@ -1807,10 +1847,25 @@
         }
     }
 
+    /**
+     * Returns the target SDK version number for a given package name.
+     *
+     * @return target SDK if the package is found or INT_MAX.
+     */
+    private int getTargetSdk(String packageName) {
+        try {
+            final ApplicationInfo ai =
+                    mPhone.getContext().getPackageManager().getApplicationInfo(packageName, 0);
+            if (ai != null) return ai.targetSdkVersion;
+        } catch (PackageManager.NameNotFoundException unexpected) {
+        }
+        return Integer.MAX_VALUE;
+    }
+
     @Override
     @SuppressWarnings("unchecked")
-    public List<NeighboringCellInfo>
-            getNeighboringCellInfo(String callingPackage, int targetSdk) {
+    public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
+        final int targetSdk = getTargetSdk(callingPackage);
         if (targetSdk >= android.os.Build.VERSION_CODES.Q) {
             throw new SecurityException(
                     "getNeighboringCellInfo() is unavailable to callers targeting Q+ SDK levels.");
@@ -1854,8 +1909,7 @@
             List<CellInfo> cellInfos = new ArrayList<CellInfo>();
             for (Phone phone : PhoneFactory.getPhones()) {
                 final List<CellInfo> info = (List<CellInfo>) sendRequest(
-                        CMD_GET_ALL_CELL_INFO,
-                        new Pair<Phone, WorkSource>(phone, workSource));
+                        CMD_GET_ALL_CELL_INFO, null, phone, workSource);
                 if (info != null) cellInfos.addAll(info);
             }
             return cellInfos;
@@ -4923,6 +4977,31 @@
     }
 
     /**
+     * Get the current modem radio state for the given slot.
+     * @param slotIndex slot index.
+     * @param callingPackage the name of the package making the call.
+     * @return the current radio power state from the modem
+     */
+    @Override
+    public int getRadioPowerState(int slotIndex, String callingPackage) {
+        Phone phone = PhoneFactory.getPhone(slotIndex);
+        if (phone != null) {
+            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                    mApp, phone.getSubId(), callingPackage, "getRadioPowerState")) {
+                return TelephonyManager.RADIO_POWER_UNAVAILABLE;
+            }
+
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                return phone.getRadioPowerState();
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+        return TelephonyManager.RADIO_POWER_UNAVAILABLE;
+    }
+
+    /**
      * Checks if data roaming is enabled on the subscription with id {@code subId}.
      *
      * <p>Requires one of the following permissions:
@@ -4980,6 +5059,23 @@
     }
 
     @Override
+    public boolean isManualNetworkSelectionAllowed(int subId) {
+        boolean isAllowed = true;
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            TelephonyPermissions.enforeceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
+                    mApp, subId, "isManualNetworkSelectionAllowed");
+            Phone phone = getPhone(subId);
+            if (phone != null) {
+                isAllowed = phone.isCspPlmnEnabled();
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+        return isAllowed;
+    }
+
+    @Override
     public UiccSlotInfo[] getUiccSlotsInfo() {
         enforceReadPrivilegedPermission();
 
diff --git a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
index 670f98d..d891da9 100644
--- a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
+++ b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
@@ -18,6 +18,7 @@
 import android.telecom.TelecomManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -76,6 +77,15 @@
     private SwitchPreference mSipReceiveCallsPreference;
     private SipPreferences mSipPreferences;
 
+    private final SubscriptionManager.OnSubscriptionsChangedListener
+            mOnSubscriptionsChangeListener =
+            new SubscriptionManager.OnSubscriptionsChangedListener() {
+        @Override
+        public void onSubscriptionsChanged() {
+            updateAccounts();
+        }
+    };
+
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -122,34 +132,8 @@
          */
         mAccountList = (PreferenceCategory) getPreferenceScreen().findPreference(
                 ACCOUNTS_LIST_CATEGORY_KEY);
-        List<PhoneAccountHandle> allNonSimAccounts =
-                getCallingAccounts(false /* includeSims */, true /* includeDisabled */);
-        // Check to see if we should show the entire section at all.
-        if (shouldShowConnectionServiceList(allNonSimAccounts)) {
-            List<PhoneAccountHandle> enabledAccounts =
-                    getCallingAccounts(true /* includeSims */, false /* includeDisabled */);
-            // Initialize the account list with the set of enabled & SIM accounts.
-            initAccountList(enabledAccounts);
 
-            mDefaultOutgoingAccount = (AccountSelectionPreference)
-                    getPreferenceScreen().findPreference(DEFAULT_OUTGOING_ACCOUNT_KEY);
-            mDefaultOutgoingAccount.setListener(this);
-
-            // Only show the 'Make Calls With..." option if there are multiple accounts.
-            if (enabledAccounts.size() > 1) {
-                updateDefaultOutgoingAccountsModel();
-            } else {
-                mAccountList.removePreference(mDefaultOutgoingAccount);
-            }
-
-            Preference allAccounts = getPreferenceScreen().findPreference(ALL_CALLING_ACCOUNTS_KEY);
-            // If there are no third party (nonSim) accounts, then don't show enable/disable dialog.
-            if (allNonSimAccounts.isEmpty() && allAccounts != null) {
-                mAccountList.removePreference(allAccounts);
-            }
-        } else {
-            getPreferenceScreen().removePreference(mAccountList);
-        }
+        updateAccounts();
 
         if (isPrimaryUser() && SipUtil.isVoipSupported(getActivity())) {
             mSipPreferences = new SipPreferences(getActivity());
@@ -183,6 +167,16 @@
             getPreferenceScreen().removePreference(
                     getPreferenceScreen().findPreference(SIP_SETTINGS_CATEGORY_PREF_KEY));
         }
+
+        SubscriptionManager.from(getActivity()).addOnSubscriptionsChangedListener(
+                mOnSubscriptionsChangeListener);
+    }
+
+    @Override
+    public void onPause() {
+        SubscriptionManager.from(getActivity()).removeOnSubscriptionsChangedListener(
+                mOnSubscriptionsChangeListener);
+        super.onPause();
     }
 
     /**
@@ -391,6 +385,40 @@
         return mTelephonyManager.isMultiSimEnabled() || allNonSimAccounts.size() > 0;
     }
 
+    private void updateAccounts() {
+        if (mAccountList != null) {
+            mAccountList.removeAll();
+            List<PhoneAccountHandle> allNonSimAccounts =
+                    getCallingAccounts(false /* includeSims */, true /* includeDisabled */);
+            // Check to see if we should show the entire section at all.
+            if (shouldShowConnectionServiceList(allNonSimAccounts)) {
+                List<PhoneAccountHandle> enabledAccounts =
+                        getCallingAccounts(true /* includeSims */, false /* includeDisabled */);
+                // Initialize the account list with the set of enabled & SIM accounts.
+                initAccountList(enabledAccounts);
+
+                mDefaultOutgoingAccount = (AccountSelectionPreference)
+                        getPreferenceScreen().findPreference(DEFAULT_OUTGOING_ACCOUNT_KEY);
+                mDefaultOutgoingAccount.setListener(this);
+
+                // Only show the 'Make Calls With..." option if there are multiple accounts.
+                if (enabledAccounts.size() > 1) {
+                    updateDefaultOutgoingAccountsModel();
+                } else {
+                    mAccountList.removePreference(mDefaultOutgoingAccount);
+                }
+
+                Preference allAccounts = getPreferenceScreen().findPreference(ALL_CALLING_ACCOUNTS_KEY);
+                // If there are no third party (nonSim) accounts, then don't show enable/disable dialog.
+                if (allNonSimAccounts.isEmpty() && allAccounts != null) {
+                    mAccountList.removePreference(allAccounts);
+                }
+            } else {
+                getPreferenceScreen().removePreference(mAccountList);
+            }
+        }
+    }
+
     private List<PhoneAccountHandle> getCallingAccounts(
             boolean includeSims, boolean includeDisabledAccounts) {
         PhoneAccountHandle emergencyAccountHandle = getEmergencyPhoneAccount();
diff --git a/src/com/android/phone/vvm/RemoteVvmTaskManager.java b/src/com/android/phone/vvm/RemoteVvmTaskManager.java
index 98cb959..50ac669 100644
--- a/src/com/android/phone/vvm/RemoteVvmTaskManager.java
+++ b/src/com/android/phone/vvm/RemoteVvmTaskManager.java
@@ -161,8 +161,7 @@
                 continue;
             }
             bindIntent.setPackage(packageName);
-            ResolveInfo info = context.getPackageManager()
-                    .resolveService(bindIntent, PackageManager.MATCH_ALL);
+            ResolveInfo info = context.getPackageManager().resolveService(bindIntent, 0);
             if (info == null) {
                 continue;
             }
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 16be893..07754c6 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -518,7 +518,8 @@
                 // Notify Telecom of the new Connection type.
                 // TODO: Switch out the underlying connection instead of creating a new
                 // one and causing UI Jank.
-                addExistingConnection(PhoneUtils.makePstnPhoneAccountHandle(phone), repConnection);
+                addExistingConnection(PhoneUtils.makePstnPhoneAccountHandleWithPrefix(
+                        phone, "", isEmergencyNumber), repConnection);
                 // Remove the old connection from Telecom after.
                 originalConnection.setDisconnected(
                         DisconnectCauseUtil.toTelecomDisconnectCause(