Merge "Move time zone detection logic to system server"
diff --git a/src/java/com/android/internal/telephony/CellBroadcastHandler.java b/src/java/com/android/internal/telephony/CellBroadcastHandler.java
index e9338de..4b317fd 100644
--- a/src/java/com/android/internal/telephony/CellBroadcastHandler.java
+++ b/src/java/com/android/internal/telephony/CellBroadcastHandler.java
@@ -28,6 +28,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.PermissionChecker;
+import android.content.pm.PackageManager;
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
@@ -214,7 +215,7 @@
      */
     protected void broadcastMessage(@NonNull SmsCbMessage message, @Nullable Uri messageUri) {
         String receiverPermission;
-        int appOp;
+        String appOp;
         String msg;
         Intent intent;
         if (message.isEmergencyMessage()) {
@@ -225,7 +226,7 @@
             //Emergency alerts need to be delivered with high priority
             intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
             receiverPermission = Manifest.permission.RECEIVE_EMERGENCY_BROADCAST;
-            appOp = AppOpsManager.OP_RECEIVE_EMERGECY_SMS;
+            appOp = AppOpsManager.OPSTR_RECEIVE_EMERGENCY_BROADCAST;
 
             intent.putExtra(EXTRA_MESSAGE, message);
             SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
@@ -238,9 +239,14 @@
                 if (additionalPackage != null) {
                     Intent additionalIntent = new Intent(intent);
                     additionalIntent.setPackage(additionalPackage);
-                    mContext.sendOrderedBroadcastAsUser(additionalIntent, UserHandle.ALL,
-                            receiverPermission, appOp, null, getHandler(), Activity.RESULT_OK,
-                            null, null);
+                    try {
+                        mContext.createPackageContextAsUser(
+                                mContext.getPackageName(), 0, UserHandle.ALL)
+                                .sendOrderedBroadcast(additionalIntent, receiverPermission, appOp,
+                                        null /* resultReceiver */, getHandler(), Activity.RESULT_OK,
+                                        null /* initialData */, null /* initialExtras */);
+                    } catch (PackageManager.NameNotFoundException ignored) {
+                    }
                 }
             }
 
@@ -250,8 +256,14 @@
             for (String pkg : pkgs) {
                 // Explicitly send the intent to all the configured cell broadcast receivers.
                 intent.setPackage(pkg);
-                mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL, receiverPermission,
-                        appOp, mReceiver, getHandler(), Activity.RESULT_OK, null, null);
+                try {
+                    mContext.createPackageContextAsUser(
+                            mContext.getPackageName(), 0, UserHandle.ALL)
+                            .sendOrderedBroadcast(intent, receiverPermission, appOp, mReceiver,
+                                    getHandler(), Activity.RESULT_OK, null /* initialData */,
+                                    null /* initialExtras */);
+                } catch (PackageManager.NameNotFoundException ignored) {
+                }
             }
         } else {
             msg = "Dispatching SMS CB, SmsCbMessage is: " + message;
@@ -262,14 +274,19 @@
             // this intent.
             intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
             receiverPermission = Manifest.permission.RECEIVE_SMS;
-            appOp = AppOpsManager.OP_RECEIVE_SMS;
+            appOp = AppOpsManager.OPSTR_RECEIVE_SMS;
 
             intent.putExtra(EXTRA_MESSAGE, message);
             SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
 
             mReceiverCount.incrementAndGet();
-            mContext.sendOrderedBroadcastAsUser(intent, UserHandle.ALL, receiverPermission, appOp,
-                    mReceiver, getHandler(), Activity.RESULT_OK, null, null);
+            try {
+                mContext.createPackageContextAsUser(mContext.getPackageName(), 0, UserHandle.ALL)
+                        .sendOrderedBroadcast(intent, receiverPermission, appOp, mReceiver,
+                                getHandler(), Activity.RESULT_OK, null /* initialData */,
+                                null /* initialExtras */);
+            } catch (PackageManager.NameNotFoundException ignored) {
+            }
         }
 
         if (messageUri != null) {
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index 3d66b60..934eddf 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -35,6 +35,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.database.SQLException;
 import android.net.Uri;
@@ -1124,7 +1125,7 @@
      * @param user user to deliver the intent to
      */
     @UnsupportedAppUsage
-    public void dispatchIntent(Intent intent, String permission, int appOp,
+    public void dispatchIntent(Intent intent, String permission, String appOp,
             Bundle opts, BroadcastReceiver resultReceiver, UserHandle user, int subId) {
         intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
         final String action = intent.getAction();
@@ -1174,13 +1175,23 @@
                     }
                 }
                 // Only pass in the resultReceiver when the USER_SYSTEM is processed.
-                mContext.sendOrderedBroadcastAsUser(intent, targetUser, permission, appOp, opts,
-                        users[i] == UserHandle.USER_SYSTEM ? resultReceiver : null,
-                        getHandler(), Activity.RESULT_OK, null, null);
+                try {
+                    mContext.createPackageContextAsUser(mContext.getPackageName(), 0, targetUser)
+                            .sendOrderedBroadcast(intent, permission, appOp, opts,
+                                    users[i] == UserHandle.USER_SYSTEM ? resultReceiver : null,
+                                    getHandler(), Activity.RESULT_OK, null /* initialData */,
+                                    null /* initialExtras */);
+                } catch (PackageManager.NameNotFoundException ignored) {
+                }
             }
         } else {
-            mContext.sendOrderedBroadcastAsUser(intent, user, permission, appOp, opts,
-                    resultReceiver, getHandler(), Activity.RESULT_OK, null, null);
+            try {
+                mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user)
+                        .sendOrderedBroadcast(intent, permission, appOp, opts, resultReceiver,
+                                getHandler(), Activity.RESULT_OK, null /* initialData */,
+                                null /* initialExtras */);
+            } catch (PackageManager.NameNotFoundException ignored) {
+            }
         }
     }
 
