Remove SMS access for apps other than current SMS handler

Bug: 110098858
Test: atest android.telephony.cts.SmsManagerTest#testContentProviderAccessRestrictions
Change-Id: I9da992565b04ca5fa2656801fd2cfe4b196ef9b4
diff --git a/api/system-current.txt b/api/system-current.txt
index 5785e4a..9dd46f7 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4446,6 +4446,7 @@
     field public static final java.lang.String INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT = "install_carrier_app_notification_persistent";
     field public static final java.lang.String INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS = "install_carrier_app_notification_sleep_millis";
     field public static final java.lang.String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
+    field public static final java.lang.String SMS_ACCESS_RESTRICTION_ENABLED = "sms_access_restriction_enabled";
     field public static final java.lang.String THEATER_MODE_ON = "theater_mode_on";
     field public static final java.lang.String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
     field public static final java.lang.String WIFI_BADGING_THRESHOLDS = "wifi_badging_thresholds";
diff --git a/api/test-current.txt b/api/test-current.txt
index 9567616..8bfda58 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -84,6 +84,7 @@
     method public static java.lang.String opToPermission(int);
     method public static int permissionToOpCode(java.lang.String);
     method public void setMode(int, int, java.lang.String, int);
+    method public void setUidMode(java.lang.String, int, int);
     method public void startWatchingActive(int[], android.app.AppOpsManager.OnOpActiveChangedListener);
     method public void stopWatchingActive(android.app.AppOpsManager.OnOpActiveChangedListener);
     method public static int strOpToOp(java.lang.String);
@@ -953,6 +954,7 @@
     field public static final java.lang.String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
     field public static final java.lang.String LOW_POWER_MODE = "low_power";
     field public static final java.lang.String LOW_POWER_MODE_STICKY = "low_power_sticky";
+    field public static final java.lang.String SMS_ACCESS_RESTRICTION_ENABLED = "sms_access_restriction_enabled";
     field public static final java.lang.String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
   }
 
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 12fb4a3..1597c8c 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -33,11 +33,7 @@
 import android.os.UserHandle;
 import android.text.TextUtils;
 
