1 /*
2  * Copyright (C) 2019 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 com.android.wallpaperbackup;
18 
19 import static android.app.WallpaperManager.FLAG_LOCK;
20 import static android.app.WallpaperManager.FLAG_SYSTEM;
21 import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
22 
23 import static com.android.wallpaperbackup.WallpaperBackupAgent.LOCK_WALLPAPER_STAGE;
24 import static com.android.wallpaperbackup.WallpaperBackupAgent.SYSTEM_WALLPAPER_STAGE;
25 import static com.android.wallpaperbackup.WallpaperBackupAgent.WALLPAPER_INFO_STAGE;
26 import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_INELIGIBLE;
27 import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_NO_METADATA;
28 import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_NO_WALLPAPER;
29 import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_QUOTA_EXCEEDED;
30 import static com.android.wallpaperbackup.WallpaperEventLogger.WALLPAPER_IMG_LOCK;
31 import static com.android.wallpaperbackup.WallpaperEventLogger.WALLPAPER_IMG_SYSTEM;
32 import static com.android.wallpaperbackup.WallpaperEventLogger.WALLPAPER_LIVE_LOCK;
33 import static com.android.wallpaperbackup.WallpaperEventLogger.WALLPAPER_LIVE_SYSTEM;
34 import static com.android.window.flags.Flags.multiCrop;
35 
36 import static com.google.common.truth.Truth.assertThat;
37 
38 import static org.junit.Assert.assertEquals;
39 import static org.junit.Assume.assumeTrue;
40 import static org.mockito.ArgumentMatchers.any;
41 import static org.mockito.ArgumentMatchers.anyBoolean;
42 import static org.mockito.ArgumentMatchers.anyInt;
43 import static org.mockito.ArgumentMatchers.argThat;
44 import static org.mockito.ArgumentMatchers.eq;
45 import static org.mockito.Mockito.never;
46 import static org.mockito.Mockito.times;
47 import static org.mockito.Mockito.verify;
48 import static org.mockito.Mockito.when;
49 
50 import android.app.WallpaperInfo;
51 import android.app.WallpaperManager;
52 import android.app.backup.BackupAnnotations;
53 import android.app.backup.BackupManager;
54 import android.app.backup.BackupRestoreEventLogger;
55 import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
56 import android.app.backup.FullBackupDataOutput;
57 import android.content.ComponentName;
58 import android.content.Context;
59 import android.content.Intent;
60 import android.content.pm.PackageManager;
61 import android.content.pm.ResolveInfo;
62 import android.graphics.Rect;
63 import android.os.FileUtils;
64 import android.os.ParcelFileDescriptor;
65 import android.os.UserHandle;
66 import android.service.wallpaper.WallpaperService;
67 import android.util.SparseArray;
68 import android.util.Xml;
69 
70 import androidx.test.InstrumentationRegistry;
71 import androidx.test.core.app.ApplicationProvider;
72 import androidx.test.runner.AndroidJUnit4;
73 
74 import com.android.internal.content.PackageMonitor;
75 import com.android.modules.utils.TypedXmlSerializer;
76 import com.android.wallpaperbackup.utils.ContextWithServiceOverrides;
77 
78 import org.junit.After;
79 import org.junit.Before;
80 import org.junit.Rule;
81 import org.junit.Test;
82 import org.junit.rules.TemporaryFolder;
83 import org.junit.runner.RunWith;
84 import org.mockito.ArgumentMatcher;
85 import org.mockito.Mock;
86 import org.mockito.MockitoAnnotations;
87 
88 import java.io.File;
89 import java.io.FileInputStream;
90 import java.io.FileOutputStream;
91 import java.io.IOException;
92 import java.util.ArrayList;
93 import java.util.List;
94 import java.util.Map;
95 import java.util.Optional;
96 
97 @RunWith(AndroidJUnit4.class)
98 public class WallpaperBackupAgentTest {
99     private static final String TEST_WALLPAPER_PACKAGE = "wallpaper_package";
100 
101     private static final int TEST_SYSTEM_WALLPAPER_ID = 1;
102     private static final int TEST_LOCK_WALLPAPER_ID = 2;
103     private static final int NO_LOCK_WALLPAPER_ID = -1;
104     // An arbitrary user.
105     private static final UserHandle USER_HANDLE = new UserHandle(15);
106 
107     @Mock
108     private FullBackupDataOutput mOutput;
109     @Mock
110     private WallpaperManager mWallpaperManager;
111     @Mock
112     private Context mMockContext;
113     @Mock
114     private BackupManager mBackupManager;
115 
116     @Rule
117     public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
118 
119     private ContextWithServiceOverrides mContext;
120     private IsolatedWallpaperBackupAgent mWallpaperBackupAgent;
121     private ComponentName mWallpaperComponent;
122 
123     @Before
setUp()124     public void setUp() {
125         MockitoAnnotations.initMocks(this);
126         when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_SYSTEM))).thenReturn(true);
127         when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_LOCK))).thenReturn(true);
128 
129         mContext = new ContextWithServiceOverrides(ApplicationProvider.getApplicationContext());
130         mContext.injectSystemService(WallpaperManager.class, mWallpaperManager);
131 
132         mWallpaperBackupAgent = new IsolatedWallpaperBackupAgent();
133         mWallpaperBackupAgent.attach(mContext);
134         mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
135                 BackupAnnotations.OperationType.BACKUP);
136 
137         mWallpaperComponent = new ComponentName(TEST_WALLPAPER_PACKAGE, "");
138     }
139 
140     @After
tearDown()141     public void tearDown() {
142         FileUtils.deleteContents(mContext.getFilesDir());
143     }
144 
145     @Test
testOnFullBackup_backsUpEmptyFile()146     public void testOnFullBackup_backsUpEmptyFile() throws IOException {
147         mWallpaperBackupAgent.onFullBackup(mOutput);
148 
149         assertThat(getBackedUpFileOptional("empty").isPresent()).isTrue();
150     }
151 
152     @Test
testOnFullBackup_noExistingInfoStage_backsUpInfoFile()153     public void testOnFullBackup_noExistingInfoStage_backsUpInfoFile() throws Exception {
154         mockWallpaperInfoFileWithContents("fake info file");
155 
156         mWallpaperBackupAgent.onFullBackup(mOutput);
157 
158         assertFileContentEquals(getBackedUpFileOptional(WALLPAPER_INFO_STAGE).get(),
159                 "fake info file");
160     }
161 
162     @Test
testOnFullBackup_existingInfoStage_noChange_backsUpAlreadyStagedInfoFile()163     public void testOnFullBackup_existingInfoStage_noChange_backsUpAlreadyStagedInfoFile()
164             throws Exception {
165         // Do a backup first so the info file is staged.
166         mockWallpaperInfoFileWithContents("old info file");
167         // Provide system and lock wallpapers but don't change them in between backups.
168         mockSystemWallpaperFileWithContents("system wallpaper");
169         mockLockWallpaperFileWithContents("lock wallpaper");
170         mWallpaperBackupAgent.onFullBackup(mOutput);
171         mWallpaperBackupAgent.mBackedUpFiles.clear();
172         // This new wallpaper should be ignored since the ID of neither wallpaper changed.
173         mockWallpaperInfoFileWithContents("new info file");
174 
175         mWallpaperBackupAgent.onFullBackup(mOutput);
176 
177         assertFileContentEquals(getBackedUpFileOptional(WALLPAPER_INFO_STAGE).get(),
178                 "old info file");
179     }
180 
181     @Test
testOnFullBackup_existingInfoStage_sysChanged_backsUpNewInfoFile()182     public void testOnFullBackup_existingInfoStage_sysChanged_backsUpNewInfoFile()
183             throws Exception {
184         // Do a backup first so the backed up system wallpaper ID is persisted to disk.
185         mockWallpaperInfoFileWithContents("old info file");
186         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
187         mWallpaperBackupAgent.onFullBackup(mOutput);
188         mWallpaperBackupAgent.mBackedUpFiles.clear();
189         // Mock that the user changed the system wallpaper.
190         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID + 1, TEST_LOCK_WALLPAPER_ID);
191         mockWallpaperInfoFileWithContents("new info file");
192 
193         mWallpaperBackupAgent.onFullBackup(mOutput);
194 
195         assertFileContentEquals(getBackedUpFileOptional(WALLPAPER_INFO_STAGE).get(),
196                 "new info file");
197     }
198 
199     @Test
testOnFullBackup_existingInfoStage_lockChanged_backsUpNewInfoFile()200     public void testOnFullBackup_existingInfoStage_lockChanged_backsUpNewInfoFile()
201             throws Exception {
202         // Do a backup first so the backed up lock wallpaper ID is persisted to disk.
203         mockWallpaperInfoFileWithContents("old info file");
204         mockLockWallpaperFileWithContents("lock wallpaper");
205         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
206         mWallpaperBackupAgent.onFullBackup(mOutput);
207         mWallpaperBackupAgent.mBackedUpFiles.clear();
208         // Mock that the user changed the system wallpaper.
209         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID + 1);
210         mockWallpaperInfoFileWithContents("new info file");
211 
212         mWallpaperBackupAgent.onFullBackup(mOutput);
213 
214         assertFileContentEquals(getBackedUpFileOptional(WALLPAPER_INFO_STAGE).get(),
215                 "new info file");
216     }
217 
218     @Test
testOnFullBackup_systemWallpaperNotEligible_doesNotBackUpSystemWallpaper()219     public void testOnFullBackup_systemWallpaperNotEligible_doesNotBackUpSystemWallpaper()
220             throws Exception {
221         when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_SYSTEM))).thenReturn(false);
222         mockSystemWallpaperFileWithContents("system wallpaper");
223         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
224 
225         mWallpaperBackupAgent.onFullBackup(mOutput);
226 
227         assertThat(getBackedUpFileOptional(SYSTEM_WALLPAPER_STAGE).isPresent()).isFalse();
228     }
229 
230     @Test
testOnFullBackup_existingSystemStage_noSysChange_backsUpAlreadyStagedFile()231     public void testOnFullBackup_existingSystemStage_noSysChange_backsUpAlreadyStagedFile()
232             throws Exception {
233         // Do a backup first so that a stage file is created.
234         mockSystemWallpaperFileWithContents("system wallpaper");
235         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
236         mWallpaperBackupAgent.onFullBackup(mOutput);
237         mWallpaperBackupAgent.mBackedUpFiles.clear();
238         // This new file should be ignored since the ID of the wallpaper did not change.
239         mockSystemWallpaperFileWithContents("new system wallpaper");
240 
241         mWallpaperBackupAgent.onFullBackup(mOutput);
242 
243         assertFileContentEquals(getBackedUpFileOptional(SYSTEM_WALLPAPER_STAGE).get(),
244                 "system wallpaper");
245     }
246 
247     @Test
testOnFullBackup_existingSystemStage_sysChanged_backsUpNewSystemWallpaper()248     public void testOnFullBackup_existingSystemStage_sysChanged_backsUpNewSystemWallpaper()
249             throws Exception {
250         // Do a backup first so that a stage file is created.
251         mockSystemWallpaperFileWithContents("system wallpaper");
252         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
253         mWallpaperBackupAgent.onFullBackup(mOutput);
254         mWallpaperBackupAgent.mBackedUpFiles.clear();
255         // Mock that the system wallpaper was changed by the user.
256         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID + 1, NO_LOCK_WALLPAPER_ID);
257         mockSystemWallpaperFileWithContents("new system wallpaper");
258 
259         mWallpaperBackupAgent.onFullBackup(mOutput);
260 
261         assertFileContentEquals(getBackedUpFileOptional(SYSTEM_WALLPAPER_STAGE).get(),
262                 "new system wallpaper");
263     }
264 
265     @Test
testOnFullBackup_noExistingSystemStage_backsUpSystemWallpaper()266     public void testOnFullBackup_noExistingSystemStage_backsUpSystemWallpaper()
267             throws Exception {
268         mockSystemWallpaperFileWithContents("system wallpaper");
269         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
270 
271         mWallpaperBackupAgent.onFullBackup(mOutput);
272 
273         assertFileContentEquals(getBackedUpFileOptional(SYSTEM_WALLPAPER_STAGE).get(),
274                 "system wallpaper");
275     }
276 
277     @Test
testOnFullBackup_lockWallpaperNotEligible_doesNotBackUpLockWallpaper()278     public void testOnFullBackup_lockWallpaperNotEligible_doesNotBackUpLockWallpaper()
279             throws Exception {
280         when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_LOCK))).thenReturn(false);
281         mockLockWallpaperFileWithContents("lock wallpaper");
282         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
283 
284         mWallpaperBackupAgent.onFullBackup(mOutput);
285 
286         assertThat(getBackedUpFileOptional(LOCK_WALLPAPER_STAGE).isPresent()).isFalse();
287     }
288 
289     @Test
testOnFullBackup_existingLockStage_lockWallpaperRemovedByUser_NotBackUpOldStage()290     public void testOnFullBackup_existingLockStage_lockWallpaperRemovedByUser_NotBackUpOldStage()
291             throws Exception {
292         // Do a backup first so that a stage file is created.
293         mockLockWallpaperFileWithContents("lock wallpaper");
294         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
295         mWallpaperBackupAgent.onFullBackup(mOutput);
296         mWallpaperBackupAgent.mBackedUpFiles.clear();
297         // Mock the ID of the lock wallpaper to indicate it's not set.
298         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
299 
300         mWallpaperBackupAgent.onFullBackup(mOutput);
301 
302         assertThat(getBackedUpFileOptional(LOCK_WALLPAPER_STAGE).isPresent()).isFalse();
303     }
304 
305     @Test
testOnFullBackup_existingLockStage_lockWallpaperRemovedByUser_deletesExistingStage()306     public void testOnFullBackup_existingLockStage_lockWallpaperRemovedByUser_deletesExistingStage()
307             throws Exception {
308         // Do a backup first so that a stage file is created.
309         mockLockWallpaperFileWithContents("lock wallpaper");
310         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
311         mWallpaperBackupAgent.onFullBackup(mOutput);
312         mWallpaperBackupAgent.mBackedUpFiles.clear();
313         // Mock the ID of the lock wallpaper to indicate it's not set.
314         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
315 
316         mWallpaperBackupAgent.onFullBackup(mOutput);
317 
318         assertThat(new File(mContext.getFilesDir(), LOCK_WALLPAPER_STAGE).exists()).isFalse();
319     }
320 
321     @Test
testOnFullBackup_existingLockStage_noLockChange_backsUpAlreadyStagedFile()322     public void testOnFullBackup_existingLockStage_noLockChange_backsUpAlreadyStagedFile()
323             throws Exception {
324         // Do a backup first so that a stage file is created.
325         mockLockWallpaperFileWithContents("old lock wallpaper");
326         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
327         mWallpaperBackupAgent.onFullBackup(mOutput);
328         mWallpaperBackupAgent.mBackedUpFiles.clear();
329         // This new file should be ignored since the ID of the wallpaper did not change.
330         mockLockWallpaperFileWithContents("new lock wallpaper");
331 
332         mWallpaperBackupAgent.onFullBackup(mOutput);
333 
334         assertFileContentEquals(getBackedUpFileOptional(LOCK_WALLPAPER_STAGE).get(),
335                 "old lock wallpaper");
336     }
337 
338     @Test
testOnFullBackup_existingLockStage_lockChanged_backsUpNewLockWallpaper()339     public void testOnFullBackup_existingLockStage_lockChanged_backsUpNewLockWallpaper()
340             throws Exception {
341         // Do a backup first so that a stage file is created.
342         mockLockWallpaperFileWithContents("old lock wallpaper");
343         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
344         mWallpaperBackupAgent.onFullBackup(mOutput);
345         mWallpaperBackupAgent.mBackedUpFiles.clear();
346         // Mock that the lock wallpaper was changed by the user.
347         mockLockWallpaperFileWithContents("new lock wallpaper");
348         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID + 1);
349 
350         mWallpaperBackupAgent.onFullBackup(mOutput);
351 
352         assertFileContentEquals(getBackedUpFileOptional(LOCK_WALLPAPER_STAGE).get(),
353                 "new lock wallpaper");
354     }
355 
356     @Test
testOnFullBackup_noExistingLockStage_backsUpLockWallpaper()357     public void testOnFullBackup_noExistingLockStage_backsUpLockWallpaper()
358             throws Exception {
359         mockLockWallpaperFileWithContents("lock wallpaper");
360         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
361 
362         mWallpaperBackupAgent.onFullBackup(mOutput);
363 
364         assertFileContentEquals(getBackedUpFileOptional(LOCK_WALLPAPER_STAGE).get(),
365                 "lock wallpaper");
366     }
367 
368     @Test
testUpdateWallpaperComponent_systemAndLock()369     public void testUpdateWallpaperComponent_systemAndLock() throws IOException {
370         mWallpaperBackupAgent.mIsDeviceInRestore = true;
371         mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
372                 /* which */ FLAG_LOCK | FLAG_SYSTEM);
373 
374         // Imitate wallpaper component installation.
375         mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE,
376                 /* uid */0);
377         verify(mWallpaperManager, times(1))
378                 .setWallpaperComponentWithFlags(mWallpaperComponent, FLAG_LOCK | FLAG_SYSTEM);
379         verify(mWallpaperManager, never())
380                 .setWallpaperComponentWithFlags(mWallpaperComponent, FLAG_SYSTEM);
381         verify(mWallpaperManager, never())
382                 .setWallpaperComponentWithFlags(mWallpaperComponent, FLAG_LOCK);
383         verify(mWallpaperManager, never()).clear(anyInt());
384     }
385 
386     @Test
testUpdateWallpaperComponent_systemOnly()387     public void testUpdateWallpaperComponent_systemOnly()
388             throws IOException {
389         mWallpaperBackupAgent.mIsDeviceInRestore = true;
390 
391         mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
392                 /* which */ FLAG_SYSTEM);
393 
394         // Imitate wallpaper component installation.
395         mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE,
396                 /* uid */0);
397 
398         verify(mWallpaperManager, times(1))
399                 .setWallpaperComponentWithFlags(mWallpaperComponent, FLAG_SYSTEM);
400         verify(mWallpaperManager, never())
401                 .setWallpaperComponentWithFlags(mWallpaperComponent, FLAG_LOCK);
402         verify(mWallpaperManager, never())
403                 .setWallpaperComponentWithFlags(mWallpaperComponent, FLAG_LOCK | FLAG_SYSTEM);
404         verify(mWallpaperManager, never()).clear(anyInt());
405     }
406 
407     @Test
testUpdateWallpaperComponent_deviceNotInRestore_doesNotApply()408     public void testUpdateWallpaperComponent_deviceNotInRestore_doesNotApply()
409             throws IOException {
410         mWallpaperBackupAgent.mIsDeviceInRestore = false;
411 
412         mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
413                 /* which */ FLAG_LOCK | FLAG_SYSTEM);
414 
415         // Imitate wallpaper component installation.
416         mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE,
417                 /* uid */0);
418 
419         verify(mWallpaperManager, never()).setWallpaperComponent(mWallpaperComponent);
420         verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK));
421     }
422 
423     @Test
testUpdateWallpaperComponent_differentPackageInstalled_doesNotApply()424     public void testUpdateWallpaperComponent_differentPackageInstalled_doesNotApply()
425             throws IOException {
426         mWallpaperBackupAgent.mIsDeviceInRestore = false;
427 
428         mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
429                 /* which */ FLAG_LOCK | FLAG_SYSTEM);
430 
431         // Imitate "wrong" wallpaper component installation.
432         mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(/* packageName */"",
433                 /* uid */0);
434 
435         verify(mWallpaperManager, never()).setWallpaperComponent(mWallpaperComponent);
436         verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK));
437     }
438 
439     @Test
testOnFullBackup_systemWallpaperImgSuccess_logsSuccess()440     public void testOnFullBackup_systemWallpaperImgSuccess_logsSuccess() throws Exception {
441         mockSystemWallpaperFileWithContents("system wallpaper");
442         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
443 
444         mWallpaperBackupAgent.onFullBackup(mOutput);
445 
446         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
447                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
448         assertThat(result).isNotNull();
449         assertThat(result.getSuccessCount()).isEqualTo(1);
450     }
451 
452     @Test
testOnFullBackup_systemWallpaperImgIneligible_logsFailure()453     public void testOnFullBackup_systemWallpaperImgIneligible_logsFailure() throws Exception {
454         when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_SYSTEM))).thenReturn(false);
455         mockSystemWallpaperFileWithContents("system wallpaper");
456         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
457 
458         mWallpaperBackupAgent.onFullBackup(mOutput);
459 
460         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
461                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
462         assertThat(result).isNotNull();
463         assertThat(result.getFailCount()).isEqualTo(1);
464         assertThat(result.getErrors()).containsKey(ERROR_INELIGIBLE);
465     }
466 
467     @Test
testOnFullBackup_systemWallpaperImgMissing_logsFailure()468     public void testOnFullBackup_systemWallpaperImgMissing_logsFailure() throws Exception {
469         mWallpaperBackupAgent.onFullBackup(mOutput);
470 
471         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
472                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
473         assertThat(result).isNotNull();
474         assertThat(result.getFailCount()).isEqualTo(1);
475         assertThat(result.getErrors()).containsKey(ERROR_NO_WALLPAPER);
476     }
477 
478     @Test
testOnFullBackup_systemWallpaperImgMissingButHasLiveComponent_logsLiveSuccess()479     public void testOnFullBackup_systemWallpaperImgMissingButHasLiveComponent_logsLiveSuccess()
480             throws Exception {
481         mockWallpaperInfoFileWithContents("info file");
482         when(mWallpaperManager.getWallpaperInfo(anyInt())).thenReturn(getFakeWallpaperInfo());
483 
484         mWallpaperBackupAgent.onFullBackup(mOutput);
485 
486         DataTypeResult result = getLoggingResult(WALLPAPER_LIVE_SYSTEM,
487                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
488         assertThat(result).isNotNull();
489         assertThat(result.getSuccessCount()).isEqualTo(1);
490         assertThat(result.getMetadataHash()).isNotNull();
491     }
492 
493     @Test
testOnFullBackup_systemWallpaperImgMissingButHasLiveComponent_logsNothingForImg()494     public void testOnFullBackup_systemWallpaperImgMissingButHasLiveComponent_logsNothingForImg()
495             throws Exception {
496         mockWallpaperInfoFileWithContents("info file");
497         when(mWallpaperManager.getWallpaperInfo(anyInt())).thenReturn(getFakeWallpaperInfo());
498 
499         mWallpaperBackupAgent.onFullBackup(mOutput);
500 
501         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
502                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
503         assertThat(result).isNull();
504     }
505 
506     @Test
testOnFullBackup_lockWallpaperImgSuccess_logsSuccess()507     public void testOnFullBackup_lockWallpaperImgSuccess_logsSuccess() throws Exception {
508         mockLockWallpaperFileWithContents("lock wallpaper");
509         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
510 
511         mWallpaperBackupAgent.onFullBackup(mOutput);
512 
513         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
514                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
515         assertThat(result).isNotNull();
516         assertThat(result.getSuccessCount()).isEqualTo(1);
517     }
518 
519     @Test
testOnFullBackup_lockWallpaperImgIneligible_logsFailure()520     public void testOnFullBackup_lockWallpaperImgIneligible_logsFailure() throws Exception {
521         when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_LOCK))).thenReturn(false);
522         mockLockWallpaperFileWithContents("lock wallpaper");
523         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
524 
525         mWallpaperBackupAgent.onFullBackup(mOutput);
526 
527         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
528                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
529         assertThat(result).isNotNull();
530         assertThat(result.getFailCount()).isEqualTo(1);
531         assertThat(result.getErrors()).containsKey(ERROR_INELIGIBLE);
532     }
533 
534     @Test
testOnFullBackup_lockWallpaperImgMissing_logsFailure()535     public void testOnFullBackup_lockWallpaperImgMissing_logsFailure() throws Exception {
536         mWallpaperBackupAgent.onFullBackup(mOutput);
537 
538         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
539                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
540         assertThat(result).isNotNull();
541         assertThat(result.getFailCount()).isEqualTo(1);
542         assertThat(result.getErrors()).containsKey(ERROR_NO_WALLPAPER);
543     }
544 
545     @Test
testOnFullBackup_lockWallpaperImgMissingButHasLiveComponent_logsLiveSuccess()546     public void testOnFullBackup_lockWallpaperImgMissingButHasLiveComponent_logsLiveSuccess()
547             throws Exception {
548         mockWallpaperInfoFileWithContents("info file");
549         when(mWallpaperManager.getWallpaperInfo(anyInt())).thenReturn(getFakeWallpaperInfo());
550 
551         mWallpaperBackupAgent.onFullBackup(mOutput);
552 
553         DataTypeResult result = getLoggingResult(WALLPAPER_LIVE_LOCK,
554                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
555         assertThat(result).isNotNull();
556         assertThat(result.getSuccessCount()).isEqualTo(1);
557         assertThat(result.getMetadataHash()).isNotNull();
558     }
559 
560     @Test
testOnFullBackup_lockWallpaperImgMissingButHasLiveComponent_logsNothingForImg()561     public void testOnFullBackup_lockWallpaperImgMissingButHasLiveComponent_logsNothingForImg()
562             throws Exception {
563         mockWallpaperInfoFileWithContents("info file");
564         when(mWallpaperManager.getWallpaperInfo(anyInt())).thenReturn(getFakeWallpaperInfo());
565 
566         mWallpaperBackupAgent.onFullBackup(mOutput);
567 
568         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
569                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
570         assertThat(result).isNull();
571     }
572 
573 
574     @Test
testOnFullBackup_exceptionThrown_logsException()575     public void testOnFullBackup_exceptionThrown_logsException() throws Exception {
576         when(mWallpaperManager.isWallpaperBackupEligible(anyInt())).thenThrow(
577                 new RuntimeException());
578         mWallpaperBackupAgent.onFullBackup(mOutput);
579 
580         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
581                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
582         assertThat(result).isNotNull();
583         assertThat(result.getFailCount()).isEqualTo(1);
584         assertThat(result.getErrors()).containsKey(RuntimeException.class.getName());
585     }
586 
587     @Test
testOnFullBackup_lastBackupOverQuota_logsLockFailure()588     public void testOnFullBackup_lastBackupOverQuota_logsLockFailure() throws Exception {
589         mockSystemWallpaperFileWithContents("system wallpaper");
590         mockLockWallpaperFileWithContents("lock wallpaper");
591         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
592         markAgentAsOverQuota();
593 
594         mWallpaperBackupAgent.onFullBackup(mOutput);
595 
596         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
597                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
598         assertThat(result).isNotNull();
599         assertThat(result.getFailCount()).isEqualTo(1);
600         assertThat(result.getErrors()).containsKey(ERROR_QUOTA_EXCEEDED);
601     }
602 
603     @Test
testOnFullBackup_lastBackupOverQuota_logsSystemSuccess()604     public void testOnFullBackup_lastBackupOverQuota_logsSystemSuccess() throws Exception {
605         mockSystemWallpaperFileWithContents("system wallpaper");
606         mockLockWallpaperFileWithContents("lock wallpaper");
607         mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
608         markAgentAsOverQuota();
609 
610         mWallpaperBackupAgent.onFullBackup(mOutput);
611 
612         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
613                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
614         assertThat(result).isNotNull();
615         assertThat(result.getSuccessCount()).isEqualTo(1);
616     }
617 
618     @Test
testOnRestore_wallpaperImgSuccess_logsSuccess()619     public void testOnRestore_wallpaperImgSuccess_logsSuccess() throws Exception {
620         mockStagedWallpaperFile(WALLPAPER_INFO_STAGE);
621         mockStagedWallpaperFile(SYSTEM_WALLPAPER_STAGE);
622         mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
623                 BackupAnnotations.OperationType.RESTORE);
624 
625         mWallpaperBackupAgent.onRestoreFinished();
626 
627         // wallpaper will be applied to home & lock screen, a success for both screens is expected
628         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
629                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
630         assertThat(result).isNotNull();
631         assertThat(result.getSuccessCount()).isEqualTo(1);
632 
633         result = getLoggingResult(WALLPAPER_IMG_LOCK,
634                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
635         assertThat(result).isNotNull();
636         assertThat(result.getSuccessCount()).isEqualTo(1);
637     }
638 
639     @Test
testOnRestore_lockWallpaperImgSuccess_logsSuccess()640     public void testOnRestore_lockWallpaperImgSuccess_logsSuccess() throws Exception {
641         mockStagedWallpaperFile(WALLPAPER_INFO_STAGE);
642         mockStagedWallpaperFile(LOCK_WALLPAPER_STAGE);
643         mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
644                 BackupAnnotations.OperationType.RESTORE);
645 
646         mWallpaperBackupAgent.onRestoreFinished();
647 
648         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
649                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
650         assertThat(result).isNotNull();
651         assertThat(result.getSuccessCount()).isEqualTo(1);
652     }
653 
654     @Test
testOnRestore_systemWallpaperImgMissingAndNoLive_logsFailure()655     public void testOnRestore_systemWallpaperImgMissingAndNoLive_logsFailure() throws Exception {
656         mockStagedWallpaperFile(WALLPAPER_INFO_STAGE);
657         mockStagedWallpaperFile(LOCK_WALLPAPER_STAGE);
658         mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
659                 BackupAnnotations.OperationType.RESTORE);
660 
661         mWallpaperBackupAgent.onRestoreFinished();
662 
663         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
664                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
665         assertThat(result).isNotNull();
666         assertThat(result.getFailCount()).isEqualTo(1);
667         assertThat(result.getErrors()).containsKey(ERROR_NO_WALLPAPER);
668 
669     }
670 
671     @Test
testOnRestore_wallpaperImgMissingAndNoLive_logsFailure()672     public void testOnRestore_wallpaperImgMissingAndNoLive_logsFailure() throws Exception {
673         mockStagedWallpaperFile(WALLPAPER_INFO_STAGE);
674         mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
675                 BackupAnnotations.OperationType.RESTORE);
676 
677         mWallpaperBackupAgent.onRestoreFinished();
678 
679         for (String wallpaper: List.of(WALLPAPER_IMG_LOCK, WALLPAPER_IMG_SYSTEM)) {
680             DataTypeResult result = getLoggingResult(wallpaper,
681                     mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
682             assertThat(result).isNotNull();
683             assertThat(result.getFailCount()).isEqualTo(1);
684             assertThat(result.getErrors()).containsKey(ERROR_NO_WALLPAPER);
685         }
686     }
687 
688     @Test
testOnRestore_wallpaperInfoMissing_logsFailure()689     public void testOnRestore_wallpaperInfoMissing_logsFailure() throws Exception {
690         mockStagedWallpaperFile(SYSTEM_WALLPAPER_STAGE);
691         mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
692                 BackupAnnotations.OperationType.RESTORE);
693 
694         mWallpaperBackupAgent.onRestoreFinished();
695 
696         DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
697                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
698         assertThat(result).isNotNull();
699         assertThat(result.getFailCount()).isEqualTo(1);
700         assertThat(result.getErrors()).containsKey(ERROR_NO_METADATA);
701     }
702 
703     @Test
testOnRestore_imgMissingButWallpaperInfoHasLive_doesNotLogImg()704     public void testOnRestore_imgMissingButWallpaperInfoHasLive_doesNotLogImg() throws Exception {
705         mockRestoredLiveWallpaperFile();
706         mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
707                 BackupAnnotations.OperationType.RESTORE);
708 
709         mWallpaperBackupAgent.onRestoreFinished();
710 
711         DataTypeResult system = getLoggingResult(WALLPAPER_IMG_SYSTEM,
712                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
713         DataTypeResult lock = getLoggingResult(WALLPAPER_IMG_LOCK,
714                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
715         assertThat(system).isNull();
716         assertThat(lock).isNull();
717     }
718 
719     @Test
testOnRestore_throwsException_logsErrors()720     public void testOnRestore_throwsException_logsErrors() throws Exception {
721         if (!multiCrop()) {
722             when(mWallpaperManager.setStream(any(), any(), anyBoolean(), anyInt()))
723                     .thenThrow(new RuntimeException());
724         } else {
725             when(mWallpaperManager.setStreamWithCrops(any(), any(SparseArray.class), anyBoolean(),
726                     anyInt())).thenThrow(new RuntimeException());
727         }
728         mockStagedWallpaperFile(SYSTEM_WALLPAPER_STAGE);
729         mockStagedWallpaperFile(WALLPAPER_INFO_STAGE);
730         mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
731                 BackupAnnotations.OperationType.RESTORE);
732 
733         mWallpaperBackupAgent.onRestoreFinished();
734 
735         DataTypeResult system = getLoggingResult(WALLPAPER_IMG_SYSTEM,
736                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
737         DataTypeResult lock = getLoggingResult(WALLPAPER_IMG_LOCK,
738                 mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
739         assertThat(system).isNotNull();
740         assertThat(system.getFailCount()).isEqualTo(1);
741         assertThat(system.getErrors()).containsKey(RuntimeException.class.getName());
742         assertThat(lock).isNotNull();
743         assertThat(lock.getFailCount()).isEqualTo(1);
744         assertThat(lock.getErrors()).containsKey(RuntimeException.class.getName());
745     }
746 
747     @Test
testUpdateWallpaperComponent_delayedRestore_logsSuccess()748     public void testUpdateWallpaperComponent_delayedRestore_logsSuccess() throws Exception {
749         mWallpaperBackupAgent.mIsDeviceInRestore = true;
750         when(mWallpaperManager.setWallpaperComponent(any())).thenReturn(true);
751         when(mWallpaperManager.setWallpaperComponentWithFlags(any(), eq(FLAG_LOCK | FLAG_SYSTEM)))
752                 .thenReturn(true);
753         BackupRestoreEventLogger logger = new BackupRestoreEventLogger(
754                 BackupAnnotations.OperationType.RESTORE);
755         when(mBackupManager.getDelayedRestoreLogger()).thenReturn(logger);
756         mWallpaperBackupAgent.setBackupManagerForTesting(mBackupManager);
757 
758         mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
759                 /* which */ FLAG_LOCK | FLAG_SYSTEM);
760         // Imitate wallpaper component installation.
761         mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE,
762                 /* uid */0);
763 
764         DataTypeResult system = getLoggingResult(WALLPAPER_LIVE_SYSTEM, logger.getLoggingResults());
765         DataTypeResult lock = getLoggingResult(WALLPAPER_LIVE_LOCK, logger.getLoggingResults());
766         assertThat(system).isNotNull();
767         assertThat(system.getSuccessCount()).isEqualTo(1);
768         assertThat(lock).isNotNull();
769         assertThat(lock.getSuccessCount()).isEqualTo(1);
770     }
771 
772 
773     @Test
testUpdateWallpaperComponent_delayedRestoreFails_logsFailure()774     public void testUpdateWallpaperComponent_delayedRestoreFails_logsFailure() throws Exception {
775         mWallpaperBackupAgent.mIsDeviceInRestore = true;
776         when(mWallpaperManager.setWallpaperComponent(any())).thenReturn(false);
777         BackupRestoreEventLogger logger = new BackupRestoreEventLogger(
778                 BackupAnnotations.OperationType.RESTORE);
779         when(mBackupManager.getDelayedRestoreLogger()).thenReturn(logger);
780         mWallpaperBackupAgent.setBackupManagerForTesting(mBackupManager);
781 
782         mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
783                 /* which */ FLAG_LOCK | FLAG_SYSTEM);
784         // Imitate wallpaper component installation.
785         mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE,
786                 /* uid */0);
787 
788         DataTypeResult system = getLoggingResult(WALLPAPER_LIVE_SYSTEM, logger.getLoggingResults());
789         assertThat(system).isNotNull();
790         assertThat(system.getFailCount()).isEqualTo(1);
791         assertThat(system.getErrors()).containsKey(
792                 WallpaperEventLogger.ERROR_SET_COMPONENT_EXCEPTION);
793     }
794 
795     @Test
testUpdateWallpaperComponent_delayedRestore_packageNotInstalled_logsFailure()796     public void testUpdateWallpaperComponent_delayedRestore_packageNotInstalled_logsFailure()
797             throws Exception {
798         mWallpaperBackupAgent.mIsDeviceInRestore = false;
799         BackupRestoreEventLogger logger = new BackupRestoreEventLogger(
800                 BackupAnnotations.OperationType.RESTORE);
801         when(mBackupManager.getDelayedRestoreLogger()).thenReturn(logger);
802         mWallpaperBackupAgent.setBackupManagerForTesting(mBackupManager);
803 
804         mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
805                 /* which */ FLAG_LOCK | FLAG_SYSTEM);
806 
807         // Imitate wallpaper component installation.
808         mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE,
809                 /* uid */0);
810 
811         DataTypeResult system = getLoggingResult(WALLPAPER_LIVE_SYSTEM, logger.getLoggingResults());
812         DataTypeResult lock = getLoggingResult(WALLPAPER_LIVE_LOCK, logger.getLoggingResults());
813         assertThat(system).isNotNull();
814         assertThat(system.getFailCount()).isEqualTo(1);
815         assertThat(system.getErrors()).containsKey(
816                 WallpaperEventLogger.ERROR_LIVE_PACKAGE_NOT_INSTALLED);
817         assertThat(lock).isNotNull();
818         assertThat(lock.getFailCount()).isEqualTo(1);
819         assertThat(lock.getErrors()).containsKey(
820                 WallpaperEventLogger.ERROR_LIVE_PACKAGE_NOT_INSTALLED);
821     }
822 
823     @Test
testOnRestore_noCropHints()824     public void testOnRestore_noCropHints() throws Exception {
825         testParseCropHints(Map.of());
826     }
827 
828     @Test
testOnRestore_singleCropHint()829     public void testOnRestore_singleCropHint() throws Exception {
830         Map<Integer, Rect> testMap = Map.of(
831                 WallpaperManager.ORIENTATION_PORTRAIT, new Rect(1, 2, 3, 4));
832         testParseCropHints(testMap);
833     }
834 
835     @Test
testOnRestore_multipleCropHints()836     public void testOnRestore_multipleCropHints() throws Exception {
837         Map<Integer, Rect> testMap = Map.of(
838                 WallpaperManager.ORIENTATION_PORTRAIT, new Rect(1, 2, 3, 4),
839                 WallpaperManager.ORIENTATION_SQUARE_PORTRAIT, new Rect(5, 6, 7, 8),
840                 WallpaperManager.ORIENTATION_SQUARE_LANDSCAPE, new Rect(9, 10, 11, 12));
841         testParseCropHints(testMap);
842     }
843 
testParseCropHints(Map<Integer, Rect> testMap)844     private void testParseCropHints(Map<Integer, Rect> testMap) throws Exception {
845         assumeTrue(multiCrop());
846         mockRestoredStaticWallpaperFile(testMap);
847         mockStagedWallpaperFile(SYSTEM_WALLPAPER_STAGE);
848         mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
849                 BackupAnnotations.OperationType.RESTORE);
850 
851         mWallpaperBackupAgent.onRestoreFinished();
852 
853         ArgumentMatcher<SparseArray<Rect>> matcher = array -> {
854             boolean result = testMap.entrySet().stream().allMatch(entry -> {
855                 int key = entry.getKey();
856                 return (array.contains(key) && array.get(key).equals(testMap.get(key)));
857             });
858             for (int i = 0; i < array.size(); i++) {
859                 if (!testMap.containsKey(array.keyAt(i))) result = false;
860             }
861             return result;
862         };
863         verify(mWallpaperManager).setStreamWithCrops(any(), argThat(matcher), eq(true), anyInt());
864     }
865 
mockCurrentWallpaperIds(int systemWallpaperId, int lockWallpaperId)866     private void mockCurrentWallpaperIds(int systemWallpaperId, int lockWallpaperId) {
867         when(mWallpaperManager.getWallpaperId(eq(FLAG_SYSTEM))).thenReturn(systemWallpaperId);
868         when(mWallpaperManager.getWallpaperId(eq(FLAG_LOCK))).thenReturn(lockWallpaperId);
869     }
870 
createTemporaryFileWithContentString(String contents)871     private File createTemporaryFileWithContentString(String contents) throws Exception {
872         File file = mTemporaryFolder.newFile();
873         try (FileOutputStream outputStream = new FileOutputStream(file)) {
874             outputStream.write(contents.getBytes());
875         }
876         return file;
877     }
878 
assertFileContentEquals(File file, String expected)879     private void assertFileContentEquals(File file, String expected) throws Exception {
880         try (FileInputStream inputStream = new FileInputStream(file)) {
881             assertThat(new String(inputStream.readAllBytes())).isEqualTo(expected);
882         }
883     }
884 
getBackedUpFileOptional(String fileName)885     private Optional<File> getBackedUpFileOptional(String fileName) {
886         return mWallpaperBackupAgent.mBackedUpFiles.stream().filter(
887                 file -> file.getName().equals(fileName)).findFirst();
888     }
889 
mockWallpaperInfoFileWithContents(String contents)890     private void mockWallpaperInfoFileWithContents(String contents) throws Exception {
891         File fakeInfoFile = createTemporaryFileWithContentString(contents);
892         when(mWallpaperManager.getWallpaperInfoFile()).thenReturn(
893                 ParcelFileDescriptor.open(fakeInfoFile, MODE_READ_ONLY));
894     }
895 
mockSystemWallpaperFileWithContents(String contents)896     private void mockSystemWallpaperFileWithContents(String contents) throws Exception {
897         File fakeSystemWallpaperFile = createTemporaryFileWithContentString(contents);
898         when(mWallpaperManager.getWallpaperFile(eq(FLAG_SYSTEM), /* cropped = */
899                 eq(false))).thenReturn(
900                 ParcelFileDescriptor.open(fakeSystemWallpaperFile, MODE_READ_ONLY));
901     }
902 
mockLockWallpaperFileWithContents(String contents)903     private void mockLockWallpaperFileWithContents(String contents) throws Exception {
904         File fakeLockWallpaperFile = createTemporaryFileWithContentString(contents);
905         when(mWallpaperManager.getWallpaperFile(eq(FLAG_LOCK), /* cropped = */
906                 eq(false))).thenReturn(
907                 ParcelFileDescriptor.open(fakeLockWallpaperFile, MODE_READ_ONLY));
908     }
909 
mockStagedWallpaperFile(String location)910     private void mockStagedWallpaperFile(String location) throws Exception {
911         File wallpaperFile = new File(mContext.getFilesDir(), location);
912         wallpaperFile.createNewFile();
913     }
914 
mockRestoredLiveWallpaperFile()915     private void mockRestoredLiveWallpaperFile() throws Exception {
916         File wallpaperFile = new File(mContext.getFilesDir(), WALLPAPER_INFO_STAGE);
917         wallpaperFile.createNewFile();
918         FileOutputStream fstream = new FileOutputStream(wallpaperFile, false);
919         TypedXmlSerializer out = Xml.resolveSerializer(fstream);
920         out.startDocument(null, true);
921         out.startTag(null, "wp");
922         out.attribute(null, "component",
923                 getFakeWallpaperInfo().getComponent().flattenToShortString());
924         out.endTag(null, "wp");
925         out.endDocument();
926         fstream.flush();
927         FileUtils.sync(fstream);
928         fstream.close();
929     }
930 
mockRestoredStaticWallpaperFile(Map<Integer, Rect> crops)931     private void mockRestoredStaticWallpaperFile(Map<Integer, Rect> crops) throws Exception {
932         File wallpaperFile = new File(mContext.getFilesDir(), WALLPAPER_INFO_STAGE);
933         wallpaperFile.createNewFile();
934         FileOutputStream fstream = new FileOutputStream(wallpaperFile, false);
935         TypedXmlSerializer out = Xml.resolveSerializer(fstream);
936         out.startDocument(null, true);
937         out.startTag(null, "wp");
938         for (Map.Entry<Integer, Rect> entry: crops.entrySet()) {
939             String orientation = switch (entry.getKey()) {
940                 case WallpaperManager.ORIENTATION_PORTRAIT -> "Portrait";
941                 case WallpaperManager.ORIENTATION_LANDSCAPE -> "Landscape";
942                 case WallpaperManager.ORIENTATION_SQUARE_PORTRAIT -> "SquarePortrait";
943                 case WallpaperManager.ORIENTATION_SQUARE_LANDSCAPE -> "SquareLandscape";
944                 default -> throw new IllegalArgumentException("Invalid orientation");
945             };
946             Rect rect = entry.getValue();
947             out.attributeInt(null, "cropLeft" + orientation, rect.left);
948             out.attributeInt(null, "cropTop" + orientation, rect.top);
949             out.attributeInt(null, "cropRight" + orientation, rect.right);
950             out.attributeInt(null, "cropBottom" + orientation, rect.bottom);
951         }
952         out.endTag(null, "wp");
953         out.endDocument();
954         fstream.flush();
955         FileUtils.sync(fstream);
956         fstream.close();
957     }
958 
getFakeWallpaperInfo()959     private WallpaperInfo getFakeWallpaperInfo() throws Exception {
960         Context context = InstrumentationRegistry.getTargetContext();
961         Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
962         intent.setPackage("com.android.wallpaperbackup.tests");
963         PackageManager pm = context.getPackageManager();
964         List<ResolveInfo> result = pm.queryIntentServices(intent, PackageManager.GET_META_DATA);
965         assertEquals(1, result.size());
966         ResolveInfo info = result.get(0);
967         return new WallpaperInfo(context, info);
968     }
969 
markAgentAsOverQuota()970     private void markAgentAsOverQuota() throws Exception {
971         // Create over quota file to indicate the last backup was over quota
972         File quotaFile = new File(mContext.getFilesDir(), WallpaperBackupAgent.QUOTA_SENTINEL);
973         quotaFile.createNewFile();
974 
975         // Now redo the setup of the agent to pick up the over quota
976         mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
977                 BackupAnnotations.OperationType.BACKUP);
978     }
979 
getLoggingResult(String dataType, List<DataTypeResult> results)980     private static DataTypeResult getLoggingResult(String dataType, List<DataTypeResult> results) {
981         for (DataTypeResult result : results) {
982             if ((result.getDataType()).equals(dataType)) {
983                 return result;
984             }
985         }
986         return null;
987     }
988 
989     private class IsolatedWallpaperBackupAgent extends WallpaperBackupAgent {
990         List<File> mBackedUpFiles = new ArrayList<>();
991         PackageMonitor mWallpaperPackageMonitor;
992         boolean mIsDeviceInRestore = false;
993 
994         @Override
backupFile(File file, FullBackupDataOutput data)995         protected void backupFile(File file, FullBackupDataOutput data) {
996             mBackedUpFiles.add(file);
997         }
998 
999         @Override
servicePackageExists(ComponentName comp)1000         boolean servicePackageExists(ComponentName comp) {
1001             return false;
1002         }
1003 
1004         @Override
isDeviceInRestore()1005         boolean isDeviceInRestore() {
1006             return mIsDeviceInRestore;
1007         }
1008 
1009         @Override
getWallpaperPackageMonitor(ComponentName componentName, int which)1010         PackageMonitor getWallpaperPackageMonitor(ComponentName componentName, int which) {
1011             mWallpaperPackageMonitor = super.getWallpaperPackageMonitor(componentName, which);
1012             return mWallpaperPackageMonitor;
1013         }
1014 
1015         @Override
getBaseContext()1016         public Context getBaseContext() {
1017             return mMockContext;
1018         }
1019     }
1020 }
1021