Loading packages/SystemUI/res-keyguard/values/styles.xml +1 −1 Original line number Diff line number Diff line Loading @@ -128,7 +128,7 @@ <item name="android:windowNoTitle">true</item> <item name="android:windowFullscreen">true</item> <item name="android:windowContentOverlay">@null</item> <item name="android:colorBackground">@*android:color/background_material_dark</item> <item name="android:colorBackground">@android:color/transparent</item> </style> <style name="TextAppearance.Keyguard"> Loading packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt +4 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,10 @@ constructor( super.onCreate(savedInstanceState) onCreateV2() val window = window ?: return val layoutParams = window.attributes layoutParams.flags = layoutParams.flags or WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER window.attributes = layoutParams } fun onCreateV2() { Loading services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +103 −24 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.Manifest.permission.MANAGE_EXTERNAL_STORAGE; import static android.Manifest.permission.READ_WALLPAPER_INTERNAL; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; import static android.app.Flags.enableConnectedDisplaysWallpaper; import static android.app.Flags.fixWallpaperChanged; import static android.app.Flags.liveWallpaperContentHandling; import static android.app.Flags.removeNextWallpaperComponent; Loading Loading @@ -89,6 +90,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; import android.multiuser.Flags; import android.os.Binder; import android.os.Bundle; Loading Loading @@ -655,8 +657,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub private final MyPackageMonitor mMonitor; private final AppOpsManager mAppOpsManager; private final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() { private final DisplayListener mDisplayListener = new DisplayListener() { @Override public void onDisplayAdded(int displayId) { Loading @@ -665,24 +666,64 @@ 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)) { if (mLastWallpaper.connection != null && mLastWallpaper.connection.containsDisplay(displayId)) { targetWallpaper = mLastWallpaper; } else if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null && mFallbackWallpaper.connection.containsDisplay(displayId)) { } else if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null && mFallbackWallpaper.connection.containsDisplay( displayId)) { targetWallpaper = mFallbackWallpaper; } if (targetWallpaper == null) return; DisplayConnector connector = targetWallpaper.connection.getDisplayConnectorOrCreate(displayId); targetWallpaper.connection.getDisplayConnectorOrCreate( displayId); if (connector == null) return; connector.disconnectLocked(targetWallpaper.connection); targetWallpaper.connection.removeDisplayConnector(displayId); mWallpaperDisplayHelper.removeDisplayData(displayId); } } mWallpaperDisplayHelper.removeDisplayData(displayId); for (int i = mColorsChangedListeners.size() - 1; i >= 0; i--) { final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> callbacks = mColorsChangedListeners.valueAt(i); Loading Loading @@ -1627,6 +1668,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub public void onScreenTurnedOn(int displayId) { notifyScreenTurnedOn(displayId); } @Override public void onScreenTurningOn(int displayId) { notifyScreenTurningOn(displayId); Loading Loading @@ -3707,6 +3749,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } if (newWallpaper.mWhich == (FLAG_SYSTEM | FLAG_LOCK)) { mLastWallpaper = newWallpaper; mLastLockWallpaper = null; } else if (newWallpaper.mWhich == FLAG_SYSTEM) { mLastWallpaper = newWallpaper; } else if (newWallpaper.mWhich == FLAG_LOCK) { Loading Loading @@ -3916,6 +3959,40 @@ public class WallpaperManagerService extends IWallpaperManager.Stub if (mLastWallpaper == null) { return; } if (enableConnectedDisplaysWallpaper()) { int useFallbackWallpaperWhich = 0; List<WallpaperData> wallpapers = new ArrayList<>(); wallpapers.add(mLastWallpaper); // If the system and the lock wallpapers are not the same, we should also // establish a display connector to the lock wallpaper for this display. if (mLastLockWallpaper != null && mLastWallpaper != mLastLockWallpaper) { wallpapers.add(mLastLockWallpaper); } for (int i = 0; i < wallpapers.size(); i++) { WallpaperData wallpaper = wallpapers.get(i); if (supportsMultiDisplay(wallpaper.connection)) { final DisplayConnector connector = wallpaper.connection.getDisplayConnectorOrCreate(displayId); if (connector != null) { connector.connectLocked(wallpaper.connection, wallpaper); } else { Slog.w(TAG, "Fail to connect to wallpaper for display id " + displayId + " due to null connector. Use fallback wallpaper."); useFallbackWallpaperWhich |= wallpaper.mWhich; } } else { useFallbackWallpaperWhich |= wallpaper.mWhich; } } if (useFallbackWallpaperWhich == 0 || mFallbackWallpaper == null || mFallbackWallpaper.connection == null) { return; } mFallbackWallpaper.mWhich = useFallbackWallpaperWhich; } else { if (supportsMultiDisplay(mLastWallpaper.connection)) { final DisplayConnector connector = mLastWallpaper.connection.getDisplayConnectorOrCreate(displayId); Loading @@ -3923,6 +4000,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub connector.connectLocked(mLastWallpaper.connection, mLastWallpaper); return; } } // System wallpaper does not support multiple displays, attach this display to // the fallback wallpaper. if (mFallbackWallpaper != null && mFallbackWallpaper Loading services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java +256 −2 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertEquals; Loading Loading @@ -65,6 +66,7 @@ import android.content.pm.ParceledListSlice; import android.content.pm.ServiceInfo; import android.graphics.Color; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.RemoteException; Loading @@ -75,6 +77,7 @@ import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; import android.service.wallpaper.IWallpaperConnection; import android.service.wallpaper.IWallpaperEngine; import android.service.wallpaper.IWallpaperService; import android.service.wallpaper.WallpaperService; import android.testing.TestableContext; import android.util.Log; Loading Loading @@ -105,6 +108,7 @@ import org.junit.Test; import org.junit.rules.RuleChain; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.quality.Strictness; Loading Loading @@ -154,6 +158,8 @@ public class WallpaperManagerServiceTests { private WallpaperManagerService mService; private static IWallpaperConnection.Stub sWallpaperService; private static WindowManagerInternal sWindowManagerInternal; @BeforeClass public static void setUpClass() { sMockitoSession = mockitoSession() Loading @@ -163,8 +169,8 @@ public class WallpaperManagerServiceTests { .spyStatic(WallpaperManager.class) .startMocking(); final WindowManagerInternal dmi = mock(WindowManagerInternal.class); LocalServices.addService(WindowManagerInternal.class, dmi); sWindowManagerInternal = mock(WindowManagerInternal.class); LocalServices.addService(WindowManagerInternal.class, sWindowManagerInternal); sContext.addMockSystemService(Context.APP_OPS_SERVICE, mock(AppOpsManager.class)); Loading Loading @@ -335,6 +341,43 @@ public class WallpaperManagerServiceTests { verifyCurrentSystemData(testUserId); } /** * Test setWallpaperComponent with FLAG_LOCK should update the mLastLockWallpaper. */ @Test public void testSetLockWallpaper() { final int testUserId = USER_SYSTEM; mService.switchUser(testUserId, null); verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent); verifyCurrentSystemData(testUserId); mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(), FLAG_LOCK, testUserId); verifyLastLockWallpaperData(testUserId, sImageWallpaperComponentName); verifyCurrentSystemData(testUserId); } /** * Test setWallpaperComponent with FLAG_LOCK and then setWallpaperComponent with * FLAG_LOCK | FLAG_SYSTEM should set mLastLockWallpaper to null. */ @Test public void testSetLockWallpaperThenSetLockAndSystemWallpaper_setLastLockWallpaperToNull() { final int testUserId = USER_SYSTEM; mService.switchUser(testUserId, null); verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent); verifyCurrentSystemData(testUserId); mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(), FLAG_LOCK, testUserId); mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(), FLAG_LOCK | FLAG_SYSTEM, testUserId); verifyLastWallpaperData(testUserId, sImageWallpaperComponentName); assertThat(mService.mLastLockWallpaper).isNull(); verifyCurrentSystemData(testUserId); } /** * Tests that when setWallpaperComponent is called with the currently set component, a command * is issued to the wallpaper. Loading Loading @@ -661,6 +704,171 @@ public class WallpaperManagerServiceTests { assertPfdAndFileContentsEqual(pfd, originalSystemWallpaperFile); } // Verify a secondary display added started @Test @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER) public void displayAdded_sameSystemAndLockWallpaper_shouldAttachWallpaperServiceOnce() 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)); // WHEN displayId, 2, is ready. WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService( WallpaperManagerInternal.class); wallpaperManagerInternal.onDisplayReady(testDisplayId); // Then there is a connection established for the system & lock wallpaper for display ID, 2. verify(mockIWallpaperService).attach( /* connection= */ eq(wallpaper.connection), /* windowToken= */ any(), /* windowType= */ anyInt(), /* isPreview= */ anyBoolean(), /* reqWidth= */ anyInt(), /* reqHeight= */ anyInt(), /* padding= */ any(), /* displayId= */ eq(testDisplayId), /* which= */ eq(FLAG_SYSTEM | FLAG_LOCK), /* info= */ any(), /* description= */ any()); } @Test @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER) public void displayAdded_differentSystemAndLockWallpapers_shouldAttachWallpaperServiceTwice() 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)); // WHEN displayId, 2, is ready. WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService( WallpaperManagerInternal.class); wallpaperManagerInternal.onDisplayReady(testDisplayId); // Then there is a connection established for the system wallpaper for display ID, 2. verify(mockIWallpaperService).attach( /* connection= */ eq(systemWallpaper.connection), /* windowToken= */ any(), /* windowType= */ anyInt(), /* isPreview= */ anyBoolean(), /* reqWidth= */ anyInt(), /* reqHeight= */ anyInt(), /* padding= */ any(), /* displayId= */ eq(testDisplayId), /* which= */ eq(FLAG_SYSTEM), /* info= */ any(), /* description= */ any()); // Then there is a connection established for the lock wallpaper for display ID, 2. verify(mockIWallpaperService).attach( /* connection= */ eq(lockWallpaper.connection), /* windowToken= */ any(), /* windowType= */ anyInt(), /* isPreview= */ anyBoolean(), /* reqWidth= */ anyInt(), /* reqHeight= */ anyInt(), /* padding= */ any(), /* displayId= */ eq(testDisplayId), /* which= */ eq(FLAG_LOCK), /* info= */ any(), /* description= */ any()); } // Verify a secondary display added end // Verify a secondary display removed started @Test @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER) public void displayRemoved_sameSystemAndLockWallpaper_shouldDetachWallpaperServiceOnce() throws Exception { ArgumentCaptor<DisplayListener> displayListenerCaptor = ArgumentCaptor.forClass( DisplayListener.class); verify(mDisplayManager).registerDisplayListener(displayListenerCaptor.capture(), eq(null)); // 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. DisplayListener displayListener = displayListenerCaptor.getValue(); displayListener.onDisplayRemoved(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 displayRemoved_differentSystemAndLockWallpapers_shouldDetachWallpaperServiceTwice() throws Exception { ArgumentCaptor<DisplayListener> displayListenerCaptor = ArgumentCaptor.forClass( DisplayListener.class); verify(mDisplayManager).registerDisplayListener(displayListenerCaptor.capture(), eq(null)); // 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. DisplayListener displayListener = displayListenerCaptor.getValue(); displayListener.onDisplayRemoved(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 removed 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 @@ -681,11 +889,31 @@ public class WallpaperManagerServiceTests { lastData.connection); } private void verifyLastLockWallpaperData(int lastUserId, ComponentName expectedComponent) { final WallpaperData lastLockData = mService.mLastLockWallpaper; assertWithMessage("Last wallpaper must not be null").that(lastLockData).isNotNull(); assertWithMessage("Last wallpaper component must be equals.") .that(expectedComponent) .isEqualTo(lastLockData.getComponent()); assertWithMessage("The user id in last wallpaper should be the last switched user") .that(lastUserId) .isEqualTo(lastLockData.userId); assertWithMessage("Must exist user data connection on last wallpaper data") .that(lastLockData.connection) .isNotNull(); } private void verifyCurrentSystemData(int userId) { final WallpaperData lastData = mService.mLastWallpaper; final WallpaperData wallpaper = mService.getCurrentWallpaperData(FLAG_SYSTEM, userId); assertEquals("Last wallpaper should be equals to current system wallpaper", lastData, wallpaper); final WallpaperData lastLockData = mService.mLastLockWallpaper; final WallpaperData lockWallpaper = mService.getCurrentWallpaperData(FLAG_LOCK, userId); assertWithMessage("Last lock wallpaper should be equals to current lock wallpaper") .that(lastLockData) .isEqualTo(lockWallpaper); } private void verifyDisplayData() { Loading @@ -697,6 +925,32 @@ public class WallpaperManagerServiceTests { }); } /** * Sets up mock displays for testing. * * <p>This method creates mock {@link Display} objects and configures the {@link DisplayManager} * to return them. It also sets up the {@link WindowManagerInternal} to indicate that all * displays support home. * * @param displayIds A list of display IDs to create mock displays for. */ private void setUpDisplays(List<Integer> displayIds) { doReturn(true).when(sWindowManagerInternal).isHomeSupportedOnDisplay(anyInt()); Display[] mockDisplays = new Display[displayIds.size()]; for (int i = 0; i < displayIds.size(); i++) { final int displayId = displayIds.get(i); final Display mockDisplay = mock(Display.class); mockDisplays[i] = mockDisplay; doReturn(DISPLAY_SIZE_DIMENSION).when(mockDisplay).getMaximumSizeDimension(); doReturn(mockDisplay).when(mDisplayManager).getDisplay(eq(displayId)); doReturn(displayId).when(mockDisplay).getDisplayId(); doReturn(true).when(mockDisplay).hasAccess(anyInt()); } doReturn(mockDisplays).when(mDisplayManager).getDisplays(); } /** * Asserts that the contents of the given {@link ParcelFileDescriptor} and {@link File} contain * exactly the same bytes. Loading Loading
packages/SystemUI/res-keyguard/values/styles.xml +1 −1 Original line number Diff line number Diff line Loading @@ -128,7 +128,7 @@ <item name="android:windowNoTitle">true</item> <item name="android:windowFullscreen">true</item> <item name="android:windowContentOverlay">@null</item> <item name="android:colorBackground">@*android:color/background_material_dark</item> <item name="android:colorBackground">@android:color/transparent</item> </style> <style name="TextAppearance.Keyguard"> Loading
packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt +4 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,10 @@ constructor( super.onCreate(savedInstanceState) onCreateV2() val window = window ?: return val layoutParams = window.attributes layoutParams.flags = layoutParams.flags or WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER window.attributes = layoutParams } fun onCreateV2() { Loading
services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +103 −24 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.Manifest.permission.MANAGE_EXTERNAL_STORAGE; import static android.Manifest.permission.READ_WALLPAPER_INTERNAL; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; import static android.app.Flags.enableConnectedDisplaysWallpaper; import static android.app.Flags.fixWallpaperChanged; import static android.app.Flags.liveWallpaperContentHandling; import static android.app.Flags.removeNextWallpaperComponent; Loading Loading @@ -89,6 +90,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; import android.multiuser.Flags; import android.os.Binder; import android.os.Bundle; Loading Loading @@ -655,8 +657,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub private final MyPackageMonitor mMonitor; private final AppOpsManager mAppOpsManager; private final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() { private final DisplayListener mDisplayListener = new DisplayListener() { @Override public void onDisplayAdded(int displayId) { Loading @@ -665,24 +666,64 @@ 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)) { if (mLastWallpaper.connection != null && mLastWallpaper.connection.containsDisplay(displayId)) { targetWallpaper = mLastWallpaper; } else if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null && mFallbackWallpaper.connection.containsDisplay(displayId)) { } else if (mFallbackWallpaper != null && mFallbackWallpaper.connection != null && mFallbackWallpaper.connection.containsDisplay( displayId)) { targetWallpaper = mFallbackWallpaper; } if (targetWallpaper == null) return; DisplayConnector connector = targetWallpaper.connection.getDisplayConnectorOrCreate(displayId); targetWallpaper.connection.getDisplayConnectorOrCreate( displayId); if (connector == null) return; connector.disconnectLocked(targetWallpaper.connection); targetWallpaper.connection.removeDisplayConnector(displayId); mWallpaperDisplayHelper.removeDisplayData(displayId); } } mWallpaperDisplayHelper.removeDisplayData(displayId); for (int i = mColorsChangedListeners.size() - 1; i >= 0; i--) { final SparseArray<RemoteCallbackList<IWallpaperManagerCallback>> callbacks = mColorsChangedListeners.valueAt(i); Loading Loading @@ -1627,6 +1668,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub public void onScreenTurnedOn(int displayId) { notifyScreenTurnedOn(displayId); } @Override public void onScreenTurningOn(int displayId) { notifyScreenTurningOn(displayId); Loading Loading @@ -3707,6 +3749,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } if (newWallpaper.mWhich == (FLAG_SYSTEM | FLAG_LOCK)) { mLastWallpaper = newWallpaper; mLastLockWallpaper = null; } else if (newWallpaper.mWhich == FLAG_SYSTEM) { mLastWallpaper = newWallpaper; } else if (newWallpaper.mWhich == FLAG_LOCK) { Loading Loading @@ -3916,6 +3959,40 @@ public class WallpaperManagerService extends IWallpaperManager.Stub if (mLastWallpaper == null) { return; } if (enableConnectedDisplaysWallpaper()) { int useFallbackWallpaperWhich = 0; List<WallpaperData> wallpapers = new ArrayList<>(); wallpapers.add(mLastWallpaper); // If the system and the lock wallpapers are not the same, we should also // establish a display connector to the lock wallpaper for this display. if (mLastLockWallpaper != null && mLastWallpaper != mLastLockWallpaper) { wallpapers.add(mLastLockWallpaper); } for (int i = 0; i < wallpapers.size(); i++) { WallpaperData wallpaper = wallpapers.get(i); if (supportsMultiDisplay(wallpaper.connection)) { final DisplayConnector connector = wallpaper.connection.getDisplayConnectorOrCreate(displayId); if (connector != null) { connector.connectLocked(wallpaper.connection, wallpaper); } else { Slog.w(TAG, "Fail to connect to wallpaper for display id " + displayId + " due to null connector. Use fallback wallpaper."); useFallbackWallpaperWhich |= wallpaper.mWhich; } } else { useFallbackWallpaperWhich |= wallpaper.mWhich; } } if (useFallbackWallpaperWhich == 0 || mFallbackWallpaper == null || mFallbackWallpaper.connection == null) { return; } mFallbackWallpaper.mWhich = useFallbackWallpaperWhich; } else { if (supportsMultiDisplay(mLastWallpaper.connection)) { final DisplayConnector connector = mLastWallpaper.connection.getDisplayConnectorOrCreate(displayId); Loading @@ -3923,6 +4000,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub connector.connectLocked(mLastWallpaper.connection, mLastWallpaper); return; } } // System wallpaper does not support multiple displays, attach this display to // the fallback wallpaper. if (mFallbackWallpaper != null && mFallbackWallpaper Loading
services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java +256 −2 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wallpaper.WallpaperUtils.WALLPAPER; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertEquals; Loading Loading @@ -65,6 +66,7 @@ import android.content.pm.ParceledListSlice; import android.content.pm.ServiceInfo; import android.graphics.Color; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.RemoteException; Loading @@ -75,6 +77,7 @@ import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; import android.service.wallpaper.IWallpaperConnection; import android.service.wallpaper.IWallpaperEngine; import android.service.wallpaper.IWallpaperService; import android.service.wallpaper.WallpaperService; import android.testing.TestableContext; import android.util.Log; Loading Loading @@ -105,6 +108,7 @@ import org.junit.Test; import org.junit.rules.RuleChain; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.quality.Strictness; Loading Loading @@ -154,6 +158,8 @@ public class WallpaperManagerServiceTests { private WallpaperManagerService mService; private static IWallpaperConnection.Stub sWallpaperService; private static WindowManagerInternal sWindowManagerInternal; @BeforeClass public static void setUpClass() { sMockitoSession = mockitoSession() Loading @@ -163,8 +169,8 @@ public class WallpaperManagerServiceTests { .spyStatic(WallpaperManager.class) .startMocking(); final WindowManagerInternal dmi = mock(WindowManagerInternal.class); LocalServices.addService(WindowManagerInternal.class, dmi); sWindowManagerInternal = mock(WindowManagerInternal.class); LocalServices.addService(WindowManagerInternal.class, sWindowManagerInternal); sContext.addMockSystemService(Context.APP_OPS_SERVICE, mock(AppOpsManager.class)); Loading Loading @@ -335,6 +341,43 @@ public class WallpaperManagerServiceTests { verifyCurrentSystemData(testUserId); } /** * Test setWallpaperComponent with FLAG_LOCK should update the mLastLockWallpaper. */ @Test public void testSetLockWallpaper() { final int testUserId = USER_SYSTEM; mService.switchUser(testUserId, null); verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent); verifyCurrentSystemData(testUserId); mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(), FLAG_LOCK, testUserId); verifyLastLockWallpaperData(testUserId, sImageWallpaperComponentName); verifyCurrentSystemData(testUserId); } /** * Test setWallpaperComponent with FLAG_LOCK and then setWallpaperComponent with * FLAG_LOCK | FLAG_SYSTEM should set mLastLockWallpaper to null. */ @Test public void testSetLockWallpaperThenSetLockAndSystemWallpaper_setLastLockWallpaperToNull() { final int testUserId = USER_SYSTEM; mService.switchUser(testUserId, null); verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent); verifyCurrentSystemData(testUserId); mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(), FLAG_LOCK, testUserId); mService.setWallpaperComponent(sImageWallpaperComponentName, sContext.getOpPackageName(), FLAG_LOCK | FLAG_SYSTEM, testUserId); verifyLastWallpaperData(testUserId, sImageWallpaperComponentName); assertThat(mService.mLastLockWallpaper).isNull(); verifyCurrentSystemData(testUserId); } /** * Tests that when setWallpaperComponent is called with the currently set component, a command * is issued to the wallpaper. Loading Loading @@ -661,6 +704,171 @@ public class WallpaperManagerServiceTests { assertPfdAndFileContentsEqual(pfd, originalSystemWallpaperFile); } // Verify a secondary display added started @Test @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER) public void displayAdded_sameSystemAndLockWallpaper_shouldAttachWallpaperServiceOnce() 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)); // WHEN displayId, 2, is ready. WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService( WallpaperManagerInternal.class); wallpaperManagerInternal.onDisplayReady(testDisplayId); // Then there is a connection established for the system & lock wallpaper for display ID, 2. verify(mockIWallpaperService).attach( /* connection= */ eq(wallpaper.connection), /* windowToken= */ any(), /* windowType= */ anyInt(), /* isPreview= */ anyBoolean(), /* reqWidth= */ anyInt(), /* reqHeight= */ anyInt(), /* padding= */ any(), /* displayId= */ eq(testDisplayId), /* which= */ eq(FLAG_SYSTEM | FLAG_LOCK), /* info= */ any(), /* description= */ any()); } @Test @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER) public void displayAdded_differentSystemAndLockWallpapers_shouldAttachWallpaperServiceTwice() 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)); // WHEN displayId, 2, is ready. WallpaperManagerInternal wallpaperManagerInternal = LocalServices.getService( WallpaperManagerInternal.class); wallpaperManagerInternal.onDisplayReady(testDisplayId); // Then there is a connection established for the system wallpaper for display ID, 2. verify(mockIWallpaperService).attach( /* connection= */ eq(systemWallpaper.connection), /* windowToken= */ any(), /* windowType= */ anyInt(), /* isPreview= */ anyBoolean(), /* reqWidth= */ anyInt(), /* reqHeight= */ anyInt(), /* padding= */ any(), /* displayId= */ eq(testDisplayId), /* which= */ eq(FLAG_SYSTEM), /* info= */ any(), /* description= */ any()); // Then there is a connection established for the lock wallpaper for display ID, 2. verify(mockIWallpaperService).attach( /* connection= */ eq(lockWallpaper.connection), /* windowToken= */ any(), /* windowType= */ anyInt(), /* isPreview= */ anyBoolean(), /* reqWidth= */ anyInt(), /* reqHeight= */ anyInt(), /* padding= */ any(), /* displayId= */ eq(testDisplayId), /* which= */ eq(FLAG_LOCK), /* info= */ any(), /* description= */ any()); } // Verify a secondary display added end // Verify a secondary display removed started @Test @EnableFlags(Flags.FLAG_ENABLE_CONNECTED_DISPLAYS_WALLPAPER) public void displayRemoved_sameSystemAndLockWallpaper_shouldDetachWallpaperServiceOnce() throws Exception { ArgumentCaptor<DisplayListener> displayListenerCaptor = ArgumentCaptor.forClass( DisplayListener.class); verify(mDisplayManager).registerDisplayListener(displayListenerCaptor.capture(), eq(null)); // 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. DisplayListener displayListener = displayListenerCaptor.getValue(); displayListener.onDisplayRemoved(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 displayRemoved_differentSystemAndLockWallpapers_shouldDetachWallpaperServiceTwice() throws Exception { ArgumentCaptor<DisplayListener> displayListenerCaptor = ArgumentCaptor.forClass( DisplayListener.class); verify(mDisplayManager).registerDisplayListener(displayListenerCaptor.capture(), eq(null)); // 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. DisplayListener displayListener = displayListenerCaptor.getValue(); displayListener.onDisplayRemoved(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 removed 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 @@ -681,11 +889,31 @@ public class WallpaperManagerServiceTests { lastData.connection); } private void verifyLastLockWallpaperData(int lastUserId, ComponentName expectedComponent) { final WallpaperData lastLockData = mService.mLastLockWallpaper; assertWithMessage("Last wallpaper must not be null").that(lastLockData).isNotNull(); assertWithMessage("Last wallpaper component must be equals.") .that(expectedComponent) .isEqualTo(lastLockData.getComponent()); assertWithMessage("The user id in last wallpaper should be the last switched user") .that(lastUserId) .isEqualTo(lastLockData.userId); assertWithMessage("Must exist user data connection on last wallpaper data") .that(lastLockData.connection) .isNotNull(); } private void verifyCurrentSystemData(int userId) { final WallpaperData lastData = mService.mLastWallpaper; final WallpaperData wallpaper = mService.getCurrentWallpaperData(FLAG_SYSTEM, userId); assertEquals("Last wallpaper should be equals to current system wallpaper", lastData, wallpaper); final WallpaperData lastLockData = mService.mLastLockWallpaper; final WallpaperData lockWallpaper = mService.getCurrentWallpaperData(FLAG_LOCK, userId); assertWithMessage("Last lock wallpaper should be equals to current lock wallpaper") .that(lastLockData) .isEqualTo(lockWallpaper); } private void verifyDisplayData() { Loading @@ -697,6 +925,32 @@ public class WallpaperManagerServiceTests { }); } /** * Sets up mock displays for testing. * * <p>This method creates mock {@link Display} objects and configures the {@link DisplayManager} * to return them. It also sets up the {@link WindowManagerInternal} to indicate that all * displays support home. * * @param displayIds A list of display IDs to create mock displays for. */ private void setUpDisplays(List<Integer> displayIds) { doReturn(true).when(sWindowManagerInternal).isHomeSupportedOnDisplay(anyInt()); Display[] mockDisplays = new Display[displayIds.size()]; for (int i = 0; i < displayIds.size(); i++) { final int displayId = displayIds.get(i); final Display mockDisplay = mock(Display.class); mockDisplays[i] = mockDisplay; doReturn(DISPLAY_SIZE_DIMENSION).when(mockDisplay).getMaximumSizeDimension(); doReturn(mockDisplay).when(mDisplayManager).getDisplay(eq(displayId)); doReturn(displayId).when(mockDisplay).getDisplayId(); doReturn(true).when(mockDisplay).hasAccess(anyInt()); } doReturn(mockDisplays).when(mDisplayManager).getDisplays(); } /** * Asserts that the contents of the given {@link ParcelFileDescriptor} and {@link File} contain * exactly the same bytes. Loading