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.QUERY_ALL_PACKAGES;
20 import static android.Manifest.permission.READ_WALLPAPER_INTERNAL;
21 import static android.app.WallpaperManager.FLAG_LOCK;
22 import static android.app.WallpaperManager.FLAG_SYSTEM;
23 import static android.app.cts.wallpapers.util.WallpaperTestUtils.getBitmap;
24 import static android.app.cts.wallpapers.util.WallpaperTestUtils.isSimilar;
25 
26 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
27 
28 import static com.google.common.truth.Truth.assertWithMessage;
29 
30 import static org.junit.Assume.assumeFalse;
31 import static org.junit.Assume.assumeTrue;
32 
33 import android.app.WallpaperManager;
34 import android.content.Context;
35 import android.content.pm.PackageManager;
36 import android.graphics.Bitmap;
37 import android.graphics.BitmapFactory;
38 import android.graphics.Canvas;
39 import android.graphics.Color;
40 import android.graphics.drawable.Drawable;
41 import android.os.ParcelFileDescriptor;
42 
43 import androidx.test.InstrumentationRegistry;
44 import androidx.test.runner.AndroidJUnit4;
45 
46 import org.junit.AfterClass;
47 import org.junit.Before;
48 import org.junit.BeforeClass;
49 import org.junit.Test;
50 import org.junit.runner.RunWith;
51 import org.mockito.MockitoAnnotations;
52 
53 import java.io.IOException;
54 import java.util.function.Supplier;
55 
56 /**
57  * Tests for {@link WallpaperManager} and related classes for target SDK 33.
58  * This tests that for API U and above,
59  * apps that target SDK 33 will receive data from the default wallpaper
60  * when trying to read the wallpaper through the public API, except if the app has the permission
61  * {@value android.Manifest.permission#READ_WALLPAPER_INTERNAL}.
62  *
63  * <p>
64  * See the different test cases to see which methods are concerned.
65  * </p>
66  */
67 @RunWith(AndroidJUnit4.class)
68 public class WallpaperManagerSdk33Test {
69 
70     private static WallpaperManager sWallpaperManager;
71     private static Bitmap sDefaultBitmap;
72     private static Bitmap sRedBitmap;
73     private static boolean sTvTarget;
74 
75     /**
76      * Note: all tests in this class assume to start with a red bitmap on both system & lock screen.
77      * As changing the wallpaper takes time, this initialization is only done here
78      * and not in {@link #setUp}, since doing so would slow down the test suite substantially.
79      * Tests that change the wallpaper are responsible to restore the red wallpaper
80      * with {@link #setRedWallpaper()} when finished.
81      */
82     @BeforeClass
setUpClass()83     public static void setUpClass() throws IOException {
84         Context context = InstrumentationRegistry.getTargetContext();
85 
86         // ignore for TV targets
87         PackageManager packageManager = context.getPackageManager();
88         sTvTarget = packageManager != null
89                 && (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
90                 || packageManager.hasSystemFeature(PackageManager.FEATURE_TELEVISION));
91         if (sTvTarget) return;
92 
93         sWallpaperManager = WallpaperManager.getInstance(context);
94         sWallpaperManager.clear(FLAG_SYSTEM | FLAG_LOCK);
95 
96         // ignore for targets that have a live default wallpaper
97         runWithShellPermissionIdentity(
98                 () -> assumeTrue(sWallpaperManager.getWallpaperInfo(FLAG_SYSTEM) == null),
99                 QUERY_ALL_PACKAGES);
100 
101         sDefaultBitmap = runWithShellPermissionIdentity(
102                 () -> sWallpaperManager.getBitmap(), READ_WALLPAPER_INTERNAL);
103 
104         sRedBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
105         Canvas canvas = new Canvas(sRedBitmap);
106         canvas.drawColor(Color.RED);
107         setRedWallpaper();
108     }
109 
110     @Before
setUp()111     public void setUp() throws Exception {
112         assumeFalse("WallpaperManagerSdk33Test is not meaningful for TV targets", sTvTarget);
113         assumeTrue("Device does not support wallpapers", sWallpaperManager.isWallpaperSupported());
114         MockitoAnnotations.initMocks(this);
115     }
116 
117     @AfterClass
tearDownClass()118     public static void tearDownClass() throws IOException {
119         if (sRedBitmap != null && !sRedBitmap.isRecycled()) sRedBitmap.recycle();
120         if (sWallpaperManager != null) sWallpaperManager.clear(FLAG_SYSTEM | FLAG_LOCK);
121         sWallpaperManager = null;
122     }
123 
124     @Test
getDrawable_noPermission_returnsDefault()125     public void getDrawable_noPermission_returnsDefault() {
126         assertReturnsDefault(sWallpaperManager::getDrawable, "getDrawable");
127     }
128 
129     @Test
getDrawable_withPermission_returnsCurrent()130     public void getDrawable_withPermission_returnsCurrent() {
131         assertReturnsCurrent(sWallpaperManager::getDrawable, "getDrawable");
132     }
133 
134     @Test
getFastDrawable_noPermission_returnsDefault()135     public void getFastDrawable_noPermission_returnsDefault() {
136         assertReturnsDefault(sWallpaperManager::getFastDrawable, "getFastDrawable");
137     }
138 
139     @Test
getFastDrawable_withPermission_returnsCurrent()140     public void getFastDrawable_withPermission_returnsCurrent() {
141         assertReturnsCurrent(sWallpaperManager::getFastDrawable, "getFastDrawable");
142     }
143 
144     @Test
peekDrawable_noPermission_returnsDefault()145     public void peekDrawable_noPermission_returnsDefault() {
146         assertReturnsDefault(sWallpaperManager::peekDrawable, "peekDrawable");
147     }
148 
149     @Test
peekDrawable_withPermission_returnsCurrent()150     public void peekDrawable_withPermission_returnsCurrent() {
151         assertReturnsCurrent(sWallpaperManager::peekDrawable, "peekDrawable");
152     }
153 
154     @Test
peekFastDrawable_noPermission_returnsDefault()155     public void peekFastDrawable_noPermission_returnsDefault() {
156         assertReturnsDefault(sWallpaperManager::peekFastDrawable, "peekFastDrawable");
157     }
158 
159     @Test
peekFastDrawable_withPermission_returnsCurrent()160     public void peekFastDrawable_withPermission_returnsCurrent() {
161         assertReturnsCurrent(sWallpaperManager::peekFastDrawable, "peekFastDrawable");
162     }
163 
164     @Test
getWallpaperFile_system_noPermission_returnsDefault()165     public void getWallpaperFile_system_noPermission_returnsDefault() {
166         ParcelFileDescriptor parcelFileDescriptor = sWallpaperManager.getWallpaperFile(FLAG_SYSTEM);
167         if (parcelFileDescriptor != null) {
168             Bitmap bitmap = BitmapFactory.decodeFileDescriptor(
169                     parcelFileDescriptor.getFileDescriptor());
170             assertWithMessage(
171                     "with no permission, getWallpaperFile(FLAG_SYSTEM) "
172                             + "should return the default system wallpaper file")
173                     .that(isSimilar(bitmap, sDefaultBitmap, false))
174                     .isTrue();
175         }
176     }
177 
178     @Test
getWallpaperFile_lock_noPermission_returnsDefault()179     public void getWallpaperFile_lock_noPermission_returnsDefault() throws IOException {
180         sWallpaperManager.setBitmap(sRedBitmap, null, true, FLAG_LOCK);
181         ParcelFileDescriptor parcelFileDescriptor = sWallpaperManager.getWallpaperFile(FLAG_LOCK);
182         sWallpaperManager.clear(FLAG_SYSTEM | FLAG_LOCK);
183         try {
184             if (parcelFileDescriptor != null) {
185                 Bitmap bitmap = BitmapFactory.decodeFileDescriptor(
186                         parcelFileDescriptor.getFileDescriptor());
187                 assertWithMessage(
188                         "with no permission, getWallpaperFile(FLAG_LOCK) "
189                                 + "should return the default system wallpaper file")
190                         .that(isSimilar(bitmap, sDefaultBitmap, false))
191                         .isTrue();
192             }
193         } finally {
194             setRedWallpaper();
195         }
196     }
197 
198     @Test
getWallpaperFile_system_withPermission_returnsCurrent()199     public void getWallpaperFile_system_withPermission_returnsCurrent() {
200         ParcelFileDescriptor parcelFileDescriptor = runWithShellPermissionIdentity(
201                 () -> sWallpaperManager.getWallpaperFile(FLAG_SYSTEM), READ_WALLPAPER_INTERNAL);
202         Bitmap bitmap = BitmapFactory.decodeFileDescriptor(
203                 parcelFileDescriptor.getFileDescriptor());
204         assertWithMessage(
205                 "with permission, getWallpaperFile(FLAG_SYSTEM)"
206                         + "should return the currennt system wallpaper file")
207                 .that(isSimilar(bitmap, sRedBitmap, true))
208                 .isTrue();
209     }
210 
211     @Test
getWallpaperFile_lock_withPermission_doesNotReturnDefault()212     public void getWallpaperFile_lock_withPermission_doesNotReturnDefault() throws IOException {
213         sWallpaperManager.setBitmap(sRedBitmap, null, true, FLAG_LOCK);
214         ParcelFileDescriptor parcelFileDescriptor = runWithShellPermissionIdentity(
215                 () -> sWallpaperManager.getWallpaperFile(FLAG_LOCK), READ_WALLPAPER_INTERNAL);
216         try {
217             if (parcelFileDescriptor != null) {
218                 Bitmap bitmap = BitmapFactory.decodeFileDescriptor(
219                         parcelFileDescriptor.getFileDescriptor());
220                 assertWithMessage(
221                         "with permission, getWallpaperFile(FLAG_LOCK)"
222                                 + "should not return the default system wallpaper")
223                         .that(isSimilar(bitmap, sDefaultBitmap, true))
224                         .isFalse();
225             }
226         } finally {
227             setRedWallpaper();
228         }
229     }
230 
assertReturnsDefault(Supplier<Drawable> methodToTest, String methodName)231     private void assertReturnsDefault(Supplier<Drawable> methodToTest, String methodName) {
232         Drawable drawable = methodToTest.get();
233         assertWithMessage(
234                 "with no permission, " + methodName + " should return null or the default bitmap")
235                 .that(drawable == null || isSimilar(getBitmap(drawable), sDefaultBitmap, false))
236                 .isTrue();
237     }
238 
assertReturnsCurrent(Supplier<Drawable> methodToTest, String methodName)239     private void assertReturnsCurrent(Supplier<Drawable> methodToTest, String methodName) {
240         Drawable drawable = runWithShellPermissionIdentity(
241                 () -> methodToTest.get(), READ_WALLPAPER_INTERNAL);
242         assertWithMessage(
243                 "with permission, " + methodName + " should return the current bitmap")
244                 .that(isSimilar(getBitmap(drawable), sRedBitmap, true)).isTrue();
245     }
246 
setRedWallpaper()247     private static void setRedWallpaper() throws IOException {
248         sWallpaperManager.setBitmap(sRedBitmap,
249                 null /* visibleCropHint= */,
250                 true /* allowBackup */,
251                 FLAG_SYSTEM | FLAG_LOCK /* which */);
252     }
253 }
254