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