• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Flags.FLAG_LIVE_WALLPAPER_CONTENT_HANDLING;
22 import static android.app.Flags.liveWallpaperContentHandling;
23 import static android.app.WallpaperManager.FLAG_LOCK;
24 import static android.app.WallpaperManager.FLAG_SYSTEM;
25 import static android.app.cts.wallpapers.WallpaperManagerTestUtils.WallpaperChange;
26 import static android.app.cts.wallpapers.WallpaperManagerTestUtils.WallpaperState;
27 import static android.app.cts.wallpapers.WallpaperManagerTestUtils.runAndAwaitChanges;
28 import static android.app.cts.wallpapers.WallpaperManagerTestUtils.runAndAwaitColorChanges;
29 import static android.app.cts.wallpapers.util.WallpaperTestUtils.isSimilar;
30 import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
31 import static android.content.pm.PackageManager.FEATURE_LIVE_WALLPAPER;
32 import static android.content.pm.PackageManager.FEATURE_SECURE_LOCK_SCREEN;
33 import static android.content.pm.PackageManager.FEATURE_WATCH;
34 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
35 import static android.opengl.cts.Egl14Utils.getMaxTextureSize;
36 
37 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
38 import static com.android.window.flags.Flags.FLAG_MULTI_CROP;
39 
40 import static com.google.common.truth.Truth.assertThat;
41 import static com.google.common.truth.Truth.assertWithMessage;
42 
43 import static org.junit.Assert.assertThrows;
44 import static org.junit.Assert.assertTrue;
45 import static org.junit.Assume.assumeFalse;
46 import static org.junit.Assume.assumeTrue;
47 import static org.mockito.ArgumentMatchers.any;
48 import static org.mockito.ArgumentMatchers.anyInt;
49 import static org.mockito.ArgumentMatchers.nullable;
50 import static org.mockito.Mockito.atLeast;
51 import static org.mockito.Mockito.never;
52 import static org.mockito.Mockito.spy;
53 import static org.mockito.Mockito.verify;
54 
55 import android.app.Activity;
56 import android.app.Instrumentation;
57 import android.app.WallpaperColors;
58 import android.app.WallpaperInfo;
59 import android.app.WallpaperManager;
60 import android.app.wallpaper.WallpaperDescription;
61 import android.app.wallpaper.WallpaperInstance;
62 import android.content.BroadcastReceiver;
63 import android.content.ComponentName;
64 import android.content.Context;
65 import android.content.Intent;
66 import android.content.IntentFilter;
67 import android.graphics.Bitmap;
68 import android.graphics.Canvas;
69 import android.graphics.Color;
70 import android.graphics.ColorSpace;
71 import android.graphics.Paint;
72 import android.graphics.Point;
73 import android.graphics.Rect;
74 import android.graphics.drawable.Drawable;
75 import android.hardware.display.DisplayManager;
76 import android.os.Handler;
77 import android.os.HandlerThread;
78 import android.os.IBinder;
79 import android.os.Looper;
80 import android.platform.test.annotations.RequiresFlagsDisabled;
81 import android.platform.test.annotations.RequiresFlagsEnabled;
82 import android.platform.test.flag.junit.CheckFlagsRule;
83 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
84 import android.server.wm.LockScreenSession;
85 import android.server.wm.WindowManagerState;
86 import android.server.wm.WindowManagerStateHelper;
87 import android.util.Log;
88 import android.util.SparseArray;
89 import android.view.Display;
90 import android.view.Window;
91 import android.view.WindowManager;
92 
93 import androidx.test.InstrumentationRegistry;
94 import androidx.test.rule.ActivityTestRule;
95 
96 import com.android.compatibility.common.util.CtsTouchUtils;
97 import com.android.window.flags.Flags;
98 
99 import com.google.testing.junit.testparameterinjector.TestParameter;
100 import com.google.testing.junit.testparameterinjector.TestParameterInjector;
101 
102 import org.junit.After;
103 import org.junit.AfterClass;
104 import org.junit.Before;
105 import org.junit.Ignore;
106 import org.junit.Rule;
107 import org.junit.Test;
108 import org.junit.runner.RunWith;
109 import org.mockito.MockitoAnnotations;
110 
111 import java.io.ByteArrayInputStream;
112 import java.io.ByteArrayOutputStream;
113 import java.io.IOException;
114 import java.util.ArrayList;
115 import java.util.LinkedList;
116 import java.util.List;
117 import java.util.Map;
118 import java.util.concurrent.CountDownLatch;
119 import java.util.concurrent.TimeUnit;
120 import java.util.concurrent.atomic.AtomicBoolean;
121 import java.util.function.Consumer;
122 
123 /**
124  * Tests for {@link WallpaperManager} and related classes.
125  * <p>
126  * Note: the wallpapers {@link TestLiveWallpaper}, {@link TestLiveWallpaperNoUnfoldTransition},
127  * {@link TestLiveWallpaperSupportingAmbientMode} draw the screen in
128  * cyan, magenta, yellow, respectively.
129  * </p>
130  */
131 @RunWith(TestParameterInjector.class)
132 public class WallpaperManagerTest {
133 
134     private static final boolean DEBUG = false;
135     private static final String TAG = "WallpaperManagerTest";
136 
137     private static final ComponentName TEST_COMPONENT_NAME = new ComponentName(
138             TestLiveWallpaper.class.getPackageName(), TestLiveWallpaper.class.getName());
139     // Default wait time for async operations
140     private static final int SLEEP_MS = 500;
141     private static final int DIM_LISTENER_TIMEOUT_SECS = 30;
142 
143     private WallpaperManager mWallpaperManager;
144     private static WallpaperManager sWallpaperManager = null;
145     private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();;
146     private Context mContext;
147     private CtsTouchUtils mCtsTouchUtils;
148     private Handler mHandler;
149     private BroadcastReceiver mBroadcastReceiver;
150     private CountDownLatch mCountDownLatch;
151     private boolean mEnableWcg;
152 
153     // WallpaperInfo object for the built-in default wallpaper of the device.
154     // Always null if the device uses ImageWallpaper by default.
155     private WallpaperInfo mDefaultWallpaperInfo;
156 
157     private static final WindowManagerStateHelper sWindowManagerStateHelper =
158             new WindowManagerStateHelper();
159 
160     @Rule
161     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
162 
163     @Rule
164     public ActivityTestRule<WallpaperTestActivity> mActivityTestRule = new ActivityTestRule<>(
165             WallpaperTestActivity.class,
166             false /* initialTouchMode */,
167             false /* launchActivity */);
168 
169     @Rule
170     public ActivityTestRule<WallpaperOverlayTestActivity> mOverlayActivityTestRule =
171             new ActivityTestRule<>(
172                     WallpaperOverlayTestActivity.class,
173                     false /* initialTouchMode */,
174                     false /* launchActivity */);
175 
176     @Before
setUp()177     public void setUp() throws Exception {
178         // grant READ_WALLPAPER_INTERNAL for all tests
179         mInstrumentation.getUiAutomation()
180                 .adoptShellPermissionIdentity(READ_WALLPAPER_INTERNAL);
181 
182         mContext = InstrumentationRegistry.getTargetContext();
183         WallpaperWindowsTestUtils.setContext(mContext);
184         mCtsTouchUtils = new CtsTouchUtils(mContext);
185         mWallpaperManager = WallpaperManager.getInstance(mContext);
186         sWallpaperManager = mWallpaperManager;
187         assumeTrue("Device does not support wallpapers", mWallpaperManager.isWallpaperSupported());
188 
189         // TODO(b/328312997): revisit this test once we have a strategy for live wallpaper on AAOS.
190         assumeFalse("AAOS doesn't support FEATURE_LIVE_WALLPAPER",
191                 mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
192 
193         MockitoAnnotations.initMocks(this);
194         final HandlerThread handlerThread = new HandlerThread("TestCallbacks");
195         handlerThread.start();
196         mHandler = new Handler(handlerThread.getLooper());
197         mCountDownLatch = new CountDownLatch(1);
198         mBroadcastReceiver = new BroadcastReceiver() {
199             @Override
200             public void onReceive(Context context, Intent intent) {
201                 mCountDownLatch.countDown();
202                 if (DEBUG) {
203                     Log.d(TAG, "broadcast state count down: " + mCountDownLatch.getCount());
204                 }
205             }
206         };
207         mContext.registerReceiver(mBroadcastReceiver,
208                 new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED));
209         mEnableWcg = mWallpaperManager.shouldEnableWideColorGamut();
210         runAndAwaitColorChanges(5, TimeUnit.SECONDS, FLAG_SYSTEM | FLAG_LOCK,
211                 mWallpaperManager, mHandler, mWallpaperManager::clear);
212         if (mDefaultWallpaperInfo == null) {
213             mDefaultWallpaperInfo = mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM);
214         }
215 
216         assertWithMessage("Home screen wallpaper must be set after setUp()").that(
217                 mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isAtLeast(0);
218         assertWithMessage("Lock screen wallpaper must be unset after setUp()").that(
219                 mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
220 
221         TestWallpaperService.Companion.resetCounts();
222     }
223 
224     @After
tearDown()225     public void tearDown() {
226         // drop READ_WALLPAPER_INTERNAL
227         mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
228 
229         if (mBroadcastReceiver != null) {
230             mContext.unregisterReceiver(mBroadcastReceiver);
231         }
232         TestWallpaperService.Companion.checkAssertions();
233         TestWallpaperService.Companion.resetCounts();
234     }
235 
236     /**
237      * Reset all wallpapers to default after the test suite has been executed.
238      */
239     @AfterClass
tearDownClass()240     public static void tearDownClass() throws IOException {
241         if (sWallpaperManager != null) {
242             sWallpaperManager.clear(FLAG_SYSTEM | FLAG_LOCK);
243         }
244         sWallpaperManager = null;
245     }
246 
247     @Test
setBitmap_homeScreen_homeStatic_lockScreenUnset_setsLockToHomeAndUpdatesHome()248     public void setBitmap_homeScreen_homeStatic_lockScreenUnset_setsLockToHomeAndUpdatesHome()
249             throws IOException {
250         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
251         Canvas canvas = new Canvas(tmpWallpaper);
252         canvas.drawColor(Color.RED);
253 
254         try {
255             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
256             mWallpaperManager.setBitmap(tmpWallpaper, /* visibleCropHint= */
257                     null, /* allowBackup= */true, FLAG_SYSTEM);
258             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
259                     origHomeWallpaperId);
260             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origHomeWallpaperId);
261         } finally {
262             tmpWallpaper.recycle();
263         }
264     }
265 
266     @Test
setBitmap_homeScreen_homeLive_lockScreenUnset_setsLockToHomeAndUpdatesHome()267     public void setBitmap_homeScreen_homeLive_lockScreenUnset_setsLockToHomeAndUpdatesHome()
268             throws IOException {
269         runWithShellPermissionIdentity(() -> {
270             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM | FLAG_LOCK);
271         });
272         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
273         Canvas canvas = new Canvas(tmpWallpaper);
274         canvas.drawColor(Color.RED);
275 
276         try {
277             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
278             mWallpaperManager.setBitmap(tmpWallpaper, /* visibleCropHint= */
279                     null, /* allowBackup= */true, FLAG_SYSTEM);
280             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
281                     origHomeWallpaperId);
282             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origHomeWallpaperId);
283         } finally {
284             tmpWallpaper.recycle();
285         }
286     }
287 
288     @Test
setBitmap_lockScreen_lockScreenUnset_changesLockOnly()289     public void setBitmap_lockScreen_lockScreenUnset_changesLockOnly() throws IOException {
290         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
291         Canvas canvas = new Canvas(tmpWallpaper);
292         canvas.drawColor(Color.RED);
293 
294         try {
295             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
296             mWallpaperManager.setBitmap(tmpWallpaper, /* visibleCropHint= */
297                     null, /* allowBackup= */true, FLAG_LOCK);
298             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isEqualTo(
299                     origHomeWallpaperId);
300             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isAtLeast(0);
301         } finally {
302             tmpWallpaper.recycle();
303         }
304     }
305 
306     @Test
setBitmap_lockScreen_lockScreenSet_changesLockOnly()307     public void setBitmap_lockScreen_lockScreenSet_changesLockOnly() throws IOException {
308         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
309         Canvas canvas = new Canvas(tmpWallpaper);
310         canvas.drawColor(Color.GREEN);
311 
312         try {
313             mWallpaperManager.setBitmap(tmpWallpaper, null, true, FLAG_LOCK);
314             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
315             int origLockWallpaperId = mWallpaperManager.getWallpaperId(FLAG_LOCK);
316             canvas.drawColor(Color.RED);
317             mWallpaperManager.setBitmap(tmpWallpaper, /* visibleCropHint= */
318                     null, /* allowBackup= */true, FLAG_LOCK);
319             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isEqualTo(
320                     origHomeWallpaperId);
321             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isNotEqualTo(
322                     origLockWallpaperId);
323         } finally {
324             tmpWallpaper.recycle();
325         }
326     }
327 
328     @Test
setBitmap_both_lockScreenUnset_changesHome()329     public void setBitmap_both_lockScreenUnset_changesHome() throws IOException {
330         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
331         Canvas canvas = new Canvas(tmpWallpaper);
332         canvas.drawColor(Color.RED);
333 
334         try {
335             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
336             mWallpaperManager.setBitmap(tmpWallpaper, /* visibleCropHint= */
337                     null, /* allowBackup= */true, FLAG_SYSTEM | FLAG_LOCK);
338             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
339                     origHomeWallpaperId);
340             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
341         } finally {
342             tmpWallpaper.recycle();
343         }
344     }
345 
346     @Test
setBitmap_both_lockScreenSet_changesHomeAndClearsLock()347     public void setBitmap_both_lockScreenSet_changesHomeAndClearsLock() throws IOException {
348         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
349         Canvas canvas = new Canvas(tmpWallpaper);
350         canvas.drawColor(Color.GREEN);
351 
352         try {
353             mWallpaperManager.setBitmap(tmpWallpaper, null, true, FLAG_LOCK);
354             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
355             int origLockWallpaperId = mWallpaperManager.getWallpaperId(FLAG_LOCK);
356             canvas.drawColor(Color.RED);
357             mWallpaperManager.setBitmap(tmpWallpaper, /* visibleCropHint= */
358                     null, /* allowBackup= */true, FLAG_SYSTEM | FLAG_LOCK);
359             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
360                     origHomeWallpaperId);
361             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
362         } finally {
363             tmpWallpaper.recycle();
364         }
365     }
366 
367     @Test
setBitmap_default_lockScreenUnset_sameAsBoth()368     public void setBitmap_default_lockScreenUnset_sameAsBoth() throws IOException {
369         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
370         Canvas canvas = new Canvas(tmpWallpaper);
371         canvas.drawColor(Color.RED);
372 
373         try {
374             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
375             mWallpaperManager.setBitmap(tmpWallpaper);
376             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
377                     origHomeWallpaperId);
378             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
379         } finally {
380             tmpWallpaper.recycle();
381         }
382     }
383 
384     @Test
setResource_homeScreen_homeStatic_lockScreenUnset_setsLockToHomeAndUpdatesHome()385     public void setResource_homeScreen_homeStatic_lockScreenUnset_setsLockToHomeAndUpdatesHome()
386             throws IOException {
387         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
388         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
389         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
390                 origHomeWallpaperId);
391         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origHomeWallpaperId);
392     }
393 
394     @Test
setResource_homeScreen_homeLive_lockScreenUnset_setsLockToHomeAndUpdatesHome()395     public void setResource_homeScreen_homeLive_lockScreenUnset_setsLockToHomeAndUpdatesHome()
396             throws IOException {
397         runWithShellPermissionIdentity(() -> {
398             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM | FLAG_LOCK);
399         });
400         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
401 
402         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
403 
404         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
405                 origHomeWallpaperId);
406         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origHomeWallpaperId);
407     }
408 
409     @Test
setResource_homeScreen_lockScreenSet_changesHomeOnly()410     public void setResource_homeScreen_lockScreenSet_changesHomeOnly() throws IOException {
411         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
412         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
413         int origLockWallpaperId = mWallpaperManager.getWallpaperId(FLAG_LOCK);
414         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_SYSTEM);
415         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
416                 origHomeWallpaperId);
417         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origLockWallpaperId);
418     }
419 
420     @Test
setResource_lockScreen_lockScreenUnset_changesLockOnly()421     public void setResource_lockScreen_lockScreenUnset_changesLockOnly() throws IOException {
422         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
423         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
424         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isEqualTo(
425                 origHomeWallpaperId);
426         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isAtLeast(0);
427     }
428 
429     @Test
setResource_lockScreen_lockScreenSet_changesLockOnly()430     public void setResource_lockScreen_lockScreenSet_changesLockOnly() throws IOException {
431         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
432         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
433         int origLockWallpaperId = mWallpaperManager.getWallpaperId(FLAG_LOCK);
434         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_LOCK);
435         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isEqualTo(
436                 origHomeWallpaperId);
437         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isNotEqualTo(
438                 origLockWallpaperId);
439     }
440 
441     @Test
setResource_both_lockScreenUnset_changesHome()442     public void setResource_both_lockScreenUnset_changesHome() throws IOException {
443         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
444         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM | FLAG_LOCK);
445         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
446                 origHomeWallpaperId);
447         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
448     }
449 
450     @Test
setResource_both_lockScreenSet_changesHomeAndClearsLock()451     public void setResource_both_lockScreenSet_changesHomeAndClearsLock() throws IOException {
452         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
453         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
454         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_SYSTEM | FLAG_LOCK);
455         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
456                 origHomeWallpaperId);
457         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
458     }
459 
460     // This is just to be sure that setResource call the overload with `which`.
461     @Test
setResource_default_lockScreenUnset_sameAsBoth()462     public void setResource_default_lockScreenUnset_sameAsBoth() throws IOException {
463         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
464         mWallpaperManager.setResource(R.drawable.icon_red);
465         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(
466                 origHomeWallpaperId);
467         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
468     }
469 
470     @Test
setWallpaperComponent_homeScreen_homeStatic_lockScreenUnset_migratesThenSetsHome()471     public void setWallpaperComponent_homeScreen_homeStatic_lockScreenUnset_migratesThenSetsHome() {
472         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
473         runWithShellPermissionIdentity(() -> {
474             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM);
475         });
476 
477         assertWithMessage("System wallpaper must change").that(
478                 mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(origHomeWallpaperId);
479         assertWithMessage("Lock wallpaper mush not change").that(
480                 mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origHomeWallpaperId);
481     }
482 
483     @Test
setWallpaperComponent_homeScreen_homeLive_lockScreenUnset_migratesThenSetsHome()484     public void setWallpaperComponent_homeScreen_homeLive_lockScreenUnset_migratesThenSetsHome() {
485         runWithShellPermissionIdentity(() -> {
486             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM | FLAG_LOCK);
487         });
488         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
489 
490         runWithShellPermissionIdentity(() -> {
491             ComponentName newComponentName = new ComponentName(
492                     TestLiveWallpaperNoUnfoldTransition.class.getPackageName(),
493                     TestLiveWallpaperNoUnfoldTransition.class.getName());
494             setWallpaperComponentAndWait(newComponentName, FLAG_SYSTEM);
495         });
496 
497         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(origHomeWallpaperId);
498         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origHomeWallpaperId);
499     }
500 
501     @Test
setWallpaperComponent_homeScreen_lockScreenSet_changesHomeOnly()502     public void setWallpaperComponent_homeScreen_lockScreenSet_changesHomeOnly()
503             throws IOException {
504         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
505         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
506         int origLockWallpaperId = mWallpaperManager.getWallpaperId(FLAG_LOCK);
507         runWithShellPermissionIdentity(() -> {
508             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM);
509         });
510         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(origHomeWallpaperId);
511         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isEqualTo(origLockWallpaperId);
512     }
513 
514     @Test
setWallpaperComponent_lockScreen_lockScreenUnset_changesLockOnly()515     public void setWallpaperComponent_lockScreen_lockScreenUnset_changesLockOnly() {
516         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
517         runWithShellPermissionIdentity(() -> {
518             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_LOCK);
519         });
520         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isEqualTo(origHomeWallpaperId);
521         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isAtLeast(0);
522     }
523 
524     @Test
setWallpaperComponent_lockScreen_lockScreenSet_changeLockOnly()525     public void setWallpaperComponent_lockScreen_lockScreenSet_changeLockOnly()
526             throws IOException {
527         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
528         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
529         int origLockWallpaperId = mWallpaperManager.getWallpaperId(FLAG_LOCK);
530         runWithShellPermissionIdentity(() -> {
531             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_LOCK);
532         });
533         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isEqualTo(origHomeWallpaperId);
534         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isNotEqualTo(origLockWallpaperId);
535     }
536 
537     @Test
setWallpaperComponent_both_lockScreenUnset_setsHomeToBoth()538     public void setWallpaperComponent_both_lockScreenUnset_setsHomeToBoth() {
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_both_lockScreenSet_changesLockOnly()548     public void setWallpaperComponent_both_lockScreenSet_changesLockOnly()
549             throws IOException {
550         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
551         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
552         runWithShellPermissionIdentity(() -> {
553             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM | FLAG_LOCK);
554         });
555         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(origHomeWallpaperId);
556         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
557     }
558 
559     @Test
setWallpaperComponent_default_lockScreenUnset_behavesLikeBoth()560     public void setWallpaperComponent_default_lockScreenUnset_behavesLikeBoth() {
561         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
562         runWithShellPermissionIdentity(() -> {
563             mWallpaperManager.setWallpaperComponent(TEST_COMPONENT_NAME);
564         });
565         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(origHomeWallpaperId);
566         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
567     }
568 
569     @Test
setStaticWallpaper_doesNotSetWallpaperInfo()570     public void setStaticWallpaper_doesNotSetWallpaperInfo() throws IOException {
571         assertNullOrDefaultWallpaper(FLAG_SYSTEM);
572         assertNullOrDefaultWallpaper(FLAG_LOCK);
573 
574         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
575         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_LOCK);
576 
577         assertThat(mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM)).isNull();
578         assertThat(mWallpaperManager.getWallpaperInfo(FLAG_LOCK)).isNull();
579     }
580 
581     @Test
setLiveWallpaper_homeScreen_setsHomeWallpaperInfo()582     public void setLiveWallpaper_homeScreen_setsHomeWallpaperInfo() {
583         assertNullOrDefaultWallpaper(FLAG_SYSTEM);
584         assertNullOrDefaultWallpaper(FLAG_LOCK);
585 
586         runWithShellPermissionIdentity(() -> {
587             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM);
588         });
589 
590         assertNotNullOrDefaultWallpaper(FLAG_SYSTEM);
591         assertNullOrDefaultWallpaper(FLAG_LOCK);
592     }
593 
594     @Test
setLiveWallpaper_lockScreen_setsLockWallpaperInfo()595     public void setLiveWallpaper_lockScreen_setsLockWallpaperInfo() {
596         assertNullOrDefaultWallpaper(FLAG_SYSTEM);
597         assertNullOrDefaultWallpaper(FLAG_LOCK);
598 
599         runWithShellPermissionIdentity(() -> {
600             setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_LOCK);
601         });
602 
603         assertNullOrDefaultWallpaper(FLAG_SYSTEM);
604         assertNotNullOrDefaultWallpaper(FLAG_LOCK);
605     }
606 
607     @Test
getWallpaperInfo_badFlagsArgument_throwsException()608     public void getWallpaperInfo_badFlagsArgument_throwsException() {
609         assertThrows(IllegalArgumentException.class, () ->
610                 mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM | FLAG_LOCK));
611     }
612 
613     @Test
setStaticWallpaper_homeScreen_wallpaperInstanceCorrect()614     public void setStaticWallpaper_homeScreen_wallpaperInstanceCorrect() throws IOException {
615         assertNullOrDefaultWallpaper(FLAG_SYSTEM);
616 
617         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
618 
619         assertThat(mWallpaperManager.getWallpaperInstance(FLAG_SYSTEM)).isNotNull();
620         assertThat(mWallpaperManager.getWallpaperInstance(FLAG_SYSTEM).getInfo()).isNull();
621     }
622 
623     @Test
setStaticWallpaper_lockScreen_wallpaperInstanceCorrect()624     public void setStaticWallpaper_lockScreen_wallpaperInstanceCorrect() throws IOException {
625         assertNullOrDefaultWallpaper(FLAG_LOCK);
626 
627         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_LOCK);
628 
629         assertThat(mWallpaperManager.getWallpaperInstance(FLAG_LOCK)).isNotNull();
630         assertThat(mWallpaperManager.getWallpaperInstance(FLAG_LOCK).getInfo()).isNull();
631     }
632 
633     @Test
setStaticWallpaper_both_wallpaperInstanceCorrect()634     public void setStaticWallpaper_both_wallpaperInstanceCorrect() throws IOException {
635         assertNullOrDefaultWallpaper(FLAG_SYSTEM);
636         assertNullOrDefaultWallpaper(FLAG_LOCK);
637 
638         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_SYSTEM | FLAG_LOCK);
639 
640         assertThat(mWallpaperManager.getWallpaperInstance(FLAG_SYSTEM)).isNotNull();
641         assertThat(mWallpaperManager.getWallpaperInstance(FLAG_SYSTEM).getInfo()).isNull();
642         assertThat(mWallpaperManager.getWallpaperInstance(FLAG_LOCK)).isNull();
643     }
644 
645     @Test
setLiveWallpaper_homeScreen_wallpaperInstanceCorrect()646     public void setLiveWallpaper_homeScreen_wallpaperInstanceCorrect() {
647         assertNullOrDefaultWallpaper(FLAG_SYSTEM);
648 
649         runWithShellPermissionIdentity(() ->
650                 setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM));
651 
652         assertNotNullOrDefaultInstance(FLAG_SYSTEM);
653     }
654 
655     @Test
setLiveWallpaper_lockScreen_wallpaperInstanceCorrect()656     public void setLiveWallpaper_lockScreen_wallpaperInstanceCorrect() {
657         assertNullOrDefaultWallpaper(FLAG_LOCK);
658 
659         runWithShellPermissionIdentity(() ->
660                 setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_LOCK));
661 
662         assertNotNullOrDefaultInstance(FLAG_LOCK);
663     }
664 
665     @Test
setLiveWallpaper_both_wallpaperInstanceCorrect()666     public void setLiveWallpaper_both_wallpaperInstanceCorrect() {
667         assertNullOrDefaultWallpaper(FLAG_SYSTEM);
668         assertNullOrDefaultWallpaper(FLAG_LOCK);
669 
670         runWithShellPermissionIdentity(() ->
671                 setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM | FLAG_LOCK));
672 
673         assertNotNullOrDefaultInstance(FLAG_SYSTEM);
674         assertThat(mWallpaperManager.getWallpaperInstance(FLAG_LOCK)).isNull();
675     }
676 
677     @Test
getWallpaperInstance_badFlagsArgument_throwsException()678     public void getWallpaperInstance_badFlagsArgument_throwsException() {
679         assertThrows(IllegalArgumentException.class, () ->
680                 mWallpaperManager.getWallpaperInstance(FLAG_SYSTEM | FLAG_LOCK));
681     }
682 
683     @Test
wallpaperChangedBroadcastTest()684     public void wallpaperChangedBroadcastTest() {
685         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
686         Canvas canvas = new Canvas(tmpWallpaper);
687         canvas.drawColor(Color.BLACK);
688 
689         try {
690             mWallpaperManager.setBitmap(tmpWallpaper);
691 
692             // Wait for up to 5 sec since this is an async call.
693             // Should fail if Intent.ACTION_WALLPAPER_CHANGED isn't delivered.
694             assertWithMessage("Timed out waiting for Intent").that(
695                     mCountDownLatch.await(5, TimeUnit.SECONDS)).isTrue();
696         } catch (InterruptedException | IOException e) {
697             throw new AssertionError("Intent.ACTION_WALLPAPER_CHANGED not received.");
698         } finally {
699             tmpWallpaper.recycle();
700         }
701     }
702 
703     @Test
wallpaperClearBroadcastTest()704     public void wallpaperClearBroadcastTest() {
705         try {
706             mWallpaperManager.clear(FLAG_LOCK | FLAG_SYSTEM);
707 
708             // Wait for 5 sec since this is an async call.
709             // Should fail if Intent.ACTION_WALLPAPER_CHANGED isn't delivered.
710             assertWithMessage("Timed out waiting for Intent").that(
711                     mCountDownLatch.await(5, TimeUnit.SECONDS)).isTrue();
712         } catch (InterruptedException | IOException e) {
713             throw new AssertionError(e);
714         }
715     }
716 
717     /**
718      * Test that {@link WallpaperManager#clear(int)} triggers the correct number of
719      * {@link android.service.wallpaper.WallpaperService.Engine#onDestroy()} in different scenarios.
720      */
721     @Test
testClear()722     public void testClear() throws IOException {
723         // map of: argument passed to clear(int) -> WallpaperState -> expected number of onDestroy
724         Map<Integer, Map<WallpaperState, Integer>> testMap = Map.of(
725                 FLAG_LOCK,
726                 Map.of(WallpaperState.LIVE_DIFF_MULTI, 1, WallpaperState.LIVE_SAME_SINGLE, 0),
727                 FLAG_SYSTEM,
728                 Map.of(WallpaperState.LIVE_DIFF_MULTI, 1, WallpaperState.LIVE_SAME_SINGLE, 0),
729                 FLAG_SYSTEM | FLAG_LOCK, Map.of(
730                         WallpaperState.LIVE_DIFF_MULTI, 2, WallpaperState.LIVE_SAME_SINGLE, 1));
731 
732         Map<WallpaperState, String> stateDescriptions = Map.of(
733                 WallpaperState.LIVE_DIFF_MULTI, "two different live wallpapers",
734                 WallpaperState.LIVE_SAME_SINGLE, "a shared live wallpaper");
735 
736         Map<Integer, String> flagDescriptions = Map.of(
737                 FLAG_LOCK, "FLAG_LOCK",
738                 FLAG_SYSTEM, "FLAG_SYSTEM",
739                 FLAG_SYSTEM | FLAG_LOCK, "FLAG_SYSTEM | FLAG_LOCK");
740 
741         Map<Integer, String> destroyCountDescriptions = Map.of(
742                 0, "not destroy any engine",
743                 1, "destroy exactly one engine",
744                 2, "destroy two engines");
745 
746         runWithShellPermissionIdentity(() -> {
747             for (Map.Entry<Integer, Map<WallpaperState, Integer>> entry : testMap.entrySet()) {
748                 int which = entry.getKey();
749                 Map<WallpaperState, Integer> map = entry.getValue();
750                 for (Map.Entry<WallpaperState, Integer> e : map.entrySet()) {
751                     WallpaperState initialState = e.getKey();
752                     int expectedCount = e.getValue();
753                     WallpaperManagerTestUtils.goToState(mWallpaperManager, initialState);
754                     TestWallpaperService.Companion.resetCounts();
755                     runAndAwaitChanges(5, TimeUnit.SECONDS, 0, expectedCount, 0, () -> {
756                         mWallpaperManager.clear(which);
757                     });
758                     for (int testWhich : List.of(FLAG_SYSTEM, FLAG_LOCK)) {
759                         if ((testWhich & which) > 0) {
760                             assertNullOrDefaultWallpaper(testWhich);
761                         } else {
762                             assertNotNullOrDefaultWallpaper(testWhich);
763                         }
764                     }
765                     String expectedBehaviourMessage = String.format("With %s, clear(%s) should %s",
766                             stateDescriptions.get(initialState),
767                             flagDescriptions.get(which),
768                             destroyCountDescriptions.get(expectedCount));
769                     assertWithMessage(expectedBehaviourMessage)
770                             .that(TestWallpaperService.Companion.getDestroyCount())
771                             .isEqualTo(expectedCount);
772                 }
773             }
774         });
775     }
776 
777     @Test
invokeOnColorsChangedListenerTest_systemOnly()778     public void invokeOnColorsChangedListenerTest_systemOnly() {
779         verifyColorListenerInvoked(FLAG_SYSTEM, FLAG_SYSTEM);
780     }
781 
782     @Test
invokeOnColorsChangedListenerTest_lockOnly()783     public void invokeOnColorsChangedListenerTest_lockOnly() {
784         verifyColorListenerInvoked(FLAG_LOCK, FLAG_LOCK);
785     }
786 
787     @Test
invokeOnColorsChangedListenerTest_both()788     public void invokeOnColorsChangedListenerTest_both() {
789         int both = FLAG_LOCK | FLAG_SYSTEM;
790         verifyColorListenerInvoked(both, both);
791     }
792 
793     @Test
invokeOnColorsChangedListenerTest_clearLock()794     public void invokeOnColorsChangedListenerTest_clearLock() throws IOException {
795         verifyColorListenerInvokedClearing(FLAG_LOCK);
796     }
797 
798     @Test
invokeOnColorsChangedListenerTest_clearSystem()799     public void invokeOnColorsChangedListenerTest_clearSystem() throws IOException {
800         verifyColorListenerInvokedClearing(FLAG_SYSTEM);
801     }
802 
803     /**
804      * Removing a listener should not invoke it anymore
805      */
806     @Test
addRemoveOnColorsChangedListenerTest_onlyInvokeAdded()807     public void addRemoveOnColorsChangedListenerTest_onlyInvokeAdded() throws IOException {
808         ensureCleanState();
809 
810         final CountDownLatch latch = new CountDownLatch(1);
811         WallpaperManager.OnColorsChangedListener counter = (colors, whichWp) -> latch.countDown();
812 
813         // Add and remove listener
814         WallpaperManager.OnColorsChangedListener listener = getTestableListener();
815         mWallpaperManager.addOnColorsChangedListener(listener, mHandler);
816         mWallpaperManager.removeOnColorsChangedListener(listener);
817 
818         // Verify that the listener is not called
819         mWallpaperManager.addOnColorsChangedListener(counter, mHandler);
820         try {
821             mWallpaperManager.setResource(R.drawable.icon_red);
822             if (!latch.await(5, TimeUnit.SECONDS)) {
823                 throw new AssertionError("Registered listener not invoked");
824             }
825         } catch (InterruptedException | IOException e) {
826             throw new RuntimeException(e);
827         }
828         verify(listener, never()).onColorsChanged(any(WallpaperColors.class), anyInt());
829         mWallpaperManager.removeOnColorsChangedListener(counter);
830     }
831 
832     /**
833      * Suggesting desired dimensions is only a hint to the system that can be ignored.
834      *
835      * Test if the desired minimum width or height the WallpaperManager returns
836      * is greater than 0. If so, then we check whether that the size is the dimension
837      * that was suggested.
838      */
839     @Test
suggestDesiredDimensionsTest()840     public void suggestDesiredDimensionsTest() {
841         final Point min = getScreenSize();
842         int w = min.x * 3;
843         int h = min.y * 2;
844 
845         // b/120847476: WallpaperManager limits at GL_MAX_TEXTURE_SIZE
846         final int max = getMaxTextureSize();
847         if (max > 0) {
848             w = Math.min(w, max);
849             h = Math.min(h, max);
850         }
851 
852         assertDesiredDimension(new Point(min.x / 2, min.y / 2), new Point(min.x / 2, min.y / 2));
853 
854         assertDesiredDimension(new Point(w, h), new Point(w, h));
855 
856         assertDesiredDimension(new Point(min.x / 2, h), new Point(min.x / 2, h));
857 
858         assertDesiredDimension(new Point(w, min.y / 2), new Point(w, min.y / 2));
859     }
860 
861     @Test
862     @Ignore("b/265007420")
wallpaperColors_primary()863     public void wallpaperColors_primary() {
864         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
865         Canvas canvas = new Canvas(tmpWallpaper);
866         canvas.drawColor(Color.RED);
867 
868         try {
869             mWallpaperManager.setBitmap(tmpWallpaper);
870             WallpaperColors colors = mWallpaperManager.getWallpaperColors(
871                     FLAG_SYSTEM);
872 
873             // Check that primary color is almost red
874             Color primary = colors.getPrimaryColor();
875             final float delta = 0.1f;
876             assertWithMessage("red").that(primary.red()).isWithin(delta).of(1f);
877             assertWithMessage("green").that(primary.green()).isWithin(delta).of(0f);
878             assertWithMessage("blue").that(primary.blue()).isWithin(delta).of(0f);
879 
880             assertThat(colors.getSecondaryColor()).isNull();
881             assertThat(colors.getTertiaryColor()).isNull();
882         } catch (IOException e) {
883             throw new RuntimeException(e);
884         } finally {
885             tmpWallpaper.recycle();
886         }
887     }
888 
889     @Test
890     @Ignore("b/265007420")
wallpaperColors_secondary()891     public void wallpaperColors_secondary() {
892         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
893         Canvas canvas = new Canvas(tmpWallpaper);
894         canvas.drawColor(Color.RED);
895         // Make 20% of the wallpaper BLUE so that secondary color is BLUE
896         canvas.clipRect(0, 0, 100, 20);
897         canvas.drawColor(Color.BLUE);
898 
899         try {
900             mWallpaperManager.setBitmap(tmpWallpaper);
901             WallpaperColors colors = mWallpaperManager.getWallpaperColors(
902                     FLAG_SYSTEM);
903 
904             // Check that the secondary color is almost blue
905             Color secondary = colors.getSecondaryColor();
906             final float delta = 0.15f;
907             assertWithMessage("red").that(secondary.red()).isWithin(delta).of(0f);
908             assertWithMessage("green").that(secondary.green()).isWithin(delta).of(0f);
909             assertWithMessage("blue").that(secondary.blue()).isWithin(delta).of(1f);
910         } catch (IOException e) {
911             throw new RuntimeException(e);
912         } finally {
913             tmpWallpaper.recycle();
914         }
915     }
916 
917     @Test
highRatioWallpaper_largeWidth()918     public void highRatioWallpaper_largeWidth() throws Exception {
919         Bitmap highRatioWallpaper = Bitmap.createBitmap(8000, 800, Bitmap.Config.ARGB_8888);
920         Canvas canvas = new Canvas(highRatioWallpaper);
921         canvas.drawColor(Color.RED);
922 
923         try {
924             mWallpaperManager.setBitmap(highRatioWallpaper);
925             assertBitmapDimensions(mWallpaperManager.getBitmap());
926         } finally {
927             highRatioWallpaper.recycle();
928         }
929     }
930 
931     @Test
highRatioWallpaper_largeHeight()932     public void highRatioWallpaper_largeHeight() throws Exception {
933         Bitmap highRatioWallpaper = Bitmap.createBitmap(800, 8000, Bitmap.Config.ARGB_8888);
934         Canvas canvas = new Canvas(highRatioWallpaper);
935         canvas.drawColor(Color.RED);
936 
937         try {
938             mWallpaperManager.setBitmap(highRatioWallpaper);
939             assertBitmapDimensions(mWallpaperManager.getBitmap());
940         } finally {
941             highRatioWallpaper.recycle();
942         }
943     }
944 
945     @Test
highResolutionWallpaper()946     public void highResolutionWallpaper() throws Exception {
947         Bitmap highResolutionWallpaper = Bitmap.createBitmap(10000, 10000, Bitmap.Config.ARGB_8888);
948         Canvas canvas = new Canvas(highResolutionWallpaper);
949         canvas.drawColor(Color.BLUE);
950 
951         try {
952             mWallpaperManager.setBitmap(highResolutionWallpaper);
953             assertBitmapDimensions(mWallpaperManager.getBitmap());
954         } finally {
955             highResolutionWallpaper.recycle();
956         }
957     }
958 
959     @Test
testWideGamutWallpaper()960     public void testWideGamutWallpaper() throws IOException {
961         final ColorSpace srgb = ColorSpace.get(ColorSpace.Named.SRGB);
962         final ColorSpace p3 = ColorSpace.get(ColorSpace.Named.DISPLAY_P3);
963         final Bitmap.Config config = Bitmap.Config.ARGB_8888;
964         final Bitmap srgbBitmap = Bitmap.createBitmap(100, 100, config);
965         final Bitmap p3Bitmap = Bitmap.createBitmap(100, 100, config, false, p3);
966 
967         try {
968             // sRGB is the default color space
969             mWallpaperManager.setBitmap(srgbBitmap);
970             assertThat(mWallpaperManager.getBitmap().getColorSpace()).isEqualTo(srgb);
971 
972             // If wide gamut is enabled, Display-P3 should be supported.
973             mWallpaperManager.setBitmap(p3Bitmap);
974 
975             final boolean isDisplayP3 = mWallpaperManager.getBitmap().getColorSpace().equals(p3);
976             // Assert false only when device enabled WCG, but display does not support Display-P3
977             assertThat(mEnableWcg && !isDisplayP3).isFalse();
978         } finally {
979             srgbBitmap.recycle();
980             p3Bitmap.recycle();
981         }
982     }
983 
984     @Test
testWallpaperSupportsWcg()985     public void testWallpaperSupportsWcg() throws IOException {
986         final int sysWallpaper = FLAG_SYSTEM;
987 
988         final Bitmap srgbBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
989         final Bitmap p3Bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888, false,
990                 ColorSpace.get(ColorSpace.Named.DISPLAY_P3));
991 
992         try {
993             mWallpaperManager.setBitmap(srgbBitmap);
994             assertThat(mWallpaperManager.wallpaperSupportsWcg(sysWallpaper)).isFalse();
995 
996             mWallpaperManager.setBitmap(p3Bitmap);
997             assertThat(mWallpaperManager.wallpaperSupportsWcg(sysWallpaper)).isEqualTo(mEnableWcg);
998         } finally {
999             srgbBitmap.recycle();
1000             p3Bitmap.recycle();
1001         }
1002     }
1003 
1004     /**
1005      * Check that all the callback methods of the wallpaper are invoked by the same thread.
1006      * Also checks that the callback methods are called in a proper order.
1007      * See {@link TestWallpaperService} to see the checks that are performed.
1008      */
1009     @Test
wallpaperCallbackMainThreadTest()1010     public void wallpaperCallbackMainThreadTest() {
1011 
1012         // use a wallpaper supporting ambient mode, to trigger Engine.onAmbientModeChanged
1013         ComponentName componentName = new ComponentName(
1014                 TestLiveWallpaperSupportingAmbientMode.class.getPackageName(),
1015                 TestLiveWallpaperSupportingAmbientMode.class.getName());
1016         runWithShellPermissionIdentity(() ->
1017                 mWallpaperManager.setWallpaperComponent(componentName));
1018 
1019         // trigger Engine.onDesiredDimensionsChanged
1020         mWallpaperManager.suggestDesiredDimensions(1000, 1000);
1021 
1022         Activity activity = mActivityTestRule.launchActivity(null);
1023 
1024         Window window = activity.getWindow();
1025         IBinder windowToken = window.getDecorView().getWindowToken();
1026 
1027         // send some command to trigger Engine.onCommand
1028         mWallpaperManager.sendWallpaperCommand(
1029                 windowToken, WallpaperManager.COMMAND_TAP, 50, 50, 0, null);
1030 
1031         // trigger Engine.onZoomChanged
1032         mWallpaperManager.setWallpaperZoomOut(windowToken, 0.5f);
1033 
1034         // trigger Engine.onTouchEvent
1035         mCtsTouchUtils.emulateTapOnViewCenter(
1036                 InstrumentationRegistry.getInstrumentation(), null,
1037                 activity.findViewById(android.R.id.content));
1038 
1039         mActivityTestRule.finishActivity();
1040         runWithShellPermissionIdentity(() -> mWallpaperManager.clearWallpaper());
1041     }
1042 
1043     @Test
peekWallpaperCaching_cachesWallpaper()1044     public void peekWallpaperCaching_cachesWallpaper() throws IOException {
1045         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1046 
1047         // Get the current bitmap, and check that the second call returns the cached bitmap
1048         Bitmap bitmap1 = mWallpaperManager.getBitmapAsUser(mContext.getUserId(),
1049                 false /* hardware */, FLAG_SYSTEM);
1050         assertThat(bitmap1).isNotNull();
1051         assertThat(mWallpaperManager.getBitmapAsUser(mContext.getUserId(), false /* hardware */,
1052                 FLAG_SYSTEM)).isSameInstanceAs(bitmap1);
1053 
1054         // Change the wallpaper to invalidate the cached bitmap
1055         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_SYSTEM);
1056 
1057         // Get the new bitmap, and check that the second call returns the newly cached bitmap
1058         Bitmap bitmap2 = mWallpaperManager.getBitmapAsUser(mContext.getUserId(),
1059                 false /* hardware */, FLAG_SYSTEM);
1060         assertThat(bitmap2).isNotSameInstanceAs(bitmap1);
1061         assertThat(mWallpaperManager.getBitmapAsUser(mContext.getUserId(), false /* hardware */,
1062                 FLAG_SYSTEM)).isSameInstanceAs(bitmap2);
1063     }
1064 
1065     @Test
peekWallpaperCaching_differentWhich_doesNotReturnCached()1066     public void peekWallpaperCaching_differentWhich_doesNotReturnCached() throws IOException {
1067         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1068         mWallpaperManager.setResource(R.drawable.icon_green, FLAG_LOCK);
1069 
1070         Bitmap bitmapSystem = mWallpaperManager.getBitmapAsUser(mContext.getUserId(),
1071                 false /* hardware */, FLAG_SYSTEM);
1072         Bitmap bitmapLock = mWallpaperManager.getBitmapAsUser(mContext.getUserId(),
1073                 false /* hardware */, FLAG_LOCK);
1074         assertThat(bitmapLock).isNotSameInstanceAs(bitmapSystem);
1075 
1076     }
1077 
1078     @Test
peekWallpaperCaching_bitmapRecycled_doesNotReturnCached()1079     public void peekWallpaperCaching_bitmapRecycled_doesNotReturnCached() throws IOException {
1080         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1081 
1082         Bitmap bitmap = mWallpaperManager.getBitmapAsUser(mContext.getUserId(),
1083                 false /* hardware */, FLAG_SYSTEM);
1084         assertThat(bitmap).isNotNull();
1085         bitmap.recycle();
1086         assertThat(mWallpaperManager.getBitmapAsUser(mContext.getUserId(), false /* hardware */,
1087                 FLAG_SYSTEM)).isNotSameInstanceAs(bitmap);
1088     }
1089 
1090     @Test
peekWallpaperCaching_differentUser_doesNotReturnCached()1091     public void peekWallpaperCaching_differentUser_doesNotReturnCached() throws IOException {
1092         final int bogusUserId = -1;
1093         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1094 
1095         Bitmap bitmap = mWallpaperManager.getBitmapAsUser(mContext.getUserId(),
1096                 false /* hardware */, FLAG_SYSTEM);
1097         assertThat(bitmap).isNotNull();
1098 
1099         // If the cached bitmap was determined to be invalid, this leads to a call to
1100         // WallpaperManager.Globals#getCurrentWallpaperLocked() for a different user, which
1101         // generates a security exception: the exception indicates that the cached bitmap was
1102         // invalid, which is the desired result.
1103         assertThrows(SecurityException.class,
1104                 () -> mWallpaperManager.getBitmapAsUser(bogusUserId, false /* hardware */,
1105                         FLAG_SYSTEM));
1106     }
1107 
1108     @Test
peekWallpaperDimensions_homeScreen_succeeds()1109     public void peekWallpaperDimensions_homeScreen_succeeds() throws IOException {
1110         final int width = 100;
1111         final int height = 200;
1112         Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
1113         Canvas canvas = new Canvas(bitmap);
1114         canvas.drawColor(Color.RED);
1115         mWallpaperManager.setBitmap(bitmap);
1116 
1117         Bitmap croppedBitmap = mWallpaperManager.getBitmap();
1118         Rect expectedSize = new Rect(0, 0, croppedBitmap.getWidth(), croppedBitmap.getHeight());
1119         Rect actualSize = mWallpaperManager.peekBitmapDimensions();
1120 
1121         assertThat(actualSize).isEqualTo(expectedSize);
1122     }
1123 
1124     @Test
peekWallpaperDimensions_lockScreenUnset_succeeds()1125     public void peekWallpaperDimensions_lockScreenUnset_succeeds() {
1126         Rect actualSize = mWallpaperManager.peekBitmapDimensions(FLAG_LOCK);
1127 
1128         assertThat(actualSize).isNull();
1129     }
1130 
1131     @Test
peekWallpaperDimensions_lockScreenSet_succeeds()1132     public void peekWallpaperDimensions_lockScreenSet_succeeds() throws IOException {
1133         Bitmap homeBitmap = Bitmap.createBitmap(150 /* width */, 150 /* width */,
1134                 Bitmap.Config.ARGB_8888);
1135         Canvas homeCanvas = new Canvas(homeBitmap);
1136         homeCanvas.drawColor(Color.RED);
1137         mWallpaperManager.setBitmap(homeBitmap, /* visibleCropHint */ null, /* allowBackup */true,
1138                 FLAG_SYSTEM);
1139         final int width = 100;
1140         final int height = 200;
1141         Bitmap lockBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
1142         Canvas lockCanvas = new Canvas(lockBitmap);
1143         lockCanvas.drawColor(Color.RED);
1144         mWallpaperManager.setBitmap(lockBitmap, /* visibleCropHint */ null, /* allowBackup */true,
1145                 FLAG_LOCK);
1146 
1147         Drawable drawable = mWallpaperManager.getDrawable(FLAG_LOCK);
1148         Rect expectedSize = new Rect(
1149                 0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
1150         Rect actualSize = mWallpaperManager.peekBitmapDimensions(FLAG_LOCK);
1151 
1152         assertThat(actualSize).isEqualTo(expectedSize);
1153     }
1154 
1155     @Test
getDrawable_homeScreen_succeeds()1156     public void getDrawable_homeScreen_succeeds() throws IOException {
1157         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1158         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1159 
1160         Drawable actual = mWallpaperManager.getDrawable(FLAG_SYSTEM);
1161 
1162         assertWithMessage("Drawables must represent the same image").that(
1163                 isSimilar(actual, expected, true)).isTrue();
1164     }
1165 
1166     @Test
getDrawable_lockScreenUnset_returnsNull()1167     public void getDrawable_lockScreenUnset_returnsNull() {
1168         Drawable actual = mWallpaperManager.getDrawable(FLAG_LOCK);
1169 
1170         assertThat(actual).isNull();
1171     }
1172 
1173     @Test
getDrawable_lockScreenSet_succeeds()1174     public void getDrawable_lockScreenSet_succeeds() throws IOException {
1175         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1176         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
1177 
1178         Drawable actual = mWallpaperManager.getDrawable(FLAG_LOCK);
1179 
1180         assertWithMessage("Drawables must represent the same image").that(
1181                 isSimilar(actual, expected, true)).isTrue();
1182     }
1183 
1184     @Test
getDrawable_default_sameAsHome()1185     public void getDrawable_default_sameAsHome() throws IOException {
1186         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1187         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1188 
1189         Drawable actual = mWallpaperManager.getDrawable();
1190 
1191         assertWithMessage("Drawables must represent the same image").that(
1192                 isSimilar(actual, expected, true)).isTrue();
1193     }
1194 
1195     @Test
getFastDrawable_homeScreen_succeeds()1196     public void getFastDrawable_homeScreen_succeeds() throws IOException {
1197         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1198         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1199 
1200         Drawable actual = mWallpaperManager.getFastDrawable(FLAG_SYSTEM);
1201 
1202         assertWithMessage("Drawables must represent the same image").that(
1203                 isSimilar(actual, expected, true)).isTrue();
1204     }
1205 
1206     @Test
getFastDrawable_lockScreenUnset_returnsNull()1207     public void getFastDrawable_lockScreenUnset_returnsNull() {
1208         Drawable actual = mWallpaperManager.getFastDrawable(FLAG_LOCK);
1209 
1210         assertThat(actual).isNull();
1211     }
1212 
1213     @Test
getFastDrawable_lockScreenSet_succeeds()1214     public void getFastDrawable_lockScreenSet_succeeds() throws IOException {
1215         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1216         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
1217 
1218         Drawable actual = mWallpaperManager.getFastDrawable(FLAG_LOCK);
1219 
1220         assertWithMessage("Drawables must represent the same image").that(
1221                 isSimilar(actual, expected, true)).isTrue();
1222     }
1223 
1224     @Test
getFastDrawable_default_sameAsHome()1225     public void getFastDrawable_default_sameAsHome() throws IOException {
1226         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1227         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1228 
1229         Drawable actual = mWallpaperManager.getFastDrawable();
1230 
1231         assertWithMessage("Drawables must represent the same image").that(
1232                 isSimilar(actual, expected, true)).isTrue();
1233     }
1234 
1235     @Test
peekDrawable_homeScreen_succeeds()1236     public void peekDrawable_homeScreen_succeeds() throws IOException {
1237         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1238         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1239 
1240         Drawable actual = mWallpaperManager.peekDrawable(FLAG_SYSTEM);
1241 
1242         assertWithMessage("Drawables must represent the same image").that(
1243                 isSimilar(actual, expected, true)).isTrue();
1244     }
1245 
1246     @Test
peekDrawable_lockScreenUnset_returnsNull()1247     public void peekDrawable_lockScreenUnset_returnsNull() {
1248         Drawable actual = mWallpaperManager.peekDrawable(FLAG_LOCK);
1249 
1250         assertThat(actual).isNull();
1251     }
1252 
1253     @Test
peekDrawable_lockScreenSet_succeeds()1254     public void peekDrawable_lockScreenSet_succeeds() throws IOException {
1255         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1256         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
1257 
1258         Drawable actual = mWallpaperManager.peekDrawable(FLAG_LOCK);
1259 
1260         assertWithMessage("Drawables must represent the same image").that(
1261                 isSimilar(actual, expected, true)).isTrue();
1262     }
1263 
1264     @Test
peekDrawable_default_sameAsHome()1265     public void peekDrawable_default_sameAsHome() throws IOException {
1266         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1267         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1268 
1269         Drawable actual = mWallpaperManager.peekDrawable();
1270 
1271         assertWithMessage("Drawables must represent the same image").that(
1272                 isSimilar(actual, expected, true)).isTrue();
1273     }
1274 
1275     @Test
peekFastDrawable_homeScreen_succeeds()1276     public void peekFastDrawable_homeScreen_succeeds() throws IOException {
1277         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1278         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1279 
1280         Drawable actual = mWallpaperManager.peekFastDrawable(FLAG_SYSTEM);
1281 
1282         assertWithMessage("Drawables must represent the same image").that(
1283                 isSimilar(actual, expected, true)).isTrue();
1284     }
1285 
1286     @Test
peekFastDrawable_lockScreenUnset_returnsNull()1287     public void peekFastDrawable_lockScreenUnset_returnsNull() {
1288         Drawable actual = mWallpaperManager.peekFastDrawable(FLAG_LOCK);
1289 
1290         assertThat(actual).isNull();
1291     }
1292 
1293     @Test
peekFastDrawable_lockScreenSet_succeeds()1294     public void peekFastDrawable_lockScreenSet_succeeds() throws IOException {
1295         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1296         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_LOCK);
1297 
1298         Drawable actual = mWallpaperManager.peekFastDrawable(FLAG_LOCK);
1299 
1300         assertWithMessage("Drawables must represent the same image").that(
1301                 isSimilar(actual, expected, true)).isTrue();
1302     }
1303 
1304     @Test
peekFastDrawable_default_sameAsHome()1305     public void peekFastDrawable_default_sameAsHome() throws IOException {
1306         Drawable expected = mContext.getDrawable(R.drawable.icon_red);
1307         mWallpaperManager.setResource(R.drawable.icon_red, FLAG_SYSTEM);
1308 
1309         Drawable actual = mWallpaperManager.peekFastDrawable();
1310 
1311         assertWithMessage("Drawables must represent the same image").that(
1312                 isSimilar(actual, expected, true)).isTrue();
1313     }
1314 
1315     /**
1316      * For every possible (state, change) couple, checks that the number of times
1317      * {@link TestWallpaperService.FakeEngine#onDestroy} and
1318      * {@link TestWallpaperService.FakeEngine#onCreate} are called is correct.
1319      */
1320     @Test
testEngineCallbackCountsParam( @estParameter WallpaperManagerTestUtils.WallpaperState state)1321     public void testEngineCallbackCountsParam(
1322             @TestParameter WallpaperManagerTestUtils.WallpaperState state)
1323             throws IOException {
1324         DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
1325         assumeTrue("this test item is not suitable for multi screen devices"
1326                 + " that expand display screens", displayManager.getDisplays().length <= 1);
1327 
1328         ArrayList<String> errorMessages = new ArrayList<>();
1329         runWithShellPermissionIdentity(() -> {
1330             for (WallpaperChange change: state.allPossibleChanges()) {
1331                 WallpaperManagerTestUtils.goToState(mWallpaperManager, state);
1332                 TestWallpaperService.Companion.resetCounts();
1333                 final int expectedCreateCount =
1334                         state.expectedNumberOfLiveWallpaperCreate(change);
1335                 final int expectedDestroyCount =
1336                         state.expectedNumberOfLiveWallpaperDestroy(change);
1337 
1338                 runAndAwaitChanges(5, TimeUnit.SECONDS,
1339                         expectedCreateCount, expectedDestroyCount, 0, () -> {
1340                             WallpaperManagerTestUtils.performChange(mWallpaperManager, change);
1341                         });
1342 
1343                 int actualCreateCount = TestWallpaperService.Companion.getCreateCount();
1344                 String createMessage = String.format(
1345                         "Expected %s calls to Engine#onCreate, got %s. ",
1346                         expectedCreateCount, actualCreateCount);
1347                 if (actualCreateCount != expectedCreateCount) {
1348                     errorMessages.add(
1349                             createMessage + "\n" + state.reproduceDescription(change));
1350                 }
1351 
1352                 int actualDestroyCount = TestWallpaperService.Companion.getDestroyCount();
1353                 String destroyMessage = String.format(
1354                         "Expected %s calls to Engine#onDestroy, got %s. ",
1355                         expectedDestroyCount, actualDestroyCount);
1356                 if (actualDestroyCount != expectedDestroyCount) {
1357                     errorMessages.add(
1358                             destroyMessage + "\n" + state.reproduceDescription(change));
1359                 }
1360             }
1361         });
1362         assertWithMessage(String.join("\n\n", errorMessages))
1363                 .that(errorMessages.size()).isEqualTo(0);
1364     }
1365 
1366     /**
1367      * Check that the wallpaper windows that window manager is handling
1368      * are exactly the expected ones
1369      */
1370     @Test
testExistingWallpaperWindows()1371     public void testExistingWallpaperWindows() {
1372         DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
1373         assumeTrue("this test item is not suitable for multi screen devices"
1374                 + " that expand display screens", displayManager.getDisplays().length <= 1);
1375 
1376         assumeTrue("Test requires FEATURE_LIVE_WALLPAPER",
1377                 mContext.getPackageManager().hasSystemFeature(FEATURE_LIVE_WALLPAPER));
1378         runWithShellPermissionIdentity(() -> {
1379             WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper =
1380                     new WallpaperWindowsTestUtils.WallpaperWindowsHelper(sWindowManagerStateHelper);
1381             // Two independent wallpapers
1382             WallpaperManagerTestUtils.goToState(
1383                     mWallpaperManager, WallpaperState.LIVE_DIFF_MULTI);
1384             assertWallpapersMatching(wallpaperWindowsHelper,
1385                     List.of(mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM).getServiceName(),
1386                             mWallpaperManager.getWallpaperInfo(FLAG_LOCK).getServiceName()));
1387             // One shared wallpaper
1388             WallpaperManagerTestUtils.goToState(
1389                     mWallpaperManager, WallpaperState.LIVE_SAME_SINGLE);
1390             assertWallpapersMatching(wallpaperWindowsHelper, List.of(
1391                     mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM).getServiceName()));
1392         });
1393     }
1394 
startAndWaitActivity()1395     private void startAndWaitActivity() {
1396         mActivityTestRule.launchActivity(null);
1397         sWindowManagerStateHelper.waitAndAssertActivityState(
1398                 mActivityTestRule.getActivity().getComponentName(),
1399                 WindowManagerState.STATE_RESUMED);
1400     }
1401 
1402     /**
1403      * Check that the windows which have the role of home screen wallpapers
1404      * are actually visible on home screen
1405      */
1406     @Test
testSystemAndLockWallpaperVisibility_onHomeScreen()1407     public void testSystemAndLockWallpaperVisibility_onHomeScreen() {
1408         assumeTrue("Test requires FEATURE_LIVE_WALLPAPER",
1409                 mContext.getPackageManager().hasSystemFeature(FEATURE_LIVE_WALLPAPER));
1410         try (LockScreenSession lockScreenSession =
1411                      new LockScreenSession(mInstrumentation, sWindowManagerStateHelper)) {
1412             runWithShellPermissionIdentity(() -> {
1413                 WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper =
1414                         new WallpaperWindowsTestUtils.WallpaperWindowsHelper(
1415                                 sWindowManagerStateHelper);
1416                 lockScreenSession.disableLockScreen().unlockDevice();
1417 
1418                 // Launch an activity that shows the wallpaper to make sure it is not behind
1419                 // opaque activities
1420                 startAndWaitActivity();
1421 
1422                 // Two independent wallpapers
1423                 WallpaperManagerTestUtils.goToState(mWallpaperManager,
1424                         WallpaperState.LIVE_DIFF_MULTI);
1425                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_SYSTEM,
1426                         true /* shouldBeShown */, "System wallpaper is hidden on home screen");
1427 
1428                 // Shared wallpaper
1429                 WallpaperManagerTestUtils.goToState(
1430                         mWallpaperManager, WallpaperState.LIVE_SAME_SINGLE);
1431                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_SYSTEM | FLAG_LOCK,
1432                         true /* shouldBeShown */, "Shared wallpaper is hidden on home screen");
1433             });
1434         }
1435     }
1436 
1437     /**
1438      * Check that the windows which have the role of lock screen wallpapers
1439      * are actually visible on lock screen
1440      */
1441     @Test
testSystemAndLockWallpaperVisibility_onLockScreen()1442     public void testSystemAndLockWallpaperVisibility_onLockScreen() throws Exception {
1443         assumeFalse("Test requires support for different lock and home screen wallpapers",
1444                 mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH));
1445 
1446         assumeTrue("Test requires FEATURE_SECURE_LOCK_SCREEN",
1447                 mContext.getPackageManager().hasSystemFeature(FEATURE_SECURE_LOCK_SCREEN));
1448         assumeTrue("Test requires FEATURE_LIVE_WALLPAPER",
1449                 mContext.getPackageManager().hasSystemFeature(FEATURE_LIVE_WALLPAPER));
1450         try (LockScreenSession lockScreenSession =
1451                      new LockScreenSession(mInstrumentation, sWindowManagerStateHelper)) {
1452             runWithShellPermissionIdentity(() -> {
1453                 WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper =
1454                         new WallpaperWindowsTestUtils.WallpaperWindowsHelper(
1455                                 sWindowManagerStateHelper);
1456 
1457                 // Two independent wallpapers
1458                 WallpaperManagerTestUtils.goToState(mWallpaperManager,
1459                         WallpaperState.LIVE_DIFF_MULTI);
1460 
1461                 lockScreenSession.gotoKeyguard();
1462                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_SYSTEM,
1463                         false /* shouldBeShown */,
1464                         "System wallpaper is showing on lock screen");
1465                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_LOCK, true /* shouldBeShown */,
1466                         "Lock wallpaper is hidden on lock screen");
1467 
1468                 // Shared wallpaper
1469                 WallpaperManagerTestUtils.goToState(
1470                         mWallpaperManager, WallpaperState.LIVE_SAME_SINGLE);
1471                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_SYSTEM | FLAG_LOCK,
1472                         true /* shouldBeShown */, "Shared wallpaper is hidden on lock screen");
1473             });
1474         }
1475     }
1476 
1477     /**
1478      * Verify that a shared wallpaper is visible behind a show wallpaper activity on lockscreen
1479      */
1480     @Test
testSharedWallpaperVisibilityBehindActivity_onLockScreen()1481     public void testSharedWallpaperVisibilityBehindActivity_onLockScreen() throws Exception {
1482         assumeTrue("Test requires FEATURE_SECURE_LOCK_SCREEN",
1483                 mContext.getPackageManager().hasSystemFeature(FEATURE_SECURE_LOCK_SCREEN));
1484         assumeTrue("Test requires FEATURE_LIVE_WALLPAPER",
1485                 mContext.getPackageManager().hasSystemFeature(FEATURE_LIVE_WALLPAPER));
1486         try (LockScreenSession lockScreenSession =
1487                      new LockScreenSession(mInstrumentation, sWindowManagerStateHelper)) {
1488             runWithShellPermissionIdentity(() -> {
1489                 WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper =
1490                         new WallpaperWindowsTestUtils.WallpaperWindowsHelper(
1491                                 sWindowManagerStateHelper);
1492 
1493                 startAndWaitActivity();
1494 
1495                 // Make sure a live wallpaper is configured and used for both home and lock
1496                 // screens.
1497                 final WallpaperInfo homeInfo = mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM);
1498                 final int lockInfo = mWallpaperManager.getWallpaperId(FLAG_LOCK);
1499                 if (homeInfo == null || lockInfo >= 0) {
1500                     WallpaperManagerTestUtils.goToState(mWallpaperManager,
1501                             WallpaperState.LIVE_SAME_SINGLE);
1502                 }
1503 
1504                 lockScreenSession.gotoKeyguard();
1505                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_SYSTEM | FLAG_LOCK,
1506                         true /* shouldBeShown */,
1507                         "Shared wallpaper should be showing behind activity");
1508             });
1509         }
1510     }
1511 
1512     /**
1513      * Verify that the home wallpaper is never visible behind an activity on lock screen, and that
1514      * the lock screen wallpaper is visible when it has its own window.
1515      */
1516     @Test
testIndependentWallpaperVisibilityBehindActivity_onLockScreen()1517     public void testIndependentWallpaperVisibilityBehindActivity_onLockScreen() throws Exception {
1518         assumeFalse("Test requires support for different lock and home screen wallpapers",
1519                 mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH));
1520         assumeTrue("Test requires FEATURE_SECURE_LOCK_SCREEN",
1521                 mContext.getPackageManager().hasSystemFeature(FEATURE_SECURE_LOCK_SCREEN));
1522         assumeTrue("Test requires FEATURE_LIVE_WALLPAPER",
1523                 mContext.getPackageManager().hasSystemFeature(FEATURE_LIVE_WALLPAPER));
1524 
1525         try (LockScreenSession lockScreenSession =
1526                      new LockScreenSession(mInstrumentation, sWindowManagerStateHelper)) {
1527             runWithShellPermissionIdentity(() -> {
1528                 WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper =
1529                         new WallpaperWindowsTestUtils.WallpaperWindowsHelper(
1530                                 sWindowManagerStateHelper);
1531 
1532                 startAndWaitActivity();
1533 
1534                 WallpaperState wallpaperState = WallpaperState.LIVE_DIFF_MULTI;
1535                 WallpaperManagerTestUtils.goToState(mWallpaperManager, wallpaperState);
1536                 lockScreenSession.gotoKeyguard();
1537                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_LOCK,
1538                         true /* shouldBeShown */,
1539                         "Lock wallpaper should be showing behind an activity");
1540                 assertWallpaperIsShown(wallpaperWindowsHelper, FLAG_SYSTEM,
1541                         false /* shouldBeShown */,
1542                         "Home wallpaper should not be showing behind an activity on lock screen");
1543             });
1544         }
1545     }
1546 
1547     @Test
1548     @Ignore("b/281082882")
setDimAmount_lockScreenUnset_notifiesColorsChangedBothTogether()1549     public void setDimAmount_lockScreenUnset_notifiesColorsChangedBothTogether() {
1550         ensureCleanState();
1551 
1552         final CountDownLatch latch = new CountDownLatch(1);
1553         WallpaperManager.OnColorsChangedListener counter = (colors, whichWp) -> latch.countDown();
1554         final LinkedList<Integer> receivedFlags = new LinkedList<>();
1555         WallpaperManager.OnColorsChangedListener listener = (colors, whichWp) -> receivedFlags.add(
1556                 whichWp);
1557         mWallpaperManager.addOnColorsChangedListener(listener, mHandler);
1558         mWallpaperManager.addOnColorsChangedListener(counter, mHandler);
1559         final float initialDim = runWithShellPermissionIdentity(
1560                 mWallpaperManager::getWallpaperDimAmount);
1561         final float newDim = initialDim > 0 ? 0.5f * initialDim : 0.5f;
1562 
1563         try {
1564             runWithShellPermissionIdentity(() -> {
1565                 mWallpaperManager.setWallpaperDimAmount(newDim);
1566             });
1567             boolean latchSuccess = latch.await(DIM_LISTENER_TIMEOUT_SECS, TimeUnit.SECONDS);
1568             assertWithMessage("Registered listener not invoked").that(latchSuccess).isTrue();
1569         } catch (InterruptedException e) {
1570             throw new RuntimeException(e);
1571         } finally {
1572             runWithShellPermissionIdentity(() ->
1573                     mWallpaperManager.setWallpaperDimAmount(initialDim));
1574         }
1575 
1576         assertThat(receivedFlags).containsExactly(FLAG_SYSTEM | FLAG_LOCK);
1577         mWallpaperManager.removeOnColorsChangedListener(listener);
1578         mWallpaperManager.removeOnColorsChangedListener(counter);
1579     }
1580 
1581     @Test
1582     @Ignore("b/281082882")
setDimAmount_lockScreenSet_notifiesColorsChangedBothSeparately()1583     public void setDimAmount_lockScreenSet_notifiesColorsChangedBothSeparately() {
1584         ensureCleanState(FLAG_LOCK);
1585         ensureCleanState(FLAG_SYSTEM);
1586 
1587         final CountDownLatch latch = new CountDownLatch(2);
1588         WallpaperManager.OnColorsChangedListener counter = (colors, whichWp) -> latch.countDown();
1589         final LinkedList<Integer> receivedFlags = new LinkedList<>();
1590         WallpaperManager.OnColorsChangedListener listener = (colors, whichWp) -> receivedFlags.add(
1591                 whichWp);
1592         mWallpaperManager.addOnColorsChangedListener(listener, mHandler);
1593         final float initialDim = runWithShellPermissionIdentity(
1594                 mWallpaperManager::getWallpaperDimAmount);
1595         final float newDim = initialDim > 0 ? 0.5f * initialDim : 0.5f;
1596 
1597         mWallpaperManager.addOnColorsChangedListener(counter, mHandler);
1598         try {
1599             runWithShellPermissionIdentity(() -> {
1600                 mWallpaperManager.setWallpaperDimAmount(newDim);
1601             });
1602             boolean latchSuccess = latch.await(DIM_LISTENER_TIMEOUT_SECS, TimeUnit.SECONDS);
1603             assertWithMessage("Registered listener not invoked").that(latchSuccess).isTrue();
1604         } catch (InterruptedException e) {
1605             throw new RuntimeException(e);
1606         } finally {
1607             runWithShellPermissionIdentity(() ->
1608                     mWallpaperManager.setWallpaperDimAmount(initialDim));
1609         }
1610 
1611         assertThat(receivedFlags).containsExactly(FLAG_SYSTEM, FLAG_LOCK);
1612         mWallpaperManager.removeOnColorsChangedListener(listener);
1613         mWallpaperManager.removeOnColorsChangedListener(counter);
1614     }
1615 
assertWallpapersMatching(WallpaperWindowsTestUtils.WallpaperWindowsHelper windows, List<String> expectedWallpaperPackageNames)1616     private void assertWallpapersMatching(WallpaperWindowsTestUtils.WallpaperWindowsHelper windows,
1617             List<String> expectedWallpaperPackageNames) {
1618 
1619         boolean match = windows.waitForMatchingPackages(expectedWallpaperPackageNames);
1620         assertWithMessage("Lists do not match. Expected: "
1621                 + expectedWallpaperPackageNames + " but received " + windows.dumpPackages())
1622                 .that(match).isTrue();
1623     }
1624 
1625     /** Check if wallpaper corresponding to wallpaperFlag has visibility matching shouldBeShown */
assertWallpaperIsShown( WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper, int wallpaperFlag, boolean shouldBeShown, String errorMsg)1626     private void assertWallpaperIsShown(
1627             WallpaperWindowsTestUtils.WallpaperWindowsHelper wallpaperWindowsHelper,
1628             int wallpaperFlag,
1629             boolean shouldBeShown,
1630             String errorMsg) {
1631         String wpServiceName = mWallpaperManager.getWallpaperInfo(
1632                 (wallpaperFlag & FLAG_SYSTEM) != 0 ? FLAG_SYSTEM : FLAG_LOCK).getServiceName();
1633 
1634         boolean matchingVisibility = wallpaperWindowsHelper
1635                 .waitForMatchingWindowVisibility(wpServiceName, shouldBeShown);
1636         assertWithMessage(errorMsg + "\n" + wallpaperWindowsHelper.dumpWindows())
1637                 .that(matchingVisibility).isTrue();
1638     }
1639 
1640     /**
1641      * Granting android.permission.ALWAYS_UPDATE_WALLPAPER should allow the wallpaper
1642      * commands to be sent even when activity is not in focus
1643      * Note that there is no window to focus in this test
1644      */
1645     @RequiresFlagsEnabled(Flags.FLAG_ALWAYS_UPDATE_WALLPAPER_PERMISSION)
1646     @Test
1647     @Ignore("b/313534425")
testAlwaysUpdateWallpaperPermission_allowOutOfFocusWallpaperCommand()1648     public void testAlwaysUpdateWallpaperPermission_allowOutOfFocusWallpaperCommand() {
1649 
1650         /* Clear previous wallpaper commands */
1651         TestLiveWallpaper.Companion.resetPrevAction();
1652 
1653         runWithShellPermissionIdentity(
1654                 () -> {
1655                     mWallpaperManager.setWallpaperComponent(TEST_COMPONENT_NAME);
1656 
1657                     /* Activity that will be overlaid and lose focus */
1658                     WallpaperOverlayTestActivity overlayActivity =
1659                             mOverlayActivityTestRule.launchActivity(null);
1660                     sWindowManagerStateHelper.waitAndAssertActivityState(
1661                             overlayActivity.getComponentName(),
1662                             WindowManagerState.STATE_RESUMED);
1663                     assertTrue(
1664                             "overlayActivity does not have required permission",
1665                             overlayActivity.checkSelfPermission(ALWAYS_UPDATE_WALLPAPER)
1666                                     == PERMISSION_GRANTED);
1667 
1668                     /* Launch base activity to cover the overlay activity */
1669                     Activity baseActivity = mActivityTestRule.launchActivity(null);
1670                     sWindowManagerStateHelper.waitAndAssertActivityState(
1671                             baseActivity.getComponentName(),
1672                             WindowManagerState.STATE_RESUMED);
1673 
1674                     /* Send wallpaper command with ALWAYS_UPDATE_WALLPAPER permission */
1675                     overlayActivity.sendWallpaperCommand(WallpaperManager.COMMAND_TAP);
1676 
1677                     /* Allow time for the wallpaper command to be sent over IPC stack */
1678                     try {
1679                         Thread.sleep(SLEEP_MS);
1680                     } catch (InterruptedException e) {
1681                         throw new RuntimeException(e);
1682                     }
1683 
1684                     assertWithMessage("Wallpaper command is not sent with permission")
1685                             .that(TestLiveWallpaper.Companion.getPrevAction())
1686                             .isEqualTo(WallpaperManager.COMMAND_TAP);
1687                 });
1688     }
1689 
1690     @Test
1691     @RequiresFlagsEnabled({FLAG_MULTI_CROP})
testSetWallpaperWithCrops_noCrop()1692     public void testSetWallpaperWithCrops_noCrop() {
1693         Point screenSize = getScreenSize();
1694         int bitmapHeight = 3 * screenSize.y;
1695         int bitmapWidth = 2 * screenSize.x;
1696         Point bitmapSize = new Point(bitmapWidth, bitmapHeight);
1697         Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
1698         Canvas canvas = new Canvas(bitmap);
1699         canvas.drawColor(Color.RED);
1700         runWithShellPermissionIdentity(() -> {
1701             for (int which : List.of(FLAG_SYSTEM, FLAG_LOCK, FLAG_SYSTEM | FLAG_LOCK)) {
1702                 Rect expectedCrop = mWallpaperManager
1703                         .getBitmapCrops(bitmapSize, List.of(screenSize), Map.of()).getFirst();
1704                 mWallpaperManager.setBitmapWithCrops(bitmap, Map.of(), true, which);
1705                 int sourceFlag = which == FLAG_LOCK ? FLAG_LOCK : FLAG_SYSTEM;
1706                 Rect absoluteCrop = mWallpaperManager.getBitmapCrops(
1707                         List.of(screenSize), sourceFlag, true).getFirst();
1708                 assertAlmostEqual(expectedCrop, absoluteCrop);
1709                 Rect relativeCrop = mWallpaperManager.getBitmapCrops(
1710                         List.of(screenSize), sourceFlag, false).getFirst();
1711                 float tolerance = 2f / Math.min(relativeCrop.width(), relativeCrop.height());
1712                 assertThat((float) relativeCrop.width() / relativeCrop.height()).isWithin(tolerance)
1713                         .of((float) expectedCrop.width() / expectedCrop.height());
1714             }
1715         });
1716     }
1717 
1718     @Test
1719     @RequiresFlagsEnabled({FLAG_MULTI_CROP})
1720     @RequiresFlagsDisabled(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
testSetWallpaperWithCrops_singleCrop()1721     public void testSetWallpaperWithCrops_singleCrop() {
1722         Point displaySize = getScreenSize();
1723 
1724         Point bitmapSize = new Point(100, 100);
1725         Bitmap bitmap = Bitmap.createBitmap(bitmapSize.x, bitmapSize.y, Bitmap.Config.ARGB_8888);
1726 
1727         float scale = Math.max((float) displaySize.x / bitmapSize.x,
1728                 (float) displaySize.y / bitmapSize.y);
1729         Rect crop = new Rect(0, 0, (int) (displaySize.x / scale), (int) (displaySize.y / scale));
1730         Map<Point, Rect> cropHints = Map.of(displaySize, crop);
1731 
1732         assertCorrectCrop(bitmap, cropHints, false);
1733     }
1734 
1735     @Test
1736     @RequiresFlagsEnabled({FLAG_MULTI_CROP, FLAG_LIVE_WALLPAPER_CONTENT_HANDLING})
testSetWallpaperWithCrops_description_singleCrop()1737     public void testSetWallpaperWithCrops_description_singleCrop() {
1738         Point displaySize = getScreenSize();
1739 
1740         Point bitmapSize = new Point(100, 100);
1741         Bitmap bitmap = Bitmap.createBitmap(bitmapSize.x, bitmapSize.y, Bitmap.Config.ARGB_8888);
1742 
1743         float scale = Math.max((float) displaySize.x / bitmapSize.x,
1744                 (float) displaySize.y / bitmapSize.y);
1745         Rect crop = new Rect(0, 0, (int) (displaySize.x / scale), (int) (displaySize.y / scale));
1746         Map<Point, Rect> cropHints = Map.of(displaySize, crop);
1747 
1748         assertCorrectCrop(bitmap, cropHints, true);
1749     }
1750 
1751     @Test
1752     @RequiresFlagsEnabled({FLAG_MULTI_CROP})
1753     @RequiresFlagsDisabled(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
testSetWallpaperWithCrops_twoCrops()1754     public void testSetWallpaperWithCrops_twoCrops() {
1755         Point displaySize = getScreenSize();
1756         assumeFalse(displaySize.x == displaySize.y);
1757         Point rotatedDisplaySize = new Point(displaySize.y, displaySize.x);
1758 
1759         Point bitmapSize = new Point(300, 800);
1760         Bitmap bitmap = Bitmap.createBitmap(bitmapSize.x, bitmapSize.y, Bitmap.Config.ARGB_8888);
1761 
1762         float scale = Math.max((float) displaySize.x / bitmapSize.x,
1763                 (float) displaySize.y / bitmapSize.y);
1764         Rect crop = new Rect(
1765                 bitmapSize.x - (int) (displaySize.x / scale),
1766                 bitmapSize.y - (int) (displaySize.y / scale),
1767                 bitmapSize.x, bitmapSize.y);
1768         float rotatedScale = Math.max((float) rotatedDisplaySize.x / bitmapSize.x,
1769                 (float) rotatedDisplaySize.y / bitmapSize.y);
1770         Rect rotatedCrop = new Rect(0, 0,
1771                 (int) (rotatedDisplaySize.x / rotatedScale),
1772                 (int) (rotatedDisplaySize.y / rotatedScale));
1773         Map<Point, Rect> cropHints = Map.of(displaySize, crop, rotatedDisplaySize, rotatedCrop);
1774 
1775         assertCorrectCrop(bitmap, cropHints, false);
1776     }
1777 
1778     @Test
1779     @RequiresFlagsEnabled({FLAG_MULTI_CROP, FLAG_LIVE_WALLPAPER_CONTENT_HANDLING})
testSetWallpaperWithCrops_description_twoCrops()1780     public void testSetWallpaperWithCrops_description_twoCrops() {
1781         Point displaySize = getScreenSize();
1782         assumeFalse(displaySize.x == displaySize.y);
1783         Point rotatedDisplaySize = new Point(displaySize.y, displaySize.x);
1784 
1785         Point bitmapSize = new Point(300, 800);
1786         Bitmap bitmap = Bitmap.createBitmap(bitmapSize.x, bitmapSize.y, Bitmap.Config.ARGB_8888);
1787 
1788         float scale = Math.max((float) displaySize.x / bitmapSize.x,
1789                 (float) displaySize.y / bitmapSize.y);
1790         Rect crop = new Rect(
1791                 bitmapSize.x - (int) (displaySize.x / scale),
1792                 bitmapSize.y - (int) (displaySize.y / scale),
1793                 bitmapSize.x, bitmapSize.y);
1794         float rotatedScale = Math.max((float) rotatedDisplaySize.x / bitmapSize.x,
1795                 (float) rotatedDisplaySize.y / bitmapSize.y);
1796         Rect rotatedCrop = new Rect(0, 0,
1797                 (int) (rotatedDisplaySize.x / rotatedScale),
1798                 (int) (rotatedDisplaySize.y / rotatedScale));
1799         Map<Point, Rect> cropHints = Map.of(displaySize, crop, rotatedDisplaySize, rotatedCrop);
1800 
1801         assertCorrectCrop(bitmap, cropHints, true);
1802     }
1803 
1804     //// Tests specific to live wallpaper content handling
1805 
1806     @Test
1807     @Ignore("b/393392368")
1808     @RequiresFlagsEnabled(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
setWallpaperComponentWithDescription_succeeds()1809     public void setWallpaperComponentWithDescription_succeeds() {
1810         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
1811         // TODO(b/393392368) Add component
1812         WallpaperDescription description = new WallpaperDescription.Builder().build();
1813 
1814         runWithShellPermissionIdentity(
1815                 () -> setWallpaperDescriptionAndWait(description, FLAG_SYSTEM | FLAG_LOCK));
1816 
1817         assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM)).isNotEqualTo(origHomeWallpaperId);
1818         assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
1819         // TODO(b/393392368) Verify instance or component
1820     }
1821 
1822     @Test
1823     @RequiresFlagsEnabled(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
getWallpaperInstance_liveWallpaper_both_succeeds()1824     public void getWallpaperInstance_liveWallpaper_both_succeeds() {
1825         String id = "id_1";
1826         // TODO(b/393392368) Use setWallpaperDescriptionAndWait
1827         runWithShellPermissionIdentity(
1828                 () -> {
1829                     setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_SYSTEM | FLAG_LOCK);
1830                     WallpaperInstance instance =
1831                             mWallpaperManager.getWallpaperInstance(FLAG_SYSTEM);
1832                     assertThat(instance).isNotNull();
1833                     assertThat(instance.getDescription().getComponent())
1834                             .isEqualTo(TEST_COMPONENT_NAME);
1835                     assertThat(mWallpaperManager.getWallpaperInstance(FLAG_LOCK)).isNull();
1836                 });
1837     }
1838 
1839     @Test
1840     @RequiresFlagsEnabled(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
getWallpaperInstance_liveWallpaper_lockOnly_succeeds()1841     public void getWallpaperInstance_liveWallpaper_lockOnly_succeeds() {
1842         int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
1843         String id = "id_1";
1844         // TODO(b/393392368) Use setWallpaperDescriptionAndWait
1845         runWithShellPermissionIdentity(
1846                 () -> {
1847                     setWallpaperComponentAndWait(TEST_COMPONENT_NAME, FLAG_LOCK);
1848                     assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM))
1849                             .isEqualTo(origHomeWallpaperId);
1850                     WallpaperInstance homeInstance =
1851                             mWallpaperManager.getWallpaperInstance(FLAG_SYSTEM);
1852                     assertThat(homeInstance).isNotNull();
1853                     assertThat(homeInstance.getDescription()).isNotNull();
1854                     WallpaperInstance lockInstance =
1855                             mWallpaperManager.getWallpaperInstance(FLAG_LOCK);
1856                     assertThat(lockInstance).isNotNull();
1857                     assertThat(lockInstance.getDescription().getComponent())
1858                             .isEqualTo(TEST_COMPONENT_NAME);
1859                 });
1860     }
1861 
1862     @Test
1863     @RequiresFlagsEnabled(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
setBitmapWithDescription_both_succeeds()1864     public void setBitmapWithDescription_both_succeeds() throws IOException {
1865         // based on setBitmap_both_lockScreenSet_changesHomeAndClearsLock()
1866         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
1867         Canvas canvas = new Canvas(tmpWallpaper);
1868         canvas.drawColor(Color.GREEN);
1869         WallpaperDescription description = new WallpaperDescription.Builder().setId("id").build();
1870 
1871         try {
1872             mWallpaperManager.setBitmapWithDescription(
1873                     tmpWallpaper,
1874                     new WallpaperDescription.Builder().setId("ignored").build(),
1875                     true,
1876                     FLAG_LOCK);
1877             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
1878             canvas.drawColor(Color.RED);
1879 
1880             mWallpaperManager.setBitmapWithDescription(
1881                     tmpWallpaper, description, /* allowBackup= */ true, FLAG_SYSTEM | FLAG_LOCK);
1882 
1883             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM))
1884                     .isNotEqualTo(origHomeWallpaperId);
1885             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
1886             // TODO(b/380245309) Verify instance id and description
1887         } finally {
1888             tmpWallpaper.recycle();
1889         }
1890     }
1891 
1892     @Test
1893     @RequiresFlagsEnabled(FLAG_LIVE_WALLPAPER_CONTENT_HANDLING)
setStreamWithDescription_both_succeeds()1894     public void setStreamWithDescription_both_succeeds() throws IOException {
1895         Bitmap tmpWallpaper = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
1896         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
1897         tmpWallpaper.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
1898         ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
1899         WallpaperDescription description = new WallpaperDescription.Builder().setId("id").build();
1900 
1901         try {
1902             mWallpaperManager.setStreamWithDescription(
1903                     inputStream,
1904                     new WallpaperDescription.Builder().setId("ignored").build(),
1905                     true,
1906                     FLAG_LOCK);
1907             int origHomeWallpaperId = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
1908 
1909             mWallpaperManager.setStreamWithDescription(
1910                     inputStream, description, /* allowBackup= */ true, FLAG_SYSTEM | FLAG_LOCK);
1911 
1912             assertThat(mWallpaperManager.getWallpaperId(FLAG_SYSTEM))
1913                     .isNotEqualTo(origHomeWallpaperId);
1914             assertThat(mWallpaperManager.getWallpaperId(FLAG_LOCK)).isLessThan(0);
1915             // TODO(b/380245309) Verify instance id and description
1916         } finally {
1917             tmpWallpaper.recycle();
1918         }
1919     }
1920 
1921     //// Helper methods
1922 
1923     /**
1924      * Helper to check the consistency between the following when correct cropsHints are provided:
1925      *
1926      * <ul>
1927      *   <li>{@link WallpaperManager#setBitmapWithCrops(Bitmap, Map, boolean, int)}
1928      *   <li>{@link WallpaperManager#getBitmapCrops(List, int, boolean)}
1929      *   <li>{@link WallpaperManager#getBitmapCrops(Point, List, Map)}
1930      * </ul>
1931      *
1932      * <p>This helper is called with cropHints that:
1933      *
1934      * <ul>
1935      *   <li>have an entry for the current screen size
1936      *   <li>have crops that are proportional to their associated display size.
1937      * </ul>
1938      *
1939      * In such a case, the suggested crops should not be modified or adjusted.
1940      *
1941      * <p>This function can use either the older set functions that take crop hints directly or the
1942      * newer functions that use {@link WallpaperDescription}. Specify useDescription=true for the
1943      * latter. This value must match the flag state or an exception will be thrown.
1944      */
assertCorrectCrop( Bitmap bitmap, Map<Point, Rect> cropHints, boolean useDescription)1945     private void assertCorrectCrop(
1946             Bitmap bitmap, Map<Point, Rect> cropHints, boolean useDescription) {
1947         if (useDescription ^ liveWallpaperContentHandling()) {
1948             throw new IllegalArgumentException("useDescription does not match flag value");
1949         }
1950         Point currentScreenSize = getScreenSize();
1951         Rect currentScreenCrop = cropHints.get(currentScreenSize);
1952         if (currentScreenCrop == null) throw new IllegalArgumentException();
1953 
1954         // paint the crop for the current display in green, and the rest of the bitmap in red
1955         Canvas canvas = new Canvas(bitmap);
1956         canvas.drawColor(Color.RED);
1957         Paint paint = new Paint();
1958         paint.setColor(Color.GREEN);
1959         canvas.drawRect(currentScreenCrop, paint);
1960 
1961         Point bitmapSize = new Point(bitmap.getWidth(), bitmap.getHeight());
1962         List<Point> displaySizes = cropHints.keySet().stream().toList();
1963 
1964         // check that getBitmapCrops doesn't modify the crops when correct crops hints are provided
1965         List<Rect> expectedBitmapCrops = mWallpaperManager.getBitmapCrops(
1966                 bitmapSize, displaySizes, cropHints);
1967         for (int i = 0; i < displaySizes.size(); i++) {
1968             Point displaySize = displaySizes.get(i);
1969             Rect crop = cropHints.get(displaySize);
1970             if (crop != null) assertAlmostEqual(crop, expectedBitmapCrops.get(i));
1971         }
1972 
1973         Consumer<Integer> setStreamUtil = which -> {
1974             ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
1975             bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
1976             ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
1977             try {
1978                 if (useDescription) {
1979                     WallpaperDescription description = new WallpaperDescription.Builder()
1980                             .setCropHints(cropHints).build();
1981                     mWallpaperManager.setStreamWithDescription(inputStream, description, true,
1982                             which);
1983                 } else {
1984                     mWallpaperManager.setStreamWithCrops(inputStream, cropHints, true, which);
1985                 }
1986             } catch (IOException e) {
1987                 throw new RuntimeException(e);
1988             }
1989         };
1990 
1991         Consumer<Integer> setBitmapUtil = which -> {
1992             try {
1993                 if (useDescription) {
1994                     WallpaperDescription description = new WallpaperDescription.Builder()
1995                             .setCropHints(cropHints).build();
1996                     mWallpaperManager.setBitmapWithDescription(bitmap, description, true, which);
1997                 } else {
1998                     mWallpaperManager.setBitmapWithCrops(bitmap, cropHints, true, which);
1999                 }
2000             } catch (IOException e) {
2001                 throw new RuntimeException(e);
2002             }
2003         };
2004 
2005         runWithShellPermissionIdentity(() -> {
2006             for (int which : List.of(FLAG_SYSTEM, FLAG_LOCK, FLAG_SYSTEM | FLAG_LOCK)) {
2007                 for (Consumer<Integer> setWallpaperUtil : List.of(setStreamUtil, setBitmapUtil)) {
2008                     setWallpaperUtil.accept(which);
2009 
2010                     int sourceFlag = which == FLAG_LOCK ? FLAG_LOCK : FLAG_SYSTEM;
2011 
2012                     if (useDescription) {
2013                         // TODO(b/380245309) Update this check when description crop logic updated.
2014                         WallpaperInstance instance = mWallpaperManager.getWallpaperInstance(
2015                                 sourceFlag);
2016                         if (instance != null) {
2017                             assertThat(instance.getDescription()).isNotNull();
2018                             SparseArray<Rect> descCropHints =
2019                                     instance.getDescription().getCropHints();
2020                             assertThat(descCropHints).isNotNull();
2021                         }
2022                     }
2023 
2024                     List<Rect> actualBitmapCrops = mWallpaperManager.getBitmapCrops(
2025                             displaySizes, sourceFlag, true);
2026 
2027                     for (int i = 0; i < actualBitmapCrops.size(); i++) {
2028                         assertAlmostEqual(expectedBitmapCrops.get(i), actualBitmapCrops.get(i));
2029                     }
2030 
2031                     Bitmap croppedBitmap = mWallpaperManager.getBitmapAsUser(
2032                             mContext.getUserId(), false, sourceFlag);
2033                     Rect actualScreenCrop = mWallpaperManager.getBitmapCrops(
2034                             List.of(currentScreenSize), sourceFlag, false).getFirst();
2035                     assertAlmostGreen(croppedBitmap, actualScreenCrop);
2036                 }
2037             }
2038         });
2039     }
2040 
assertAlmostEqual(Rect expected, Rect actual)2041     private void assertAlmostEqual(Rect expected, Rect actual) {
2042         assertThat(actual.left).isAtLeast(expected.left - 1);
2043         assertThat(actual.left).isAtMost(expected.left + 1);
2044         assertThat(actual.top).isAtLeast(expected.top - 1);
2045         assertThat(actual.top).isAtMost(expected.top + 1);
2046         assertThat(actual.right).isAtLeast(expected.right - 1);
2047         assertThat(actual.right).isAtMost(expected.right + 1);
2048         assertThat(actual.bottom).isAtLeast(expected.bottom - 1);
2049         assertThat(actual.bottom).isAtMost(expected.bottom + 1);
2050     }
2051 
assertAlmostGreen(Bitmap bitmap, Rect crop)2052     private void assertAlmostGreen(Bitmap bitmap, Rect crop) {
2053         for (int y = crop.bottom + 1; y < crop.top - 1; y += 5) {
2054             for (int x = crop.left + 1; x < crop.right - 1; x += 5) {
2055                 assertThat(bitmap.getPixel(x, y)).isEqualTo(Color.GREEN);
2056             }
2057         }
2058     }
2059 
assertBitmapDimensions(Bitmap bitmap)2060     private void assertBitmapDimensions(Bitmap bitmap) {
2061         int maxSize = getMaxTextureSize();
2062         boolean safe = false;
2063         if (bitmap != null) {
2064             safe = bitmap.getWidth() <= maxSize && bitmap.getHeight() <= maxSize;
2065         }
2066         assertThat(safe).isTrue();
2067     }
2068 
assertDesiredDimension(Point suggestedSize, Point expectedSize)2069     private void assertDesiredDimension(Point suggestedSize, Point expectedSize) {
2070         mWallpaperManager.suggestDesiredDimensions(suggestedSize.x, suggestedSize.y);
2071         Point actualSize = new Point(mWallpaperManager.getDesiredMinimumWidth(),
2072                 mWallpaperManager.getDesiredMinimumHeight());
2073         if (actualSize.x > 0 || actualSize.y > 0) {
2074             if ((actualSize.x != expectedSize.x || actualSize.y != expectedSize.y)) {
2075                 throw new AssertionError(
2076                         "Expected x: " + expectedSize.x + " y: " + expectedSize.y
2077                                 + ", got x: " + actualSize.x + " y: " + actualSize.y);
2078             }
2079         }
2080     }
2081 
getScreenSize()2082     private Point getScreenSize() {
2083         WindowManager wm = mContext.getSystemService(WindowManager.class);
2084         Display d = wm.getDefaultDisplay();
2085         Point p = new Point();
2086         d.getRealSize(p);
2087         return p;
2088     }
2089 
2090     /**
2091      * Helper to set a listener and verify if it was called with the same flags.
2092      * Executes operation synchronously. Params are FLAG_LOCK, FLAG_SYSTEM or a combination of both.
2093      *
2094      * @param which wallpaper destinations to set
2095      * @param whichExpected wallpaper destinations that should receive listener calls
2096      */
verifyColorListenerInvoked(int which, int whichExpected)2097     private void verifyColorListenerInvoked(int which, int whichExpected) {
2098         ensureCleanState();
2099         int expected = 0;
2100         if ((whichExpected & FLAG_LOCK) != 0) expected++;
2101         if ((whichExpected & FLAG_SYSTEM) != 0) expected++;
2102         ArrayList<Integer> received = new ArrayList<>();
2103 
2104         final CountDownLatch latch = new CountDownLatch(expected);
2105         Handler handler = new Handler(Looper.getMainLooper());
2106 
2107         WallpaperManager.OnColorsChangedListener listener = getTestableListener();
2108         final AtomicBoolean allOk = new AtomicBoolean(true);
2109         WallpaperManager.OnColorsChangedListener counter = (colors, whichWp) -> {
2110             handler.post(() -> {
2111                 final boolean wantSystem = (whichExpected & FLAG_SYSTEM) != 0;
2112                 final boolean wantLock = (whichExpected & FLAG_LOCK) != 0;
2113                 final boolean gotSystem = (whichWp & FLAG_SYSTEM) != 0;
2114                 final boolean gotLock = (whichWp & FLAG_LOCK) != 0;
2115                 received.add(whichWp);
2116                 boolean ok = true;
2117 
2118                 if (gotLock) {
2119                     if (wantLock) {
2120                         latch.countDown();
2121                     } else {
2122                         ok = false;
2123                     }
2124                 }
2125                 if (gotSystem) {
2126                     if (wantSystem) {
2127                         latch.countDown();
2128                     } else {
2129                         ok = false;
2130                     }
2131                 }
2132                 if (!ok) {
2133                     allOk.set(false);
2134                     Log.e(TAG,
2135                             "Unexpected which flag: " + whichWp + " should be: " + whichExpected);
2136                 }
2137             });
2138         };
2139 
2140         mWallpaperManager.addOnColorsChangedListener(listener, mHandler);
2141         mWallpaperManager.addOnColorsChangedListener(counter, mHandler);
2142 
2143         try {
2144             mWallpaperManager.setResource(R.drawable.icon_red, which);
2145             boolean eventsReceived = latch.await(5, TimeUnit.SECONDS);
2146             assertWithMessage("Timed out waiting for color events. Expected: "
2147                     + whichExpected + " received: " + received)
2148                     .that(eventsReceived).isTrue();
2149             // Wait in case there are additional unwanted callbacks
2150             Thread.sleep(SLEEP_MS);
2151             assertWithMessage("Unexpected which flag, check logs for details")
2152                     .that(allOk.get()).isTrue();
2153         } catch (InterruptedException | IOException e) {
2154             throw new RuntimeException(e);
2155         } finally {
2156             mWallpaperManager.removeOnColorsChangedListener(listener);
2157             mWallpaperManager.removeOnColorsChangedListener(counter);
2158         }
2159     }
2160 
2161     /**
2162      * Helper to clear a wallpaper synchronously.
2163      *
2164      * @param which FLAG_LOCK, FLAG_SYSTEM or a combination of both.
2165      */
verifyColorListenerInvokedClearing(int which)2166     private void verifyColorListenerInvokedClearing(int which) {
2167         ensureCleanState(which);
2168 
2169         final CountDownLatch latch = new CountDownLatch(1);
2170 
2171         WallpaperManager.OnColorsChangedListener listener = getTestableListener();
2172         WallpaperManager.OnColorsChangedListener counter = (colors, whichWp) -> {
2173             latch.countDown();
2174         };
2175 
2176         mWallpaperManager.addOnColorsChangedListener(listener, mHandler);
2177         mWallpaperManager.addOnColorsChangedListener(counter, mHandler);
2178 
2179         try {
2180             mWallpaperManager.clear(which);
2181             latch.await(5, TimeUnit.SECONDS);
2182         } catch (InterruptedException | IOException e) {
2183             throw new RuntimeException(e);
2184         }
2185 
2186         verify(listener, atLeast(1))
2187                 .onColorsChanged(nullable(WallpaperColors.class), anyInt());
2188 
2189         mWallpaperManager.removeOnColorsChangedListener(listener);
2190         mWallpaperManager.removeOnColorsChangedListener(counter);
2191     }
2192 
ensureCleanState()2193     private void ensureCleanState() {
2194         ensureCleanState(FLAG_SYSTEM | FLAG_LOCK);
2195     }
2196 
2197     /**
2198      * Helper method to set a bitmap on the specified destination(s).
2199      */
ensureCleanState(int flags)2200     private void ensureCleanState(int flags) {
2201         Bitmap bmp = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
2202         Canvas canvas = new Canvas(bmp);
2203         canvas.drawColor(Color.BLUE);
2204 
2205         try {
2206             runAndAwaitColorChanges(5, TimeUnit.SECONDS, flags, mWallpaperManager, mHandler, () -> {
2207                 if (flags == (FLAG_SYSTEM | FLAG_LOCK)) {
2208                     mWallpaperManager.setBitmap(bmp);
2209                 } else {
2210                     mWallpaperManager.setBitmap(bmp, /* visibleCropHint= */
2211                             null, /* allowBackup= */true, flags);
2212                 }
2213             });
2214         } catch (Exception e) {
2215             throw new RuntimeException(e);
2216         } finally {
2217             bmp.recycle();
2218         }
2219     }
2220 
assertNullOrDefaultWallpaper(int which)2221     private void assertNullOrDefaultWallpaper(int which) {
2222         WallpaperInfo wallpaperInfo = mWallpaperManager.getWallpaperInfo(which);
2223         if (mDefaultWallpaperInfo == null) assertThat(wallpaperInfo).isNull();
2224         if (wallpaperInfo == null) return;
2225         assertThat(wallpaperInfo.getComponent()).isEqualTo(mDefaultWallpaperInfo.getComponent());
2226     }
2227 
assertNotNullOrDefaultWallpaper(int which)2228     private void assertNotNullOrDefaultWallpaper(int which) {
2229         WallpaperInfo wallpaperInfo = mWallpaperManager.getWallpaperInfo(which);
2230         assertThat(wallpaperInfo).isNotNull();
2231         if (mDefaultWallpaperInfo != null) {
2232             assertThat(wallpaperInfo.getComponent()).isNotEqualTo(
2233                     mDefaultWallpaperInfo.getComponent());
2234         }
2235     }
2236 
assertNotNullOrDefaultInstance(int which)2237     private void assertNotNullOrDefaultInstance(int which) {
2238         runWithShellPermissionIdentity(() -> {
2239             WallpaperInstance instance = mWallpaperManager.getWallpaperInstance(which);
2240             assertThat(instance).isNotNull();
2241             assertThat(instance.getInfo()).isNotNull();
2242             if (mDefaultWallpaperInfo != null) {
2243                 assertThat(instance.getInfo().getComponent()).isNotEqualTo(
2244                         mDefaultWallpaperInfo.getComponent());
2245             }
2246         });
2247     }
2248 
setWallpaperComponentAndWait(ComponentName component, int which)2249     private void setWallpaperComponentAndWait(ComponentName component, int which) {
2250         setWallpaperComponentAndWait(component, which, 1, 1);
2251     }
2252 
setWallpaperComponentAndWait(ComponentName component, int which, int created, int destroyed)2253     private void setWallpaperComponentAndWait(ComponentName component, int which, int created,
2254             int destroyed) {
2255         runAndAwaitChanges(
2256                 SLEEP_MS, TimeUnit.MILLISECONDS, created, destroyed, 0,
2257                 () -> mWallpaperManager.setWallpaperComponentWithFlags(component, which));
2258     }
2259 
setWallpaperDescriptionAndWait(WallpaperDescription description, int which)2260     private void setWallpaperDescriptionAndWait(WallpaperDescription description, int which) {
2261         int createdCount = 1;
2262         int destroyedCount = 1;
2263         runAndAwaitChanges(
2264                 SLEEP_MS,
2265                 TimeUnit.MILLISECONDS,
2266                 createdCount,
2267                 destroyedCount,
2268                 0,
2269                 () -> mWallpaperManager.setWallpaperComponentWithDescription(description, which));
2270     }
2271 
getTestableListener()2272     public WallpaperManager.OnColorsChangedListener getTestableListener() {
2273         // Unfortunately mockito cannot mock anonymous classes or lambdas.
2274         return spy(new TestableColorListener());
2275     }
2276 
2277     public static class TestableColorListener implements WallpaperManager.OnColorsChangedListener {
2278         @Override
onColorsChanged(WallpaperColors colors, int which)2279         public void onColorsChanged(WallpaperColors colors, int which) {
2280             Log.d(TAG, "TestableColorListener received colors: " + colors + ", which: " + which);
2281         }
2282     }
2283 }
2284