Add tests to WallpaperBackupAgent
We're currently seeing the WallpaperBackupAgent generate data
for a backup even when nothing has changed. In order to verify
that any fix resolves this we should put appropriate tests in
place which first verify the issue and then break and need
updating when the issue is resolved.
This CL adds some initial tests to give us the test infrastructure
we can use to create the null-diff tests.
Test: atest WallpaperBackupAgentTests
Bug: 140995339
Change-Id: I188e39f9a032b0b9be01faa77597a8698d9e4c57
diff --git a/packages/WallpaperBackup/Android.bp b/packages/WallpaperBackup/Android.bp
index 56020cd..748eb40 100644
--- a/packages/WallpaperBackup/Android.bp
+++ b/packages/WallpaperBackup/Android.bp
@@ -24,3 +24,27 @@
certificate: "platform",
privileged: false,
}
+
+android_test {
+ name: "WallpaperBackupAgentTests",
+ manifest: "test/AndroidManifest.xml",
+ test_config: "test/AndroidTest.xml",
+ srcs: [
+ // Include the app source code because the app runs as the system user on-device.
+ "src/**/*.java",
+ "test/src/**/*.java"
+ ],
+ libs: [
+ "android.test.base",
+ "android.test.runner",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "mockito-target-minus-junit4",
+ "truth-prebuilt",
+ ],
+ certificate: "platform",
+ platform_apis: true,
+ test_suites: ["device-tests"]
+}
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index da90189..1c2c640 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -39,6 +39,8 @@
import android.util.Slog;
import android.util.Xml;
+import com.android.internal.annotations.VisibleForTesting;
+
import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -89,7 +91,7 @@
Slog.v(TAG, "onCreate()");
}
- File wallpaperDir = Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM);
+ File wallpaperDir = getWallpaperDir();
mWallpaperInfo = new File(wallpaperDir, WALLPAPER_INFO);
mWallpaperFile = new File(wallpaperDir, WALLPAPER);
mLockWallpaperFile = new File(wallpaperDir, WALLPAPER_LOCK);
@@ -102,6 +104,11 @@
}
}
+ @VisibleForTesting
+ protected File getWallpaperDir() {
+ return Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM);
+ }
+
@Override
public void onFullBackup(FullBackupDataOutput data) throws IOException {
// To avoid data duplication and disk churn, use links as the stage.
@@ -119,7 +126,7 @@
FileOutputStream touch = new FileOutputStream(empty);
touch.close();
}
- fullBackupFile(empty, data);
+ backupFile(empty, data);
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
final int lastSysGeneration = prefs.getInt(SYSTEM_GENERATION, -1);
@@ -155,7 +162,7 @@
FileUtils.copyFileOrThrow(mWallpaperInfo, infoStage);
}
if (DEBUG) Slog.v(TAG, "Storing wallpaper metadata");
- fullBackupFile(infoStage, data);
+ backupFile(infoStage, data);
}
if (sysEligible && mWallpaperFile.exists()) {
if (sysChanged || !imageStage.exists()) {
@@ -163,7 +170,7 @@
FileUtils.copyFileOrThrow(mWallpaperFile, imageStage);
}
if (DEBUG) Slog.v(TAG, "Storing system wallpaper image");
- fullBackupFile(imageStage, data);
+ backupFile(imageStage, data);
prefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply();
}
@@ -174,7 +181,7 @@
FileUtils.copyFileOrThrow(mLockWallpaperFile, lockImageStage);
}
if (DEBUG) Slog.v(TAG, "Storing lock wallpaper image");
- fullBackupFile(lockImageStage, data);
+ backupFile(lockImageStage, data);
prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
}
} catch (Exception e) {
@@ -189,6 +196,12 @@
}
}
+ @VisibleForTesting
+ // fullBackupFile is final, so we intercept backups here in tests.
+ protected void backupFile(File file, FullBackupDataOutput data) {
+ fullBackupFile(file, data);
+ }
+
@Override
public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
if (DEBUG) {
diff --git a/packages/WallpaperBackup/test/AndroidManifest.xml b/packages/WallpaperBackup/test/AndroidManifest.xml
new file mode 100644
index 0000000..44ab1b6
--- /dev/null
+++ b/packages/WallpaperBackup/test/AndroidManifest.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.wallpaperbackup.tests">
+
+ <application android:label="WallpaperBackup Tests">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.wallpaperbackup.tests"
+ android:label="WallpaperBackup Tests"/>
+</manifest>
+
diff --git a/packages/WallpaperBackup/test/AndroidTest.xml b/packages/WallpaperBackup/test/AndroidTest.xml
new file mode 100644
index 0000000..f2e7782
--- /dev/null
+++ b/packages/WallpaperBackup/test/AndroidTest.xml
@@ -0,0 +1,27 @@
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs sample instrumentation test.">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="WallpaperBackupAgentTests.apk" />
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-tag" value="WallpaperBackupAgentTests" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.wallpaperbackup.tests" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/tests/WallpaperBackupAgentTest.java b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/tests/WallpaperBackupAgentTest.java
new file mode 100644
index 0000000..46a7dfe
--- /dev/null
+++ b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/tests/WallpaperBackupAgentTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wallpaperbackup.tests;
+
+import static android.app.WallpaperManager.FLAG_LOCK;
+import static android.app.WallpaperManager.FLAG_SYSTEM;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.WallpaperManager;
+import android.app.backup.FullBackupDataOutput;
+import android.content.SharedPreferences;
+import android.os.UserHandle;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.wallpaperbackup.WallpaperBackupAgent;
+import com.android.wallpaperbackup.utils.ContextWithServiceOverrides;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class WallpaperBackupAgentTest {
+ private static final String SYSTEM_GENERATION = "system_gen";
+ private static final String LOCK_GENERATION = "lock_gen";
+
+ @Mock private FullBackupDataOutput mOutput;
+ @Mock private WallpaperManager mWallpaperManager;
+ @Mock private SharedPreferences mSharedPreferences;
+
+ @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
+
+ private ContextWithServiceOverrides mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = new ContextWithServiceOverrides(ApplicationProvider.getApplicationContext());
+ mContext.injectSystemService(WallpaperManager.class, mWallpaperManager);
+ mContext.setSharedPreferencesOverride(mSharedPreferences);
+ }
+
+ @Test
+ public void testOnFullBackup_withNoChanges_onlyBacksUpEmptyFile() throws IOException {
+ WallpaperBackupAgent wallpaperBackupAgent = new WallpaperBackupAgent();
+ initialiseAgent(wallpaperBackupAgent);
+
+ when(mWallpaperManager.getWallpaperIdForUser(eq(FLAG_SYSTEM), eq(UserHandle.USER_SYSTEM)))
+ .thenReturn(1);
+ when(mWallpaperManager.getWallpaperIdForUser(eq(FLAG_LOCK), eq(UserHandle.USER_SYSTEM)))
+ .thenReturn(1);
+ when(mSharedPreferences.getInt(eq(SYSTEM_GENERATION), eq(-1))).thenReturn(1);
+ when(mSharedPreferences.getInt(eq(LOCK_GENERATION), eq(-1))).thenReturn(1);
+
+ wallpaperBackupAgent.onFullBackup(mOutput);
+
+ verify(mOutput); // Backup of empty file only
+ }
+
+ @Test
+ public void testOnFullBackup_withOnlyChangedSystem_updatesTheSharedPreferences()
+ throws IOException {
+ // Create a system wallpaper file
+ mTemporaryFolder.newFile("wallpaper_orig");
+ // Create stageing file to simulate he wallpaper being ready to back up
+ new File(mContext.getFilesDir(), "wallpaper-stage").createNewFile();
+
+ WallpaperBackupAgent wallpaperBackupAgent =
+ new IsolatedWallpaperBackupAgent(mTemporaryFolder.getRoot());
+ initialiseAgent(wallpaperBackupAgent);
+
+ SharedPreferences.Editor preferenceEditor = mock(SharedPreferences.Editor.class);
+
+ when(mWallpaperManager.getWallpaperIdForUser(eq(FLAG_SYSTEM), eq(UserHandle.USER_SYSTEM)))
+ .thenReturn(2);
+ when(mWallpaperManager.getWallpaperIdForUser(eq(FLAG_LOCK), eq(UserHandle.USER_SYSTEM)))
+ .thenReturn(1);
+ when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_SYSTEM))).thenReturn(true);
+ when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_LOCK))).thenReturn(true);
+ when(mSharedPreferences.getInt(eq(SYSTEM_GENERATION), eq(-1))).thenReturn(1);
+ when(mSharedPreferences.getInt(eq(LOCK_GENERATION), eq(-1))).thenReturn(1);
+ when(mSharedPreferences.edit()).thenReturn(preferenceEditor);
+ when(preferenceEditor.putInt(eq(SYSTEM_GENERATION), eq(2))).thenReturn(preferenceEditor);
+
+ wallpaperBackupAgent.onFullBackup(mOutput);
+
+ verify(preferenceEditor).putInt(eq(SYSTEM_GENERATION), eq(2));
+ }
+
+ private void initialiseAgent(WallpaperBackupAgent agent) {
+ agent.attach(mContext);
+ agent.onCreate();
+ }
+
+ private static class IsolatedWallpaperBackupAgent extends WallpaperBackupAgent {
+ File mWallpaperBaseDirectory;
+ List<File> mBackedUpFiles = new ArrayList();
+
+ IsolatedWallpaperBackupAgent(File wallpaperBaseDirectory) {
+ mWallpaperBaseDirectory = wallpaperBaseDirectory;
+ }
+
+ @Override
+ protected File getWallpaperDir() {
+ return mWallpaperBaseDirectory;
+ }
+
+ @Override
+ protected void backupFile(File file, FullBackupDataOutput data) {
+ mBackedUpFiles.add(file);
+ }
+ }
+}
diff --git a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/utils/ContextWithServiceOverrides.java b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/utils/ContextWithServiceOverrides.java
new file mode 100644
index 0000000..df5d74a
--- /dev/null
+++ b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/utils/ContextWithServiceOverrides.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wallpaperbackup.utils;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.SharedPreferences;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ContextWithServiceOverrides extends ContextWrapper {
+ private static final String TAG = "ContextWithOverrides";
+
+ private Map<String, Object> mInjectedSystemServices = new HashMap<>();
+ private SharedPreferences mSharedPreferencesOverride;
+
+ public ContextWithServiceOverrides(Context base) {
+ super(base);
+ }
+
+ public <S> void injectSystemService(Class<S> cls, S service) {
+ final String name = getSystemServiceName(cls);
+ mInjectedSystemServices.put(name, service);
+ }
+
+ @Override
+ public Context getApplicationContext() {
+ return this;
+ }
+
+ @Override
+ public Object getSystemService(String name) {
+ if (mInjectedSystemServices.containsKey(name)) {
+ return mInjectedSystemServices.get(name);
+ }
+ return super.getSystemService(name);
+ }
+
+ public void setSharedPreferencesOverride(SharedPreferences override) {
+ mSharedPreferencesOverride = override;
+ }
+
+ @Override
+ public SharedPreferences getSharedPreferences(String name, int mode) {
+ return mSharedPreferencesOverride == null
+ ? super.getSharedPreferences(name, mode)
+ : mSharedPreferencesOverride;
+ }
+}