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

Commit 9769af0c authored by Marcelo Arteiro's avatar Marcelo Arteiro
Browse files

Add internal listener for wallpaper color changes

This change introduces new APIs in `WallpaperManagerInternal` to allow other system services to listen for wallpaper color changes and retrieve the latest colors.

- `addOnColorsChangedListener`: Allows system components to register a callback that is invoked via a Handler whenever wallpaper colors change for any user.
- `removeOnColorsChangedListener`: Removes the listener registered with `addOnColorsChangedListener`.
- `getWallpaperColors`: Retrieves the `WallpaperColors` of either system or lock wallpapers for a given user.

`WallpaperManagerService` is updated to manage and notify these new internal listeners. Unit tests are added to verify the new functionality.

Bug: 333694176
Bug: 440236342
Test: WallpaperManagerServiceTests
Flag: EXEMPT no logical change
Change-Id: I6b0b961a10d7443dfa162898bb97c42af5d11802
parent 940d70b4
Loading
Loading
Loading
Loading
+45 −1
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package com.android.server.wallpaper;

import android.app.WallpaperColors;
import android.os.Handler;


/**
 * Wallpaper manager local system service interface.
 *
@@ -36,4 +40,44 @@ public abstract class WallpaperManagerInternal {

    /** Notifies when the screen starts turning on and is not yet visible to the user. */
    public abstract void onScreenTurningOn(int displayId);

    /**
     * Get the primary colors of the wallpaper configured in the given user.
     * @param which wallpaper type. Must be either FLAG_SYSTEM or FLAG_LOCK
     * @param userId Owner of the wallpaper.
     * @return {@link WallpaperColors} or null if colors are unknown.
     * @hide
     */
    public abstract WallpaperColors getWallpaperColors(int which, int userId);

    /**
     * Callback for receiving notifications about wallpaper color changes.
     *
     * @see #addOnColorsChangedListener(ColorsChangedCallbackInternal, Handler)
     */
    public interface ColorsChangedCallbackInternal {
        /**
         * Called when the wallpaper colors have changed for a specific user and display.
         *
         * @param colors            The new {@link WallpaperColors} of the wallpaper.
         * @param which             A combination of
         *                          {@link android.app.WallpaperManager#FLAG_SYSTEM} and/or
         *                          {@link android.app.WallpaperManager#FLAG_LOCK} to indicate which
         *                          wallpaper's colors have changed.
         * @param displayId         The id of the display which wallpaper colors have changed.
         * @param userId            The id of the user whose wallpaper colors have changed.
         * @param fromForegroundApp true if the color change originated from a foreground app.
         */
        void onColorsChanged(WallpaperColors colors, int which, int displayId, int userId,
                boolean fromForegroundApp);
    }

    /**
     * Adds a listener for wallpaper color changes.
     *
     * @param listener The listener to add.
     * @param handler  The handler on which the listener will be invoked.
     */
    public abstract void addOnColorsChangedListener(ColorsChangedCallbackInternal listener,
            Handler handler);
}
 No newline at end of file
