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

Commit 6b09e047 authored by Lingyu Feng's avatar Lingyu Feng
Browse files

Notify wallpaper via onDisplayRemoveSystemDecorations when starting mirroring

This in CL, when the connected display is switched from extended mode to
mirroring mode:
(1) WM sends onDisplayRemoveSystemDecorations() to wallpaper.
(2) Wallpaper then performs similar actions to those triggered by
onDisplayRemoved().

Bug: 352461502
Flag: com.android.server.display.feature.flags.enable_display_content_mode_management
Test: atest WallpaperManagerServiceTests
Test: manually (adb shell settings put secure mirror_built_in_display {1|0})
Change-Id: I4482bf6b609da7a6ab5fb44edbe6734ff766700e
parent 3f4ab0a7
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -28,6 +28,9 @@ public abstract class WallpaperManagerInternal {
     */
     */
    public abstract void onDisplayReady(int displayId);
    public abstract void onDisplayReady(int displayId);


    /** Notifies when display stop showing system decorations and wallpaper. */
    public abstract void onDisplayRemoveSystemDecorations(int displayId);

    /** Notifies when the screen finished turning on and is visible to the user. */
    /** Notifies when the screen finished turning on and is visible to the user. */
    public abstract void onScreenTurnedOn(int displayId);
    public abstract void onScreenTurnedOn(int displayId);


+80 −65
Original line number Original line Diff line number Diff line
@@ -665,71 +665,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub


        @Override
        @Override
        public void onDisplayRemoved(int displayId) {
        public void onDisplayRemoved(int displayId) {
            synchronized (mLock) {
            onDisplayRemovedInternal(displayId);
                if (enableConnectedDisplaysWallpaper()) {
                    // There could be at most 2 wallpaper connections per display:
                    // 1. system & lock are the same: mLastWallpaper
                    // 2. system, lock are different: mLastWallpaper, mLastLockWallpaper
                    // 3. fallback used as both system & lock wallpaper: mFallbackWallpaper
                    // 4. fallback used as lock only wallpaper: mFallbackWallpaper,
                    //    mLastWallpaper
                    // 5. fallback used as system only wallpaper: mFallbackWallpaper,
                    //    mLastLockWallpaper
                    List<WallpaperData> pendingDisconnectWallpapers = new ArrayList<>();
                    if (mLastWallpaper != null && mLastWallpaper.connection != null
                            && mLastWallpaper.connection.containsDisplay(displayId)) {
                        pendingDisconnectWallpapers.add(mLastWallpaper);
                    }
                    if (mLastLockWallpaper != null && mLastLockWallpaper.connection != null
                            && mLastLockWallpaper.connection.containsDisplay(displayId)) {
                        pendingDisconnectWallpapers.add(mLastLockWallpaper);
                    }
                    if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null
                            && mFallbackWallpaper.connection.containsDisplay(displayId)) {
                        pendingDisconnectWallpapers.add(mFallbackWallpaper);
                    }
                    for (int i = 0; i < pendingDisconnectWallpapers.size(); i++) {
                        WallpaperData wallpaper = pendingDisconnectWallpapers.get(i);
                        DisplayConnector displayConnector =
                                wallpaper.connection.getDisplayConnectorOrCreate(displayId);
                        if (displayConnector == null) {
                            Slog.w(TAG,
                                    "Fail to disconnect wallpaper upon display removal");
                            return;
                        }
                        displayConnector.disconnectLocked(wallpaper.connection);
                        wallpaper.connection.removeDisplayConnector(displayId);
                    }
                } else {
                    if (mLastWallpaper != null) {
                        WallpaperData targetWallpaper = null;
                        if (mLastWallpaper.connection != null
                                && mLastWallpaper.connection.containsDisplay(displayId)) {
                            targetWallpaper = mLastWallpaper;
                        } else if (mFallbackWallpaper != null
                                && mFallbackWallpaper.connection != null
                                && mFallbackWallpaper.connection.containsDisplay(
                                displayId)) {
                            targetWallpaper = mFallbackWallpaper;
                        }
                        if (targetWallpaper == null) return;
                        DisplayConnector connector =
                                targetWallpaper.connection.getDisplayConnectorOrCreate(
                                        displayId);
                        if (connector == null) return;
                        connector.disconnectLocked(targetWallpaper.connection);
                        targetWallpaper.connection.removeDisplayConnector(displayId);
                    }
                }

                mWallpaperDisplayHelper.removeDisplayData(displayId);

                for (int i = mColorsChangedListeners.size() - 1; i >= 0; i--) {
                    final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> callbacks =
                            mColorsChangedListeners.valueAt(i);
                    callbacks.delete(displayId);
                }
            }
        }
        }


        @Override
        @Override
