Merge "Use TelecomManager#placeCall to place emergency calls."
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a84fd0c..f8afe6f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -283,10 +283,10 @@
     <string name="exception_error">Network or SIM card error.</string>
     <!-- Status message displayed in the "Call settings error" dialog when
          current SS request is modified to a different request by STK CC -->
-    <string name="stk_cc_ss_to_dial_error">SS request modified to DIAL request.</string>
-    <string name="stk_cc_ss_to_ussd_error">SS request modified to USSD request.</string>
-    <string name="stk_cc_ss_to_ss_error">SS request modified to new SS request.</string>
-    <string name="stk_cc_ss_to_dial_video_error">SS request modified to Video DIAL request.</string>
+    <string name="stk_cc_ss_to_dial_error">SS request changed to regular call</string>
+    <string name="stk_cc_ss_to_ussd_error">SS request changed to USSD request</string>
+    <string name="stk_cc_ss_to_ss_error">Changed to new SS request</string>
+    <string name="stk_cc_ss_to_dial_video_error">SS request changed to video call</string>
 
     <!-- Status message displayed in the "Call settings error" dialog when operation fails due to FDN
          [CHAR LIMIT=NONE] -->
@@ -369,7 +369,7 @@
     <!-- Available networks screen, text when no networks are found -->
     <string name="empty_networks_list">No networks found.</string>
     <!-- Available networks screen, toast when an error is encountered when searching for networks -->
-    <string name="network_query_error">Error while searching for networks.</string>
+    <string name="network_query_error">Couldn\'t find networks. Try again.</string>
     <!-- Available networks screen, toast when registering on a specific network -->
     <string name="register_on_network">Registering on <xliff:g id="network">%s</xliff:g>\u2026</string>
     <!-- Available networks screen, toast when SIM card isn't allowed on a network -->
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 2bb8d6f..86f0aa4 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -56,6 +56,7 @@
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.TelephonyPermissions;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
 
@@ -777,12 +778,23 @@
     @Override public
     @NonNull
     PersistableBundle getConfigForSubId(int subId) {
+        // TODO(b/73136824): Migrate to TelephonyPermissions#checkCallingOrSelfReadPhoneState.
         try {
             mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, null);
             // SKIP checking run-time READ_PHONE_STATE since using PRIVILEGED
         } catch (SecurityException e) {
-            mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, null);
+            try {
+                mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, null);
+            } catch (SecurityException securityException) {
+                // If we don't have the runtime permission, but do have carrier privileges, that
+                // suffices for reading phone state.
+                if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+                    throw securityException;
+                }
+                TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(subId, null);
+            }
         }
+
         int phoneId = SubscriptionManager.getPhoneId(subId);
         PersistableBundle retConfig = CarrierConfigManager.getDefaultConfig();
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
diff --git a/src/com/android/phone/NetworkQueryService.java b/src/com/android/phone/NetworkQueryService.java
index 86f4b11..22b5509 100644
--- a/src/com/android/phone/NetworkQueryService.java
+++ b/src/com/android/phone/NetworkQueryService.java
@@ -79,7 +79,7 @@
     private static final boolean INCREMENTAL_RESULTS = true;
     // The parameters below are in seconds
     private static final int SEARCH_PERIODICITY_SEC = 5;
-    private static final int MAX_SEARCH_TIME_SEC = 60;
+    private static final int MAX_SEARCH_TIME_SEC = 300;
     private static final int INCREMENTAL_RESULTS_PERIODICITY_SEC = 3;
 
     /**
diff --git a/src/com/android/phone/NetworkSelectListPreference.java b/src/com/android/phone/NetworkSelectListPreference.java
index cc54b09..c2ed1ae 100644
--- a/src/com/android/phone/NetworkSelectListPreference.java
+++ b/src/com/android/phone/NetworkSelectListPreference.java
@@ -411,7 +411,7 @@
                 String networkTitle = getNetworkTitle(cellInfo);
                 if (!networkEntriesList.contains(networkTitle)) {
                     networkEntriesList.add(networkTitle);
-                    networkEntryValuesList.add(Integer.toString(networkEntriesList.size() + 1));
+                    networkEntryValuesList.add(getOperatorNumeric(cellInfo));
                 }
             }
             setEntries(networkEntriesList.toArray(new CharSequence[networkEntriesList.size()]));
@@ -510,6 +510,16 @@
     }
 
     /**
+     * Returns the operator numeric (MCCMNC) obtained in the manual search.
+     *
+     * @param cellInfo contains the information of the network.
+     * @return MCCMNC string.
+     */
+    private String getOperatorNumeric(CellInfo cellInfo) {
+        return getOperatorInfoFromCellInfo(cellInfo).getOperatorNumeric();
+    }
+
+    /**
      * Wrap a cell info into an operator info.
      */
     private OperatorInfo getOperatorInfoFromCellInfo(CellInfo cellInfo) {
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 84addf7..de41481 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -2038,7 +2038,13 @@
                 mApp, subId, callingPackage, "getVisualVoicemailPackageName")) {
             return null;
         }
