Merge "Unfocus wallpaper updated with permission" into main
diff --git a/core/api/current.txt b/core/api/current.txt
index 36c2f01..3392d25 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -7662,7 +7662,7 @@
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_EXTERNAL_STORAGE, "android.permission.READ_WALLPAPER_INTERNAL"}) public android.graphics.drawable.Drawable peekFastDrawable();
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_EXTERNAL_STORAGE, "android.permission.READ_WALLPAPER_INTERNAL"}) public android.graphics.drawable.Drawable peekFastDrawable(int);
     method public void removeOnColorsChangedListener(@NonNull android.app.WallpaperManager.OnColorsChangedListener);
-    method public void sendWallpaperCommand(android.os.IBinder, String, int, int, int, android.os.Bundle);
+    method @RequiresPermission(value="android.permission.ALWAYS_UPDATE_WALLPAPER", conditional=true) public void sendWallpaperCommand(android.os.IBinder, String, int, int, int, android.os.Bundle);
     method @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.SET_WALLPAPER) public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean, int) throws java.io.IOException;
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 0185080..a02fd84 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -36,6 +36,7 @@
     field public static final String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK";
     field public static final String ALLOW_PLACE_IN_MULTI_PANE_SETTINGS = "android.permission.ALLOW_PLACE_IN_MULTI_PANE_SETTINGS";
     field public static final String ALLOW_SLIPPERY_TOUCHES = "android.permission.ALLOW_SLIPPERY_TOUCHES";
+    field public static final String ALWAYS_UPDATE_WALLPAPER = "android.permission.ALWAYS_UPDATE_WALLPAPER";
     field public static final String AMBIENT_WALLPAPER = "android.permission.AMBIENT_WALLPAPER";
     field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS";
     field public static final String ASSOCIATE_COMPANION_DEVICES = "android.permission.ASSOCIATE_COMPANION_DEVICES";
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 5d7993d..c31aa01 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -2670,6 +2670,8 @@
      * @param z Arbitrary integer argument based on command.
      * @param extras Optional additional information for the command, or null.
      */
+    @RequiresPermission(value = android.Manifest.permission.ALWAYS_UPDATE_WALLPAPER,
+            conditional = true)
     public void sendWallpaperCommand(IBinder windowToken, String action,
             int x, int y, int z, Bundle extras) {
         try {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b29a4e6..86cf80e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4032,6 +4032,13 @@
     <permission android:name="android.permission.READ_WALLPAPER_INTERNAL"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allow apps to always update wallpaper by sending data.
+        @SystemApi
+        @hide
+    -->
+    <permission android:name="android.permission.ALWAYS_UPDATE_WALLPAPER"
+        android:protectionLevel="internal|role" />
+
     <!-- ===================================================== -->
     <!-- Permissions for changing the system clock / time zone -->
     <!-- ===================================================== -->
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 215cc8e..323f65f 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -849,11 +849,15 @@
     <!-- Permission required for accessing all content provider mime types -->
     <uses-permission android:name="android.permission.GET_ANY_PROVIDER_TYPE" />
 
+    <!-- Permission required for CTS test - CtsWallpaperTestCases -->
+    <uses-permission android:name="android.permission.ALWAYS_UPDATE_WALLPAPER" />
+
     <application
         android:label="@string/app_label"
         android:theme="@android:style/Theme.DeviceDefault.DayNight"
         android:defaultToDeviceProtectedStorage="true"
         android:directBootAware="true">
+
         <provider
             android:name="androidx.core.content.FileProvider"
             android:authorities="com.android.shell"
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index b49c5fb..1845ae8 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.Manifest.permission.ALWAYS_UPDATE_WALLPAPER;
 import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS;
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
@@ -112,6 +113,7 @@
     final boolean mCanCreateSystemApplicationOverlay;
     final boolean mCanHideNonSystemOverlayWindows;
     final boolean mCanSetUnrestrictedGestureExclusion;
+    final boolean mCanAlwaysUpdateWallpaper;
     private AlertWindowNotification mAlertWindowNotification;
     private boolean mShowingAlertWindowNotificationAllowed;
     private boolean mClientDead = false;
@@ -144,6 +146,9 @@
         mCanSetUnrestrictedGestureExclusion =
                 service.mContext.checkCallingOrSelfPermission(SET_UNRESTRICTED_GESTURE_EXCLUSION)
                         == PERMISSION_GRANTED;
+        mCanAlwaysUpdateWallpaper =
+                service.mContext.checkCallingOrSelfPermission(ALWAYS_UPDATE_WALLPAPER)
+                        == PERMISSION_GRANTED;
         mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications;
         mDragDropController = mService.mDragDropController;
         StringBuilder sb = new StringBuilder();
@@ -621,8 +626,15 @@
             final long ident = Binder.clearCallingIdentity();
             try {
                 final WindowState windowState = mService.windowForClientLocked(this, window, true);
-                return windowState.getDisplayContent().mWallpaperController
-                        .sendWindowWallpaperCommand(windowState, action, x, y, z, extras, sync);
+                WallpaperController wallpaperController =
+                        windowState.getDisplayContent().mWallpaperController;
+                if (mCanAlwaysUpdateWallpaper
+                        || windowState == wallpaperController.getWallpaperTarget()
+                        || windowState == wallpaperController.getPrevWallpaperTarget()) {
+                    return wallpaperController.sendWindowWallpaperCommandUnchecked(
+                            windowState, action, x, y, z, extras, sync);
+                }
+                return null;
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index af770e2..7e5dabb 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -298,6 +298,10 @@
         return mWallpaperTarget;
     }
 
+    WindowState getPrevWallpaperTarget() {
+        return mPrevWallpaperTarget;
+    }
+
     boolean isWallpaperTarget(WindowState win) {
         return win == mWallpaperTarget;
     }
@@ -565,12 +569,10 @@
         }
     }
 
-    Bundle sendWindowWallpaperCommand(
-            WindowState window, String action, int x, int y, int z, Bundle extras, boolean sync) {
-        if (window == mWallpaperTarget || window == mPrevWallpaperTarget) {
-            sendWindowWallpaperCommand(action, x, y, z, extras, sync);
-        }
-
+    Bundle sendWindowWallpaperCommandUnchecked(
+            WindowState window, String action, int x, int y, int z,
+            Bundle extras, boolean sync) {
+        sendWindowWallpaperCommand(action, x, y, z, extras, sync);
         return null;
     }