1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app.cts.wallpapers;
18 
19 import static android.Manifest.permission.ALWAYS_UPDATE_WALLPAPER;
20 import static android.Manifest.permission.READ_WALLPAPER_INTERNAL;
21 import static android.app.WallpaperManager.FLAG_LOCK;
22 import static android.app.WallpaperManager.FLAG_SYSTEM;
23 import static android.app.cts.wallpapers.WallpaperManagerTestUtils.WallpaperChange;
24 import static android.app.cts.wallpapers.WallpaperManagerTestUtils.WallpaperState;
25 import static android.app.cts.wallpapers.WallpaperManagerTestUtils.runAndAwaitChanges;
26 import static android.app.cts.wallpapers.WallpaperManagerTestUtils.runAndAwaitColorChanges;
27 import static android.app.cts.wallpapers.util.WallpaperTestUtils.isSimilar;
28 import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
29 import static android.content.pm.PackageManager.FEATURE_LIVE_WALLPAPER;
30 import static android.content.pm.PackageManager.FEATURE_SECURE_LOCK_SCREEN;
31 import static android.content.pm.PackageManager.FEATURE_WATCH;
32 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
33 import static android.opengl.cts.Egl14Utils.getMaxTextureSize;
34 
35 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
36 
37 import static com.google.common.truth.Truth.assertThat;
38 import static com.google.common.truth.Truth.assertWithMessage;
39 
40 import static org.junit.Assert.assertThrows;
41 import static org.junit.Assert.assertTrue;
42 import static org.junit.Assume.assumeFalse;
43 import static org.junit.Assume.assumeTrue;
44 import static org.mockito.ArgumentMatchers.any;
45 import static org.mockito.ArgumentMatchers.anyInt;
46 import static org.mockito.ArgumentMatchers.nullable;
47 import static org.mockito.Mockito.atLeast;
48 import static org.mockito.Mockito.never;
49 import static org.mockito.Mockito.spy;
50 import static org.mockito.Mockito.verify;
51 
52 import android.app.Activity;
53 import android.app.Instrumentation;
54 import android.app.WallpaperColors;
55 import android.app.WallpaperInfo;
56 import android.app.WallpaperManager;
57 import android.content.BroadcastReceiver;
58 import android.content.ComponentName;
59 import android.content.Context;
60 import android.content.Intent;
61 import android.content.IntentFilter;
62 import android.graphics.Bitmap;
63 import android.graphics.Canvas;
64 import android.graphics.Color;
65 import android.graphics.ColorSpace;
66 import android.graphics.Point;
67 import android.graphics.Rect;
68 import android.graphics.drawable.Drawable;
69 import android.os.Handler;
70 import android.os.HandlerThread;
71 import android.os.IBinder;
72 import android.os.Looper;
73 import android.platform.test.annotations.RequiresFlagsEnabled;
74 import android.platform.test.flag.junit.CheckFlagsRule;
75 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
76 import android.server.wm.LockScreenSession;
77 import android.server.wm.WindowManagerState;
78 import android.server.wm.WindowManagerStateHelper;
79 import android.util.Log;
80 import android.view.Display;
81 import android.view.Window;
82 import android.view.WindowManager;
83 
84 import androidx.test.InstrumentationRegistry;
85 import androidx.test.rule.ActivityTestRule;
86 
87 import com.android.compatibility.common.util.CtsTouchUtils;
88 import com.android.window.flags.Flags;
89 
90 import com.google.testing.junit.testparameterinjector.TestParameter;
91 import com.google.testing.junit.testparameterinjector.TestParameterInjector;
92 
93 import org.junit.After;
94 import org.junit.AfterClass;
95 import org.junit.Before;
96 import org.junit.Ignore;
97 import org.junit.Rule;
98 import org.junit.Test;
99 import org.junit.runner.RunWith;
100 import org.mockito.MockitoAnnotations;
101 
102 import java.io.IOException;
103 import java.util.ArrayList;
104 import java.util.LinkedList;
105 import java.util.List;
106 import java.util.Map;
107 import java.util.concurrent.CountDownLatch;
108 import java.util.concurrent.TimeUnit;
109 import java.util.concurrent.atomic.AtomicBoolean;
110 
111 /**
112  * Tests for {@link WallpaperManager} and related classes.
113  * <p>
114  * Note: the wallpapers {@link TestLiveWallpaper}, {@link TestLiveWallpaperNoUnfoldTransition},
115  * {@link TestLiveWallpaperSupportingAmbientMode} draw the screen in
116  * cyan, magenta, yellow, respectively.
117  * </p>
118  */
119 @RunWith(TestParameterInjector.class)
120 public class WallpaperManagerTest {
121 
122     private static final boolean DEBUG = false;
123     private static final String TAG = "WallpaperManagerTest";
124 
125     private static final ComponentName TEST_COMPONENT_NAME = new ComponentName(
126             TestLiveWallpaper.class.getPackageName(), TestLiveWallpaper.class.getName());
127     // Default wait time for async operations
128     private static final int SLEEP_MS = 500;
129     private static final int DIM_LISTENER_TIMEOUT_SECS = 30;
130 
131     private WallpaperManager mWallpaperManager;
132     private static WallpaperManager sWallpaperManager = null;
133     private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();;
134     private Context mContext;
135     private CtsTouchUtils mCtsTouchUtils;
136     private Handler mHandler;
137     private BroadcastReceiver mBroadcastReceiver;
138     private CountDownLatch mCountDownLatch;
139     private boolean mEnableWcg;
140 
141     // WallpaperInfo object for the built-in default wallpaper of the device.
142     // Always null if the device uses ImageWallpaper by default.
143     private WallpaperInfo mDefaultWallpaperInfo;
144 
145     private static final WindowManagerStateHelper sWindowManagerStateHelper =
146             new WindowManagerStateHelper();
147 
148     @Rule
149     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
150 
151     @Rule
152     public ActivityTestRule<WallpaperTestActivity> mActivityTestRule = new ActivityTestRule<>(
153             WallpaperTestActivity.class,
154             false /* initialTouchMode */,
155             false /* launchActivity */);
156 
157     @Rule
158     public ActivityTestRule<WallpaperOverlayTestActivity> mOverlayActivityTestRule =
159             new ActivityTestRule<>(
160                     WallpaperOverlayTestActivity.class,
161                     false /* initialTouchMode */,
162                     false /* launchActivity */);
163 
164     @Before
setUp()165     public void setUp() throws Exception {
166         // grant READ_WALLPAPER_INTERNAL for all tests
167         mInstrumentation.getUiAutomation()
168                 .adoptShellPermissionIdentity(READ_WALLPAPER_INTERNAL);
169 
170         mContext = InstrumentationRegistry.getTargetContext();
171         WallpaperWindowsTestUtils.setContext(mContext);
172         mCtsTouchUtils = new CtsTouchUtils(mContext);
173         mWallpaperManager = WallpaperManager.getInstance(mContext);
174         sWallpaperManager = mWallpaperManager;
175         assumeTrue("Device does not support wallpapers", mWallpaperManager.isWallpaperSupported());
176 
177         // TODO(b/328312997): revisit this test once we have a strategy for live wallpaper on AAOS.
178         assumeFalse("AAOS doesn't support FEATURE_LIVE_WALLPAPER",
179                 mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
180 
181         MockitoAnnotations.initMocks(this);
182         final HandlerThread handlerThread = new HandlerThread("TestCallbacks");
183         handlerThread.start();
184         mHandler = new Handler(handlerThread.getLooper());
185         mCountDownLatch = new CountDownLatch(1);
186         mBroadcastReceiver = new BroadcastReceiver() {
187             @Override
188             public void onReceive(Context context, Intent intent) {
189                 mCountDownLatch.countDown();
190                 if (DEBUG) {
191                     Log.d(TAG, "broadcast state count down: " + mCountDownLatch.getCount());
192                 }
193             }
194         };
195         mContext.registerReceiver(mBroadcastReceiver,
196                 new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED));
197         mEnableWcg = mWallpaperManager.shouldEnableWideColorGamut();
198         runAndAwaitColorChanges(5, TimeUnit.SECONDS, FLAG_SYSTEM | FLAG_LOCK,
199                 mWallpaperManager, mHandler, mWallpaperManager::clear);
200         if (mDefaultWallpaperInfo == null) {
201             mDefaultWallpaperInfo = mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM);
202         }
203 
204         assertWithMessage("Home screen wallpaper must be set after setUp()").that(
205                 mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isAtLeast(0);
206         assertWithMessage("Lock screen wallpaper must be unset after setUp()").that(
207                 mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
208 
209         TestWallpaperService.Companion.resetCounts();
210     }
211 
212     @After
tearDown()213     public void tearDown() {
214         // drop READ_WALLPAPER_INTERNAL
215         mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
216 
217         if (mBroadcastReceiver != null) {
218             mContext.unregisterReceiver(mBroadcastReceiver);
219         }
220         TestWallpaperService.Companion.checkAssertions();
221         TestWallpaperService.Companion.resetCounts();
222     }
223 
224     /**
225      * Reset all wallpapers to default after the test suite has been executed.
226      */
227     @AfterClass
tearDownClass()228     public static void tearDownClass() throws IOException {
229         if (sWallpaperManager != null) {
230             sWallpaperManager.clear(FLAG_SYSTEM | FLAG_LOCK);
231         }
232         sWallpaperManager = null;
233     }
234 
235     @Test
setBitmap_homeScreen_homeStatic_lockScreenUnset_setsLockToHomeAndUpdatesHome()236     public void setBitmap_homeScreen_homeStatic_lockScreenUnset_setsLockToHomeAndUpdatesHome()
237             throws IOException {
238         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
239         Canvas canvas = new Canvas(tmpWallpaper);
240         canvas.drawColor(Color.RED);
241 
242         try {
243             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
244             mWallpaperManager.setBitmap(tmpWallpaper, /* visibleCropHint= */
245                     null, /* allowBackup= */true, FLAG_SYSTEM);
246             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
247                     origHomeWallpaperId);
248             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origHomeWallpaperId);
249         } finally {
250             tmpWallpaper.recycle();
251         }
252     }
253 
254     @Test
setBitmap_homeScreen_homeLive_lockScreenUnset_setsLockToHomeAndUpdatesHome()255     public void setBitmap_homeScreen_homeLive_lockScreenUnset_setsLockToHomeAndUpdatesHome()
256             throws IOException {
257         runWithShellPermissionIdentity(() -> {
258             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM | FLAG_LOCK);
259         });
260         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
261         Canvas canvas = new Canvas(tmpWallpaper);
262         canvas.drawColor(Color.RED);
263 
264         try {
265             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
266             mWallpaperManager.setBitmap(tmpWallpaper, /* visibleCropHint= */
267                     null, /* allowBackup= */true, FLAG_SYSTEM);
268             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
269                     origHomeWallpaperId);
270             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origHomeWallpaperId);
271         } finally {
272             tmpWallpaper.recycle();
273         }
274     }
275 
276     @Test
setBitmap_lockScreen_lockScreenUnset_changesLockOnly()277     public void setBitmap_lockScreen_lockScreenUnset_changesLockOnly() throws IOException {
278         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
279         Canvas canvas = new Canvas(tmpWallpaper);
280         canvas.drawColor(Color.RED);
281 
282         try {
283             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
284             mWallpaperManager.setBitmap(tmpWallpaper, /* visibleCropHint= */
285                     null, /* allowBackup= */true, FLAG_LOCK);
286             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isEqualTo(
287                     origHomeWallpaperId);
288             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isAtLeast(0);
289         } finally {
290             tmpWallpaper.recycle();
291         }
292     }
293 
294     @Test
setBitmap_lockScreen_lockScreenSet_changesLockOnly()295     public void setBitmap_lockScreen_lockScreenSet_changesLockOnly() throws IOException {
296         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
297         Canvas canvas = new Canvas(tmpWallpaper);
298         canvas.drawColor(Color.GREEN);
299 
300         try {
301             mWallpaperManager.setBitmap(tmpWallpaper, null, true, FLAG_LOCK);
302             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
303             int origLockWallpaperId = mWallpaperManager.getWallpaperId(FLAG_LOCK);
304             canvas.drawColor(Color.RED);
305             mWallpaperManager.setBitmap(tmpWallpaper, /* visibleCropHint= */
306                     null, /* allowBackup= */true, FLAG_LOCK);
307             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isEqualTo(
308                     origHomeWallpaperId);
309             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isNotEqualTo(
310                     origLockWallpaperId);
311         } finally {
312             tmpWallpaper.recycle();
313         }
314     }
315 
316     @Test
setBitmap_both_lockScreenUnset_changesHome()317     public void setBitmap_both_lockScreenUnset_changesHome() throws IOException {
318         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
319         Canvas canvas = new Canvas(tmpWallpaper);
320         canvas.drawColor(Color.RED);
321 
322         try {
323             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
324             mWallpaperManager.setBitmap(tmpWallpaper, /* visibleCropHint= */
325                     null, /* allowBackup= */true, FLAG_SYSTEM | FLAG_LOCK);
326             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
327                     origHomeWallpaperId);
328             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
329         } finally {
330             tmpWallpaper.recycle();
331         }
332     }
333 
334     @Test
setBitmap_both_lockScreenSet_changesHomeAndClearsLock()335     public void setBitmap_both_lockScreenSet_changesHomeAndClearsLock() throws IOException {
336         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
337         Canvas canvas = new Canvas(tmpWallpaper);
338         canvas.drawColor(Color.GREEN);
339 
340         try {
341             mWallpaperManager.setBitmap(tmpWallpaper, null, true, FLAG_LOCK);
342             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
343             int origLockWallpaperId = mWallpaperManager.getWallpaperId(FLAG_LOCK);
344             canvas.drawColor(Color.RED);
345             mWallpaperManager.setBitmap(tmpWallpaper, /* visibleCropHint= */
346                     null, /* allowBackup= */true, FLAG_SYSTEM | FLAG_LOCK);
347             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
348                     origHomeWallpaperId);
349             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
350         } finally {
351             tmpWallpaper.recycle();
352         }
353     }
354 
355     @Test
setBitmap_default_lockScreenUnset_sameAsBoth()356     public void setBitmap_default_lockScreenUnset_sameAsBoth() throws IOException {
357         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
358         Canvas canvas = new Canvas(tmpWallpaper);
359         canvas.drawColor(Color.RED);
360 
361         try {
362             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
363             mWallpaperManager.setBitmap(tmpWallpaper);
364             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
365                     origHomeWallpaperId);
366             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
367         } finally {
368             tmpWallpaper.recycle();
369         }
370     }
371 
372     @Test
setResource_homeScreen_homeStatic_lockScreenUnset_setsLockToHomeAndUpdatesHome()373     public void setResource_homeScreen_homeStatic_lockScreenUnset_setsLockToHomeAndUpdatesHome()
374             throws IOException {
375         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
376         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
377         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
378                 origHomeWallpaperId);
379         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origHomeWallpaperId);
380     }
381 
382     @Test
setResource_homeScreen_homeLive_lockScreenUnset_setsLockToHomeAndUpdatesHome()383     public void setResource_homeScreen_homeLive_lockScreenUnset_setsLockToHomeAndUpdatesHome()
384             throws IOException {
385         runWithShellPermissionIdentity(() -> {
386             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM | FLAG_LOCK);
387         });
388         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
389 
390         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
391 
392         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
393                 origHomeWallpaperId);
394         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origHomeWallpaperId);
395     }
396 
397     @Test
setResource_homeScreen_lockScreenSet_changesHomeOnly()398     public void setResource_homeScreen_lockScreenSet_changesHomeOnly() throws IOException {
399         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
400         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
401         int origLockWallpaperId = mWallpaperManager.getWallpaperId(FLAG_LOCK);
402         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_SYSTEM);
403         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
404                 origHomeWallpaperId);
405         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origLockWallpaperId);
406     }
407 
408     @Test
setResource_lockScreen_lockScreenUnset_changesLockOnly()409     public void setResource_lockScreen_lockScreenUnset_changesLockOnly() throws IOException {
410         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
411         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
412         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isEqualTo(
413                 origHomeWallpaperId);
414         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isAtLeast(0);
415     }
416 
417     @Test
setResource_lockScreen_lockScreenSet_changesLockOnly()418     public void setResource_lockScreen_lockScreenSet_changesLockOnly() throws IOException {
419         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
420         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
421         int origLockWallpaperId = mWallpaperManager.getWallpaperId(FLAG_LOCK);
422         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_LOCK);
423         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isEqualTo(
424                 origHomeWallpaperId);
425         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isNotEqualTo(
426                 origLockWallpaperId);
427     }
428 
429     @Test
setResource_both_lockScreenUnset_changesHome()430     public void setResource_both_lockScreenUnset_changesHome() throws IOException {
431         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
432         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM | FLAG_LOCK);
433         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
434                 origHomeWallpaperId);
435         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
436     }
437 
438     @Test
setResource_both_lockScreenSet_changesHomeAndClearsLock()439     public void setResource_both_lockScreenSet_changesHomeAndClearsLock() throws IOException {
440         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
441         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
442         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_SYSTEM | FLAG_LOCK);
443         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
444                 origHomeWallpaperId);
445         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
446     }
447 
448     // This is just to be sure that setResource call the overload with `which`.
449     @Test
setResource_default_lockScreenUnset_sameAsBoth()450     public void setResource_default_lockScreenUnset_sameAsBoth() throws IOException {
451         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
452         mWallpaperManager.setResource(R.drawable.icon_red);
453         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
454                 origHomeWallpaperId);
455         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
456     }
457 
458     @Test
setWallpaperComponent_homeScreen_homeStatic_lockScreenUnset_migratesThenSetsHome()459     public void setWallpaperComponent_homeScreen_homeStatic_lockScreenUnset_migratesThenSetsHome() {
460         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
461         runWithShellPermissionIdentity(() -> {
462             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM);
463         });
464 
465         assertWithMessage("System wallpaper must change").that(
466                 mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(origHomeWallpaperId);
467         assertWithMessage("Lock wallpaper mush not change").that(
468                 mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origHomeWallpaperId);
469     }
470 
471     @Test
setWallpaperComponent_homeScreen_homeLive_lockScreenUnset_migratesThenSetsHome()472     public void setWallpaperComponent_homeScreen_homeLive_lockScreenUnset_migratesThenSetsHome() {
473         runWithShellPermissionIdentity(() -> {
474             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM | FLAG_LOCK);
475         });
476         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
477 
478         runWithShellPermissionIdentity(() -> {
479             ComponentName newComponentName = new ComponentName(
480                     TestLiveWallpaperNoUnfoldTransition.class.getPackageName(),
481                     TestLiveWallpaperNoUnfoldTransition.class.getName());
482             setWallpaperComponentAndWait(newComponentName, FLAG_SYSTEM);
483         });
484 
485         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(origHomeWallpaperId);
486         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origHomeWallpaperId);
487     }
488 
489     @Test
setWallpaperComponent_homeScreen_lockScreenSet_changesHomeOnly()490     public void setWallpaperComponent_homeScreen_lockScreenSet_changesHomeOnly()
491             throws IOException {
492         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
493         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
494         int origLockWallpaperId = mWallpaperManager.getWallpaperId(FLAG_LOCK);
495         runWithShellPermissionIdentity(() -> {
496             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM);
497         });
498         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(origHomeWallpaperId);
499         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origLockWallpaperId);
500     }
501 
502     @Test
setWallpaperComponent_lockScreen_lockScreenUnset_changesLockOnly()503     public void setWallpaperComponent_lockScreen_lockScreenUnset_changesLockOnly() {
504         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
505         runWithShellPermissionIdentity(() -> {
506             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_LOCK);
507         });
508         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isEqualTo(origHomeWallpaperId);
509         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isAtLeast(0);
510     }
511 
512     @Test
setWallpaperComponent_lockScreen_lockScreenSet_changeLockOnly()513     public void setWallpaperComponent_lockScreen_lockScreenSet_changeLockOnly()
514             throws IOException {
515         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
516         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
517         int origLockWallpaperId = mWallpaperManager.getWallpaperId(FLAG_LOCK);
518         runWithShellPermissionIdentity(() -> {
519             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_LOCK);
520         });
521         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isEqualTo(origHomeWallpaperId);
522         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isNotEqualTo(origLockWallpaperId);
523     }
524 
525     @Test
setWallpaperComponent_both_lockScreenUnset_setsHomeToBoth()526     public void setWallpaperComponent_both_lockScreenUnset_setsHomeToBoth() {
527         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
528         runWithShellPermissionIdentity(() -> {
529             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM | FLAG_LOCK);
530         });
531         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(origHomeWallpaperId);
532         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
533     }
534 
535     @Test
setWallpaperComponent_both_lockScreenSet_changesLockOnly()536     public void setWallpaperComponent_both_lockScreenSet_changesLockOnly()
537             throws IOException {
538         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
539         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
540         runWithShellPermissionIdentity(() -> {
541             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM | FLAG_LOCK);
542         });
543         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(origHomeWallpaperId);
544         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
545     }
546 
547     @Test
setWallpaperComponent_default_lockScreenUnset_behavesLikeBoth()548     public void setWallpaperComponent_default_lockScreenUnset_behavesLikeBoth() {
549         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
550         runWithShellPermissionIdentity(() -> {
551             mWallpaperManager.setWallpaperComponent(TEST_COMPONENT_NAME);
552         });
553         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(origHomeWallpaperId);
554         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
555     }
556 
557     @Test
setStaticWallpaper_doesNotSetWallpaperInfo()558     public void setStaticWallpaper_doesNotSetWallpaperInfo() throws IOException {
559         assertNullOrDefaultWallpaper(FLAG_SYSTEM);
560         assertNullOrDefaultWallpaper(FLAG_LOCK);
561 
562         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
563         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_LOCK);
564 
565         assertThat(mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM)).isNull();
566         assertThat(mWallpaperManager.getWallpaperInfo(FLAG_LOCK)).isNull();
567     }
568 
569     @Test
setLiveWallpaper_homeScreen_setsHomeWallpaperInfo()570     public void setLiveWallpaper_homeScreen_setsHomeWallpaperInfo() {
571         assertNullOrDefaultWallpaper(FLAG_SYSTEM);
572         assertNullOrDefaultWallpaper(FLAG_LOCK);
573 
574         runWithShellPermissionIdentity(() -> {
575             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM);
576         });
577 
578         assertNotNullOrDefaultWallpaper(FLAG_SYSTEM);
579         assertNullOrDefaultWallpaper(FLAG_LOCK);
580     }
581 
582     @Test
setLiveWallpaper_lockScreen_setsLockWallpaperInfo()583     public void setLiveWallpaper_lockScreen_setsLockWallpaperInfo() {
584         assertNullOrDefaultWallpaper(FLAG_SYSTEM);
585         assertNullOrDefaultWallpaper(FLAG_LOCK);
586 
587         runWithShellPermissionIdentity(() -> {
588             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_LOCK);
589         });
590 
591         assertNullOrDefaultWallpaper(FLAG_SYSTEM);
592         assertNotNullOrDefaultWallpaper(FLAG_LOCK);
593     }
594 
595     @Test
getWallpaperInfo_badFlagsArgument_throwsException()596     public void getWallpaperInfo_badFlagsArgument_throwsException() {
597         assertThrows(IllegalArgumentException.class, () ->
598                 mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM | FLAG_LOCK));
599     }
600 
601     @Test
wallpaperChangedBroadcastTest()602     public void wallpaperChangedBroadcastTest() {
603         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
604         Canvas canvas = new Canvas(tmpWallpaper);
605         canvas.drawColor(Color.BLACK);
606 
607         try {
608             mWallpaperManager.setBitmap(tmpWallpaper);
609 
610             // Wait for up to 5 sec since this is an async call.
611             // Should fail if Intent.ACTION_WALLPAPER_CHANGED isn't delivered.
612             assertWithMessage("Timed out waiting for Intent").that(
613                     mCountDownLatch.await(5, TimeUnit.SECONDS)).isTrue();
614         } catch (InterruptedException | IOException e) {
615             throw new AssertionError("Intent.ACTION_WALLPAPER_CHANGED not received.");
616         } finally {
617             tmpWallpaper.recycle();
618         }
619     }
620 
621     @Test
wallpaperClearBroadcastTest()622     public void wallpaperClearBroadcastTest() {
623         try {
624             mWallpaperManager.clear(FLAG_LOCK | FLAG_SYSTEM);
625 
626             // Wait for 5 sec since this is an async call.
627             // Should fail if Intent.ACTION_WALLPAPER_CHANGED isn't delivered.
628             assertWithMessage("Timed out waiting for Intent").that(
629                     mCountDownLatch.await(5, TimeUnit.SECONDS)).isTrue();
630         } catch (InterruptedException | IOException e) {
631             throw new AssertionError(e);
632         }
633     }
634 
635     /**
636      * Test that {@link WallpaperManager#clear(int)} triggers the correct number of
637      * {@link android.service.wallpaper.WallpaperService.Engine#onDestroy()} in different scenarios.
638      */
639     @Test
testClear()640     public void testClear() throws IOException {
641         // map of: argument passed to clear(int) -> WallpaperState -> expected number of onDestroy
642         Map<Integer, Map<WallpaperState, Integer>> testMap = Map.of(
643                 FLAG_LOCK,
644                 Map.of(WallpaperState.LIVE_DIFF_MULTI, 1, WallpaperState.LIVE_SAME_SINGLE, 0),
645                 FLAG_SYSTEM,
646                 Map.of(WallpaperState.LIVE_DIFF_MULTI, 1, WallpaperState.LIVE_SAME_SINGLE, 0),
647                 FLAG_SYSTEM | FLAG_LOCK, Map.of(
648                         WallpaperState.LIVE_DIFF_MULTI, 2, WallpaperState.LIVE_SAME_SINGLE, 1));
649 
650         Map<WallpaperState, String> stateDescriptions = Map.of(
651                 WallpaperState.LIVE_DIFF_MULTI, "two different live wallpapers",
652                 WallpaperState.LIVE_SAME_SINGLE, "a shared live wallpaper");
653 
654         Map<Integer, String> flagDescriptions = Map.of(
655                 FLAG_LOCK, "FLAG_LOCK",
656                 FLAG_SYSTEM, "FLAG_SYSTEM",
657                 FLAG_SYSTEM | FLAG_LOCK, "FLAG_SYSTEM | FLAG_LOCK");
658 
659         Map<Integer, String> destroyCountDescriptions = Map.of(
660                 0, "not destroy any engine",
661                 1, "destroy exactly one engine",
662                 2, "destroy two engines");
663 
664         runWithShellPermissionIdentity(() -> {
665             for (Map.Entry<Integer, Map<WallpaperState, Integer>> entry : testMap.entrySet()) {
666                 int which = entry.getKey();
667                 Map<WallpaperState, Integer> map = entry.getValue();
668                 for (Map.Entry<WallpaperState, Integer> e : map.entrySet()) {
669                     WallpaperState initialState = e.getKey();
670                     int expectedCount = e.getValue();
671                     WallpaperManagerTestUtils.goToState(mWallpaperManager, initialState);
672                     TestWallpaperService.Companion.resetCounts();
673                     runAndAwaitChanges(5, TimeUnit.SECONDS, 0, expectedCount, 0, () -> {
674                         mWallpaperManager.clear(which);
675                     });
676                     for (int testWhich : List.of(FLAG_SYSTEM, FLAG_LOCK)) {
677                         if ((testWhich & which) > 0) {
678                             assertNullOrDefaultWallpaper(testWhich);
679                         } else {
680                             assertNotNullOrDefaultWallpaper(testWhich);
681                         }
682                     }
683                     String expectedBehaviourMessage = String.format("With %s, clear(%s) should %s",
684                             stateDescriptions.get(initialState),
685                             flagDescriptions.get(which),
686                             destroyCountDescriptions.get(expectedCount));
687                     assertWithMessage(expectedBehaviourMessage)
688                             .that(TestWallpaperService.Companion.getDestroyCount())
689                             .isEqualTo(expectedCount);
690                 }
691             }
692         });
693     }
694 
695     @Test
invokeOnColorsChangedListenerTest_systemOnly()696     public void invokeOnColorsChangedListenerTest_systemOnly() {
697         verifyColorListenerInvoked(FLAG_SYSTEM, FLAG_SYSTEM);
698     }
699 
700     @Test
invokeOnColorsChangedListenerTest_lockOnly()701     public void invokeOnColorsChangedListenerTest_lockOnly() {
702         verifyColorListenerInvoked(FLAG_LOCK, FLAG_LOCK);
703     }
704 
705     @Test
invokeOnColorsChangedListenerTest_both()706     public void invokeOnColorsChangedListenerTest_both() {
707         int both = FLAG_LOCK | FLAG_SYSTEM;
708         verifyColorListenerInvoked(both, both);
709     }
710 
711     @Test
invokeOnColorsChangedListenerTest_clearLock()712     public void invokeOnColorsChangedListenerTest_clearLock() throws IOException {
713         verifyColorListenerInvokedClearing(FLAG_LOCK);
714     }
715 
716     @Test
invokeOnColorsChangedListenerTest_clearSystem()717     public void invokeOnColorsChangedListenerTest_clearSystem() throws IOException {
718         verifyColorListenerInvokedClearing(FLAG_SYSTEM);
719     }
720 
721     /**
722      * Removing a listener should not invoke it anymore
723      */
724     @Test
addRemoveOnColorsChangedListenerTest_onlyInvokeAdded()725     public void addRemoveOnColorsChangedListenerTest_onlyInvokeAdded() throws IOException {
726         ensureCleanState();
727 
728         final CountDownLatch latch = new CountDownLatch(1);
729         WallpaperManager.OnColorsChangedListener counter = (colors, whichWp) -> latch.countDown();
730 
731         // Add and remove listener
732         WallpaperManager.OnColorsChangedListener listener = getTestableListener();
733         mWallpaperManager.addOnColorsChangedListener(listener, mHandler);
734         mWallpaperManager.removeOnColorsChangedListener(listener);
735 
736         // Verify that the listener is not called
737         mWallpaperManager.addOnColorsChangedListener(counter, mHandler);
738         try {
739             mWallpaperManager.setResource(R.drawable.icon_red);
740             if (!latch.await(5, TimeUnit.SECONDS)) {
741                 throw new AssertionError("Registered listener not invoked");
742             }
743         } catch (InterruptedException | IOException e) {
744             throw new RuntimeException(e);
745         }
746         verify(listener, never()).onColorsChanged(any(WallpaperColors.class), anyInt());
747         mWallpaperManager.removeOnColorsChangedListener(counter);
748     }
749 
750     /**
751      * Suggesting desired dimensions is only a hint to the system that can be ignored.
752      *
753      * Test if the desired minimum width or height the WallpaperManager returns
754      * is greater than 0. If so, then we check whether that the size is the dimension
755      * that was suggested.
756      */
757     @Test
suggestDesiredDimensionsTest()758     public void suggestDesiredDimensionsTest() {
759         final Point min = getScreenSize();
760         int w = min.x * 3;
761         int h = min.y * 2;
762 
763         // b/120847476: WallpaperManager limits at GL_MAX_TEXTURE_SIZE
764         final int max = getMaxTextureSize();
765         if (max > 0) {
766             w = Math.min(w, max);
767             h = Math.min(h, max);
768         }
769 
770         assertDesiredDimension(new Point(min.x / 2, min.y / 2), new Point(min.x / 2, min.y / 2));
771 
772         assertDesiredDimension(new Point(w, h), new Point(w, h));
773 
774         assertDesiredDimension(new Point(min.x / 2, h), new Point(min.x / 2, h));
775 
776         assertDesiredDimension(new Point(w, min.y / 2), new Point(w, min.y / 2));
777     }
778 
779     @Test
780     @Ignore("b/265007420")
wallpaperColors_primary()781     public void wallpaperColors_primary() {
782         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
783         Canvas canvas = new Canvas(tmpWallpaper);
784         canvas.drawColor(Color.RED);
785 
786         try {
787             mWallpaperManager.setBitmap(tmpWallpaper);
788             WallpaperColors colors = mWallpaperManager.getWallpaperColors(
789                     FLAG_SYSTEM);
790 
791             // Check that primary color is almost red
792             Color primary = colors.getPrimaryColor();
793             final float delta = 0.1f;
794             assertWithMessage("red").that(primary.red()).isWithin(delta).of(1f);
795             assertWithMessage("green").that(primary.green()).isWithin(delta).of(0f);
796             assertWithMessage("blue").that(primary.blue()).isWithin(delta).of(0f);
797 
798             assertThat(colors.getSecondaryColor()).isNull();
799             assertThat(colors.getTertiaryColor()).isNull();
800         } catch (IOException e) {
801             throw new RuntimeException(e);
802         } finally {
803             tmpWallpaper.recycle();
804         }
805     }
806 
807     @Test
808     @Ignore("b/265007420")
wallpaperColors_secondary()809     public void wallpaperColors_secondary() {
810         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
811         Canvas canvas = new Canvas(tmpWallpaper);
812         canvas.drawColor(Color.RED);
813         // Make 20% of the wallpaper BLUE so that secondary color is BLUE
814         canvas.clipRect(0, 0, 100, 20);
815         canvas.drawColor(Color.BLUE);
816 
817         try {
818             mWallpaperManager.setBitmap(tmpWallpaper);
819             WallpaperColors colors = mWallpaperManager.getWallpaperColors(
820                     FLAG_SYSTEM);
821 
822             // Check that the secondary color is almost blue
823             Color secondary = colors.getSecondaryColor();
824             final float delta = 0.15f;
825             assertWithMessage("red").that(secondary.red()).isWithin(delta).of(0f);
826             assertWithMessage("green").that(secondary.green()).isWithin(delta).of(0f);
827             assertWithMessage("blue").that(secondary.blue()).isWithin(delta).of(1f);
828         } catch (IOException e) {
829             throw new RuntimeException(e);
830         } finally {
831             tmpWallpaper.recycle();
832         }
833     }
834 
835     @Test
highRatioWallpaper_largeWidth()836     public void highRatioWallpaper_largeWidth() throws Exception {
837         Bitmap highRatioWallpaper = Bitmap.createBitmap(8000, 800, Bitmap.Config.ARGB_8888);
838         Canvas canvas = new Canvas(highRatioWallpaper);
839         canvas.drawColor(Color.RED);
840 
841         try {
842             mWallpaperManager.setBitmap(highRatioWallpaper);
843             assertBitmapDimensions(mWallpaperManager.getBitmap());
844         } finally {
845             highRatioWallpaper.recycle();
846         }
847     }
848 
849     @Test
highRatioWallpaper_largeHeight()850     public void highRatioWallpaper_largeHeight() throws Exception {
851         Bitmap highRatioWallpaper = Bitmap.createBitmap(800, 8000, Bitmap.Config.ARGB_8888);
852         Canvas canvas = new Canvas(highRatioWallpaper);
853         canvas.drawColor(Color.RED);
854 
855         try {
856             mWallpaperManager.setBitmap(highRatioWallpaper);
857             assertBitmapDimensions(mWallpaperManager.getBitmap());
858         } finally {
859             highRatioWallpaper.recycle();
860         }
861     }
862 
863     @Test
highResolutionWallpaper()864     public void highResolutionWallpaper() throws Exception {
865         Bitmap highResolutionWallpaper = Bitmap.createBitmap(10000, 10000, Bitmap.Config.ARGB_8888);
866         Canvas canvas = new Canvas(highResolutionWallpaper);
867         canvas.drawColor(Color.BLUE);
868 
869         try {
870             mWallpaperManager.setBitmap(highResolutionWallpaper);
871             assertBitmapDimensions(mWallpaperManager.getBitmap());
872         } finally {
873             highResolutionWallpaper.recycle();
874         }
875     }
876 
877     @Test
testWideGamutWallpaper()878     public void testWideGamutWallpaper() throws IOException {
879         final ColorSpace srgb = ColorSpace.get(ColorSpace.Named.SRGB);
880         final ColorSpace p3 = ColorSpace.get(ColorSpace.Named.DISPLAY_P3);
881         final Bitmap.Config config = Bitmap.Config.ARGB_8888;
882         final Bitmap srgbBitmap = Bitmap.createBitmap(100, 100, config);
883         final Bitmap p3Bitmap = Bitmap.createBitmap(100, 100, config, false, p3);
884 
885         try {
886             // sRGB is the default color space
887             mWallpaperManager.setBitmap(srgbBitmap);
888             assertThat(mWallpaperManager.getBitmap().getColorSpace()).isEqualTo(srgb);
889 
890             // If wide gamut is enabled, Display-P3 should be supported.
891             mWallpaperManager.setBitmap(p3Bitmap);
892 
893             final boolean isDisplayP3 = mWallpaperManager.getBitmap().getColorSpace().equals(p3);
894             // Assert false only when device enabled WCG, but display does not support Display-P3
895             assertThat(mEnableWcg && !isDisplayP3).isFalse();
896         } finally {
897             srgbBitmap.recycle();
898             p3Bitmap.recycle();
899         }
900     }
901 
902     @Test
testWallpaperSupportsWcg()903     public void testWallpaperSupportsWcg() throws IOException {
904         final int sysWallpaper = FLAG_SYSTEM;
905 
906         final Bitmap srgbBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
907         final Bitmap p3Bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888, false,
908                 ColorSpace.get(ColorSpace.Named.DISPLAY_P3));
909 
910         try {
911             mWallpaperManager.setBitmap(srgbBitmap);
912             assertThat(mWallpaperManager.wallpaperSupportsWcg(sysWallpaper)).isFalse();
913 
914             mWallpaperManager.setBitmap(p3Bitmap);
915             assertThat(mWallpaperManager.wallpaperSupportsWcg(sysWallpaper)).isEqualTo(mEnableWcg);
916         } finally {
917             srgbBitmap.recycle();
918             p3Bitmap.recycle();
919         }
920     }
921 
922     /**
923      * Check that all the callback methods of the wallpaper are invoked by the same thread.
924      * Also checks that the callback methods are called in a proper order.
925      * See {@link TestWallpaperService} to see the checks that are performed.
926      */
927     @Test
wallpaperCallbackMainThreadTest()928     public void wallpaperCallbackMainThreadTest() {
929 
930         // use a wallpaper supporting ambient mode, to trigger Engine.onAmbientModeChanged
931         ComponentName componentName = new ComponentName(
932                 TestLiveWallpaperSupportingAmbientMode.class.getPackageName(),
933                 TestLiveWallpaperSupportingAmbientMode.class.getName());
934         runWithShellPermissionIdentity(() ->
935                 mWallpaperManager.setWallpaperComponent(componentName));
936 
937         // trigger Engine.onDesiredDimensionsChanged
938         mWallpaperManager.suggestDesiredDimensions(1000, 1000);
939 
940         Activity activity = mActivityTestRule.launchActivity(null);
941 
942         Window window = activity.getWindow();
943         IBinder windowToken = window.getDecorView().getWindowToken();
944 
945         // send some command to trigger Engine.onCommand
946         mWallpaperManager.sendWallpaperCommand(
947                 windowToken, WallpaperManager.COMMAND_TAP, 50, 50, 0, null);
948 
949         // trigger Engine.onZoomChanged
950         mWallpaperManager.setWallpaperZoomOut(windowToken, 0.5f);
951 
952         // trigger Engine.onTouchEvent
953         mCtsTouchUtils.emulateTapOnViewCenter(
954                 InstrumentationRegistry.getInstrumentation(), null,
955                 activity.findViewById(android.R.id.content));
956 
957         mActivityTestRule.finishActivity();
958         runWithShellPermissionIdentity(() -> mWallpaperManager.clearWallpaper());
959     }
960 
961     @Test
peekWallpaperCaching_cachesWallpaper()962     public void peekWallpaperCaching_cachesWallpaper() throws IOException {
963         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
964 
965         // Get the current bitmap, and check that the second call returns the cached bitmap
966         Bitmap bitmap1 = mWallpaperManager.getBitmapAsUser(mContext.getUserId(),
967                 false /* hardware */, FLAG_SYSTEM);
968         assertThat(bitmap1).isNotNull();
969         assertThat(mWallpaperManager.getBitmapAsUser(mContext.getUserId(), false /* hardware */,
970                 FLAG_SYSTEM)).isSameInstanceAs(bitmap1);
971 
972         // Change the wallpaper to invalidate the cached bitmap
973         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_SYSTEM);
974 
975         // Get the new bitmap, and check that the second call returns the newly cached bitmap
976         Bitmap bitmap2 = mWallpaperManager.getBitmapAsUser(mContext.getUserId(),
977                 false /* hardware */, FLAG_SYSTEM);
978         assertThat(bitmap2).isNotSameInstanceAs(bitmap1);
979         assertThat(mWallpaperManager.getBitmapAsUser(mContext.getUserId(), false /* hardware */,
980                 FLAG_SYSTEM)).isSameInstanceAs(bitmap2);
981     }
982 
983     @Test
peekWallpaperCaching_differentWhich_doesNotReturnCached()984     public void peekWallpaperCaching_differentWhich_doesNotReturnCached() throws IOException {
985         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
986         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_LOCK);
987 
988         Bitmap bitmapSystem = mWallpaperManager.getBitmapAsUser(mContext.getUserId(),
989                 false /* hardware */, FLAG_SYSTEM);
990         Bitmap bitmapLock = mWallpaperManager.getBitmapAsUser(mContext.getUserId(),
991                 false /* hardware */, FLAG_LOCK);
992         assertThat(bitmapLock).isNotSameInstanceAs(bitmapSystem);
993 
994     }
995 
996     @Test
peekWallpaperCaching_bitmapRecycled_doesNotReturnCached()997     public void peekWallpaperCaching_bitmapRecycled_doesNotReturnCached() throws IOException {
998         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
999 
1000         Bitmap bitmap = mWallpaperManager.getBitmapAsUser(mContext.getUserId(),
1001                 false /* hardware */, FLAG_SYSTEM);
1002         assertThat(bitmap).isNotNull();
1003         bitmap.recycle();
1004         assertThat(mWallpaperManager.getBitmapAsUser(mContext.getUserId(), false /* hardware */,
1005                 FLAG_SYSTEM)).isNotSameInstanceAs(bitmap);
1006     }
1007 
1008     @Test
peekWallpaperCaching_differentUser_doesNotReturnCached()1009     public void peekWallpaperCaching_differentUser_doesNotReturnCached() throws IOException {
1010         final int bogusUserId = -1;
1011         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1012 
1013         Bitmap bitmap = mWallpaperManager.getBitmapAsUser(mContext.getUserId(),
1014                 false /* hardware */, FLAG_SYSTEM);
1015         assertThat(bitmap).isNotNull();
1016 
1017         // If the cached bitmap was determined to be invalid, this leads to a call to
1018         // WallpaperManager.Globals#getCurrentWallpaperLocked() for a different user, which
1019         // generates a security exception: the exception indicates that the cached bitmap was
1020         // invalid, which is the desired result.
1021         assertThrows(SecurityException.class,
1022                 () -> mWallpaperManager.getBitmapAsUser(bogusUserId, false /* hardware */,
1023                         FLAG_SYSTEM));
1024     }
1025 
1026     @Test
peekWallpaperDimensions_homeScreen_succeeds()1027     public void peekWallpaperDimensions_homeScreen_succeeds() throws IOException {
1028         final int width = 100;
1029         final int height = 200;
1030         Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
1031         Canvas canvas = new Canvas(bitmap);
1032         canvas.drawColor(Color.RED);
1033         mWallpaperManager.setBitmap(bitmap);
1034 
1035         Bitmap croppedBitmap = mWallpaperManager.getBitmap();
1036         Rect expectedSize = new Rect(0, 0, croppedBitmap.getWidth(), croppedBitmap.getHeight());
1037         Rect actualSize = mWallpaperManager.peekBitmapDimensions();
1038 
1039         assertThat(actualSize).isEqualTo(expectedSize);
1040     }
1041 
1042     @Test
peekWallpaperDimensions_lockScreenUnset_succeeds()1043     public void peekWallpaperDimensions_lockScreenUnset_succeeds() {
1044         Rect actualSize = mWallpaperManager.peekBitmapDimensions(FLAG_LOCK);
1045 
1046         assertThat(actualSize).isNull();
1047     }
1048 
1049     @Test
peekWallpaperDimensions_lockScreenSet_succeeds()1050     public void peekWallpaperDimensions_lockScreenSet_succeeds() throws IOException {
1051         Bitmap homeBitmap = Bitmap.createBitmap(150 /* width */, 150 /* width */,
1052                 Bitmap.Config.ARGB_8888);
1053         Canvas homeCanvas = new Canvas(homeBitmap);
1054         homeCanvas.drawColor(Color.RED);
1055         mWallpaperManager.setBitmap(homeBitmap, /* visibleCropHint */ null, /* allowBackup */true,
1056                 FLAG_SYSTEM);
1057         final int width = 100;
1058         final int height = 200;
1059         Bitmap lockBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
1060         Canvas lockCanvas = new Canvas(lockBitmap);
1061         lockCanvas.drawColor(Color.RED);
1062         mWallpaperManager.setBitmap(lockBitmap, /* visibleCropHint */ null, /* allowBackup */true,
1063                 FLAG_LOCK);
1064 
1065         Drawable drawable = mWallpaperManager.getDrawable(FLAG_LOCK);
1066         Rect expectedSize = new Rect(
1067                 0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
1068         Rect actualSize = mWallpaperManager.peekBitmapDimensions(FLAG_LOCK);
1069 
1070         assertThat(actualSize).isEqualTo(expectedSize);
1071     }
1072 
1073     @Test
getDrawable_homeScreen_succeeds()1074     public void getDrawable_homeScreen_succeeds() throws IOException {
1075         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1076         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1077 
1078         Drawable actual = mWallpaperManager.getDrawable(FLAG_SYSTEM);
1079 
1080         assertWithMessage("Drawables must represent the same image").that(
1081                 isSimilar(actual, expected, true)).isTrue();
1082     }
1083 
1084     @Test
getDrawable_lockScreenUnset_returnsNull()1085     public void getDrawable_lockScreenUnset_returnsNull() {
1086         Drawable actual = mWallpaperManager.getDrawable(FLAG_LOCK);
1087 
1088         assertThat(actual).isNull();
1089     }
1090 
1091     @Test
getDrawable_lockScreenSet_succeeds()1092     public void getDrawable_lockScreenSet_succeeds() throws IOException {
1093         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1094         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
1095 
1096         Drawable actual = mWallpaperManager.getDrawable(FLAG_LOCK);
1097 
1098         assertWithMessage("Drawables must represent the same image").that(
1099                 isSimilar(actual, expected, true)).isTrue();
1100     }
1101 
1102     @Test
getDrawable_default_sameAsHome()1103     public void getDrawable_default_sameAsHome() throws IOException {
1104         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1105         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1106 
1107         Drawable actual = mWallpaperManager.getDrawable();
1108 
1109         assertWithMessage("Drawables must represent the same image").that(
1110                 isSimilar(actual, expected, true)).isTrue();
1111     }
1112 
1113     @Test
getFastDrawable_homeScreen_succeeds()1114     public void getFastDrawable_homeScreen_succeeds() throws IOException {
1115         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1116         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1117 
1118         Drawable actual = mWallpaperManager.getFastDrawable(FLAG_SYSTEM);
1119 
1120         assertWithMessage("Drawables must represent the same image").that(
1121                 isSimilar(actual, expected, true)).isTrue();
1122     }
1123 
1124     @Test
getFastDrawable_lockScreenUnset_returnsNull()1125     public void getFastDrawable_lockScreenUnset_returnsNull() {
1126         Drawable actual = mWallpaperManager.getFastDrawable(FLAG_LOCK);
1127 
1128         assertThat(actual).isNull();
1129     }
1130 
1131     @Test
getFastDrawable_lockScreenSet_succeeds()1132     public void getFastDrawable_lockScreenSet_succeeds() throws IOException {
1133         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1134         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
1135 
1136         Drawable actual = mWallpaperManager.getFastDrawable(FLAG_LOCK);
1137 
1138         assertWithMessage("Drawables must represent the same image").that(
1139                 isSimilar(actual, expected, true)).isTrue();
1140     }
1141 
1142     @Test
getFastDrawable_default_sameAsHome()1143     public void getFastDrawable_default_sameAsHome() throws IOException {
1144         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1145         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1146 
1147         Drawable actual = mWallpaperManager.getFastDrawable();
1148 
1149         assertWithMessage("Drawables must represent the same image").that(
1150                 isSimilar(actual, expected, true)).isTrue();
1151     }
1152 
1153     @Test
peekDrawable_homeScreen_succeeds()1154     public void peekDrawable_homeScreen_succeeds() throws IOException {
1155         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1156         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1157 
1158         Drawable actual = mWallpaperManager.peekDrawable(FLAG_SYSTEM);
1159 
1160         assertWithMessage("Drawables must represent the same image").that(
1161                 isSimilar(actual, expected, true)).isTrue();
1162     }
1163 
1164     @Test
peekDrawable_lockScreenUnset_returnsNull()1165     public void peekDrawable_lockScreenUnset_returnsNull() {
1166         Drawable actual = mWallpaperManager.peekDrawable(FLAG_LOCK);
1167 
1168         assertThat(actual).isNull();
1169     }
1170 
1171     @Test
peekDrawable_lockScreenSet_succeeds()1172     public void peekDrawable_lockScreenSet_succeeds() throws IOException {
1173         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1174         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
1175 
1176         Drawable actual = mWallpaperManager.peekDrawable(FLAG_LOCK);
1177 
1178         assertWithMessage("Drawables must represent the same image").that(
1179                 isSimilar(actual, expected, true)).isTrue();
1180     }
1181 
1182     @Test
peekDrawable_default_sameAsHome()1183     public void peekDrawable_default_sameAsHome() throws IOException {
1184         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1185         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1186 
1187         Drawable actual = mWallpaperManager.peekDrawable();
1188 
1189         assertWithMessage("Drawables must represent the same image").that(
1190                 isSimilar(actual, expected, true)).isTrue();
1191     }
1192 
1193     @Test
peekFastDrawable_homeScreen_succeeds()1194     public void peekFastDrawable_homeScreen_succeeds() throws IOException {
1195         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1196         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1197 
1198         Drawable actual = mWallpaperManager.peekFastDrawable(FLAG_SYSTEM);
1199 
1200         assertWithMessage("Drawables must represent the same image").that(
1201                 isSimilar(actual, expected, true)).isTrue();
1202     }
1203 
1204     @Test
peekFastDrawable_lockScreenUnset_returnsNull()1205     public void peekFastDrawable_lockScreenUnset_returnsNull() {
1206         Drawable actual = mWallpaperManager.peekFastDrawable(FLAG_LOCK);
1207 
1208         assertThat(actual).isNull();
1209     }
1210 
1211     @Test
peekFastDrawable_lockScreenSet_succeeds()1212     public void peekFastDrawable_lockScreenSet_succeeds() throws IOException {
1213         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1214         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
1215 
1216         Drawable actual = mWallpaperManager.peekFastDrawable(FLAG_LOCK);
1217 
1218         assertWithMessage("Drawables must represent the same image").that(
1219                 isSimilar(actual, expected, true)).isTrue();
1220     }
1221 
1222     @Test
peekFastDrawable_default_sameAsHome()1223     public void peekFastDrawable_default_sameAsHome() throws IOException {
1224         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1225         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1226 
1227         Drawable actual = mWallpaperManager.peekFastDrawable();
1228 
1229         assertWithMessage("Drawables must represent the same image").that(
1230                 isSimilar(actual, expected, true)).isTrue();
1231     }
1232 
1233     /**
1234      * For every possible (state, change) couple, checks that the number of times
1235      * {@link TestWallpaperService.FakeEngine#onDestroy} and
1236      * {@link TestWallpaperService.FakeEngine#onCreate} are called is correct.
1237      */
1238     @Test
testEngineCallbackCountsParam( @estParameter WallpaperManagerTestUtils.WallpaperState state)1239     public void testEngineCallbackCountsParam(
1240             @TestParameter WallpaperManagerTestUtils.WallpaperState state)
1241             throws IOException {
1242         ArrayList<String> errorMessages = new ArrayList<>();
1243         runWithShellPermissionIdentity(() -> {
1244             for (WallpaperChange change: state.allPossibleChanges()) {
1245                 WallpaperManagerTestUtils.goToState(mWallpaperManager, state);
1246                 TestWallpaperService.Companion.resetCounts();
1247                 final int expectedCreateCount =
1248                         state.expectedNumberOfLiveWallpaperCreate(change);
1249                 final int expectedDestroyCount =
1250                         state.expectedNumberOfLiveWallpaperDestroy(change);
1251 
1252                 runAndAwaitChanges(5, TimeUnit.SECONDS,
1253                         expectedCreateCount, expectedDestroyCount, 0, () -> {
1254                             WallpaperManagerTestUtils.performChange(mWallpaperManager, change);
1255                         });
1256 
1257                 int actualCreateCount = TestWallpaperService.Companion.getCreateCount();
1258                 String createMessage = String.format(
1259                         "Expected %s calls to Engine#onCreate, got %s. ",
1260                         expectedCreateCount, actualCreateCount);
1261                 if (actualCreateCount != expectedCreateCount) {
1262                     errorMessages.add(
1263                             createMessage + "\n" + state.reproduceDescription(change));
1264                 }
1265 
1266                 int actualDestroyCount = TestWallpaperService.Companion.getDestroyCount();
1267                 String destroyMessage = String.format(
1268                         "Expected %s calls to Engine#onDestroy, got %s. ",
1269                         expectedDestroyCount, actualDestroyCount);
1270                 if (actualDestroyCount != expectedDestroyCount) {
1271                     errorMessages.add(
1272                             destroyMessage + "\n" + state.reproduceDescription(change));
1273                 }
1274             }
1275         });
1276         assertWithMessage(String.join("\n\n", errorMessages))
1277                 .that(errorMessages.size()).isEqualTo(0);
1278     }
1279 
1280     /**
1281      * Check that the wallpaper windows that window manager is handling
1282      * are exactly the expected ones
1283      */
1284     @Test
testExistingWallpaperWindows()1285     public void testExistingWallpaperWindows() {
1286         assumeTrue("Test requires FEATURE_LIVE_WALLPAPER",
1287                 mContext.getPackageManager().hasSystemFeature(FEATURE_LIVE_WALLPAPER));
1288         runWithShellPermissionIdentity(() -> {
1289             WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper =
1290                     new WallpaperWindowsTestUtils.WallpaperWindowsHelper(sWindowManagerStateHelper);
1291             // Two independent wallpapers
1292             WallpaperManagerTestUtils.goToState(
1293                     mWallpaperManager, WallpaperState.LIVE_DIFF_MULTI);
1294             assertWallpapersMatching(wallpaperWindowsHelper,
1295                     List.of(mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM).getServiceName(),
1296                             mWallpaperManager.getWallpaperInfo(FLAG_LOCK).getServiceName()));
1297             // One shared wallpaper
1298             WallpaperManagerTestUtils.goToState(
1299                     mWallpaperManager, WallpaperState.LIVE_SAME_SINGLE);
1300             assertWallpapersMatching(wallpaperWindowsHelper, List.of(
1301                     mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM).getServiceName()));
1302         });
1303     }
1304 
startAndWaitActivity()1305     private void startAndWaitActivity() {
1306         mActivityTestRule.launchActivity(null);
1307         sWindowManagerStateHelper.waitAndAssertActivityState(
1308                 mActivityTestRule.getActivity().getComponentName(),
1309                 WindowManagerState.STATE_RESUMED);
1310     }
1311 
1312     /**
1313      * Check that the windows which have the role of home screen wallpapers
1314      * are actually visible on home screen
1315      */
1316     @Test
testSystemAndLockWallpaperVisibility_onHomeScreen()1317     public void testSystemAndLockWallpaperVisibility_onHomeScreen() {
1318         assumeTrue("Test requires FEATURE_LIVE_WALLPAPER",
1319                 mContext.getPackageManager().hasSystemFeature(FEATURE_LIVE_WALLPAPER));
1320         try (LockScreenSession lockScreenSession =
1321                      new LockScreenSession(mInstrumentation, sWindowManagerStateHelper)) {
1322             runWithShellPermissionIdentity(() -> {
1323                 WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper =
1324                         new WallpaperWindowsTestUtils.WallpaperWindowsHelper(
1325                                 sWindowManagerStateHelper);
1326                 lockScreenSession.disableLockScreen().unlockDevice();
1327 
1328                 // Launch an activity that shows the wallpaper to make sure it is not behind
1329                 // opaque activities
1330                 startAndWaitActivity();
1331 
1332                 // Two independent wallpapers
1333                 WallpaperManagerTestUtils.goToState(mWallpaperManager,
1334                         WallpaperState.LIVE_DIFF_MULTI);
1335                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_SYSTEM,
1336                         true /* shouldBeShown */, "System wallpaper is hidden on home screen");
1337 
1338                 // Shared wallpaper
1339                 WallpaperManagerTestUtils.goToState(
1340                         mWallpaperManager, WallpaperState.LIVE_SAME_SINGLE);
1341                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_SYSTEM | FLAG_LOCK,
1342                         true /* shouldBeShown */, "Shared wallpaper is hidden on home screen");
1343             });
1344         }
1345     }
1346 
1347     /**
1348      * Check that the windows which have the role of lock screen wallpapers
1349      * are actually visible on lock screen
1350      */
1351     @Test
testSystemAndLockWallpaperVisibility_onLockScreen()1352     public void testSystemAndLockWallpaperVisibility_onLockScreen() throws Exception {
1353         assumeFalse("Test requires support for different lock and home screen wallpapers",
1354                 mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH));
1355 
1356         assumeTrue("Test requires FEATURE_SECURE_LOCK_SCREEN",
1357                 mContext.getPackageManager().hasSystemFeature(FEATURE_SECURE_LOCK_SCREEN));
1358         assumeTrue("Test requires FEATURE_LIVE_WALLPAPER",
1359                 mContext.getPackageManager().hasSystemFeature(FEATURE_LIVE_WALLPAPER));
1360         try (LockScreenSession lockScreenSession =
1361                      new LockScreenSession(mInstrumentation, sWindowManagerStateHelper)) {
1362             runWithShellPermissionIdentity(() -> {
1363                 WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper =
1364                         new WallpaperWindowsTestUtils.WallpaperWindowsHelper(
1365                                 sWindowManagerStateHelper);
1366 
1367                 // Two independent wallpapers
1368                 WallpaperManagerTestUtils.goToState(mWallpaperManager,
1369                         WallpaperState.LIVE_DIFF_MULTI);
1370 
1371                 lockScreenSession.gotoKeyguard();
1372                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_SYSTEM,
1373                         false /* shouldBeShown */,
1374                         "System wallpaper is showing on lock screen");
1375                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_LOCK, true /* shouldBeShown */,
1376                         "Lock wallpaper is hidden on lock screen");
1377 
1378                 // Shared wallpaper
1379                 WallpaperManagerTestUtils.goToState(
1380                         mWallpaperManager, WallpaperState.LIVE_SAME_SINGLE);
1381                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_SYSTEM | FLAG_LOCK,
1382                         true /* shouldBeShown */, "Shared wallpaper is hidden on lock screen");
1383             });
1384         }
1385     }
1386 
1387     /**
1388      * Verify that a shared wallpaper is visible behind a show wallpaper activity on lockscreen
1389      */
1390     @Test
testSharedWallpaperVisibilityBehindActivity_onLockScreen()1391     public void testSharedWallpaperVisibilityBehindActivity_onLockScreen() throws Exception {
1392         assumeTrue("Test requires FEATURE_SECURE_LOCK_SCREEN",
1393                 mContext.getPackageManager().hasSystemFeature(FEATURE_SECURE_LOCK_SCREEN));
1394         assumeTrue("Test requires FEATURE_LIVE_WALLPAPER",
1395                 mContext.getPackageManager().hasSystemFeature(FEATURE_LIVE_WALLPAPER));
1396         try (LockScreenSession lockScreenSession =
1397                      new LockScreenSession(mInstrumentation, sWindowManagerStateHelper)) {
1398             runWithShellPermissionIdentity(() -> {
1399                 WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper =
1400                         new WallpaperWindowsTestUtils.WallpaperWindowsHelper(
1401                                 sWindowManagerStateHelper);
1402 
1403                 startAndWaitActivity();
1404 
1405                 // Make sure a live wallpaper is configured and used for both home and lock
1406                 // screens.
1407                 final WallpaperInfo homeInfo = mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM);
1408                 final int lockInfo = mWallpaperManager.getWallpaperId(FLAG_LOCK);
1409                 if (homeInfo == null || lockInfo >= 0) {
1410                     WallpaperManagerTestUtils.goToState(mWallpaperManager,
1411                             WallpaperState.LIVE_SAME_SINGLE);
1412                 }
1413 
1414                 lockScreenSession.gotoKeyguard();
1415                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_SYSTEM | FLAG_LOCK,
1416                         true /* shouldBeShown */,
1417                         "Shared wallpaper should be showing behind activity");
1418             });
1419         }
1420     }
1421 
1422     /**
1423      * Verify that the home wallpaper is never visible behind an activity on lock screen, and that
1424      * the lock screen wallpaper is visible when it has its own window.
1425      */
1426     @Test
testIndependentWallpaperVisibilityBehindActivity_onLockScreen()1427     public void testIndependentWallpaperVisibilityBehindActivity_onLockScreen() throws Exception {
1428         assumeFalse("Test requires support for different lock and home screen wallpapers",
1429                 mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH));
1430         assumeTrue("Test requires FEATURE_SECURE_LOCK_SCREEN",
1431                 mContext.getPackageManager().hasSystemFeature(FEATURE_SECURE_LOCK_SCREEN));
1432         assumeTrue("Test requires FEATURE_LIVE_WALLPAPER",
1433                 mContext.getPackageManager().hasSystemFeature(FEATURE_LIVE_WALLPAPER));
1434 
1435         try (LockScreenSession lockScreenSession =
1436                      new LockScreenSession(mInstrumentation, sWindowManagerStateHelper)) {
1437             runWithShellPermissionIdentity(() -> {
1438                 WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper =
1439                         new WallpaperWindowsTestUtils.WallpaperWindowsHelper(
1440                                 sWindowManagerStateHelper);
1441 
1442                 startAndWaitActivity();
1443 
1444                 WallpaperState wallpaperState = WallpaperState.LIVE_DIFF_MULTI;
1445                 WallpaperManagerTestUtils.goToState(mWallpaperManager, wallpaperState);
1446                 lockScreenSession.gotoKeyguard();
1447                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_LOCK,
1448                         true /* shouldBeShown */,
1449                         "Lock wallpaper should be showing behind an activity");
1450                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_SYSTEM,
1451                         false /* shouldBeShown */,
1452                         "Home wallpaper should not be showing behind an activity on lock screen");
1453             });
1454         }
1455     }
1456 
1457     @Test
1458     @Ignore("b/281082882")
setDimAmount_lockScreenUnset_notifiesColorsChangedBothTogether()1459     public void setDimAmount_lockScreenUnset_notifiesColorsChangedBothTogether() {
1460         ensureCleanState();
1461 
1462         final CountDownLatch latch = new CountDownLatch(1);
1463         WallpaperManager.OnColorsChangedListener counter = (colors, whichWp) -> latch.countDown();
1464         final LinkedList<Integer> receivedFlags = new LinkedList<>();
1465         WallpaperManager.OnColorsChangedListener listener = (colors, whichWp) -> receivedFlags.add(
1466                 whichWp);
1467         mWallpaperManager.addOnColorsChangedListener(listener, mHandler);
1468         mWallpaperManager.addOnColorsChangedListener(counter, mHandler);
1469         final float initialDim = runWithShellPermissionIdentity(
1470                 mWallpaperManager::getWallpaperDimAmount);
1471         final float newDim = initialDim > 0 ? 0.5f * initialDim : 0.5f;
1472 
1473         try {
1474             runWithShellPermissionIdentity(() -> {
1475                 mWallpaperManager.setWallpaperDimAmount(newDim);
1476             });
1477             boolean latchSuccess = latch.await(DIM_LISTENER_TIMEOUT_SECS, TimeUnit.SECONDS);
1478             assertWithMessage("Registered listener not invoked").that(latchSuccess).isTrue();
1479         } catch (InterruptedException e) {
1480             throw new RuntimeException(e);
1481         } finally {
1482             runWithShellPermissionIdentity(() ->
1483                     mWallpaperManager.setWallpaperDimAmount(initialDim));
1484         }
1485 
1486         assertThat(receivedFlags).containsExactly(FLAG_SYSTEM | FLAG_LOCK);
1487         mWallpaperManager.removeOnColorsChangedListener(listener);
1488         mWallpaperManager.removeOnColorsChangedListener(counter);
1489     }
1490 
1491     @Test
1492     @Ignore("b/281082882")
setDimAmount_lockScreenSet_notifiesColorsChangedBothSeparately()1493     public void setDimAmount_lockScreenSet_notifiesColorsChangedBothSeparately() {
1494         ensureCleanState(FLAG_LOCK);
1495         ensureCleanState(FLAG_SYSTEM);
1496 
1497         final CountDownLatch latch = new CountDownLatch(2);
1498         WallpaperManager.OnColorsChangedListener counter = (colors, whichWp) -> latch.countDown();
1499         final LinkedList<Integer> receivedFlags = new LinkedList<>();
1500         WallpaperManager.OnColorsChangedListener listener = (colors, whichWp) -> receivedFlags.add(
1501                 whichWp);
1502         mWallpaperManager.addOnColorsChangedListener(listener, mHandler);
1503         final float initialDim = runWithShellPermissionIdentity(
1504                 mWallpaperManager::getWallpaperDimAmount);
1505         final float newDim = initialDim > 0 ? 0.5f * initialDim : 0.5f;
1506 
1507         mWallpaperManager.addOnColorsChangedListener(counter, mHandler);
1508         try {
1509             runWithShellPermissionIdentity(() -> {
1510                 mWallpaperManager.setWallpaperDimAmount(newDim);
1511             });
1512             boolean latchSuccess = latch.await(DIM_LISTENER_TIMEOUT_SECS, TimeUnit.SECONDS);
1513             assertWithMessage("Registered listener not invoked").that(latchSuccess).isTrue();
1514         } catch (InterruptedException e) {
1515             throw new RuntimeException(e);
1516         } finally {
1517             runWithShellPermissionIdentity(() ->
1518                     mWallpaperManager.setWallpaperDimAmount(initialDim));
1519         }
1520 
1521         assertThat(receivedFlags).containsExactly(FLAG_SYSTEM, FLAG_LOCK);
1522         mWallpaperManager.removeOnColorsChangedListener(listener);
1523         mWallpaperManager.removeOnColorsChangedListener(counter);
1524     }
1525 
assertWallpapersMatching(WallpaperWindowsTestUtils.WallpaperWindowsHelper windows, List<String> expectedWallpaperPackageNames)1526     private void assertWallpapersMatching(WallpaperWindowsTestUtils.WallpaperWindowsHelper windows,
1527             List<String> expectedWallpaperPackageNames) {
1528 
1529         boolean match = windows.waitForMatchingPackages(expectedWallpaperPackageNames);
1530         assertWithMessage("Lists do not match. Expected: "
1531                 + expectedWallpaperPackageNames + " but received " + windows.dumpPackages())
1532                 .that(match).isTrue();
1533     }
1534 
1535     /** Check if wallpaper corresponding to wallpaperFlag has visibility matching shouldBeShown */
assertWallpaperIsShown( WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper, int wallpaperFlag, boolean shouldBeShown, String errorMsg)1536     private void assertWallpaperIsShown(
1537             WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper,
1538             int wallpaperFlag,
1539             boolean shouldBeShown,
1540             String errorMsg) {
1541         String wpServiceName = mWallpaperManager.getWallpaperInfo(
1542                 (wallpaperFlag & FLAG_SYSTEM) != 0 ? FLAG_SYSTEM : FLAG_LOCK).getServiceName();
1543 
1544         boolean matchingVisibility = wallpaperWindowsHelper
1545                 .waitForMatchingWindowVisibility(wpServiceName, shouldBeShown);
1546         assertWithMessage(errorMsg + "\n" + wallpaperWindowsHelper.dumpWindows())
1547                 .that(matchingVisibility).isTrue();
1548     }
1549 
1550     /**
1551      * Granting android.permission.ALWAYS_UPDATE_WALLPAPER should allow the wallpaper
1552      * commands to be sent even when activity is not in focus
1553      * Note that there is no window to focus in this test
1554      */
1555     @RequiresFlagsEnabled(Flags.FLAG_ALWAYS_UPDATE_WALLPAPER_PERMISSION)
1556     @Test
1557     @Ignore("b/313534425")
testAlwaysUpdateWallpaperPermission_allowOutOfFocusWallpaperCommand()1558     public void testAlwaysUpdateWallpaperPermission_allowOutOfFocusWallpaperCommand() {
1559 
1560         /* Clear previous wallpaper commands */
1561         TestLiveWallpaper.Companion.resetPrevAction();
1562 
1563         runWithShellPermissionIdentity(
1564                 () -> {
1565                     mWallpaperManager.setWallpaperComponent(TEST_COMPONENT_NAME);
1566 
1567                     /* Activity that will be overlaid and lose focus */
1568                     WallpaperOverlayTestActivity overlayActivity =
1569                             mOverlayActivityTestRule.launchActivity(null);
1570                     sWindowManagerStateHelper.waitAndAssertActivityState(
1571                             overlayActivity.getComponentName(),
1572                             WindowManagerState.STATE_RESUMED);
1573                     assertTrue(
1574                             "overlayActivity does not have required permission",
1575                             overlayActivity.checkSelfPermission(ALWAYS_UPDATE_WALLPAPER)
1576                                     == PERMISSION_GRANTED);
1577 
1578                     /* Launch base activity to cover the overlay activity */
1579                     Activity baseActivity = mActivityTestRule.launchActivity(null);
1580                     sWindowManagerStateHelper.waitAndAssertActivityState(
1581                             baseActivity.getComponentName(),
1582                             WindowManagerState.STATE_RESUMED);
1583 
1584                     /* Send wallpaper command with ALWAYS_UPDATE_WALLPAPER permission */
1585                     overlayActivity.sendWallpaperCommand(WallpaperManager.COMMAND_TAP);
1586 
1587                     /* Allow time for the wallpaper command to be sent over IPC stack */
1588                     try {
1589                         Thread.sleep(SLEEP_MS);
1590                     } catch (InterruptedException e) {
1591                         throw new RuntimeException(e);
1592                     }
1593 
1594                     assertWithMessage("Wallpaper command is not sent with permission")
1595                             .that(TestLiveWallpaper.Companion.getPrevAction())
1596                             .isEqualTo(WallpaperManager.COMMAND_TAP);
1597                 });
1598     }
1599 
assertBitmapDimensions(Bitmap bitmap)1600     private void assertBitmapDimensions(Bitmap bitmap) {
1601         int maxSize = getMaxTextureSize();
1602         boolean safe = false;
1603         if (bitmap != null) {
1604             safe = bitmap.getWidth() <= maxSize && bitmap.getHeight() <= maxSize;
1605         }
1606         assertThat(safe).isTrue();
1607     }
1608 
assertDesiredDimension(Point suggestedSize, Point expectedSize)1609     private void assertDesiredDimension(Point suggestedSize, Point expectedSize) {
1610         mWallpaperManager.suggestDesiredDimensions(suggestedSize.x, suggestedSize.y);
1611         Point actualSize = new Point(mWallpaperManager.getDesiredMinimumWidth(),
1612                 mWallpaperManager.getDesiredMinimumHeight());
1613         if (actualSize.x > 0 || actualSize.y > 0) {
1614             if ((actualSize.x != expectedSize.x || actualSize.y != expectedSize.y)) {
1615                 throw new AssertionError(
1616                         "Expected x: " + expectedSize.x + " y: " + expectedSize.y
1617                                 + ", got x: " + actualSize.x + " y: " + actualSize.y);
1618             }
1619         }
1620     }
1621 
getScreenSize()1622     private Point getScreenSize() {
1623         WindowManager wm = mContext.getSystemService(WindowManager.class);
1624         Display d = wm.getDefaultDisplay();
1625         Point p = new Point();
1626         d.getRealSize(p);
1627         return p;
1628     }
1629 
1630     /**
1631      * Helper to set a listener and verify if it was called with the same flags.
1632      * Executes operation synchronously. Params are FLAG_LOCK, FLAG_SYSTEM or a combination of both.
1633      *
1634      * @param which wallpaper destinations to set
1635      * @param whichExpected wallpaper destinations that should receive listener calls
1636      */
verifyColorListenerInvoked(int which, int whichExpected)1637     private void verifyColorListenerInvoked(int which, int whichExpected) {
1638         ensureCleanState();
1639         int expected = 0;
1640         if ((whichExpected & FLAG_LOCK) != 0) expected++;
1641         if ((whichExpected & FLAG_SYSTEM) != 0) expected++;
1642         ArrayList<Integer> received = new ArrayList<>();
1643 
1644         final CountDownLatch latch = new CountDownLatch(expected);
1645         Handler handler = new Handler(Looper.getMainLooper());
1646 
1647         WallpaperManager.OnColorsChangedListener listener = getTestableListener();
1648         final AtomicBoolean allOk = new AtomicBoolean(true);
1649         WallpaperManager.OnColorsChangedListener counter = (colors, whichWp) -> {
1650             handler.post(() -> {
1651                 final boolean wantSystem = (whichExpected & FLAG_SYSTEM) != 0;
1652                 final boolean wantLock = (whichExpected & FLAG_LOCK) != 0;
1653                 final boolean gotSystem = (whichWp & FLAG_SYSTEM) != 0;
1654                 final boolean gotLock = (whichWp & FLAG_LOCK) != 0;
1655                 received.add(whichWp);
1656                 boolean ok = true;
1657 
1658                 if (gotLock) {
1659                     if (wantLock) {
1660                         latch.countDown();
1661                     } else {
1662                         ok = false;
1663                     }
1664                 }
1665                 if (gotSystem) {
1666                     if (wantSystem) {
1667                         latch.countDown();
1668                     } else {
1669                         ok = false;
1670                     }
1671                 }
1672                 if (!ok) {
1673                     allOk.set(false);
1674                     Log.e(TAG,
1675                             "Unexpected which flag: " + whichWp + " should be: " + whichExpected);
1676                 }
1677             });
1678         };
1679 
1680         mWallpaperManager.addOnColorsChangedListener(listener, mHandler);
1681         mWallpaperManager.addOnColorsChangedListener(counter, mHandler);
1682 
1683         try {
1684             mWallpaperManager.setResource(R.drawable.icon_red, which);
1685             boolean eventsReceived = latch.await(5, TimeUnit.SECONDS);
1686             assertWithMessage("Timed out waiting for color events. Expected: "
1687                     + whichExpected + " received: " + received)
1688                     .that(eventsReceived).isTrue();
1689             // Wait in case there are additional unwanted callbacks
1690             Thread.sleep(SLEEP_MS);
1691             assertWithMessage("Unexpected which flag, check logs for details")
1692                     .that(allOk.get()).isTrue();
1693         } catch (InterruptedException | IOException e) {
1694             throw new RuntimeException(e);
1695         } finally {
1696             mWallpaperManager.removeOnColorsChangedListener(listener);
1697             mWallpaperManager.removeOnColorsChangedListener(counter);
1698         }
1699     }
1700 
1701     /**
1702      * Helper to clear a wallpaper synchronously.
1703      *
1704      * @param which FLAG_LOCK, FLAG_SYSTEM or a combination of both.
1705      */
verifyColorListenerInvokedClearing(int which)1706     private void verifyColorListenerInvokedClearing(int which) {
1707         ensureCleanState(which);
1708 
1709         final CountDownLatch latch = new CountDownLatch(1);
1710 
1711         WallpaperManager.OnColorsChangedListener listener = getTestableListener();
1712         WallpaperManager.OnColorsChangedListener counter = (colors, whichWp) -> {
1713             latch.countDown();
1714         };
1715 
1716         mWallpaperManager.addOnColorsChangedListener(listener, mHandler);
1717         mWallpaperManager.addOnColorsChangedListener(counter, mHandler);
1718 
1719         try {
1720             mWallpaperManager.clear(which);
1721             latch.await(5, TimeUnit.SECONDS);
1722         } catch (InterruptedException | IOException e) {
1723             throw new RuntimeException(e);
1724         }
1725 
1726         verify(listener, atLeast(1))
1727                 .onColorsChanged(nullable(WallpaperColors.class), anyInt());
1728 
1729         mWallpaperManager.removeOnColorsChangedListener(listener);
1730         mWallpaperManager.removeOnColorsChangedListener(counter);
1731     }
1732 
ensureCleanState()1733     private void ensureCleanState() {
1734         ensureCleanState(FLAG_SYSTEM | FLAG_LOCK);
1735     }
1736 
1737     /**
1738      * Helper method to set a bitmap on the specified destination(s).
1739      */
ensureCleanState(int flags)1740     private void ensureCleanState(int flags) {
1741         Bitmap bmp = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
1742         Canvas canvas = new Canvas(bmp);
1743         canvas.drawColor(Color.BLUE);
1744 
1745         try {
1746             runAndAwaitColorChanges(5, TimeUnit.SECONDS, flags, mWallpaperManager, mHandler, () -> {
1747                 if (flags == (FLAG_SYSTEM | FLAG_LOCK)) {
1748                     mWallpaperManager.setBitmap(bmp);
1749                 } else {
1750                     mWallpaperManager.setBitmap(bmp, /* visibleCropHint= */
1751                             null, /* allowBackup= */true, flags);
1752                 }
1753             });
1754         } catch (Exception e) {
1755             throw new RuntimeException(e);
1756         } finally {
1757             bmp.recycle();
1758         }
1759     }
1760 
assertNullOrDefaultWallpaper(int which)1761     private void assertNullOrDefaultWallpaper(int which) {
1762         WallpaperInfo wallpaperInfo = mWallpaperManager.getWallpaperInfo(which);
1763         if (mDefaultWallpaperInfo == null) assertThat(wallpaperInfo).isNull();
1764         if (wallpaperInfo == null) return;
1765         assertThat(wallpaperInfo.getComponent()).isEqualTo(mDefaultWallpaperInfo.getComponent());
1766     }
1767 
assertNotNullOrDefaultWallpaper(int which)1768     private void assertNotNullOrDefaultWallpaper(int which) {
1769         WallpaperInfo wallpaperInfo = mWallpaperManager.getWallpaperInfo(which);
1770         assertThat(wallpaperInfo).isNotNull();
1771         if (mDefaultWallpaperInfo != null) {
1772             assertThat(wallpaperInfo.getComponent()).isNotEqualTo(
1773                     mDefaultWallpaperInfo.getComponent());
1774         }
1775     }
1776 
setWallpaperComponentAndWait(ComponentName component, int which)1777     private void setWallpaperComponentAndWait(ComponentName component, int which) {
1778         setWallpaperComponentAndWait(component, which, 1, 1);
1779     }
1780 
setWallpaperComponentAndWait(ComponentName component, int which, int created, int destroyed)1781     private void setWallpaperComponentAndWait(ComponentName component, int which, int created,
1782             int destroyed) {
1783         runAndAwaitChanges(
1784                 SLEEP_MS, TimeUnit.MILLISECONDS, created, destroyed, 0,
1785                 () -> mWallpaperManager.setWallpaperComponentWithFlags(component, which));
1786     }
1787 
getTestableListener()1788     public WallpaperManager.OnColorsChangedListener getTestableListener() {
1789         // Unfortunately mockito cannot mock anonymous classes or lambdas.
1790         return spy(new TestableColorListener());
1791     }
1792 
1793     public static class TestableColorListener implements WallpaperManager.OnColorsChangedListener {
1794         @Override
onColorsChanged(WallpaperColors colors, int which)1795         public void onColorsChanged(WallpaperColors colors, int which) {
1796             Log.d(TAG, "TestableColorListener received colors: " + colors + ", which: " + which);
1797         }
1798     }
1799 }
1800