-        return RemoteVvmTaskManager.getRemotePackage(mPhone.getContext(), subId).getPackageName();
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return RemoteVvmTaskManager
+                    .getRemotePackage(mPhone.getContext(), subId).getPackageName();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
     }
 
     @Override
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index 4bae058..971dd7b 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -389,5 +389,8 @@
                         android.telephony.DisconnectCause.IMS_MERGED_SUCCESSFULLY)));
         connection.destroy();
         mImsConferences.add(conference);
+        // If one of the participants failed to join the conference, recalculate will set the
+        // conferenceable connections for the conference to show merge calls option.
+        recalculateConferenceable();
     }
 }
diff --git a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java
index 7bd0f70..6ddebb8 100644
--- a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java
+++ b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java
@@ -31,8 +31,9 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.telephony.MbmsDownloadSession;
+import android.telephony.mbms.DownloadProgressListener;
 import android.telephony.mbms.DownloadRequest;
-import android.telephony.mbms.DownloadStateCallback;
+import android.telephony.mbms.DownloadStatusListener;
 import android.telephony.mbms.FileInfo;
 import android.telephony.mbms.FileServiceInfo;
 import android.telephony.mbms.MbmsDownloadSessionCallback;
@@ -143,9 +144,16 @@
         }
 
         @Override
-        public int registerStateCallback(DownloadRequest downloadRequest,
-                DownloadStateCallback callback) throws RemoteException {
-            mDownloadStateCallbacks.put(downloadRequest, callback);
+        public int addStatusListener(DownloadRequest downloadRequest,
+                DownloadStatusListener callback) throws RemoteException {
+            mDownloadStatusCallbacks.put(downloadRequest, callback);
+            return MbmsErrors.SUCCESS;
+        }
+
+        @Override
+        public int addProgressListener(DownloadRequest downloadRequest,
+                DownloadProgressListener callback) throws RemoteException {
+            mDownloadProgressCallbacks.put(downloadRequest, callback);
             return MbmsErrors.SUCCESS;
         }
 
@@ -183,7 +191,9 @@
     // A map of app-identifiers to (maps of service-ids to sets of temp file uris in use)
     private final Map<FrontendAppIdentifier, Map<String, Set<Uri>>> mTempFilesInUse =
             new ConcurrentHashMap<>();
-    private final Map<DownloadRequest, DownloadStateCallback> mDownloadStateCallbacks =
+    private final Map<DownloadRequest, DownloadStatusListener> mDownloadStatusCallbacks =
+            new ConcurrentHashMap<>();
+    private final Map<DownloadRequest, DownloadProgressListener> mDownloadProgressCallbacks =
             new ConcurrentHashMap<>();
 
     private HandlerThread mHandlerThread;
@@ -334,13 +344,14 @@
             UriPathPair tempFile, FileInfo fileToDownload) {
         int result = MbmsDownloadSession.RESULT_SUCCESSFUL;
         // Test Callback
-        DownloadStateCallback c = mDownloadStateCallbacks.get(request);
-        if (c != null) {
-            c.onProgressUpdated(request, fileToDownload, 0, 10, 0, 10);
+        DownloadStatusListener statusListener = mDownloadStatusCallbacks.get(request);
+        DownloadProgressListener progressListener = mDownloadProgressCallbacks.get(request);
+        if (progressListener != null) {
+            progressListener.onProgressUpdated(request, fileToDownload, 0, 10, 0, 10);
         }
         // Test Callback
-        if (c != null) {
-            c.onStateUpdated(request, fileToDownload,
+        if (statusListener != null) {
+            statusListener.onStatusUpdated(request, fileToDownload,
                     MbmsDownloadSession.STATUS_ACTIVELY_DOWNLOADING);
         }
         try {
@@ -367,8 +378,8 @@
             result = MbmsDownloadSession.RESULT_CANCELLED;
         }
         // Test Callback
-        if (c != null) {
-            c.onProgressUpdated(request, fileToDownload, 10, 10, 10, 10);
+        if (progressListener != null) {
+            progressListener.onProgressUpdated(request, fileToDownload, 10, 10, 10, 10);
         }
         // Take a round-trip through the download request serialization to exercise it
         DownloadRequest request1 = DownloadRequest.Builder.fromSerializedRequest(
diff --git a/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/EmbmsTestDownloadApp.java b/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/EmbmsTestDownloadApp.java
index 76baf05..f77b4ac 100644
--- a/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/EmbmsTestDownloadApp.java
+++ b/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/EmbmsTestDownloadApp.java
@@ -27,8 +27,9 @@
 import android.support.v7.widget.RecyclerView;
 import android.telephony.MbmsDownloadSession;
 import android.telephony.SubscriptionManager;
+import android.telephony.mbms.DownloadProgressListener;
 import android.telephony.mbms.DownloadRequest;
-import android.telephony.mbms.DownloadStateCallback;
+import android.telephony.mbms.DownloadStatusListener;
 import android.telephony.mbms.FileInfo;
 import android.telephony.mbms.FileServiceInfo;
 import android.telephony.mbms.MbmsDownloadSessionCallback;
@@ -292,8 +293,8 @@
                         "No DownloadRequest Pending for progress...", Toast.LENGTH_SHORT).show();
                 return;
             }
-            mDownloadManager.registerStateCallback(req, sInstance.getMainThreadHandler()::post,
-                    new DownloadStateCallback(DownloadStateCallback.PROGRESS_UPDATES) {
+            mDownloadManager.addProgressListener(req, sInstance.getMainThreadHandler()::post,
+                    new DownloadProgressListener() {
                         @Override
                         public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
                                 int currentDownloadSize, int fullDownloadSize,
@@ -303,16 +304,6 @@
                                             + " fd: " + fullDownloadSize, Toast.LENGTH_SHORT)
                                     .show();
                         }
-
-                        @Override
-                        public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
-                                @MbmsDownloadSession.DownloadStatus int state) {
-                            // only registered for state callback, this shouldn't happen!
-                            Toast.makeText(EmbmsTestDownloadApp.this,
-                                    "State ERROR: received state update for callback that didn't"
-                                            + " filter it",
-                                    Toast.LENGTH_SHORT).show();
-                        }
                     });
         });
 
@@ -330,21 +321,10 @@
                         "No DownloadRequest Pending for state...", Toast.LENGTH_SHORT).show();
                 return;
             }
