diff options
5 files changed, 155 insertions, 60 deletions
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl index 3a2038d40952..666f7218a4f2 100644 --- a/core/java/android/app/IWallpaperManager.aidl +++ b/core/java/android/app/IWallpaperManager.aidl @@ -142,19 +142,20 @@ interface IWallpaperManager { * * @param which either {@link WallpaperManager#FLAG_LOCK} * or {@link WallpaperManager#FLAG_SYSTEM} + * @param displayId Which display is interested * @return colors of chosen wallpaper */ - WallpaperColors getWallpaperColors(int which, int userId); + WallpaperColors getWallpaperColors(int which, int userId, int displayId); /** - * Register a callback to receive color updates + * Register a callback to receive color updates from a display */ - void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId); + void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId, int displayId); /** - * Unregister a callback that was receiving color updates + * Unregister a callback that was receiving color updates from a display */ - void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId); + void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId, int displayId); /** * Called from SystemUI when it shows the AoD UI. diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 27ae0b0314d0..a929fe0f688e 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -307,13 +307,14 @@ public class WallpaperManager { * @param callback Listener * @param handler Thread to call it from. Main thread if null. * @param userId Owner of the wallpaper or UserHandle.USER_ALL + * @param displayId Caller comes from which display */ public void addOnColorsChangedListener(@NonNull OnColorsChangedListener callback, - @Nullable Handler handler, int userId) { + @Nullable Handler handler, int userId, int displayId) { synchronized (this) { if (!mColorCallbackRegistered) { try { - mService.registerWallpaperColorsCallback(this, userId); + mService.registerWallpaperColorsCallback(this, userId, displayId); mColorCallbackRegistered = true; } catch (RemoteException e) { // Failed, service is gone @@ -329,16 +330,17 @@ public class WallpaperManager { * * @param callback listener * @param userId Owner of the wallpaper or UserHandle.USER_ALL + * @param displayId Which display is interested */ public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener callback, - int userId) { + int userId, int displayId) { synchronized (this) { mColorListeners.removeIf(pair -> pair.first == callback); if (mColorListeners.size() == 0 && mColorCallbackRegistered) { mColorCallbackRegistered = false; try { - mService.unregisterWallpaperColorsCallback(this, userId); + mService.unregisterWallpaperColorsCallback(this, userId, displayId); } catch (RemoteException e) { // Failed, service is gone Log.w(TAG, "Can't unregister color updates", e); @@ -370,14 +372,14 @@ public class WallpaperManager { } } - WallpaperColors getWallpaperColors(int which, int userId) { + WallpaperColors getWallpaperColors(int which, int userId, int displayId) { if (which != FLAG_LOCK && which != FLAG_SYSTEM) { throw new IllegalArgumentException( "Must request colors for exactly one kind of wallpaper"); } try { - return mService.getWallpaperColors(which, userId); + return mService.getWallpaperColors(which, userId, displayId); } catch (RemoteException e) { // Can't get colors, connection lost. } @@ -894,7 +896,7 @@ public class WallpaperManager { @UnsupportedAppUsage public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener, @NonNull Handler handler, int userId) { - sGlobals.addOnColorsChangedListener(listener, handler, userId); + sGlobals.addOnColorsChangedListener(listener, handler, userId, mContext.getDisplayId()); } /** @@ -913,7 +915,7 @@ public class WallpaperManager { */ public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener callback, int userId) { - sGlobals.removeOnColorsChangedListener(callback, userId); + sGlobals.removeOnColorsChangedListener(callback, userId, mContext.getDisplayId()); } /** @@ -947,7 +949,7 @@ public class WallpaperManager { */ @UnsupportedAppUsage public @Nullable WallpaperColors getWallpaperColors(int which, int userId) { - return sGlobals.getWallpaperColors(which, userId); + return sGlobals.getWallpaperColors(which, userId, mContext.getDisplayId()); } /** diff --git a/core/java/android/service/wallpaper/IWallpaperConnection.aidl b/core/java/android/service/wallpaper/IWallpaperConnection.aidl index a976d0e40423..f334d9d3e874 100644 --- a/core/java/android/service/wallpaper/IWallpaperConnection.aidl +++ b/core/java/android/service/wallpaper/IWallpaperConnection.aidl @@ -27,5 +27,5 @@ interface IWallpaperConnection { void attachEngine(IWallpaperEngine engine, int displayId); void engineShown(IWallpaperEngine engine); ParcelFileDescriptor setWallpaper(String name); - void onWallpaperColorsChanged(in WallpaperColors colors); + void onWallpaperColorsChanged(in WallpaperColors colors, int displayId); } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 9079502fa6b2..984846e33b1d 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -645,7 +645,7 @@ public abstract class WallpaperService extends Service { try { final WallpaperColors newColors = onComputeColors(); if (mConnection != null) { - mConnection.onWallpaperColorsChanged(newColors); + mConnection.onWallpaperColorsChanged(newColors, mDisplay.getDisplayId()); } else { Log.w(TAG, "Can't notify system because wallpaper connection " + "was not established."); @@ -1473,7 +1473,7 @@ public abstract class WallpaperService extends Service { break; } try { - mConnection.onWallpaperColorsChanged(mEngine.onComputeColors()); + mConnection.onWallpaperColorsChanged(mEngine.onComputeColors(), mDisplayId); } catch (RemoteException e) { // Connection went away, nothing to do in here. } diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index f00877030145..01bff07d1bb0 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -350,12 +350,34 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } private void notifyWallpaperColorsChanged(@NonNull WallpaperData wallpaper, int which) { + if (wallpaper.connection != null) { + wallpaper.connection.forEachDisplayConnector(connector -> { + notifyWallpaperColorsChangedOnDisplay(wallpaper, which, connector.mDisplayId); + }); + } else { // Lock wallpaper does not have WallpaperConnection. + notifyWallpaperColorsChangedOnDisplay(wallpaper, which, DEFAULT_DISPLAY); + } + } + + private RemoteCallbackList<IWallpaperManagerCallback> getWallpaperCallbacks(int userId, + int displayId) { + RemoteCallbackList<IWallpaperManagerCallback> listeners = null; + final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> displayListeners = + mColorsChangedListeners.get(userId); + if (displayListeners != null) { + listeners = displayListeners.get(displayId); + } + return listeners; + } + + private void notifyWallpaperColorsChangedOnDisplay(@NonNull WallpaperData wallpaper, int which, + int displayId) { boolean needsExtraction; synchronized (mLock) { final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners = - mColorsChangedListeners.get(wallpaper.userId); + getWallpaperCallbacks(wallpaper.userId, displayId); final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners = - mColorsChangedListeners.get(UserHandle.USER_ALL); + getWallpaperCallbacks(UserHandle.USER_ALL, displayId); // No-op until someone is listening to it. if (emptyCallbackList(currentUserColorListeners) && emptyCallbackList(userAllColorListeners)) { @@ -363,7 +385,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } if (DEBUG) { - Slog.v(TAG, "notifyWallpaperColorsChanged " + which); + Slog.v(TAG, "notifyWallpaperColorsChangedOnDisplay " + which); } needsExtraction = wallpaper.primaryColors == null; @@ -371,7 +393,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub // Let's notify the current values, it's fine if it's null, it just means // that we don't know yet. - notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId); + notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId, displayId); if (needsExtraction) { extractColors(wallpaper); @@ -381,7 +403,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub return; } } - notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId); + notifyColorListeners(wallpaper.primaryColors, which, wallpaper.userId, displayId); } } @@ -390,14 +412,14 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } private void notifyColorListeners(@NonNull WallpaperColors wallpaperColors, int which, - int userId) { + int userId, int displayId) { final IWallpaperManagerCallback keyguardListener; final ArrayList<IWallpaperManagerCallback> colorListeners = new ArrayList<>(); synchronized (mLock) { final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners = - mColorsChangedListeners.get(userId); + getWallpaperCallbacks(userId, displayId); final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners = - mColorsChangedListeners.get(UserHandle.USER_ALL); + getWallpaperCallbacks(UserHandle.USER_ALL, displayId); keyguardListener = mKeyguardListener; if (currentUserColorListeners != null) { @@ -427,7 +449,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } - if (keyguardListener != null) { + // Only shows Keyguard on default display + if (keyguardListener != null && displayId == DEFAULT_DISPLAY) { try { keyguardListener.onWallpaperColorsChanged(wallpaperColors, which, userId); } catch (RemoteException e) { @@ -446,6 +469,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub String cropFile = null; int wallpaperId; + if (wallpaper.equals(mFallbackWallpaper)) { + extractDefaultImageWallpaperColors(); + return; + } + synchronized (mLock) { // Not having a wallpaperComponent means it's a lock screen wallpaper. final boolean imageWallpaper = mImageWallpaper.equals(wallpaper.wallpaperComponent) @@ -482,6 +510,39 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } + private void extractDefaultImageWallpaperColors() { + synchronized (mLock) { + if (mFallbackWallpaper.primaryColors != null) return; + } + + if (DEBUG) Slog.d(TAG, "Extract default image wallpaper colors"); + WallpaperColors colors = null; + final InputStream is = WallpaperManager.openDefaultWallpaper(mContext, FLAG_SYSTEM); + if (is != null) { + try { + final BitmapFactory.Options options = new BitmapFactory.Options(); + final Bitmap bitmap = BitmapFactory.decodeStream(is, null, options); + if (bitmap != null) { + colors = WallpaperColors.fromBitmap(bitmap); + bitmap.recycle(); + } + } catch (OutOfMemoryError e) { + Slog.w(TAG, "Can't decode default wallpaper stream", e); + } finally { + IoUtils.closeQuietly(is); + } + } + + if (colors == null) { + Slog.e(TAG, "Extract default image wallpaper colors failed"); + return; + } + + synchronized (mLock) { + mFallbackWallpaper.primaryColors = colors; + } + } + /** * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped * for display. @@ -696,6 +757,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub targetWallpaper.connection.removeDisplayConnector(displayId); removeDisplayData(displayId); } + for (int i = mColorsChangedListeners.size() - 1; i >= 0; i--) { + final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> callbacks = + mColorsChangedListeners.valueAt(i); + callbacks.delete(displayId); + } } } @@ -706,9 +772,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub /** * Map of color listeners per user id. - * The key will be the id of a user or UserHandle.USER_ALL - for wildcard listeners. + * The first key will be the id of a user or UserHandle.USER_ALL - for wildcard listeners. + * The secondary key will be the display id, which means which display the listener is + * interested in. */ - private final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> + private final SparseArray<SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>> mColorsChangedListeners; private WallpaperData mLastWallpaper; private IWallpaperManagerCallback mKeyguardListener; @@ -1228,9 +1296,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub /** * Called by a live wallpaper if its colors have changed. * @param primaryColors representation of wallpaper primary colors + * @param displayId for which display */ @Override - public void onWallpaperColorsChanged(WallpaperColors primaryColors) { + public void onWallpaperColorsChanged(WallpaperColors primaryColors, int displayId) { int which; synchronized (mLock) { // Do not broadcast changes on ImageWallpaper since it's handled @@ -1243,14 +1312,16 @@ public class WallpaperManagerService extends IWallpaperManager.Stub // Live wallpapers always are system wallpapers. which = FLAG_SYSTEM; - // It's also the lock screen wallpaper when we don't have a bitmap in there - WallpaperData lockedWallpaper = mLockWallpaperMap.get(mWallpaper.userId); - if (lockedWallpaper == null) { - which |= FLAG_LOCK; + // It's also the lock screen wallpaper when we don't have a bitmap in there. + if (displayId == DEFAULT_DISPLAY) { + final WallpaperData lockedWallpaper = mLockWallpaperMap.get(mWallpaper.userId); + if (lockedWallpaper == null) { + which |= FLAG_LOCK; + } } } if (which != 0) { - notifyWallpaperColorsChanged(mWallpaper, which); + notifyWallpaperColorsChangedOnDisplay(mWallpaper, which, displayId); } } @@ -1277,16 +1348,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub Slog.w(TAG, "Failed to set ambient mode state", e); } } - // TODO(multi-display) So far, we have shared the same wallpaper on each display. - // Once we have multiple wallpapers on multiple displays, please complete here. - if (displayId == DEFAULT_DISPLAY) { - try { - // This will trigger onComputeColors in the wallpaper engine. - // It's fine to be locked in here since the binder is oneway. - connector.mEngine.requestWallpaperColors(); - } catch (RemoteException e) { - Slog.w(TAG, "Failed to request wallpaper colors", e); - } + try { + // This will trigger onComputeColors in the wallpaper engine. + // It's fine to be locked in here since the binder is oneway. + connector.mEngine.requestWallpaperColors(); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to request wallpaper colors", e); } } } @@ -1681,6 +1748,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub FgThread.getHandler().post(() -> { notifyWallpaperColorsChanged(systemWallpaper, FLAG_SYSTEM); notifyWallpaperColorsChanged(lockWallpaper, FLAG_LOCK); + notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM); }); } @@ -1743,6 +1811,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub // When clearing a wallpaper, broadcast new valid colors if (data != null) { notifyWallpaperColorsChanged(data, which); + notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM); } } @@ -2084,35 +2153,47 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } @Override - public void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId) { + public void registerWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId, + int displayId) { userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, true, true, "registerWallpaperColorsCallback", null); synchronized (mLock) { - RemoteCallbackList<IWallpaperManagerCallback> userColorsChangedListeners = - mColorsChangedListeners.get(userId); - if (userColorsChangedListeners == null) { - userColorsChangedListeners = new RemoteCallbackList<>(); - mColorsChangedListeners.put(userId, userColorsChangedListeners); + SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> + userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId); + if (userDisplayColorsChangedListeners == null) { + userDisplayColorsChangedListeners = new SparseArray<>(); + mColorsChangedListeners.put(userId, userDisplayColorsChangedListeners); + } + RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners = + userDisplayColorsChangedListeners.get(displayId); + if (displayChangedListeners == null) { + displayChangedListeners = new RemoteCallbackList<>(); + userDisplayColorsChangedListeners.put(displayId, displayChangedListeners); } - userColorsChangedListeners.register(cb); + displayChangedListeners.register(cb); } } @Override - public void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId) { + public void unregisterWallpaperColorsCallback(IWallpaperManagerCallback cb, int userId, + int displayId) { userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, true, true, "unregisterWallpaperColorsCallback", null); synchronized (mLock) { - final RemoteCallbackList<IWallpaperManagerCallback> userColorsChangedListeners = - mColorsChangedListeners.get(userId); - if (userColorsChangedListeners != null) { - userColorsChangedListeners.unregister(cb); + SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> + userDisplayColorsChangedListeners = mColorsChangedListeners.get(userId); + if (userDisplayColorsChangedListeners != null) { + RemoteCallbackList<IWallpaperManagerCallback> displayChangedListeners = + userDisplayColorsChangedListeners.get(displayId); + if (displayChangedListeners != null) { + displayChangedListeners.unregister(cb); + } } } } /** - * TODO(b/115486823) Extends this method with specific display. + * TODO(multi-display) Extends this method with specific display. * Propagate ambient state to wallpaper engine. * * @param inAmbientMode {@code true} when in ambient mode, {@code false} otherwise. @@ -2125,7 +2206,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub final WallpaperData data = mWallpaperMap.get(mCurrentUserId); if (data != null && data.connection != null && data.connection.mInfo != null && data.connection.mInfo.supportsAmbientMode()) { - // TODO(b/115486823) Extends this method with specific display. + // TODO(multi-display) Extends this method with specific display. engine = data.connection.getDisplayConnectorOrCreate(DEFAULT_DISPLAY).mEngine; } else { engine = null; @@ -2151,7 +2232,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } @Override - public WallpaperColors getWallpaperColors(int which, int userId) throws RemoteException { + public WallpaperColors getWallpaperColors(int which, int userId, int displayId) + throws RemoteException { if (which != FLAG_LOCK && which != FLAG_SYSTEM) { throw new IllegalArgumentException("which should be either FLAG_LOCK or FLAG_SYSTEM"); } @@ -2169,7 +2251,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub // Try to get the system wallpaper anyway since it might // also be the lock screen wallpaper if (wallpaperData == null) { - wallpaperData = mWallpaperMap.get(userId); + wallpaperData = findWallpaperAtDisplay(userId, displayId); } if (wallpaperData == null) { @@ -2187,6 +2269,15 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } + private WallpaperData findWallpaperAtDisplay(int userId, int displayId) { + if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null + && mFallbackWallpaper.connection.containsDisplay(displayId)) { + return mFallbackWallpaper; + } else { + return mWallpaperMap.get(userId); + } + } + @Override public ParcelFileDescriptor setWallpaper(String name, String callingPackage, Rect cropHint, boolean allowBackup, Bundle extras, int which, @@ -2382,6 +2473,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub if (shouldNotifyColors) { notifyWallpaperColorsChanged(wallpaper, which); + notifyWallpaperColorsChanged(mFallbackWallpaper, FLAG_SYSTEM); } } |