@@ -1278,7 +1289,7 @@
 
         Bundle options = handleSmsWhitelisting(intent.getComponent(), isClass0);
         dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
-                AppOpsManager.OP_RECEIVE_SMS, options, resultReceiver, UserHandle.SYSTEM, subId);
+                AppOpsManager.OPSTR_RECEIVE_SMS, options, resultReceiver, UserHandle.SYSTEM, subId);
     }
 
     /**
@@ -1465,7 +1476,7 @@
                 Bundle options = handleSmsWhitelisting(null, false /* bgActivityStartAllowed */);
 
                 dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
-                        AppOpsManager.OP_RECEIVE_SMS,
+                        AppOpsManager.OPSTR_RECEIVE_SMS,
                         options, this, UserHandle.ALL, subId);
             } else if (action.equals(Intents.WAP_PUSH_DELIVER_ACTION)) {
                 // Now dispatch the notification only intent
@@ -1488,7 +1499,7 @@
 
                 String mimeType = intent.getType();
                 dispatchIntent(intent, WapPushOverSms.getPermissionForType(mimeType),
-                        WapPushOverSms.getAppOpsPermissionForIntent(mimeType), options, this,
+                        WapPushOverSms.getAppOpsStringPermissionForIntent(mimeType), options, this,
                         UserHandle.SYSTEM, subId);
             } else {
                 // Now that the intents have been deleted we can clean up the PDU data.
diff --git a/src/java/com/android/internal/telephony/WapPushOverSms.java b/src/java/com/android/internal/telephony/WapPushOverSms.java
index 776bbb6..069178d 100755
--- a/src/java/com/android/internal/telephony/WapPushOverSms.java
+++ b/src/java/com/android/internal/telephony/WapPushOverSms.java
@@ -420,7 +420,7 @@
         }
 
         handler.dispatchIntent(intent, getPermissionForType(result.mimeType),
-                getAppOpsPermissionForIntent(result.mimeType), options, receiver,
+                getAppOpsStringPermissionForIntent(result.mimeType), options, receiver,
                 UserHandle.SYSTEM, subId);
         return Activity.RESULT_OK;
     }
@@ -611,12 +611,17 @@
         return permission;
     }
 