@@ -1676,6 +1612,13 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
            onDisplayReadyInternal(displayId);
            onDisplayReadyInternal(displayId);
        }
        }


        @Override
        public void onDisplayRemoveSystemDecorations(int displayId) {
            // The display mirroring starts. The handling logic is the same as when removing a
            // display.
            onDisplayRemovedInternal(displayId);
        }

        @Override
        @Override
        public void onScreenTurnedOn(int displayId) {
        public void onScreenTurnedOn(int displayId) {
            notifyScreenTurnedOn(displayId);
            notifyScreenTurnedOn(displayId);
@@ -4035,6 +3978,78 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
        }
        }
    }
    }


    // This method may be called even if the display is not being removed from the system.
    // This can be called when the display is removed, or when the display system decorations are
    // removed to start mirroring.
    private void onDisplayRemovedInternal(int displayId) {
        synchronized (mLock) {
            if (enableConnectedDisplaysWallpaper()) {
                // There could be at most 2 wallpaper connections per display:
                // 1. system & lock are the same: mLastWallpaper
                // 2. system, lock are different: mLastWallpaper, mLastLockWallpaper
                // 3. fallback used as both system & lock wallpaper: mFallbackWallpaper
                // 4. fallback used as lock only wallpaper: mFallbackWallpaper,
                //    mLastWallpaper
                // 5. fallback used as system only wallpaper: mFallbackWallpaper,
                //    mLastLockWallpaper
                List<WallpaperData> pendingDisconnectWallpapers = new ArrayList<>();
                if (mLastWallpaper != null && mLastWallpaper.connection != null
                        && mLastWallpaper.connection.containsDisplay(displayId)) {
                    pendingDisconnectWallpapers.add(mLastWallpaper);
                }
                if (mLastLockWallpaper != null && mLastLockWallpaper.connection != null
                        && mLastLockWallpaper.connection.containsDisplay(displayId)) {
                    pendingDisconnectWallpapers.add(mLastLockWallpaper);
                }
                if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null
                        && mFallbackWallpaper.connection.containsDisplay(displayId)) {
                    pendingDisconnectWallpapers.add(mFallbackWallpaper);
                }
                for (int i = 0; i < pendingDisconnectWallpapers.size(); i++) {
                    WallpaperData wallpaper = pendingDisconnectWallpapers.get(i);
                    DisplayConnector displayConnector =
                            wallpaper.connection.getDisplayConnectorOrCreate(displayId);
                    if (displayConnector == null) {
                        Slog.w(TAG,
                                "Fail to disconnect wallpaper upon display removes system "
                                        + "decorations");
                        return;
                    }
                    displayConnector.disconnectLocked(wallpaper.connection);
                    wallpaper.connection.removeDisplayConnector(displayId);
                }
            } else {
                if (mLastWallpaper != null) {
                    WallpaperData targetWallpaper = null;
                    if (mLastWallpaper.connection != null
                            && mLastWallpaper.connection.containsDisplay(displayId)) {
                        targetWallpaper = mLastWallpaper;
                    } else if (mFallbackWallpaper != null
                            && mFallbackWallpaper.connection != null
                            && mFallbackWallpaper.connection.containsDisplay(
                            displayId)) {
                        targetWallpaper = mFallbackWallpaper;
                    }
                    if (targetWallpaper == null) return;
                    DisplayConnector connector =
                            targetWallpaper.connection.getDisplayConnectorOrCreate(
                                    displayId);
                    if (connector == null) return;
                    connector.disconnectLocked(targetWallpaper.connection);
                    targetWallpaper.connection.removeDisplayConnector(displayId);
                }
            }

            mWallpaperDisplayHelper.removeDisplayData(displayId);

            for (int i = mColorsChangedListeners.size() - 1; i >= 0; i--) {
                final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> callbacks =
                        mColorsChangedListeners.valueAt(i);
                callbacks.delete(displayId);
            }
        }
    }

    void saveSettingsLocked(int userId) {
    void saveSettingsLocked(int userId) {
        TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
        TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG);
        t.traceBegin("WPMS.saveSettingsLocked-" + userId);
        t.traceBegin("WPMS.saveSettingsLocked-" + userId);
+5 −0
Original line number Original line Diff line number Diff line
@@ -1910,6 +1910,11 @@ public class DisplayPolicy {
                    if (statusBar != null) {
                    if (statusBar != null) {
                        statusBar.onDisplayRemoveSystemDecorations(displayId);
                        statusBar.onDisplayRemoveSystemDecorations(displayId);
                    }
                    }
                    final WallpaperManagerInternal wpMgr =
                            LocalServices.getService(WallpaperManagerInternal.class);
                    if (wpMgr != null) {
                        wpMgr.onDisplayRemoveSystemDecorations(displayId);
                    }
                });
                });
    }
    }


