Loading services/core/java/com/android/server/wallpaper/WallpaperManagerInternal.java +3 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,9 @@ public abstract class WallpaperManagerInternal { */ 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. */ public abstract void onScreenTurnedOn(int displayId); Loading services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +80 −65 Original line number Diff line number Diff line Loading @@ -667,71 +667,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub @Override public void onDisplayRemoved(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 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); } } onDisplayRemovedInternal(displayId); } @Override Loading Loading @@ -1704,6 +1640,13 @@ public class WallpaperManagerService extends IWallpaperManager.Stub 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 public void onScreenTurnedOn(int displayId) { notifyScreenTurnedOn(displayId); Loading Loading @@ -4063,6 +4006,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) { TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG); t.traceBegin("WPMS.saveSettingsLocked-" + userId); Loading services/core/java/com/android/server/wm/DisplayPolicy.java +5 −0 Original line number Diff line number Diff line Loading @@ -1910,6 +1910,11 @@ public class DisplayPolicy { if (statusBar != null) { statusBar.onDisplayRemoveSystemDecorations(displayId); } final WallpaperManagerInternal wpMgr = LocalServices.getService(WallpaperManagerInternal.class); if (wpMgr != null) { wpMgr.onDisplayRemoveSystemDecorations(displayId); } }); } Loading services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java +68 −0 Original line number Diff line number Diff line Loading @@ -960,6 +960,74 @@ public class WallpaperManagerServiceTests { .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 // non-current user must not bind to wallpaper service. private void verifyNoConnectionBeforeLastUser(int lastUserId) { Loading Loading
services/core/java/com/android/server/wallpaper/WallpaperManagerInternal.java +3 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,9 @@ public abstract class WallpaperManagerInternal { */ 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. */ public abstract void onScreenTurnedOn(int displayId); Loading
services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +80 −65 Original line number Diff line number Diff line Loading @@ -667,71 +667,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub @Override public void onDisplayRemoved(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 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); } } onDisplayRemovedInternal(displayId); } @Override Loading Loading @@ -1704,6 +1640,13 @@ public class WallpaperManagerService extends IWallpaperManager.Stub 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 public void onScreenTurnedOn(int displayId) { notifyScreenTurnedOn(displayId); Loading Loading @@ -4063,6 +4006,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) { TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG); t.traceBegin("WPMS.saveSettingsLocked-" + userId); Loading
services/core/java/com/android/server/wm/DisplayPolicy.java +5 −0 Original line number Diff line number Diff line Loading @@ -1910,6 +1910,11 @@ public class DisplayPolicy { if (statusBar != null) { statusBar.onDisplayRemoveSystemDecorations(displayId); } final WallpaperManagerInternal wpMgr = LocalServices.getService(WallpaperManagerInternal.class); if (wpMgr != null) { wpMgr.onDisplayRemoveSystemDecorations(displayId); } }); } Loading
services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java +68 −0 Original line number Diff line number Diff line Loading @@ -960,6 +960,74 @@ public class WallpaperManagerServiceTests { .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 // non-current user must not bind to wallpaper service. private void verifyNoConnectionBeforeLastUser(int lastUserId) { Loading