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 22 import static com.google.common.truth.Truth.assertThat; 23 24 import static org.mockito.ArgumentMatchers.anyInt; 25 import static org.mockito.ArgumentMatchers.anyString; 26 import static org.mockito.ArgumentMatchers.eq; 27 import static org.mockito.Mockito.doNothing; 28 import static org.mockito.Mockito.inOrder; 29 import static org.mockito.Mockito.never; 30 import static org.mockito.Mockito.times; 31 import static org.mockito.Mockito.verify; 32 import static org.mockito.Mockito.when; 33 34 import android.app.WallpaperManager; 35 import android.app.backup.FullBackupDataOutput; 36 import android.content.ComponentName; 37 import android.content.Context; 38 import android.content.SharedPreferences; 39 import android.os.UserHandle; 40 41 import androidx.test.core.app.ApplicationProvider; 42 import androidx.test.runner.AndroidJUnit4; 43 44 import com.android.internal.content.PackageMonitor; 45 import com.android.wallpaperbackup.WallpaperBackupAgent; 46 import com.android.wallpaperbackup.utils.ContextWithServiceOverrides; 47 48 import org.junit.Before; 49 import org.junit.Rule; 50 import org.junit.Test; 51 import org.junit.rules.TemporaryFolder; 52 import org.junit.runner.RunWith; 53 import org.mockito.InOrder; 54 import org.mockito.Mock; 55 import org.mockito.MockitoAnnotations; 56 57 import java.io.File; 58 import java.io.IOException; 59 import java.util.ArrayList; 60 import java.util.List; 61 62 @RunWith(AndroidJUnit4.class) 63 public class WallpaperBackupAgentTest { 64 private static final String SYSTEM_GENERATION = "system_gen"; 65 private static final String LOCK_GENERATION = "lock_gen"; 66 private static final String TEST_WALLPAPER_PACKAGE = "wallpaper_package"; 67 68 private static final int TEST_SYSTEM_WALLPAPER_ID = 1; 69 private static final int TEST_LOCK_WALLPAPER_ID = 2; 70 71 @Mock private FullBackupDataOutput mOutput; 72 @Mock private WallpaperManager mWallpaperManager; 73 @Mock private SharedPreferences mSharedPreferences; 74 @Mock private SharedPreferences.Editor mSharedPreferenceEditor; 75 @Mock private Context mMockContext; 76 77 @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); 78 79 private ContextWithServiceOverrides mContext; 80 private IsolatedWallpaperBackupAgent mWallpaperBackupAgent; 81 private ComponentName mWallpaperComponent; 82 83 @Before setUp()84 public void setUp() { 85 MockitoAnnotations.initMocks(this); 86 87 when(mSharedPreferences.edit()).thenReturn(mSharedPreferenceEditor); 88 when(mSharedPreferenceEditor.putInt(anyString(), anyInt())) 89 .thenReturn(mSharedPreferenceEditor); 90 doNothing().when(mSharedPreferenceEditor).apply(); 91 92 mContext = new ContextWithServiceOverrides(ApplicationProvider.getApplicationContext()); 93 mContext.injectSystemService(WallpaperManager.class, mWallpaperManager); 94 mContext.setSharedPreferencesOverride(mSharedPreferences); 95 96 mWallpaperBackupAgent = new IsolatedWallpaperBackupAgent(mTemporaryFolder.getRoot()); 97 mWallpaperBackupAgent.attach(mContext); 98 mWallpaperBackupAgent.onCreate(); 99 100 mWallpaperComponent = new ComponentName(TEST_WALLPAPER_PACKAGE, ""); 101 } 102 103 @Test testOnFullBackup_withNoChanges_onlyBacksUpEmptyFile()104 public void testOnFullBackup_withNoChanges_onlyBacksUpEmptyFile() throws IOException { 105 mockBackedUpState(); 106 mockCurrentWallpapers(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID); 107 108 mWallpaperBackupAgent.onFullBackup(mOutput); 109 110 assertThat(mWallpaperBackupAgent.mBackedUpFiles.size()).isEqualTo(1); 111 assertThat(mWallpaperBackupAgent.mBackedUpFiles.get(0).getName()).isEqualTo("empty"); 112 } 113 114 @Test testOnFullBackup_withOnlyChangedSystem_updatesTheSharedPreferences()115 public void testOnFullBackup_withOnlyChangedSystem_updatesTheSharedPreferences() 116 throws IOException { 117 mockSystemWallpaperReadyToBackUp(); 118 mockUnbackedUpState(); 119 mockCurrentWallpapers(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID); 120 121 mWallpaperBackupAgent.onFullBackup(mOutput); 122 123 verify(mSharedPreferenceEditor).putInt(eq(SYSTEM_GENERATION), eq(TEST_SYSTEM_WALLPAPER_ID)); 124 } 125 126 @Test testOnFullBackup_withLockChangedToMatchSystem_updatesTheSharedPreferences()127 public void testOnFullBackup_withLockChangedToMatchSystem_updatesTheSharedPreferences() 128 throws IOException { 129 mockBackedUpState(); 130 mockSystemWallpaperReadyToBackUp(); 131 mockCurrentWallpapers(TEST_SYSTEM_WALLPAPER_ID, -1); 132 133 mWallpaperBackupAgent.onFullBackup(mOutput); 134 135 InOrder inOrder = inOrder(mSharedPreferenceEditor); 136 inOrder.verify(mSharedPreferenceEditor) 137 .putInt(eq(SYSTEM_GENERATION), eq(TEST_SYSTEM_WALLPAPER_ID)); 138 inOrder.verify(mSharedPreferenceEditor).apply(); 139 inOrder.verify(mSharedPreferenceEditor).putInt(eq(LOCK_GENERATION), eq(-1)); 140 inOrder.verify(mSharedPreferenceEditor).apply(); 141 } 142 143 @Test updateWallpaperComponent_doesApplyLater()144 public void updateWallpaperComponent_doesApplyLater() throws IOException { 145 mWallpaperBackupAgent.mIsDeviceInRestore = true; 146 147 mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent, 148 /* applyToLock */ true); 149 150 // Imitate wallpaper component installation. 151 mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE, 152 /* uid */0); 153 154 verify(mWallpaperManager, times(1)).setWallpaperComponent(mWallpaperComponent); 155 verify(mWallpaperManager, times(1)).clear(eq(FLAG_LOCK)); 156 } 157 158 @Test updateWallpaperComponent_applyToLockFalse_doesApplyLaterOnlyToMainScreen()159 public void updateWallpaperComponent_applyToLockFalse_doesApplyLaterOnlyToMainScreen() 160 throws IOException { 161 mWallpaperBackupAgent.mIsDeviceInRestore = true; 162 163 mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent, 164 /* applyToLock */ false); 165 166 // Imitate wallpaper component installation. 167 mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE, 168 /* uid */0); 169 170 verify(mWallpaperManager, times(1)).setWallpaperComponent(mWallpaperComponent); 171 verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK)); 172 } 173 174 @Test updateWallpaperComponent_deviceNotInRestore_doesNotApply()175 public void updateWallpaperComponent_deviceNotInRestore_doesNotApply() 176 throws IOException { 177 mWallpaperBackupAgent.mIsDeviceInRestore = false; 178 179 mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent, 180 /* applyToLock */ true); 181 182 // Imitate wallpaper component installation. 183 mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE, 184 /* uid */0); 185 186 verify(mWallpaperManager, never()).setWallpaperComponent(mWallpaperComponent); 187 verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK)); 188 } 189 190 @Test updateWallpaperComponent_differentPackageInstalled_doesNotApply()191 public void updateWallpaperComponent_differentPackageInstalled_doesNotApply() 192 throws IOException { 193 mWallpaperBackupAgent.mIsDeviceInRestore = false; 194 195 mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent, 196 /* applyToLock */ true); 197 198 // Imitate "wrong" wallpaper component installation. 199 mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(/* packageName */"", 200 /* uid */0); 201 202 verify(mWallpaperManager, never()).setWallpaperComponent(mWallpaperComponent); 203 verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK)); 204 } 205 mockUnbackedUpState()206 private void mockUnbackedUpState() { 207 mockCurrentWallpapers(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID); 208 when(mSharedPreferences.getInt(eq(SYSTEM_GENERATION), eq(-1))).thenReturn(-1); 209 when(mSharedPreferences.getInt(eq(LOCK_GENERATION), eq(-1))).thenReturn(-1); 210 } 211 mockBackedUpState()212 private void mockBackedUpState() { 213 when(mSharedPreferences.getInt(eq(SYSTEM_GENERATION), eq(-1))) 214 .thenReturn(TEST_SYSTEM_WALLPAPER_ID); 215 when(mSharedPreferences.getInt(eq(LOCK_GENERATION), eq(-1))) 216 .thenReturn(TEST_LOCK_WALLPAPER_ID); 217 } 218 mockCurrentWallpapers(int systemWallpaperId, int lockWallpaperId)219 private void mockCurrentWallpapers(int systemWallpaperId, int lockWallpaperId) { 220 when(mWallpaperManager.getWallpaperIdForUser(eq(FLAG_SYSTEM), eq(UserHandle.USER_SYSTEM))) 221 .thenReturn(systemWallpaperId); 222 when(mWallpaperManager.getWallpaperIdForUser(eq(FLAG_LOCK), eq(UserHandle.USER_SYSTEM))) 223 .thenReturn(lockWallpaperId); 224 when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_SYSTEM))).thenReturn(true); 225 when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_LOCK))).thenReturn(true); 226 } 227 mockSystemWallpaperReadyToBackUp()228 private void mockSystemWallpaperReadyToBackUp() throws IOException { 229 // Create a system wallpaper file 230 mTemporaryFolder.newFile("wallpaper_orig"); 231 // Create staging file to simulate he wallpaper being ready to back up 232 new File(mContext.getFilesDir(), "wallpaper-stage").createNewFile(); 233 } 234 235 private class IsolatedWallpaperBackupAgent extends WallpaperBackupAgent { 236 File mWallpaperBaseDirectory; 237 List<File> mBackedUpFiles = new ArrayList<>(); 238 PackageMonitor mWallpaperPackageMonitor; 239 boolean mIsDeviceInRestore = false; 240 IsolatedWallpaperBackupAgent(File wallpaperBaseDirectory)241 IsolatedWallpaperBackupAgent(File wallpaperBaseDirectory) { 242 mWallpaperBaseDirectory = wallpaperBaseDirectory; 243 } 244 245 @Override getWallpaperDir()246 protected File getWallpaperDir() { 247 return mWallpaperBaseDirectory; 248 } 249 250 @Override backupFile(File file, FullBackupDataOutput data)251 protected void backupFile(File file, FullBackupDataOutput data) { 252 mBackedUpFiles.add(file); 253 } 254 255 @Override getSharedPreferences(File file, int mode)256 public SharedPreferences getSharedPreferences(File file, int mode) { 257 return mSharedPreferences; 258 } 259 260 @Override servicePackageExists(ComponentName comp)261 boolean servicePackageExists(ComponentName comp) { 262 return false; 263 } 264 265 @Override isDeviceInRestore()266 boolean isDeviceInRestore() { 267 return mIsDeviceInRestore; 268 } 269 270 @Override getWallpaperPackageMonitor(ComponentName componentName, boolean applyToLock)271 PackageMonitor getWallpaperPackageMonitor(ComponentName componentName, 272 boolean applyToLock) { 273 mWallpaperPackageMonitor = super.getWallpaperPackageMonitor(componentName, applyToLock); 274 return mWallpaperPackageMonitor; 275 } 276 277 @Override getBaseContext()278 public Context getBaseContext() { 279 return mMockContext; 280 } 281 } 282 } 283