From 696adad6149192bd0e322c8a21fba4010cc4ce29 Mon Sep 17 00:00:00 2001 From: Yasin Kilicdere Date: Wed, 9 Nov 2022 16:24:07 +0000 Subject: [PATCH] Make ImageWallpaper handle WallpaperService messages on its own thread When a wallpaper is called to be attached, IWallpaperEngineWrapper sends a DO_ATTACH message to be handled on the main looper of the wallpaper implementation. In the case of ImageWallpaper, it is currently systemui. When system ui is occupied by other tasks, reception of this message is delayed. And this decreases the performance of switching between Android users in case the target user has an ImageWallpaper. This CL makes sure these service messages are handled on ImageWallpaper's own thread, and the drawing of the wallpaper is not delayed. Bug: 242969351 Test: Manual comparison of perfetto traces Change-Id: Ia911f1b879a20658d0b71e3486c079cbbcb081c8 --- .../service/wallpaper/WallpaperService.java | 15 +++++++++++++-- .../systemui/wallpapers/ImageWallpaper.java | 10 ++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 104570d03b42d..0fc07556df227 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -2149,6 +2149,17 @@ public abstract class WallpaperService extends Service { } } + /** + * Returns a Looper which messages such as {@link WallpaperService#DO_ATTACH}, + * {@link WallpaperService#DO_DETACH} etc. are sent to. + * By default, returns the process's main looper. + * @hide + */ + @NonNull + public Looper onProvideEngineLooper() { + return super.getMainLooper(); + } + private boolean isValid(RectF area) { if (area == null) return false; boolean valid = area.bottom > area.top && area.left < area.right @@ -2180,12 +2191,12 @@ public abstract class WallpaperService extends Service { Engine mEngine; - IWallpaperEngineWrapper(WallpaperService context, + IWallpaperEngineWrapper(WallpaperService service, IWallpaperConnection conn, IBinder windowToken, int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding, int displayId) { mWallpaperManager = getSystemService(WallpaperManager.class); - mCaller = new HandlerCaller(context, context.getMainLooper(), this, true); + mCaller = new HandlerCaller(service, service.onProvideEngineLooper(), this, true); mConnection = conn; mWindowToken = windowToken; mWindowType = windowType; diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java index ad97ef4a79bc1..5df4a5b54ccc6 100644 --- a/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java @@ -29,6 +29,7 @@ import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; import android.os.Handler; import android.os.HandlerThread; +import android.os.Looper; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; @@ -101,6 +102,15 @@ public class ImageWallpaper extends WallpaperService { mMainExecutor = mainExecutor; } + @Override + public Looper onProvideEngineLooper() { + // Receive messages on mWorker thread instead of SystemUI's main handler. + // All other wallpapers have their own process, and they can receive messages on their own + // main handler without any delay. But since ImageWallpaper lives in SystemUI, performance + // of the image wallpaper could be negatively affected when SystemUI's main handler is busy. + return mWorker != null ? mWorker.getLooper() : super.onProvideEngineLooper(); + } + @Override public void onCreate() { super.onCreate();