+40 −1
Original line number Diff line number Diff line
@@ -151,6 +151,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -466,8 +467,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub

    private void notifyWallpaperColorsChangedOnDisplay(@NonNull WallpaperData wallpaper,
            int displayId) {

        final Map<WallpaperManagerInternal.ColorsChangedCallbackInternal, Handler>
                internalListeners;
        WallpaperColors wallpaperColors = getAdjustedWallpaperColorsOnDimming(wallpaper);

        if (DEBUG) {
            Slog.v(TAG, "notifyWallpaperColorsChangedOnDisplay, displayId = " + displayId
                    + ", which = " + wallpaper.mWhich);
@@ -475,6 +478,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub

        final ArrayList<IWallpaperManagerCallback> colorListeners = new ArrayList<>();
        synchronized (mLock) {
            internalListeners = new HashMap<>(mColorsChangedListenersInternal);

            final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners =
                    getWallpaperCallbacks(wallpaper.userId, displayId);
            final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners =
@@ -497,6 +502,16 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
            }
        }

        // notifies server listeners of colors changes from all users / displays
        for (Map.Entry<WallpaperManagerInternal.ColorsChangedCallbackInternal, Handler> entry :
                internalListeners.entrySet()) {
            WallpaperManagerInternal.ColorsChangedCallbackInternal cb = entry.getKey();
            Handler handler = entry.getValue();

            handler.post(() -> cb.onColorsChanged(wallpaperColors, wallpaper.mWhich, displayId,
                    wallpaper.userId, wallpaper.fromForegroundApp));
        }

        final int count = colorListeners.size();
        for (int i = 0; i < count; i++) {
            try {
@@ -544,6 +559,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
     */
    private final SparseArray<SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>>
            mColorsChangedListeners;

    /** Map od color server listeners. */
    private final Map<WallpaperManagerInternal.ColorsChangedCallbackInternal, Handler>
            mColorsChangedListenersInternal;

    // The currently bound home or home+lock wallpaper
    protected WallpaperData mLastWallpaper;
    // The currently bound lock screen only wallpaper, or null if none
@@ -1541,6 +1561,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub

        mMonitor = new MyPackageMonitor();
        mColorsChangedListeners = new SparseArray<>();
        mColorsChangedListenersInternal = new HashMap<>();
        mWallpaperDataParser = new WallpaperDataParser(mContext, mWallpaperDisplayHelper,
                mWallpaperCropper);
        LocalServices.addService(WallpaperManagerInternal.class, new LocalService());
@@ -1592,6 +1613,24 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
        public void onScreenTurningOn(int displayId) {
            notifyScreenTurningOn(displayId);
        }

        @Override
        public void addOnColorsChangedListener(ColorsChangedCallbackInternal listener,
                Handler handler) {
            synchronized (mLock) {
                mColorsChangedListenersInternal.put(listener, handler);
            }
        }

        @Override
        public WallpaperColors getWallpaperColors(int which, int userId) {
            try {
                return WallpaperManagerService.this.getWallpaperColors(which, userId,
                        DEFAULT_DISPLAY);
            } catch (RemoteException e) {
                throw new IllegalArgumentException(e.getMessage());
            }
        }
    }

    void initialize() {
+43 −0
Original line number Diff line number Diff line
@@ -68,11 +68,15 @@ import android.content.res.Resources;
import android.graphics.Color;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.TestLooperManager;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
@@ -1368,6 +1372,45 @@ public class WallpaperManagerServiceTests {
                mService.mLastWallpaper.connection)).isTrue();
    }

    @Test
    public void testOnColorsChangedListener() {
        final int testUserId = USER_SYSTEM;
        final WallpaperColors expectedColors = new WallpaperColors(Color.valueOf(Color.RED),
                Color.valueOf(Color.GREEN), Color.valueOf(Color.BLUE));

        mService.switchUser(testUserId, null);
        WallpaperManagerInternal internal = LocalServices.getService(
                WallpaperManagerInternal.class);

        if (Looper.myLooper() == null) {
            Looper.prepare();
        }
        Looper looper = Looper.myLooper();
        TestLooperManager testLooperManager = new TestLooperManager(looper);

        final WallpaperColors[] capturedColors = new WallpaperColors[1];
        final int[] capturedWhich = new int[1];
        final int[] capturedUserId = new int[1];

        internal.addOnColorsChangedListener((colors, which, displayId, userId, fromForeground) -> {
            capturedColors[0] = colors;
            capturedWhich[0] = which;
            capturedUserId[0] = userId;
        }, new Handler(looper));

        mService.mLastWallpaper.primaryColors = expectedColors;
        mService.notifyWallpaperColorsChanged(mService.mLastWallpaper);

        Message message = testLooperManager.next();
        assertNotNull(message);
        testLooperManager.execute(message);

        assertEquals(expectedColors, capturedColors[0]);
        assertEquals(mService.mLastWallpaper.mWhich, capturedWhich[0]);
        assertEquals(mService.mLastWallpaper.userId, capturedUserId[0]);
        testLooperManager.release();
    }

    // Verify that after continue switch user from userId 0 to lastUserId, the wallpaper data for
    // non-current user must not bind to wallpaper service.
    private void verifyNoConnectionBeforeLastUser(int lastUserId) {