Control revoke-on-upgrade behavior for loc perm

By default: Revoke on upgrade, but can be disabled by setting the
location_permissions_upgrade_to_Q_mode to anything but 0.

Fixes: 127285709
Test: Upgraded from P to Q with and without
      location_permissions_upgrade_to_Q_mode set
      atest --test-mapping frameworks/base/core/java/android/provider:presubmit
Change-Id: I4dd1772e78f46c881a5f747fcf61583beec2d6a2
diff --git a/api/system-current.txt b/api/system-current.txt
index 70b9618..9ef2c4b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6116,6 +6116,7 @@
     field public static final String LAST_SETUP_SHOWN = "last_setup_shown";
     field public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS = "location_access_check_delay_millis";
     field public static final String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS = "location_access_check_interval_millis";
+    field public static final String LOCATION_PERMISSIONS_UPGRADE_TO_Q_MODE = "location_permissions_upgrade_to_q_mode";
     field public static final String LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS = "lock_screen_allow_private_notifications";
     field public static final String LOCK_SCREEN_SHOW_NOTIFICATIONS = "lock_screen_show_notifications";
     field public static final String MANUAL_RINGER_TOGGLE_COUNT = "manual_ringer_toggle_count";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f2bb87d..33f6061 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8559,6 +8559,19 @@
         public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS =
                 "location_access_check_delay_millis";
 
