summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author wilsonshih <wilsonshih@google.com> 2019-05-17 18:47:50 +0800
committer wilsonshih <wilsonshih@google.com> 2019-09-16 14:29:36 +0800
commit999ec109f1df0db2b73074f038935729ac3876f1 (patch)
treec3c0740d378608a1833699b8a3313b060c9b078f
parent7c03ce7afe7a86f5093cbc34c7693c4075a5dfd2 (diff)
Add Unit test for WallpaperManagerService.
Add some basic tests based on previous bugs we met in Q. - Launched wallpaper components shall be expected. - Display size used to generate crop image must be sane size. - No connect left after switch user continuously. - Display size and launched component should be expected after switch user and unlock device. Bug: 129797242 Test: atest FrameworksMockingServicesTests:WallpaperManagerServiceTests atest WallpaperManagerTest Change-Id: Ifae2c5f4868cedb26e27a3d76fe5d61002208536
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java64
-rw-r--r--services/tests/mockingservicestests/Android.bp1
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java364
3 files changed, 398 insertions, 31 deletions
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index b0f1e5d69be4..3cdb59beb23c 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -37,6 +37,7 @@ import android.app.UserSwitchObserver;
import android.app.WallpaperColors;
import android.app.WallpaperInfo;
import android.app.WallpaperManager;
+import android.app.WallpaperManager.SetWallpaperFlags;
import android.app.admin.DevicePolicyManager;
import android.app.backup.WallpaperBackupHelper;
import android.content.BroadcastReceiver;
@@ -73,7 +74,6 @@ import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SELinux;
-import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
@@ -91,9 +91,9 @@ import android.util.SparseBooleanArray;
import android.util.Xml;
import android.view.Display;
import android.view.DisplayInfo;
-import android.view.IWindowManager;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
@@ -739,7 +739,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
private final Context mContext;
- private final IWindowManager mIWindowManager;
private final WindowManagerInternal mWindowManagerInternal;
private final IPackageManager mIPackageManager;
private final MyPackageMonitor mMonitor;
@@ -792,7 +791,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
*/
private final SparseArray<SparseArray<RemoteCallbackList<IWallpaperManagerCallback>>>
mColorsChangedListeners;
- private WallpaperData mLastWallpaper;
+ protected WallpaperData mLastWallpaper;
private IWallpaperManagerCallback mKeyguardListener;
private boolean mWaitingForUnlock;
private boolean mShuttingDown;
@@ -825,7 +824,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
private SparseArray<DisplayData> mDisplayDatas = new SparseArray<>();
- private WallpaperData mFallbackWallpaper;
+ protected WallpaperData mFallbackWallpaper;
private final SparseBooleanArray mUserRestorecon = new SparseBooleanArray();
private int mCurrentUserId = UserHandle.USER_NULL;
@@ -900,9 +899,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
*/
final Rect cropHint = new Rect(0, 0, 0, 0);
- WallpaperData(int userId, String inputFileName, String cropFileName) {
+ WallpaperData(int userId, File wallpaperDir, String inputFileName, String cropFileName) {
this.userId = userId;
- final File wallpaperDir = getWallpaperDir(userId);
wallpaperFile = new File(wallpaperDir, inputFileName);
cropFile = new File(wallpaperDir, cropFileName);
}
@@ -917,7 +915,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
}
- private static final class DisplayData {
+ @VisibleForTesting
+ static final class DisplayData {
int mWidth = -1;
int mHeight = -1;
final Rect mPadding = new Rect(0, 0, 0, 0);
@@ -1057,13 +1056,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
return;
}
if (DEBUG) Slog.v(TAG, "Adding window token: " + mToken);
- try {
- mIWindowManager.addWindowToken(mToken, TYPE_WALLPAPER, mDisplayId);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed add wallpaper window token on display " + mDisplayId, e);
- return;
- }
-
+ mWindowManagerInternal.addWindowToken(mToken, TYPE_WALLPAPER, mDisplayId);
final DisplayData wpdData = getDisplayDataOrCreate(mDisplayId);
try {
connection.mService.attach(connection, mToken, TYPE_WALLPAPER, false,
@@ -1081,10 +1074,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
void disconnectLocked() {
if (DEBUG) Slog.v(TAG, "Removing window token: " + mToken);
- try {
- mIWindowManager.removeWindowToken(mToken, mDisplayId);
- } catch (RemoteException e) {
- }
+ mWindowManagerInternal.removeWindowToken(mToken, false/* removeWindows */,
+ mDisplayId);
try {
if (mEngine != null) {
mEngine.destroy();
@@ -1562,6 +1553,15 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
}
+ @VisibleForTesting
+ WallpaperData getCurrentWallpaperData(@SetWallpaperFlags int which, int userId) {
+ synchronized (mLock) {
+ final SparseArray<WallpaperData> wallpaperDataMap =
+ which == FLAG_SYSTEM ? mWallpaperMap : mLockWallpaperMap;
+ return wallpaperDataMap.get(userId);
+ }
+ }
+
public WallpaperManagerService(Context context) {
if (DEBUG) Slog.v(TAG, "WallpaperService startup");
mContext = context;
@@ -1569,8 +1569,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
mImageWallpaper = ComponentName.unflattenFromString(
context.getResources().getString(R.string.image_wallpaper_component));
mDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(context);
- mIWindowManager = IWindowManager.Stub.asInterface(
- ServiceManager.getService(Context.WINDOW_SERVICE));
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mIPackageManager = AppGlobals.getPackageManager();
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
@@ -1600,7 +1598,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
getWallpaperSafeLocked(UserHandle.USER_SYSTEM, FLAG_SYSTEM);
}
- private static File getWallpaperDir(int userId) {
+ File getWallpaperDir(int userId) {
return Environment.getUserSystemDirectory(userId);
}
@@ -1819,7 +1817,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// while locked, so pretend like the component was actually
// bound into place
wallpaper.wallpaperComponent = wallpaper.nextWallpaperComponent;
- final WallpaperData fallback = new WallpaperData(wallpaper.userId,
+ final WallpaperData fallback =
+ new WallpaperData(wallpaper.userId, getWallpaperDir(wallpaper.userId),
WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
ensureSaneWallpaperData(fallback, DEFAULT_DISPLAY);
bindWallpaperComponentLocked(mImageWallpaper, true, false, fallback, reply);
@@ -2380,7 +2379,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
// We know a-priori that there is no lock-only wallpaper currently
- WallpaperData lockWP = new WallpaperData(userId,
+ WallpaperData lockWP = new WallpaperData(userId, getWallpaperDir(userId),
WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
lockWP.wallpaperId = sysWP.wallpaperId;
lockWP.cropHint.set(sysWP.cropHint);
@@ -2793,7 +2792,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
}
- private static JournaledFile makeJournaledFile(int userId) {
+ private JournaledFile makeJournaledFile(int userId) {
final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
return new JournaledFile(new File(base), new File(base + ".tmp"));
}
@@ -2958,7 +2957,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// it now.
if (wallpaper == null) {
if (which == FLAG_LOCK) {
- wallpaper = new WallpaperData(userId,
+ wallpaper = new WallpaperData(userId, getWallpaperDir(userId),
WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
mLockWallpaperMap.put(userId, wallpaper);
ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
@@ -2966,7 +2965,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// sanity fallback: we're in bad shape, but establishing a known
// valid system+lock WallpaperData will keep us from dying.
Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
- wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
+ wallpaper = new WallpaperData(userId, getWallpaperDir(userId),
+ WALLPAPER, WALLPAPER_CROP);
mWallpaperMap.put(userId, wallpaper);
ensureSaneWallpaperData(wallpaper, DEFAULT_DISPLAY);
}
@@ -2985,7 +2985,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// Do this once per boot
migrateFromOld();
- wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
+ wallpaper = new WallpaperData(userId, getWallpaperDir(userId),
+ WALLPAPER, WALLPAPER_CROP);
wallpaper.allowBackup = true;
mWallpaperMap.put(userId, wallpaper);
if (!wallpaper.cropExists()) {
@@ -3037,7 +3038,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// keyguard-specific wallpaper for this user
WallpaperData lockWallpaper = mLockWallpaperMap.get(userId);
if (lockWallpaper == null) {
- lockWallpaper = new WallpaperData(userId,
+ lockWallpaper = new WallpaperData(userId, getWallpaperDir(userId),
WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP);
mLockWallpaperMap.put(userId, lockWallpaper);
}
@@ -3088,8 +3089,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
private void initializeFallbackWallpaper() {
if (mFallbackWallpaper == null) {
if (DEBUG) Slog.d(TAG, "Initialize fallback wallpaper");
- mFallbackWallpaper = new WallpaperData(
- UserHandle.USER_SYSTEM, WALLPAPER, WALLPAPER_CROP);
+ final int systemUserId = UserHandle.USER_SYSTEM;
+ mFallbackWallpaper = new WallpaperData(systemUserId, getWallpaperDir(systemUserId),
+ WALLPAPER, WALLPAPER_CROP);
mFallbackWallpaper.allowBackup = false;
mFallbackWallpaper.wallpaperId = makeWallpaperIdLocked();
bindWallpaperComponentLocked(mImageWallpaper, true, false, mFallbackWallpaper, null);
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index ad94e6159b87..8699669bf4a5 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -25,6 +25,7 @@ android_test {
"mockito-target-extended-minus-junit4",
"platform-test-annotations",
"truth-prebuilt",
+ "testables",
],
libs: [
diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
new file mode 100644
index 000000000000..307092d24d84
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/WallpaperManagerServiceTests.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wallpaper;
+
+import static android.app.WallpaperManager.FLAG_SYSTEM;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.reset;
+
+import android.app.AppGlobals;
+import android.app.AppOpsManager;
+import android.app.WallpaperManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.ServiceInfo;
+import android.hardware.display.DisplayManager;
+import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+import android.service.wallpaper.IWallpaperConnection;
+import android.service.wallpaper.WallpaperService;
+import android.testing.TestableContext;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.Display;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.dx.mockito.inline.extended.StaticMockitoSession;
+import com.android.internal.R;
+import com.android.server.LocalServices;
+import com.android.server.wallpaper.WallpaperManagerService.WallpaperData;
+import com.android.server.wm.WindowManagerInternal;
+
+import org.hamcrest.CoreMatchers;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.quality.Strictness;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Tests for the {@link WallpaperManagerService} class.
+ *
+ * Build/Install/Run:
+ * atest FrameworksMockingServicesTests:WallpaperManagerServiceTests
+ */
+@Presubmit
+@FlakyTest(bugId = 129797242)
+@RunWith(AndroidJUnit4.class)
+public class WallpaperManagerServiceTests {
+ private static final int DISPLAY_SIZE_DIMENSION = 100;
+ private static StaticMockitoSession sMockitoSession;
+
+ @ClassRule
+ public static final TestableContext sContext = new TestableContext(
+ InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
+ private static ComponentName sImageWallpaperComponentName;
+ private static ComponentName sDefaultWallpaperComponent;
+
+ private IPackageManager mIpm = AppGlobals.getPackageManager();
+
+ @Mock
+ private DisplayManager mDisplayManager;
+
+ @Rule
+ public final TemporaryFolder mFolder = new TemporaryFolder();
+ private final SparseArray<File> mTempDirs = new SparseArray<>();
+ private WallpaperManagerService mService;
+
+ @BeforeClass
+ public static void setUpClass() {
+ sMockitoSession = mockitoSession()
+ .strictness(Strictness.LENIENT)
+ .spyStatic(LocalServices.class)
+ .spyStatic(WallpaperManager.class)
+ .startMocking();
+
+ final WindowManagerInternal dmi = mock(WindowManagerInternal.class);
+ LocalServices.addService(WindowManagerInternal.class, dmi);
+
+ sContext.addMockSystemService(Context.APP_OPS_SERVICE, mock(AppOpsManager.class));
+
+ spyOn(sContext);
+ sContext.getTestablePermissions().setPermission(
+ android.Manifest.permission.SET_WALLPAPER_COMPONENT,
+ PackageManager.PERMISSION_GRANTED);
+ sContext.getTestablePermissions().setPermission(
+ android.Manifest.permission.SET_WALLPAPER,
+ PackageManager.PERMISSION_GRANTED);
+ doNothing().when(sContext).sendBroadcastAsUser(any(), any());
+
+ //Wallpaper components
+ final IWallpaperConnection.Stub wallpaperService = mock(IWallpaperConnection.Stub.class);
+ sImageWallpaperComponentName = ComponentName.unflattenFromString(
+ sContext.getResources().getString(R.string.image_wallpaper_component));
+ // Mock default wallpaper as image wallpaper if there is no pre-defined default wallpaper.
+ sDefaultWallpaperComponent = WallpaperManager.getDefaultWallpaperComponent(sContext);
+
+ if (sDefaultWallpaperComponent == null) {
+ sDefaultWallpaperComponent = sImageWallpaperComponentName;
+ doReturn(sImageWallpaperComponentName).when(() ->
+ WallpaperManager.getDefaultWallpaperComponent(any()));
+ } else {
+ sContext.addMockService(sDefaultWallpaperComponent, wallpaperService);
+ }
+
+ sContext.addMockService(sImageWallpaperComponentName, wallpaperService);
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ if (sMockitoSession != null) {
+ sMockitoSession.finishMocking();
+ sMockitoSession = null;
+ }
+ LocalServices.removeServiceForTest(WindowManagerInternal.class);
+ sImageWallpaperComponentName = null;
+ sDefaultWallpaperComponent = null;
+ reset(sContext);
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ sContext.addMockSystemService(DisplayManager.class, mDisplayManager);
+
+ final Display mockDisplay = mock(Display.class);
+ doReturn(DISPLAY_SIZE_DIMENSION).when(mockDisplay).getMaximumSizeDimension();
+ doReturn(mockDisplay).when(mDisplayManager).getDisplay(anyInt());
+
+ final Display[] displays = new Display[]{mockDisplay};
+ doReturn(displays).when(mDisplayManager).getDisplays();
+
+ spyOn(mIpm);
+ mService = new TestWallpaperManagerService(sContext);
+ spyOn(mService);
+ mService.systemReady();
+ }
+
+ @After
+ public void tearDown() {
+ LocalServices.removeServiceForTest(WallpaperManagerInternal.class);
+
+ mTempDirs.clear();
+ reset(mIpm);
+ mService = null;
+ }
+
+ protected class TestWallpaperManagerService extends WallpaperManagerService {
+ private static final String TAG = "TestWallpaperManagerService";
+
+ TestWallpaperManagerService(Context context) {
+ super(context);
+ }
+
+ @Override
+ File getWallpaperDir(int userId) {
+ File tempDir = mTempDirs.get(userId);
+ if (tempDir == null) {
+ try {
+ tempDir = mFolder.newFolder(String.valueOf(userId));
+ mTempDirs.append(userId, tempDir);
+ } catch (IOException e) {
+ Log.e(TAG, "getWallpaperDir failed at userId= " + userId);
+ }
+ }
+ return tempDir;
+ }
+
+ // Always return true for test
+ @Override
+ public boolean isWallpaperSupported(String callingPackage) {
+ return true;
+ }
+
+ // Always return true for test
+ @Override
+ public boolean isSetWallpaperAllowed(String callingPackage) {
+ return true;
+ }
+ }
+
+ /**
+ * Tests that internal basic data should be correct after boot up.
+ */
+ @Test
+ public void testDataCorrectAfterBoot() {
+ mService.switchUser(UserHandle.USER_SYSTEM, null);
+
+ final WallpaperData fallbackData = mService.mFallbackWallpaper;
+ assertEquals("Fallback wallpaper component should be ImageWallpaper.",
+ sImageWallpaperComponentName, fallbackData.wallpaperComponent);
+
+ verifyLastWallpaperData(UserHandle.USER_SYSTEM, sDefaultWallpaperComponent);
+ verifyDisplayData();
+ }
+
+ /**
+ * Tests setWallpaperComponent and clearWallpaper should work as expected.
+ */
+ @Test
+ public void testSetThenClearComponent() {
+ // Skip if there is no pre-defined default wallpaper component.
+ assumeThat(sDefaultWallpaperComponent,
+ not(CoreMatchers.equalTo(sImageWallpaperComponentName)));
+
+ final int testUserId = UserHandle.USER_SYSTEM;
+ mService.switchUser(testUserId, null);
+ verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent);
+ verifyCurrentSystemData(testUserId);
+
+ mService.setWallpaperComponent(sImageWallpaperComponentName);
+ verifyLastWallpaperData(testUserId, sImageWallpaperComponentName);
+ verifyCurrentSystemData(testUserId);
+
+ mService.clearWallpaper(null, FLAG_SYSTEM, testUserId);
+ verifyLastWallpaperData(testUserId, sDefaultWallpaperComponent);
+ verifyCurrentSystemData(testUserId);
+ }
+
+ /**
+ * Tests internal data should be correct and no crash after switch user continuously.
+ */
+ @Test
+ public void testSwitchMultipleUsers() throws Exception {
+ final int lastUserId = 5;
+ final ServiceInfo pi = mIpm.getServiceInfo(sDefaultWallpaperComponent,
+ PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, 0);
+ doReturn(pi).when(mIpm).getServiceInfo(any(), anyInt(), anyInt());
+
+ final Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
+ final ParceledListSlice ris =
+ mIpm.queryIntentServices(intent,
+ intent.resolveTypeIfNeeded(sContext.getContentResolver()),
+ PackageManager.GET_META_DATA, 0);
+ doReturn(ris).when(mIpm).queryIntentServices(any(), any(), anyInt(), anyInt());
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mIpm).checkPermission(
+ eq(android.Manifest.permission.AMBIENT_WALLPAPER), any(), anyInt());
+
+ for (int userId = 0; userId <= lastUserId; userId++) {
+ mService.switchUser(userId, null);
+ verifyLastWallpaperData(userId, sDefaultWallpaperComponent);
+ verifyCurrentSystemData(userId);
+ }
+ verifyNoConnectionBeforeLastUser(lastUserId);
+ }
+
+ /**
+ * Tests internal data should be correct and no crash after switch user + unlock user
+ * continuously.
+ * Simulating that the selected WallpaperService is not built-in. After switching users, the
+ * service should not be bound, but bound to the image wallpaper. After receiving the user
+ * unlock callback and can find the selected service for the user, the selected service should
+ * be bound.
+ */
+ @Test
+ public void testSwitchThenUnlockMultipleUsers() throws Exception {
+ final int lastUserId = 5;
+ final ServiceInfo pi = mIpm.getServiceInfo(sDefaultWallpaperComponent,
+ PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, 0);
+ doReturn(pi).when(mIpm).getServiceInfo(any(), anyInt(), anyInt());
+
+ final Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
+ final ParceledListSlice ris =
+ mIpm.queryIntentServices(intent,
+ intent.resolveTypeIfNeeded(sContext.getContentResolver()),
+ PackageManager.GET_META_DATA, 0);
+ doReturn(PackageManager.PERMISSION_GRANTED).when(mIpm).checkPermission(
+ eq(android.Manifest.permission.AMBIENT_WALLPAPER), any(), anyInt());
+
+ for (int userId = 1; userId <= lastUserId; userId++) {
+ mService.switchUser(userId, null);
+ verifyLastWallpaperData(userId, sImageWallpaperComponentName);
+ // Simulate user unlocked
+ doReturn(ris).when(mIpm).queryIntentServices(any(), any(), anyInt(), eq(userId));
+ mService.onUnlockUser(userId);
+ verifyLastWallpaperData(userId, sDefaultWallpaperComponent);
+ verifyCurrentSystemData(userId);
+ }
+ verifyNoConnectionBeforeLastUser(lastUserId);
+ verifyDisplayData();
+ }
+
+ // 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) {
+ for (int i = 0; i < lastUserId; i++) {
+ final WallpaperData userData = mService.getCurrentWallpaperData(FLAG_SYSTEM, i);
+ assertNull("No user data connection left", userData.connection);
+ }
+ }
+
+ private void verifyLastWallpaperData(int lastUserId, ComponentName expectedComponent) {
+ final WallpaperData lastData = mService.mLastWallpaper;
+ assertNotNull("Last wallpaper must not be null", lastData);
+ assertEquals("Last wallpaper component must be equals.", expectedComponent,
+ lastData.wallpaperComponent);
+ assertEquals("The user id in last wallpaper should be the last switched user",
+ lastUserId, lastData.userId);
+ assertNotNull("Must exist user data connection on last wallpaper data",
+ lastData.connection);
+ }
+
+ 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);
+ }
+
+ private void verifyDisplayData() {
+ mService.forEachDisplayData(data -> {
+ assertTrue("Display width must larger than maximum screen size",
+ data.mWidth >= DISPLAY_SIZE_DIMENSION);
+ assertTrue("Display height must larger than maximum screen size",
+ data.mHeight >= DISPLAY_SIZE_DIMENSION);
+ });
+ }
+}