-import libcore.io.Streams;
-
 import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 
 /**
  * This class is a command line utility for manipulating content. A client
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 9c47e79..a05d01b 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1256,85 +1256,85 @@
      * This specifies the default mode for each operation.
      */
     private static int[] sOpDefaultMode = new int[] {
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_IGNORED, // OP_WRITE_SMS
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_DEFAULT, // OP_WRITE_SETTINGS
-            AppOpsManager.MODE_DEFAULT, // OP_SYSTEM_ALERT_WINDOW
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_DEFAULT, // OP_GET_USAGE_STATS
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_IGNORED, // OP_PROJECT_MEDIA
-            AppOpsManager.MODE_IGNORED, // OP_ACTIVATE_VPN
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ERRORED,  // OP_MOCK_LOCATION
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,  // OP_TURN_ON_SCREEN
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_ALLOWED,  // OP_RUN_IN_BACKGROUND
-            AppOpsManager.MODE_ALLOWED,  // OP_AUDIO_ACCESSIBILITY_VOLUME
-            AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_DEFAULT,  // OP_REQUEST_INSTALL_PACKAGES
-            AppOpsManager.MODE_ALLOWED,  // OP_PICTURE_IN_PICTURE
-            AppOpsManager.MODE_DEFAULT,  // OP_INSTANT_APP_START_FOREGROUND
-            AppOpsManager.MODE_ALLOWED,  // ANSWER_PHONE_CALLS
-            AppOpsManager.MODE_ALLOWED,  // OP_RUN_ANY_IN_BACKGROUND
-            AppOpsManager.MODE_ALLOWED,  // OP_CHANGE_WIFI_STATE
-            AppOpsManager.MODE_ALLOWED,  // REQUEST_DELETE_PACKAGES
-            AppOpsManager.MODE_ALLOWED,  // OP_BIND_ACCESSIBILITY_SERVICE
-            AppOpsManager.MODE_ALLOWED,  // ACCEPT_HANDOVER
-            AppOpsManager.MODE_ERRORED,  // MANAGE_IPSEC_TUNNELS
-            AppOpsManager.MODE_ALLOWED,  // OP_START_FOREGROUND
-            AppOpsManager.MODE_ALLOWED,  // OP_BLUETOOTH_SCAN
-            AppOpsManager.MODE_ALLOWED,  // USE_BIOMETRIC
+            AppOpsManager.MODE_ALLOWED, // COARSE_LOCATION
+            AppOpsManager.MODE_ALLOWED, // FINE_LOCATION
+            AppOpsManager.MODE_ALLOWED, // GPS
+            AppOpsManager.MODE_ALLOWED, // VIBRATE
+            AppOpsManager.MODE_ALLOWED, // READ_CONTACTS
+            AppOpsManager.MODE_ALLOWED, // WRITE_CONTACTS
+            AppOpsManager.MODE_ALLOWED, // READ_CALL_LOG
+            AppOpsManager.MODE_ALLOWED, // WRITE_CALL_LOG
+            AppOpsManager.MODE_ALLOWED, // READ_CALENDAR
+            AppOpsManager.MODE_ALLOWED, // WRITE_CALENDAR
+            AppOpsManager.MODE_ALLOWED, // WIFI_SCAN
+            AppOpsManager.MODE_ALLOWED, // POST_NOTIFICATION
+            AppOpsManager.MODE_ALLOWED, // NEIGHBORING_CELLS
+            AppOpsManager.MODE_ALLOWED, // CALL_PHONE
+            AppOpsManager.MODE_DEFAULT, // READ_SMS
+            AppOpsManager.MODE_DEFAULT, // WRITE_SMS
+            AppOpsManager.MODE_DEFAULT, // RECEIVE_SMS
+            AppOpsManager.MODE_ALLOWED, // RECEIVE_EMERGENCY_BROADCAST
+            AppOpsManager.MODE_ALLOWED, // RECEIVE_MMS
+            AppOpsManager.MODE_DEFAULT, // RECEIVE_WAP_PUSH
+            AppOpsManager.MODE_DEFAULT, // SEND_SMS
+            AppOpsManager.MODE_ALLOWED, // READ_ICC_SMS
+            AppOpsManager.MODE_ALLOWED, // WRITE_ICC_SMS
+            AppOpsManager.MODE_DEFAULT, // WRITE_SETTINGS
+            AppOpsManager.MODE_DEFAULT, // SYSTEM_ALERT_WINDOW
+            AppOpsManager.MODE_ALLOWED, // ACCESS_NOTIFICATIONS
+            AppOpsManager.MODE_ALLOWED, // CAMERA
+            AppOpsManager.MODE_ALLOWED, // RECORD_AUDIO
+            AppOpsManager.MODE_ALLOWED, // PLAY_AUDIO
+            AppOpsManager.MODE_ALLOWED, // READ_CLIPBOARD
+            AppOpsManager.MODE_ALLOWED, // WRITE_CLIPBOARD
+            AppOpsManager.MODE_ALLOWED, // TAKE_MEDIA_BUTTONS
+            AppOpsManager.MODE_ALLOWED, // TAKE_AUDIO_FOCUS
+            AppOpsManager.MODE_ALLOWED, // AUDIO_MASTER_VOLUME
+            AppOpsManager.MODE_ALLOWED, // AUDIO_VOICE_VOLUME
+            AppOpsManager.MODE_ALLOWED, // AUDIO_RING_VOLUME
+            AppOpsManager.MODE_ALLOWED, // AUDIO_MEDIA_VOLUME
+            AppOpsManager.MODE_ALLOWED, // AUDIO_ALARM_VOLUME
+            AppOpsManager.MODE_ALLOWED, // AUDIO_NOTIFICATION_VOLUME
+            AppOpsManager.MODE_ALLOWED, // AUDIO_BLUETOOTH_VOLUME
+            AppOpsManager.MODE_ALLOWED, // WAKE_LOCK
+            AppOpsManager.MODE_ALLOWED, // MONITOR_LOCATION
+            AppOpsManager.MODE_ALLOWED, // MONITOR_HIGH_POWER_LOCATION
+            AppOpsManager.MODE_DEFAULT, // GET_USAGE_STATS
+            AppOpsManager.MODE_ALLOWED, // MUTE_MICROPHONE
+            AppOpsManager.MODE_ALLOWED, // TOAST_WINDOW
+            AppOpsManager.MODE_IGNORED, // PROJECT_MEDIA
+            AppOpsManager.MODE_IGNORED, // ACTIVATE_VPN
+            AppOpsManager.MODE_ALLOWED, // WRITE_WALLPAPER
+            AppOpsManager.MODE_ALLOWED, // ASSIST_STRUCTURE
+            AppOpsManager.MODE_ALLOWED, // ASSIST_SCREENSHOT
+            AppOpsManager.MODE_ALLOWED, // READ_PHONE_STATE
+            AppOpsManager.MODE_ALLOWED, // ADD_VOICEMAIL
+            AppOpsManager.MODE_ALLOWED, // USE_SIP
+            AppOpsManager.MODE_ALLOWED, // PROCESS_OUTGOING_CALLS
+            AppOpsManager.MODE_ALLOWED, // USE_FINGERPRINT
+            AppOpsManager.MODE_ALLOWED, // BODY_SENSORS
+            AppOpsManager.MODE_DEFAULT, // READ_CELL_BROADCASTS
+            AppOpsManager.MODE_ERRORED, // MOCK_LOCATION
+            AppOpsManager.MODE_ALLOWED, // READ_EXTERNAL_STORAGE
+            AppOpsManager.MODE_ALLOWED, // WRITE_EXTERNAL_STORAGE
+            AppOpsManager.MODE_ALLOWED, // TURN_SCREEN_ON
+            AppOpsManager.MODE_ALLOWED, // GET_ACCOUNTS
+            AppOpsManager.MODE_ALLOWED, // RUN_IN_BACKGROUND
+            AppOpsManager.MODE_ALLOWED, // AUDIO_ACCESSIBILITY_VOLUME
+            AppOpsManager.MODE_ALLOWED, // READ_PHONE_NUMBERS
+            AppOpsManager.MODE_DEFAULT, // REQUEST_INSTALL_PACKAGES
+            AppOpsManager.MODE_ALLOWED, // PICTURE_IN_PICTURE
+            AppOpsManager.MODE_DEFAULT, // INSTANT_APP_START_FOREGROUND
+            AppOpsManager.MODE_ALLOWED, // ANSWER_PHONE_CALLS
+            AppOpsManager.MODE_ALLOWED, // RUN_ANY_IN_BACKGROUND
+            AppOpsManager.MODE_ALLOWED, // CHANGE_WIFI_STATE
+            AppOpsManager.MODE_ALLOWED, // REQUEST_DELETE_PACKAGES
+            AppOpsManager.MODE_ALLOWED, // BIND_ACCESSIBILITY_SERVICE
+            AppOpsManager.MODE_ALLOWED, // ACCEPT_HANDOVER
+            AppOpsManager.MODE_ERRORED, // MANAGE_IPSEC_TUNNELS
+            AppOpsManager.MODE_ALLOWED, // START_FOREGROUND
+            AppOpsManager.MODE_ALLOWED, // BLUETOOTH_SCAN
+            AppOpsManager.MODE_ALLOWED, // USE_BIOMETRIC
     };
 
     /**
@@ -1345,80 +1345,80 @@
      * for whichever app is selected as the current SMS app).
      */
     private static boolean[] sOpDisableReset = new boolean[] {
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            true,      // OP_WRITE_SMS
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false,
-            false, // OP_AUDIO_ACCESSIBILITY_VOLUME
-            false,
-            false, // OP_REQUEST_INSTALL_PACKAGES
-            false, // OP_PICTURE_IN_PICTURE
-            false,
+            false, // COARSE_LOCATION
+            false, // FINE_LOCATION
+            false, // GPS
+            false, // VIBRATE
+            false, // READ_CONTACTS
+            false, // WRITE_CONTACTS
+            false, // READ_CALL_LOG
+            false, // WRITE_CALL_LOG
+            false, // READ_CALENDAR
+            false, // WRITE_CALENDAR
+            false, // WIFI_SCAN
+            false, // POST_NOTIFICATION
+            false, // NEIGHBORING_CELLS
+            false, // CALL_PHONE
+            true, // READ_SMS
+            true, // WRITE_SMS
+            true, // RECEIVE_SMS
+            false, // RECEIVE_EMERGENCY_BROADCAST
+            false, // RECEIVE_MMS
+            true, // RECEIVE_WAP_PUSH
+            true, // SEND_SMS
+            false, // READ_ICC_SMS
+            false, // WRITE_ICC_SMS
+            false, // WRITE_SETTINGS
+            false, // SYSTEM_ALERT_WINDOW
+            false, // ACCESS_NOTIFICATIONS
+            false, // CAMERA
+            false, // RECORD_AUDIO
+            false, // PLAY_AUDIO
+            false, // READ_CLIPBOARD
+            false, // WRITE_CLIPBOARD
+            false, // TAKE_MEDIA_BUTTONS
+            false, // TAKE_AUDIO_FOCUS
+            false, // AUDIO_MASTER_VOLUME
+            false, // AUDIO_VOICE_VOLUME
+            false, // AUDIO_RING_VOLUME
+            false, // AUDIO_MEDIA_VOLUME
+            false, // AUDIO_ALARM_VOLUME
+            false, // AUDIO_NOTIFICATION_VOLUME
+            false, // AUDIO_BLUETOOTH_VOLUME
+            false, // WAKE_LOCK
+            false, // MONITOR_LOCATION
+            false, // MONITOR_HIGH_POWER_LOCATION
+            false, // GET_USAGE_STATS
+            false, // MUTE_MICROPHONE
+            false, // TOAST_WINDOW
+            false, // PROJECT_MEDIA
+            false, // ACTIVATE_VPN
+            false, // WRITE_WALLPAPER
+            false, // ASSIST_STRUCTURE
+            false, // ASSIST_SCREENSHOT
+            false, // READ_PHONE_STATE
+            false, // ADD_VOICEMAIL
+            false, // USE_SIP
+            false, // PROCESS_OUTGOING_CALLS
+            false, // USE_FINGERPRINT
+            false, // BODY_SENSORS
+            true, // READ_CELL_BROADCASTS
+            false, // MOCK_LOCATION
+            false, // READ_EXTERNAL_STORAGE
+            false, // WRITE_EXTERNAL_STORAGE
+            false, // TURN_SCREEN_ON
+            false, // GET_ACCOUNTS
+            false, // RUN_IN_BACKGROUND
+            false, // AUDIO_ACCESSIBILITY_VOLUME
+            false, // READ_PHONE_NUMBERS
+            false, // REQUEST_INSTALL_PACKAGES
+            false, // PICTURE_IN_PICTURE
+            false, // INSTANT_APP_START_FOREGROUND
             false, // ANSWER_PHONE_CALLS
-            false, // OP_RUN_ANY_IN_BACKGROUND
-            false, // OP_CHANGE_WIFI_STATE
-            false, // OP_REQUEST_DELETE_PACKAGES
-            false, // OP_BIND_ACCESSIBILITY_SERVICE
+            false, // RUN_ANY_IN_BACKGROUND
+            false, // CHANGE_WIFI_STATE
+            false, // REQUEST_DELETE_PACKAGES
+            false, // BIND_ACCESSIBILITY_SERVICE
             false, // ACCEPT_HANDOVER
             false, // MANAGE_IPSEC_TUNNELS
             false, // START_FOREGROUND
@@ -1957,6 +1957,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
     public void setUidMode(String appOp, int uid, int mode) {
         try {
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index a64eead..4e1a898 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -18,6 +18,7 @@
 
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_DEFAULT;
 import static android.app.AppOpsManager.MODE_ERRORED;
 import static android.app.AppOpsManager.MODE_IGNORED;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -569,11 +570,7 @@
                 return mode;
             }
 
-            if (mReadOp != AppOpsManager.OP_NONE) {
-                return mAppOpsManager.noteProxyOp(mReadOp, callingPkg);
-            }
-
-            return AppOpsManager.MODE_ALLOWED;
+            return noteProxyOp(callingPkg, mReadOp);
         }
 
         private int enforceWritePermission(String callingPkg, Uri uri, IBinder callerToken)
@@ -583,8 +580,13 @@
                 return mode;
             }
 