+        /**
+         * What should happen to the location permissions when upgraded to Android Q.
+         *
+         * <ul>
+         *     <li>0/unset == revoke permissions</li>
+         *     <li>anything else == Don't do anything</li>
+         * </ul>
+         *
+         * @hide
+         */
+        @SystemApi
+        public static final String LOCATION_PERMISSIONS_UPGRADE_TO_Q_MODE =
+                "location_permissions_upgrade_to_q_mode";
 
         /**
          * Comma separated list of enabled overlay packages for all android.theme.customization.*
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 6360a5f..08286a1 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -235,6 +235,10 @@
         optional SettingProto mode = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
         // The App or module that changes the location mode.
         optional SettingProto changer = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+        // What should happen to the location permissions when upgraded to Android Q.
+        // 0 == revoke permissions. Anything else == do nothing.
+        optional SettingProto permissions_upgrade_to_q_mode = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
     optional Location location = 31;
 
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index ad1403d..9d34b11 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -643,6 +643,7 @@
                  Settings.Secure.LAST_SETUP_SHOWN,
                  Settings.Secure.LOCATION_CHANGER,
                  Settings.Secure.LOCATION_MODE,
+                 Settings.Secure.LOCATION_PERMISSIONS_UPGRADE_TO_Q_MODE,
                  Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT, // Candidate?
                  Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
                  Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 0f8fd92..65e2bc1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1974,6 +1974,9 @@
         dumpSetting(s, p,
                 Settings.Secure.LOCATION_CHANGER,
                 SecureSettingsProto.Location.CHANGER);
+        dumpSetting(s, p,
+                Settings.Secure.LOCATION_PERMISSIONS_UPGRADE_TO_Q_MODE,
+                SecureSettingsProto.Location.PERMISSIONS_UPGRADE_TO_Q_MODE);
         p.end(locationToken);
 
         final long locationAccessCheckToken = p.start(SecureSettingsProto.LOCATION_ACCESS_CHECK);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 303021e..46739fb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2945,7 +2945,7 @@
                         + mSdkVersion + "; regranting permissions for internal storage");
             }
             mPermissionManager.updateAllPermissions(
-                    StorageManager.UUID_PRIVATE_INTERNAL, ver.sdkVersion, mPackages.values(),
+                    StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, false, mPackages.values(),
                     mPermissionCallback);
             ver.sdkVersion = mSdkVersion;
 
@@ -5382,7 +5382,7 @@
 
         synchronized (mPackages) {
             mPermissionManager.updateAllPermissions(
-                    StorageManager.UUID_PRIVATE_INTERNAL, Build.VERSION.SDK_INT, mPackages.values(),
+                    StorageManager.UUID_PRIVATE_INTERNAL, false, false, mPackages.values(),
                     mPermissionCallback);
             for (int userId : UserManagerService.getInstance().getUserIds()) {
                 final int packageCount = mPackages.size();
@@ -20689,8 +20689,8 @@
         // try optimizing this.
         synchronized (mPackages) {
             mPermissionManager.updateAllPermissions(
-                    StorageManager.UUID_PRIVATE_INTERNAL, Build.VERSION.SDK_INT, mPackages.values(),
-                    mPermissionCallback);
+                    StorageManager.UUID_PRIVATE_INTERNAL, false, mIsPreQUpgrade,
+                    mPackages.values(), mPermissionCallback);
         }
 
         // Watch for external volumes that come and go over time
@@ -21680,8 +21680,8 @@
                 logCriticalInfo(Log.INFO, "Platform changed from " + ver.sdkVersion + " to "
                         + mSdkVersion + "; regranting permissions for " + volumeUuid);
             }
-            mPermissionManager.updateAllPermissions(volumeUuid, ver.sdkVersion, mPackages.values(),
-                    mPermissionCallback);
+            mPermissionManager.updateAllPermissions(volumeUuid, sdkUpdated, false,
+                    mPackages.values(), mPermissionCallback);
 
             // Yay, everything is now upgraded
             ver.forceCurrent();
@@ -22680,7 +22680,7 @@
         synchronized(mPackages) {
             // NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG
             mPermissionManager.updateAllPermissions(
-                    StorageManager.UUID_PRIVATE_INTERNAL, 0, mPackages.values(),
+                    StorageManager.UUID_PRIVATE_INTERNAL, true, false, mPackages.values(),
                     mPermissionCallback);
         }
     }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 3546f43..ac7338e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -74,6 +74,7 @@
 import android.permission.PermissionControllerManager;
 import android.permission.PermissionManager;
 import android.permission.PermissionManagerInternal;
+import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -2272,17 +2273,16 @@
         }
     }
 
-    private void updateAllPermissions(String volumeUuid, int oldSdkVersion,
-            Collection<PackageParser.Package> allPackages, PermissionCallback callback) {
-        boolean sdkUpdated = oldSdkVersion < Build.VERSION.SDK_INT;
-
+    private void updateAllPermissions(String volumeUuid, boolean sdkUpdated,
+            boolean updatePermissionsOnPreQUpdate, Collection<PackageParser.Package> allPackages,
+            PermissionCallback callback) {
         final int flags = UPDATE_PERMISSIONS_ALL |
                 (sdkUpdated
                         ? UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL
                         : 0);
         updatePermissions(null, null, volumeUuid, flags, allPackages, callback);
 
-        if (oldSdkVersion < Build.VERSION_CODES.Q) {
+        if (updatePermissionsOnPreQUpdate) {
             final int[] userIds = UserManagerService.getInstance().getUserIds();
 
             for (PackageParser.Package pkg : allPackages) {
@@ -2301,6 +2301,12 @@
                     final BasePermission bp = mSettings.getPermissionLocked(permName);
 
                     for (int userId : userIds) {
+                        if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                                Settings.Secure.LOCATION_PERMISSIONS_UPGRADE_TO_Q_MODE, 0, userId)
+                                != 0) {
+                            continue;
+                        }
+
                         final PermissionState permState = permsState.getRuntimePermissionState(
                                 permName, userId);
 
@@ -2777,10 +2783,11 @@
                     packageName, pkg, replaceGrant, allPackages, callback);
         }
         @Override
-        public void updateAllPermissions(String volumeUuid, int oldSdkVersion,
-                Collection<PackageParser.Package> allPackages, PermissionCallback callback) {
+        public void updateAllPermissions(String volumeUuid, boolean sdkUpdated,
+                boolean updatePermissionsOnPreQUpdate, Collection<PackageParser.Package> allPackages,
+                PermissionCallback callback) {
             PermissionManagerService.this.updateAllPermissions(
-                    volumeUuid, oldSdkVersion, allPackages, callback);
+                    volumeUuid, sdkUpdated, updatePermissionsOnPreQUpdate, allPackages, callback);
         }
         @Override
         public String[] getAppOpPermissionPackages(String permName) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 45fcf91..6c09fa0 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -83,7 +83,8 @@
     public abstract void updatePermissions(@Nullable String packageName,
             @Nullable PackageParser.Package pkg, boolean replaceGrant,
             @NonNull Collection<PackageParser.Package> allPacakges, PermissionCallback callback);
-    public abstract void updateAllPermissions(@Nullable String volumeUuid, int oldSdkVersion,
+    public abstract void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdate,
+            boolean updatePermissionsOnPreQUpdate,
             @NonNull Collection<PackageParser.Package> allPacakges, PermissionCallback callback);
 
     /**