+68 −0
Original line number Original line Diff line number Diff line
@@ -894,6 +894,74 @@ public class WallpaperManagerServiceTests {
                .isEqualTo(FLAG_LOCK | FLAG_SYSTEM);
                .isEqualTo(FLAG_LOCK | FLAG_SYSTEM);
    }
    }


    // Verify a secondary display removes system decorations started
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER)
    public void displayRemoveSystemDecorations_sameSystemAndLockWallpaper_shouldDetachWallpaperServiceOnce()
            throws Exception {
        // GIVEN the same wallpaper used for the lock and system.
        final int testUserId = USER_SYSTEM;
        mService.switchUser(testUserId, null);
        final WallpaperData wallpaper = mService.getCurrentWallpaperData(FLAG_SYSTEM, testUserId);
        IWallpaperService mockIWallpaperService = mock(IWallpaperService.class);
        wallpaper.connection.mService = mockIWallpaperService;
        // GIVEN there are two displays: DEFAULT_DISPLAY, 2
        final int testDisplayId = 2;
        setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
        // GIVEN wallpaper connections have been established for displayID, 2.
        WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
                WallpaperManagerInternal.class);
        wallpaperManagerInternal.onDisplayReady(testDisplayId);
        // Save displayConnector for displayId 2 before display removal.
        WallpaperManagerService.DisplayConnector displayConnector =
                wallpaper.connection.getDisplayConnectorOrCreate(testDisplayId);

        // WHEN displayId, 2, is removed.
        wallpaperManagerInternal.onDisplayRemoveSystemDecorations(testDisplayId);

        // Then the wallpaper connection for displayId, 2, is detached.
        verify(mockIWallpaperService).detach(eq(displayConnector.mToken));
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER)
    public void displayRemoveSystemDecorations_differentSystemAndLockWallpapers_shouldDetachWallpaperServiceTwice()
            throws Exception {
        // GIVEN different wallpapers used for the lock and system.
        final int testUserId = USER_SYSTEM;
        mService.switchUser(testUserId, null);
        mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(),
                FLAG_LOCK, testUserId);
        final WallpaperData systemWallpaper = mService.getCurrentWallpaperData(FLAG_SYSTEM,
                testUserId);
        final WallpaperData lockWallpaper = mService.getCurrentWallpaperData(FLAG_LOCK,
                testUserId);
        IWallpaperService mockIWallpaperService = mock(IWallpaperService.class);
        systemWallpaper.connection.mService = mockIWallpaperService;
        lockWallpaper.connection.mService = mockIWallpaperService;
        // GIVEN there are two displays: DEFAULT_DISPLAY, 2
        final int testDisplayId = 2;
        setUpDisplays(List.of(DEFAULT_DISPLAY, testDisplayId));
        // GIVEN wallpaper connections have been established for displayID, 2.
        WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService(
                WallpaperManagerInternal.class);
        wallpaperManagerInternal.onDisplayReady(testDisplayId);
        // Save displayConnectors for displayId 2 before display removal.
        WallpaperManagerService.DisplayConnector systemWallpaperDisplayConnector =
                systemWallpaper.connection.getDisplayConnectorOrCreate(testDisplayId);
        WallpaperManagerService.DisplayConnector lockWallpaperDisplayConnector =
                lockWallpaper.connection.getDisplayConnectorOrCreate(testDisplayId);

        // WHEN displayId, 2, is removed.
        wallpaperManagerInternal.onDisplayRemoveSystemDecorations(testDisplayId);

        // Then the system wallpaper connection for displayId, 2, is detached.
        verify(mockIWallpaperService).detach(eq(systemWallpaperDisplayConnector.mToken));
        // Then the lock wallpaper connection for displayId, 2, is detached.
        verify(mockIWallpaperService).detach(eq(lockWallpaperDisplayConnector.mToken));
    }
    // Verify a secondary display removes system decorations ended

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