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