-            if (mWriteOp != AppOpsManager.OP_NONE) {
-                return mAppOpsManager.noteProxyOp(mWriteOp, callingPkg);
+            return noteProxyOp(callingPkg, mWriteOp);
+        }
+
+        private int noteProxyOp(String callingPkg, int op) {
+            if (op != AppOpsManager.OP_NONE) {
+                int mode = mAppOpsManager.noteProxyOp(op, callingPkg);
+                return mode == MODE_DEFAULT ? interpretDefaultAppOpMode(op) : mode;
             }
 
             return AppOpsManager.MODE_ALLOWED;
@@ -609,12 +611,17 @@
             return MODE_ERRORED;
         }
 
-        final int permOp = AppOpsManager.permissionToOpCode(permission);
-        if (permOp != AppOpsManager.OP_NONE) {
-            return mTransport.mAppOpsManager.noteProxyOp(permOp, callingPkg);
-        }
+        return mTransport.noteProxyOp(callingPkg, AppOpsManager.permissionToOpCode(permission));
+    }
 
-        return MODE_ALLOWED;
+    /**
+     * Allows for custom interpretations of {@link AppOpsManager#MODE_DEFAULT} by individual
+     * content providers
+     *
+     * @hide
+     */
+    protected int interpretDefaultAppOpMode(int op) {
+        return MODE_IGNORED;
     }
 
     /** {@hide} */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ad8626c..38b7834 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -12314,6 +12314,18 @@
                 "location_global_kill_switch";
 
         /**
+         * If set to 1, app cannot request read sms permission unless it's the default sms handler.
+         *
+         * STOPSHIP: Remove this once we ship with the restriction enabled.
+         *
+         * @hide
+         */
+        @SystemApi
+        @TestApi
+        public static final String SMS_ACCESS_RESTRICTION_ENABLED =
+                "sms_access_restriction_enabled";
+
+        /**
          * If set to 1, SettingsProvider's restoreAnyVersion="true" attribute will be ignored
          * and restoring to lower version of platform API will be skipped.
          *
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index f9f725a..eb5b52c 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -739,6 +739,7 @@
         optional SettingProto short_code_rule = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto short_codes_update_content_url = 5;
         optional SettingProto short_codes_update_metadata_url = 6;
+        optional SettingProto access_restriction_enabled = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
     optional Sms sms = 109;
 
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 8f0e76b..6dadb74c 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -396,6 +396,7 @@
                     Settings.Global.SHOW_TEMPERATURE_WARNING,
                     Settings.Global.SMART_SELECTION_UPDATE_CONTENT_URL,
                     Settings.Global.SMART_SELECTION_UPDATE_METADATA_URL,
+                    Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED,
                     Settings.Global.SMS_OUTGOING_CHECK_INTERVAL_MS,
                     Settings.Global.SMS_OUTGOING_CHECK_MAX_COUNT,
                     Settings.Global.SMS_SHORT_CODE_CONFIRMATION,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index bd21b83..e5e15d5 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1140,6 +1140,9 @@
         dumpSetting(s, p,
                 Settings.Global.SMS_SHORT_CODES_UPDATE_METADATA_URL,
                 GlobalSettingsProto.Sms.SHORT_CODES_UPDATE_METADATA_URL);
+        dumpSetting(s, p,
+                Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED,
+                GlobalSettingsProto.Sms.ACCESS_RESTRICTION_ENABLED);
         p.end(smsToken);
 
         final long soundsToken = p.start(GlobalSettingsProto.SOUNDS);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index da870bd..ee0c416 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -24,6 +24,7 @@
 
     <!-- Standard permissions granted to the shell. -->
     <uses-permission android:name="android.permission.SEND_SMS" />
+    <uses-permission android:name="android.permission.READ_SMS" />
     <uses-permission android:name="android.permission.CALL_PHONE" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.READ_CONTACTS" />
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index 8202580..e194d15 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -384,7 +384,7 @@
         }
         if (!isRuntime() && !isDevelopment()) {
             throw new SecurityException("Permission " + name
-                    + " is not a changeable permission type");
+                    + " requested by " + pkg.packageName + " is not a changeable permission type");
         }
     }
 
diff --git a/telephony/java/com/android/internal/telephony/SmsApplication.java b/telephony/java/com/android/internal/telephony/SmsApplication.java
index 39722c6..54f3015 100644
--- a/telephony/java/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/java/com/android/internal/telephony/SmsApplication.java
@@ -69,6 +69,15 @@
     private static final String SCHEME_MMSTO = "mmsto";
     private static final boolean DEBUG_MULTIUSER = false;
 
+    private static final int[] DEFAULT_APP_EXCLUSIVE_APPOPS = {
+            AppOpsManager.OP_READ_SMS,
+            AppOpsManager.OP_WRITE_SMS,
+            AppOpsManager.OP_RECEIVE_SMS,
+            AppOpsManager.OP_RECEIVE_WAP_PUSH,
+            AppOpsManager.OP_SEND_SMS,
+            AppOpsManager.OP_READ_CELL_BROADCASTS
+    };
+
     private static SmsPackageMonitor sSmsPackageMonitor = null;
 
     public static class SmsApplicationData {
@@ -396,6 +405,8 @@
             final SmsApplicationData smsApplicationData = receivers.get(packageName);
             if (smsApplicationData != null) {
                 if (!smsApplicationData.isComplete()) {
+                    Log.w(LOG_TAG, "Package " + packageName
+                            + " lacks required manifest declarations to be a default sms app");
                     receivers.remove(packageName);
                 }
             }
@@ -482,53 +493,27 @@
 
         // If we found a package, make sure AppOps permissions are set up correctly
         if (applicationData != null) {
-            AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
-
             // We can only call checkOp if we are privileged (updateIfNeeded) or if the app we
             // are checking is for our current uid. Doing this check from the unprivileged current
             // SMS app allows us to tell the current SMS app that it is not in a good state and
             // needs to ask to be the current SMS app again to work properly.
             if (updateIfNeeded || applicationData.mUid == android.os.Process.myUid()) {
                 // Verify that the SMS app has permissions
-                int mode = appOps.checkOp(AppOpsManager.OP_WRITE_SMS, applicationData.mUid,
-                        applicationData.mPackageName);
-                if (mode != AppOpsManager.MODE_ALLOWED) {
-                    Rlog.e(LOG_TAG, applicationData.mPackageName + " lost OP_WRITE_SMS: " +
-                            (updateIfNeeded ? " (fixing)" : " (no permission to fix)"));
-                    if (updateIfNeeded) {
-                        appOps.setMode(AppOpsManager.OP_WRITE_SMS, applicationData.mUid,
-                                applicationData.mPackageName, AppOpsManager.MODE_ALLOWED);
-                    } else {
-                        // We can not return a package if permissions are not set up correctly
-                        applicationData = null;
-                    }
+                boolean appOpsFixed =
+                        tryFixExclusiveSmsAppops(context, applicationData, updateIfNeeded);
+                if (!appOpsFixed) {
+                    // We can not return a package if permissions are not set up correctly
+                    applicationData = null;
                 }
             }
 
             // We can only verify the phone and BT app's permissions from a privileged caller
-            if (updateIfNeeded) {
+            if (applicationData != null && updateIfNeeded) {
                 // Ensure this component is still configured as the preferred activity. Usually the
                 // current SMS app will already be the preferred activity - but checking whether or
                 // not this is true is just as expensive as reconfiguring the preferred activity so
                 // we just reconfigure every time.
-                PackageManager packageManager = context.getPackageManager();
-                configurePreferredActivity(packageManager, new ComponentName(
-                        applicationData.mPackageName, applicationData.mSendToClass),
-                        userId);
-                // Assign permission to special system apps
-                assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
-                        PHONE_PACKAGE_NAME);
-                assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
-                        BLUETOOTH_PACKAGE_NAME);
-                assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
-                        MMS_SERVICE_PACKAGE_NAME);
-                assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
-                        TELEPHONY_PROVIDER_PACKAGE_NAME);
-                // Give WRITE_SMS AppOps permission to UID 1001 which contains multiple
-                // apps, all of them should be able to write to telephony provider.
-                // This is to allow the proxy package permission check in telephony provider
-                // to pass.
-                assignWriteSmsPermissionToSystemUid(appOps, Process.PHONE_UID);
+                updateDefaultSmsApp(context, userId, applicationData);
             }
         }
         if (DEBUG_MULTIUSER) {
@@ -537,6 +522,56 @@
         return applicationData;
     }
 
+    private static void updateDefaultSmsApp(Context context, int userId,
+            SmsApplicationData applicationData) {
+        PackageManager packageManager = context.getPackageManager();
+        AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
+
+        // Configure this as the preferred activity for SENDTO sms/mms intents
+        configurePreferredActivity(packageManager, new ComponentName(
+                        applicationData.mPackageName, applicationData.mSendToClass),
+                userId);
+
+        // Assign permission to special system apps
+        assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
+                PHONE_PACKAGE_NAME);
+        assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
+                BLUETOOTH_PACKAGE_NAME);
+        assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
+                MMS_SERVICE_PACKAGE_NAME);
+        assignExclusiveSmsPermissionsToSystemApp(context, packageManager, appOps,
+                TELEPHONY_PROVIDER_PACKAGE_NAME);
+
+        // Give AppOps permission to UID 1001 which contains multiple
+        // apps, all of them should be able to write to telephony provider.
+        // This is to allow the proxy package permission check in telephony provider
+        // to pass.
+        for (int appop : DEFAULT_APP_EXCLUSIVE_APPOPS) {
+            appOps.setUidMode(appop, Process.PHONE_UID, AppOpsManager.MODE_ALLOWED);
+        }
+    }
+
+    private static boolean tryFixExclusiveSmsAppops(Context context,
+            SmsApplicationData applicationData, boolean updateIfNeeded) {
+        AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
+        for (int appOp : DEFAULT_APP_EXCLUSIVE_APPOPS) {
+            int mode = appOps.checkOp(appOp, applicationData.mUid,
+                    applicationData.mPackageName);
+            if (mode != AppOpsManager.MODE_ALLOWED) {
+                Rlog.e(LOG_TAG, applicationData.mPackageName + " lost "
+                        + AppOpsManager.modeToName(appOp) + ": "
+                        + (updateIfNeeded ? " (fixing)" : " (no permission to fix)"));
+                if (updateIfNeeded) {
+                    setExclusiveAppop(applicationData.mPackageName, appOps, appOp,
+                            AppOpsManager.MODE_ALLOWED, applicationData.mUid);
+                } else {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
     /**
      * Sets the specified package as the default SMS/MMS application. The caller of this method
      * needs to have permission to set AppOps and write to secure settings.
@@ -589,14 +624,13 @@
                 getApplicationForPackage(applications, oldPackageName) : null;
         SmsApplicationData applicationData = getApplicationForPackage(applications, packageName);
         if (applicationData != null) {
-            // Ignore OP_WRITE_SMS for the previously configured default SMS app.
+            // Ignore relevant appops for the previously configured default SMS app.
             AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
             if (oldPackageName != null) {
                 try {
-                    PackageInfo info = packageManager.getPackageInfoAsUser(oldPackageName,
-                            0, userId);
-                    appOps.setMode(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
-                            oldPackageName, AppOpsManager.MODE_IGNORED);
+                    int uid = packageManager.getPackageInfoAsUser(
+                            oldPackageName, 0, userId).applicationInfo.uid;
+                    setExclusiveAppops(oldPackageName, appOps, uid, AppOpsManager.MODE_DEFAULT);
                 } catch (NameNotFoundException e) {
                     Rlog.w(LOG_TAG, "Old SMS package not found: " + oldPackageName);
                 }
@@ -607,28 +641,11 @@
                     Settings.Secure.SMS_DEFAULT_APPLICATION, applicationData.mPackageName,
                     userId);
 
-            // Configure this as the preferred activity for SENDTO sms/mms intents
-            configurePreferredActivity(packageManager, new ComponentName(
-                    applicationData.mPackageName, applicationData.mSendToClass), userId);
+            // Allow relevant appops for the newly configured default SMS app.
+            setExclusiveAppops(applicationData.mPackageName, appOps, applicationData.mUid,
+                    AppOpsManager.MODE_ALLOWED);
 
-            // Allow OP_WRITE_SMS for the newly configured default SMS app.
-            appOps.setMode(AppOpsManager.OP_WRITE_SMS, applicationData.mUid,
-                    applicationData.mPackageName, AppOpsManager.MODE_ALLOWED);
-
-            // Assign permission to special system apps
-            assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
-                    PHONE_PACKAGE_NAME);
-            assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
-                    BLUETOOTH_PACKAGE_NAME);
-            assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
-                    MMS_SERVICE_PACKAGE_NAME);
-            assignWriteSmsPermissionToSystemApp(context, packageManager, appOps,
-                    TELEPHONY_PROVIDER_PACKAGE_NAME);
-            // Give WRITE_SMS AppOps permission to UID 1001 which contains multiple
-            // apps, all of them should be able to write to telephony provider.
-            // This is to allow the proxy package permission check in telephony provider
-            // to pass.
-            assignWriteSmsPermissionToSystemUid(appOps, Process.PHONE_UID);
+            updateDefaultSmsApp(context, userId, applicationData);
 
             if (DEBUG_MULTIUSER) {
                 Log.i(LOG_TAG, "setDefaultApplicationInternal oldAppData=" + oldAppData);
@@ -685,7 +702,7 @@
      * @param appOps The AppOps manager instance
      * @param packageName The package name of the system app
      */
