Merge "Allow COPE admin to control screen configuration" into main
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 5b28f50..a075ac5 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -12749,6 +12749,10 @@
      * <li>{@link android.provider.Settings.System#SCREEN_OFF_TIMEOUT}</li>
      * </ul>
      * <p>
+     * Starting from Android {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}, a
+     * profile owner on an organization-owned device can call this method on the parent
+     * {@link DevicePolicyManager} instance returned by
+     * {@link #getParentProfileInstance(ComponentName)} to set system settings on the parent user.
      *
      * @see android.provider.Settings.System#SCREEN_OFF_TIMEOUT
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -12758,10 +12762,9 @@
      */
     public void setSystemSetting(@NonNull ComponentName admin,
             @NonNull @SystemSettingsWhitelist String setting, String value) {
-        throwIfParentInstance("setSystemSetting");
         if (mService != null) {
             try {
-                mService.setSystemSetting(admin, setting, value);
+                mService.setSystemSetting(admin, setting, value, mParentInstance);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index aea0246..d4589dc 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -316,7 +316,7 @@
     int getLockTaskFeatures(in ComponentName who, String callerPackageName);
 
     void setGlobalSetting(in ComponentName who, in String setting, in String value);
-    void setSystemSetting(in ComponentName who, in String setting, in String value);
+    void setSystemSetting(in ComponentName who, in String setting, in String value, boolean parent);
     void setSecureSetting(in ComponentName who, in String setting, in String value);
 
     void setConfiguredNetworksLockdownState(in ComponentName who, String callerPackageName, boolean lockdown);
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index c29ea6d..441d521 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -173,3 +173,10 @@
       purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+  name: "allow_screen_brightness_control_on_cope"
+  namespace: "enterprise"
+  description: "Allow COPE admin to control screen brightness and timeout."
+  bug: "323894620"
+}
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 1919137..73e7485 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -270,7 +270,7 @@
      * Special user restrictions that profile owner of an organization-owned managed profile can
      * set on the parent profile instance to apply them on the personal profile.
      */
-    private static final Set<String> PROFILE_OWNER_ORGANIZATION_OWNED_LOCAL_RESTRICTIONS =
+    private static final Set<String> PROFILE_OWNER_ORGANIZATION_OWNED_PARENT_LOCAL_RESTRICTIONS =
             Sets.newArraySet(
                     UserManager.DISALLOW_CONFIG_BLUETOOTH,
                     UserManager.DISALLOW_CONFIG_LOCATION,
@@ -293,7 +293,9 @@
                     UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
                     UserManager.DISALLOW_UNMUTE_MICROPHONE,
                     UserManager.DISALLOW_CONFIG_DEFAULT_APPS,
-                    UserManager.DISALLOW_ADD_PRIVATE_PROFILE
+                    UserManager.DISALLOW_ADD_PRIVATE_PROFILE,
+                    UserManager.DISALLOW_CONFIG_BRIGHTNESS,
+                    UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT
     );
 
     /**
@@ -536,7 +538,7 @@
     public static boolean canParentOfProfileOwnerOfOrganizationOwnedDeviceChange(
             String restriction) {
         return PROFILE_OWNER_ORGANIZATION_OWNED_PARENT_GLOBAL_RESTRICTIONS.contains(restriction)
-                || PROFILE_OWNER_ORGANIZATION_OWNED_LOCAL_RESTRICTIONS.contains(restriction);
+                || PROFILE_OWNER_ORGANIZATION_OWNED_PARENT_LOCAL_RESTRICTIONS.contains(restriction);
     }
 
     /**
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index cb87f7e..cebd6d0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -14703,12 +14703,15 @@
     }
 
     @Override
-    public void setSystemSetting(ComponentName who, String setting, String value) {
+    public void setSystemSetting(ComponentName who, String setting, String value, boolean parent) {
         Objects.requireNonNull(who, "ComponentName is null");
         Preconditions.checkStringNotEmpty(setting, "String setting is null or empty");
         final CallerIdentity caller = getCallerIdentity(who);
         Preconditions.checkCallAuthorization(
                 isProfileOwner(caller) || isDefaultDeviceOwner(caller));
+        if (Flags.allowScreenBrightnessControlOnCope() && parent) {
+            Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller));
+        }
         checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_SYSTEM_SETTING);
 
         synchronized (getLockObject()) {
@@ -14716,9 +14719,14 @@
                 throw new SecurityException(String.format(
                         "Permission denial: device owners cannot update %1$s", setting));
             }
-
+            int affectedUser;
+            if (Flags.allowScreenBrightnessControlOnCope() && parent) {
+                affectedUser = getProfileParentId(caller.getUserId());
+            } else {
+                affectedUser = caller.getUserId();
+            }
             mInjector.binderWithCleanCallingIdentity(() ->
-                    mInjector.settingsSystemPutStringForUser(setting, value, caller.getUserId()));
+                    mInjector.settingsSystemPutStringForUser(setting, value, affectedUser));
         }
     }