You still have to re-call {@code setDrawables} even if you only make changes to the
* content of the resource with ID
* {@link DevicePolicyDrawableResource#getCallingPackageResourceId()} as the content might be
* cached and would need updating.
@@ -14437,8 +14470,10 @@ public class DevicePolicyManager {
* {@link DevicePolicyResources.Drawable.Source} will return the default drawable from
* {@code defaultDrawableLoader}.
*
- * @param drawableIds The list of IDs to remove
- * the updated resources for.
+ * Sends a broadcast with action {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to
+ * registered receivers when a resource has been reset successfully.
+ *
+ * @param drawableIds The list of IDs to remove.
*
* @throws IllegalArgumentException if IDs are not defined in
* {@link DevicePolicyResources.Drawable}
@@ -14470,6 +14505,9 @@ public class DevicePolicyManager {
* set a different value use
* {@link #getDrawableForDensity(int, int, int, Callable)}.
*
+ *
Callers should register for {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get
+ * notified when a resource has been updated.
+ *
*
Note that each call to this API loads the resource from the package that called
* {@code setDrawables} to set the updated resource.
*
@@ -14492,6 +14530,9 @@ public class DevicePolicyManager {
* could result in returning a different drawable than {@link #getDrawable(int, int, Callable)}
* if an override was set for that specific source.
*
+ *
Callers should register for {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get
+ * notified when a resource has been updated.
+ *
* @param drawableId The drawable ID to get the updated resource for.
* @param drawableStyle The drawable style to use.
* @param drawableSource The source for the caller.
@@ -14536,6 +14577,9 @@ public class DevicePolicyManager {
* Similar to {@link #getDrawable(int, int, Callable)}, but also accepts
* {@code density}. See {@link Resources#getDrawableForDensity(int, int, Resources.Theme)}.
*
+ *
Callers should register for {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get
+ * notified when a resource has been updated.
+ *
* @param drawableId The drawable ID to get the updated resource for.
* @param drawableStyle The drawable style to use.
* @param density The desired screen density indicated by the resource as
@@ -14562,6 +14606,9 @@ public class DevicePolicyManager {
* Similar to {@link #getDrawable(int, int, int, Callable)}, but also accepts
* {@code density}. See {@link Resources#getDrawableForDensity(int, int, Resources.Theme)}.
*
+ *
Callers should register for {@link #ACTION_DEVICE_POLICY_RESOURCE_UPDATED} to get
+ * notified when a resource has been updated.
+ *
* @param drawableId The drawable ID to get the updated resource for.
* @param drawableStyle The drawable style to use.
* @param drawableSource The source for the caller.
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d6bbe71586fa0..d0b9f880591d9 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -716,6 +716,7 @@
+
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java
index 20412e16b5afe..5342294028885 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceManagementResourcesProvider.java
@@ -83,7 +83,11 @@ class DeviceManagementResourcesProvider {
mInjector = requireNonNull(injector);
}
- void updateDrawables(@NonNull List drawables) {
+ /**
+ * Returns {@code false} if no resources were updated.
+ */
+ boolean updateDrawables(@NonNull List drawables) {
+ boolean updated = false;
for (int i = 0; i < drawables.size(); i++) {
int drawableId = drawables.get(i).getDrawableId();
int drawableStyle = drawables.get(i).getDrawableStyle();
@@ -93,40 +97,46 @@ class DeviceManagementResourcesProvider {
Objects.requireNonNull(resource, "ParcelableResource must be provided.");
if (drawableSource == DevicePolicyResources.Drawable.Source.UNDEFINED) {
- updateDrawable(drawableId, drawableStyle, resource);
+ updated |= updateDrawable(drawableId, drawableStyle, resource);
} else {
- updateDrawableForSource(drawableId, drawableSource, resource);
+ updated |= updateDrawableForSource(drawableId, drawableSource, resource);
}
}
- if (!drawables.isEmpty()) {
- synchronized (mLock) {
- write();
- }
+ if (!updated) {
+ return false;
+ }
+ synchronized (mLock) {
+ write();
+ return true;
}
}
- private void updateDrawable(
+ private boolean updateDrawable(
int drawableId, int drawableStyle, ParcelableResource updatableResource) {
if (!UPDATABLE_DRAWABLE_IDS.contains(drawableId)) {
throw new IllegalArgumentException(
- "Can't update drawable resource, invalid drawable "
- + "id " + drawableId);
+ "Can't update drawable resource, invalid drawable " + "id " + drawableId);
}
if (!UPDATABLE_DRAWABLE_STYLES.contains(drawableStyle)) {
throw new IllegalArgumentException(
- "Can't update drawable resource, invalid style id "
- + drawableStyle);
+ "Can't update drawable resource, invalid style id " + drawableStyle);
}
synchronized (mLock) {
if (!mUpdatedDrawablesForStyle.containsKey(drawableId)) {
mUpdatedDrawablesForStyle.put(drawableId, new HashMap<>());
}
+ ParcelableResource current = mUpdatedDrawablesForStyle.get(drawableId).get(
+ drawableStyle);
+ if (updatableResource.equals(current)) {
+ return false;
+ }
mUpdatedDrawablesForStyle.get(drawableId).put(drawableStyle, updatableResource);
+ return true;
}
}
// TODO(b/214576716): change this to respect style
- private void updateDrawableForSource(
+ private boolean updateDrawableForSource(
int drawableId, int drawableSource, ParcelableResource updatableResource) {
if (!UPDATABLE_DRAWABLE_IDS.contains(drawableId)) {
throw new IllegalArgumentException("Can't update drawable resource, invalid drawable "
@@ -140,21 +150,32 @@ class DeviceManagementResourcesProvider {
if (!mUpdatedDrawablesForSource.containsKey(drawableId)) {
mUpdatedDrawablesForSource.put(drawableId, new HashMap<>());
}
- mUpdatedDrawablesForSource.get(drawableId).put(
- drawableSource, updatableResource);
+ ParcelableResource current = mUpdatedDrawablesForSource.get(drawableId).get(
+ drawableSource);
+ if (updatableResource.equals(current)) {
+ return false;
+ }
+ mUpdatedDrawablesForSource.get(drawableId).put(drawableSource, updatableResource);
+ return true;
}
}
- void removeDrawables(@NonNull int[] drawableIds) {
+ /**
+ * Returns {@code false} if no resources were removed.
+ */
+ boolean removeDrawables(@NonNull int[] drawableIds) {
synchronized (mLock) {
+ boolean removed = false;
for (int i = 0; i < drawableIds.length; i++) {
int drawableId = drawableIds[i];
- mUpdatedDrawablesForStyle.remove(drawableId);
- mUpdatedDrawablesForSource.remove(drawableId);
+ removed |= mUpdatedDrawablesForStyle.remove(drawableId) != null
+ || mUpdatedDrawablesForSource.remove(drawableId) != null;
}
- if (drawableIds.length != 0) {
- write();
+ if (!removed) {
+ return false;
}
+ write();
+ return true;
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index af69be8680469..0595b7397a42d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -26,6 +26,7 @@ import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.admin.DeviceAdminReceiver.ACTION_COMPLIANCE_ACKNOWLEDGEMENT_REQUIRED;
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE;
+import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
@@ -56,6 +57,8 @@ import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
import static android.app.admin.DevicePolicyManager.DELEGATION_SECURITY_LOGGING;
import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
+import static android.app.admin.DevicePolicyManager.EXTRA_RESOURCE_ID;
+import static android.app.admin.DevicePolicyManager.EXTRA_RESOURCE_TYPE_DRAWABLE;
import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO;
import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI;
import static android.app.admin.DevicePolicyManager.ID_TYPE_INDIVIDUAL_ATTESTATION;
@@ -17976,12 +17979,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(drawables, "drawables must be provided.");
- // TODO(b/203548565): add new broadcast to indicate a resource has changed
- mInjector.binderWithCleanCallingIdentity(() ->
- mDeviceManagementResourcesProvider.updateDrawables(drawables));
+ mInjector.binderWithCleanCallingIdentity(() -> {
+ if (mDeviceManagementResourcesProvider.updateDrawables(drawables)) {
+ sendDrawableUpdatedBroadcast(
+ drawables.stream().mapToInt(d -> d.getDrawableId()).toArray());
+ }
+ });
}
-
@Override
public void resetDrawables(@NonNull int[] drawableIds) {
Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
@@ -17989,16 +17994,31 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(drawableIds, "drawableIds must be provided.");
- // TODO(b/203548565): add new broadcast to indicate a resource has changed
- mInjector.binderWithCleanCallingIdentity(() ->
- mDeviceManagementResourcesProvider.removeDrawables(drawableIds));
+ mInjector.binderWithCleanCallingIdentity(() -> {
+ if (mDeviceManagementResourcesProvider.removeDrawables(drawableIds)) {
+ sendDrawableUpdatedBroadcast(drawableIds);
+ }
+ });
}
@Override
- public ParcelableResource getDrawable(
- int drawableId, int drawableStyle, int drawableSource) {
+ public ParcelableResource getDrawable(int drawableId, int drawableStyle, int drawableSource) {
return mInjector.binderWithCleanCallingIdentity(() ->
mDeviceManagementResourcesProvider.getDrawable(
drawableId, drawableStyle, drawableSource));
}
+
+ private void sendDrawableUpdatedBroadcast(int[] drawableIds) {
+ final Intent intent = new Intent(ACTION_DEVICE_POLICY_RESOURCE_UPDATED);
+ intent.putExtra(EXTRA_RESOURCE_ID, drawableIds);
+ intent.putExtra(EXTRA_RESOURCE_TYPE_DRAWABLE, /* value= */ true);
+ intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+
+ List users = mUserManager.getAliveUsers();
+ for (int i = 0; i < users.size(); i++) {
+ UserHandle user = users.get(i).getUserHandle();
+ mContext.sendBroadcastAsUser(intent, user);
+ }
+ }
}