-    private static void assignWriteSmsPermissionToSystemApp(Context context,
+    private static void assignExclusiveSmsPermissionsToSystemApp(Context context,
             PackageManager packageManager, AppOpsManager appOps, String packageName) {
         // First check package signature matches the caller's package signature.
         // Since this class is only used internally by the system, this check makes sure
@@ -701,8 +718,8 @@
                     packageName);
             if (mode != AppOpsManager.MODE_ALLOWED) {
                 Rlog.w(LOG_TAG, packageName + " does not have OP_WRITE_SMS:  (fixing)");
-                appOps.setMode(AppOpsManager.OP_WRITE_SMS, info.applicationInfo.uid,
-                        packageName, AppOpsManager.MODE_ALLOWED);
+                setExclusiveAppops(packageName, appOps, info.applicationInfo.uid,
+                        AppOpsManager.MODE_ALLOWED);
             }
         } catch (NameNotFoundException e) {
             // No whitelisted system app on this device
@@ -711,8 +728,19 @@
 
     }
 
-    private static void assignWriteSmsPermissionToSystemUid(AppOpsManager appOps, int uid) {
-        appOps.setUidMode(AppOpsManager.OP_WRITE_SMS, uid, AppOpsManager.MODE_ALLOWED);
+    private static void setExclusiveAppops(String pkg, AppOpsManager appOpsManager, int uid,
+            int mode) {
+        for (int appop : DEFAULT_APP_EXCLUSIVE_APPOPS) {
+            setExclusiveAppop(pkg, appOpsManager, appop, mode, uid);
+        }
+    }
+
+    private static void setExclusiveAppop(String pkg, AppOpsManager appOpsManager, int appop,
+            int mode, int uid) {
+        // IGNORED means user explicitly revoked permission in settings, so avoid overriding it.
+        if (appOpsManager.checkOpNoThrow(appop, uid, pkg) != AppOpsManager.MODE_IGNORED) {
+            appOpsManager.setUidMode(appop, uid, mode);
+        }
     }
 
     /**