-            mDownloadManager.registerStateCallback(req, sInstance.getMainThreadHandler()::post,
-                    new DownloadStateCallback(DownloadStateCallback.STATE_UPDATES) {
+            mDownloadManager.addStatusListener(req, sInstance.getMainThreadHandler()::post,
+                    new DownloadStatusListener() {
                         @Override
-                        public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
-                                int currentDownloadSize, int fullDownloadSize,
-                                int currentDecodedSize, int fullDecodedSize) {
-                            // only registered for state callback, this shouldn't happen!
-                            Toast.makeText(EmbmsTestDownloadApp.this,
-                                    "Progress ERROR: received progress update for"
-                                            + " callback that didn't "
-                                            + "filter it", Toast.LENGTH_SHORT).show();
-                        }
-
-                        @Override
-                        public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
+                        public void onStatusUpdated(DownloadRequest request, FileInfo fileInfo,
                                 @MbmsDownloadSession.DownloadStatus int state) {
                             Toast.makeText(EmbmsTestDownloadApp.this,
                                     "State Updated (" + fileInfo + ") state: " + state,
@@ -367,8 +347,20 @@
                         "No DownloadRequest Pending for state...", Toast.LENGTH_SHORT).show();
                 return;
             }
-            mDownloadManager.registerStateCallback(req, sInstance.getMainThreadHandler()::post,
-                    new DownloadStateCallback() {
+
+            mDownloadManager.addStatusListener(req, sInstance.getMainThreadHandler()::post,
+                    new DownloadStatusListener() {
+                        @Override
+                        public void onStatusUpdated(DownloadRequest request, FileInfo fileInfo,
+                                @MbmsDownloadSession.DownloadStatus int state) {
+                            Toast.makeText(EmbmsTestDownloadApp.this,
+                                    "State Updated (" + fileInfo + ") state: " + state,
+                                    Toast.LENGTH_SHORT).show();
+                        }
+                    });
+
+            mDownloadManager.addProgressListener(req, sInstance.getMainThreadHandler()::post,
+                    new DownloadProgressListener() {
                         @Override
                         public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
                                 int currentDownloadSize, int fullDownloadSize,
@@ -378,14 +370,6 @@
                                             + " fd: " + fullDownloadSize, Toast.LENGTH_SHORT)
                                     .show();
                         }
-
-                        @Override
-                        public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
-                                @MbmsDownloadSession.DownloadStatus int state) {
-                            Toast.makeText(EmbmsTestDownloadApp.this,
-                                    "State Updated (" + fileInfo + ") state: " + state,
-                                    Toast.LENGTH_SHORT).show();
-                        }
                     });
         });
     }