-    public static int getAppOpsPermissionForIntent(String mimeType) {
-        int appOp;
+    /**
+     * Return a appOps String for the given MIME type.
+     * @param mimeType MIME type of the Intent
+     * @return The appOps String
+     */
+    public static String getAppOpsStringPermissionForIntent(String mimeType) {
+        String appOp;
         if (WspTypeDecoder.CONTENT_TYPE_B_MMS.equals(mimeType)) {
-            appOp = AppOpsManager.OP_RECEIVE_MMS;
+            appOp = AppOpsManager.OPSTR_RECEIVE_MMS;
         } else {
-            appOp = AppOpsManager.OP_RECEIVE_WAP_PUSH;
+            appOp = AppOpsManager.OPSTR_RECEIVE_WAP_PUSH;
         }
         return appOp;
     }
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
index 403b535..49b1f2f 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
@@ -1010,7 +1010,7 @@
                 }
             } else if (mSc != null && mSc.equals(SC_WAIT)) {
                 // sia = basic service group
-                int serviceClass = siToServiceClass(mSib);
+                int serviceClass = siToServiceClass(mSia);
 
                 if (isActivate() || isDeactivate()) {
                     mPhone.setCallWaiting(isActivate(), serviceClass,
diff --git a/src/java/com/android/internal/telephony/uicc/RuimRecords.java b/src/java/com/android/internal/telephony/uicc/RuimRecords.java
index ca673f0..5a1a8ac 100644
--- a/src/java/com/android/internal/telephony/uicc/RuimRecords.java
+++ b/src/java/com/android/internal/telephony/uicc/RuimRecords.java
@@ -326,7 +326,7 @@
                     // SPN is checked to have characters in printable ASCII
                     // range. If not, they are decoded with
                     // ENCODING_GSM_7BIT_ALPHABET scheme.
-                    if (TextUtils.isPrintableAsciiOnly(spn)) {
+                    if (isPrintableAsciiOnly(spn)) {
                         setServiceProviderName(spn);
                     } else {
                         if (DBG) log("Some corruption in SPN decoding = " + spn);
@@ -351,6 +351,22 @@
         }
     }
 
+    private static boolean isPrintableAsciiOnly(final CharSequence str) {
+        final int len = str.length();
+        for (int i = 0; i < len; i++) {
+            if (!isPrintableAscii(str.charAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static boolean isPrintableAscii(final char c) {
+        final int asciiFirst = 0x20;
+        final int asciiLast = 0x7E;  // included
+        return (asciiFirst <= c && c <= asciiLast) || c == '\r' || c == '\n';
+    }
+
     private class EfCsimMdnLoaded implements IccRecordLoaded {
         @Override
         public String getEfName() {
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index a7bce9c..720ad75 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -546,7 +546,11 @@
         // Resize array.
         mPhoneIdToSlotId = copyOf(mPhoneIdToSlotId, mCis.length);
 
+        // Register for new active modem for ss -> ds switch.
+        // For ds -> ss switch, there's no need to unregister as the mCis should unregister
+        // everything itself.
         for (int i = prevActiveModemCount; i < mCis.length; i++) {
+            mPhoneIdToSlotId[i] = INVALID_SLOT_ID;
             mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, i);
 
             /*
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
index 305046c..40cec03 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
@@ -61,7 +61,6 @@
 import android.os.PersistableBundle;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.telephony.TelephonyRegistryManager;
 import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.provider.Telephony.ServiceStateTable;
@@ -69,6 +68,7 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
 import android.telephony.euicc.EuiccManager;
 import android.test.mock.MockContentProvider;
 import android.test.mock.MockContentResolver;
@@ -451,6 +451,20 @@
         }
 
         @Override
+        public void sendOrderedBroadcast(Intent intent, String receiverPermission,
+                String receiverAppOp, Bundle options, BroadcastReceiver resultReceiver,
+                Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
+            logd("sendOrderedBroadcast called for " + intent.getAction());
+            mLastBroadcastOptions = options;
+            sendBroadcast(intent);
+            if (resultReceiver != null) {
+                synchronized (mOrderedBroadcastReceivers) {
+                    mOrderedBroadcastReceivers.put(intent, resultReceiver);
+                }
+            }
+        }
+
+        @Override
         public void sendStickyBroadcast(Intent intent) {
             logd("sendStickyBroadcast called for " + intent.getAction());
             synchronized (mBroadcastReceiversByAction) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
index 284a859..9d27abb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
@@ -89,7 +89,7 @@
         ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mInboundSmsHandler).dispatchIntent(intentArgumentCaptor.capture(),
                 eq(android.Manifest.permission.RECEIVE_WAP_PUSH),
-                eq(AppOpsManager.OP_RECEIVE_WAP_PUSH),
+                eq(AppOpsManager.OPSTR_RECEIVE_WAP_PUSH),
                 nullable(Bundle.class),
                 isNull(BroadcastReceiver.class),
                 eq(UserHandle.SYSTEM),
@@ -143,7 +143,7 @@
         verify(mInboundSmsHandler, never()).dispatchIntent(
                 any(Intent.class),
                 any(String.class),
-                anyInt(),
+                any(String.class),
                 any(Bundle.class),
                 any(BroadcastReceiver.class),
                 any(UserHandle.class),