Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 36597d4b authored by wilsonshih's avatar wilsonshih
Browse files

Support wallpaper on secondary displays.(7/N)

Expand the wallpaper color listener for multiple displays. This will
allow the launcher on the secondary display can also receive the
correct wallpaper color.

Bug: 115486823
Test: atest WallpaperManagerTest
Test: atest ActivityManagerMultiDisplayTests
Change-Id: I3d893537a8c606170b5641c9eb4683d09743d80c
parent d97e904c
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -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.
+11 −9
Original line number Diff line number Diff line
@@ -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());
    }

    /**
+1 −1
Original line number Diff line number Diff line
@@ -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);
}
+2 −2
Original line number Diff line number Diff line
@@ -641,7 +641,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.");
@@ -1465,7 +1465,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.
                    }
+135 −43
Original line number Diff line number Diff line
@@ -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);
                // 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,9 +1348,6 @@ 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.
@@ -1289,7 +1357,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
                }
            }
        }
        }

        @Override
        public void engineShown(IWallpaperEngine engine) {
@@ -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);
        }
    }