Merge "Add backup logging to WallpaperBackupAgent" into udc-dev

This commit is contained in:
Niamh Walsh
2023-03-22 16:31:03 +00:00
committed by Android (Google) Code Review
8 changed files with 708 additions and 13 deletions

View File

@@ -42,7 +42,7 @@ android_test {
srcs: [
// Include the app source code because the app runs as the system user on-device.
"src/**/*.java",
"test/src/**/*.java"
"test/src/**/*.java",
],
libs: [
"android.test.base",
@@ -54,7 +54,8 @@ android_test {
"mockito-target-minus-junit4",
"truth-prebuilt",
],
resource_dirs: ["test/res"],
certificate: "platform",
platform_apis: true,
test_suites: ["device-tests"]
test_suites: ["device-tests"],
}

View File

@@ -19,11 +19,18 @@ package com.android.wallpaperbackup;
import static android.app.WallpaperManager.FLAG_LOCK;
import static android.app.WallpaperManager.FLAG_SYSTEM;
import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_INELIGIBLE;
import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_NO_METADATA;
import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_NO_WALLPAPER;
import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_QUOTA_EXCEEDED;
import android.app.AppGlobals;
import android.app.WallpaperManager;
import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupManager;
import android.app.backup.BackupRestoreEventLogger.BackupRestoreError;
import android.app.backup.FullBackupDataOutput;
import android.content.ComponentName;
import android.content.Context;
@@ -103,6 +110,10 @@ public class WallpaperBackupAgent extends BackupAgent {
private boolean mQuotaExceeded;
private WallpaperManager mWallpaperManager;
private WallpaperEventLogger mEventLogger;
private boolean mSystemHasLiveComponent;
private boolean mLockHasLiveComponent;
@Override
public void onCreate() {
@@ -117,6 +128,9 @@ public class WallpaperBackupAgent extends BackupAgent {
if (DEBUG) {
Slog.v(TAG, "quota file " + mQuotaFile.getPath() + " exists=" + mQuotaExceeded);
}
BackupManager backupManager = new BackupManager(getApplicationContext());
mEventLogger = new WallpaperEventLogger(backupManager, /* wallpaperAgent */ this);
}
@Override
@@ -149,11 +163,18 @@ public class WallpaperBackupAgent extends BackupAgent {
Slog.v(TAG, "lockGen=" + lockGeneration + " : lockChanged=" + lockChanged);
}
// Due to the way image vs live wallpaper backup logic is intermingled, for logging
// purposes first check if we have live components for each wallpaper to avoid
// over-reporting errors.
mSystemHasLiveComponent = mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM) != null;
mLockHasLiveComponent = mWallpaperManager.getWallpaperInfo(FLAG_LOCK) != null;
backupWallpaperInfoFile(/* sysOrLockChanged= */ sysChanged || lockChanged, data);
backupSystemWallpaperFile(sharedPrefs, sysChanged, sysGeneration, data);
backupLockWallpaperFileIfItExists(sharedPrefs, lockChanged, lockGeneration, data);
} catch (Exception e) {
Slog.e(TAG, "Unable to back up wallpaper", e);
mEventLogger.onBackupException(e);
} finally {
// Even if this time we had to back off on attempting to store the lock image
// due to exceeding the data quota, try again next time. This will alternate
@@ -170,6 +191,14 @@ public class WallpaperBackupAgent extends BackupAgent {
if (wallpaperInfoFd == null) {
Slog.w(TAG, "Wallpaper metadata file doesn't exist");
// If we have live components, getting the file to back up somehow failed, so log it
// as an error.
if (mSystemHasLiveComponent) {
mEventLogger.onSystemLiveWallpaperBackupFailed(ERROR_NO_METADATA);
}
if (mLockHasLiveComponent) {
mEventLogger.onLockLiveWallpaperBackupFailed(ERROR_NO_METADATA);
}
return;
}
@@ -182,12 +211,22 @@ public class WallpaperBackupAgent extends BackupAgent {
if (DEBUG) Slog.v(TAG, "Storing wallpaper metadata");
backupFile(infoStage, data);
// We've backed up the info file which contains the live component, so log it as success
if (mSystemHasLiveComponent) {
mEventLogger.onSystemLiveWallpaperBackedUp(
mWallpaperManager.getWallpaperInfo(FLAG_SYSTEM));
}
if (mLockHasLiveComponent) {
mEventLogger.onLockLiveWallpaperBackedUp(mWallpaperManager.getWallpaperInfo(FLAG_LOCK));
}
}
private void backupSystemWallpaperFile(SharedPreferences sharedPrefs,
boolean sysChanged, int sysGeneration, FullBackupDataOutput data) throws IOException {
if (!mWallpaperManager.isWallpaperBackupEligible(FLAG_SYSTEM)) {
Slog.d(TAG, "System wallpaper ineligible for backup");
logSystemImageErrorIfNoLiveComponent(ERROR_INELIGIBLE);
return;
}
@@ -197,6 +236,7 @@ public class WallpaperBackupAgent extends BackupAgent {
if (systemWallpaperImageFd == null) {
Slog.w(TAG, "System wallpaper doesn't exist");
logSystemImageErrorIfNoLiveComponent(ERROR_NO_WALLPAPER);
return;
}
@@ -210,8 +250,17 @@ public class WallpaperBackupAgent extends BackupAgent {
if (DEBUG) Slog.v(TAG, "Storing system wallpaper image");
backupFile(imageStage, data);
sharedPrefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply();
mEventLogger.onSystemImageWallpaperBackedUp();
}
private void logSystemImageErrorIfNoLiveComponent(@BackupRestoreError String error) {
if (mSystemHasLiveComponent) {
return;
}
mEventLogger.onSystemImageWallpaperBackupFailed(error);
}
private void backupLockWallpaperFileIfItExists(SharedPreferences sharedPrefs,
boolean lockChanged, int lockGeneration, FullBackupDataOutput data) throws IOException {
final File lockImageStage = new File(getFilesDir(), LOCK_WALLPAPER_STAGE);
@@ -224,11 +273,13 @@ public class WallpaperBackupAgent extends BackupAgent {
}
Slog.d(TAG, "No lockscreen wallpaper set, add nothing to backup");
sharedPrefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
logLockImageErrorIfNoLiveComponent(ERROR_NO_WALLPAPER);
return;
}
if (!mWallpaperManager.isWallpaperBackupEligible(FLAG_LOCK)) {
Slog.d(TAG, "Lock screen wallpaper ineligible for backup");
logLockImageErrorIfNoLiveComponent(ERROR_INELIGIBLE);
return;
}
@@ -239,11 +290,13 @@ public class WallpaperBackupAgent extends BackupAgent {
// set, but we can't find it.
if (lockWallpaperFd == null) {
Slog.w(TAG, "Lock wallpaper doesn't exist");
logLockImageErrorIfNoLiveComponent(ERROR_NO_WALLPAPER);
return;
}
if (mQuotaExceeded) {
Slog.w(TAG, "Not backing up lock screen wallpaper. Quota was exceeded last time");
logLockImageErrorIfNoLiveComponent(ERROR_QUOTA_EXCEEDED);
return;
}
@@ -255,6 +308,14 @@ public class WallpaperBackupAgent extends BackupAgent {
if (DEBUG) Slog.v(TAG, "Storing lock wallpaper image");
backupFile(lockImageStage, data);
sharedPrefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
mEventLogger.onLockImageWallpaperBackedUp();
}
private void logLockImageErrorIfNoLiveComponent(@BackupRestoreError String error) {
if (mLockHasLiveComponent) {
return;
}
mEventLogger.onLockImageWallpaperBackupFailed(error);
}
/**

View File

@@ -0,0 +1,139 @@
/*
* Copyright (C) 2023 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;
import android.annotation.Nullable;
import android.app.WallpaperInfo;
import android.app.backup.BackupManager;
import android.app.backup.BackupRestoreEventLogger;
import android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType;
import android.app.backup.BackupRestoreEventLogger.BackupRestoreError;
import com.android.internal.annotations.VisibleForTesting;
import java.util.HashSet;
import java.util.Set;
/**
* Log backup / restore related events using {@link BackupRestoreEventLogger}.
*/
public class WallpaperEventLogger {
/* Static image used as system (or home) screen wallpaper */
@BackupRestoreDataType
@VisibleForTesting
static final String WALLPAPER_IMG_SYSTEM = "wlp_img_system";
/* Static image used as lock screen wallpaper */
@BackupRestoreDataType
@VisibleForTesting
static final String WALLPAPER_IMG_LOCK = "wlp_img_lock";
/* Live component used as system (or home) screen wallpaper */
@BackupRestoreDataType
@VisibleForTesting
static final String WALLPAPER_LIVE_SYSTEM = "wlp_live_system";
/* Live component used as lock screen wallpaper */
@BackupRestoreDataType
@VisibleForTesting
static final String WALLPAPER_LIVE_LOCK = "wlp_live_lock";
@BackupRestoreError
static final String ERROR_INELIGIBLE = "ineligible";
@BackupRestoreError
static final String ERROR_NO_METADATA = "no_metadata";
@BackupRestoreError
static final String ERROR_NO_WALLPAPER = "no_wallpaper";
@BackupRestoreError
static final String ERROR_QUOTA_EXCEEDED = "quota_exceeded";
private final BackupRestoreEventLogger mLogger;
private final Set<String> mProcessedDataTypes = new HashSet<>();
WallpaperEventLogger(BackupManager backupManager, WallpaperBackupAgent wallpaperAgent) {
mLogger = backupManager.getBackupRestoreEventLogger(/* backupAgent */ wallpaperAgent);
}
void onSystemImageWallpaperBackedUp() {
logBackupSuccessInternal(WALLPAPER_IMG_SYSTEM, /* liveComponentWallpaperInfo */ null);
}
void onLockImageWallpaperBackedUp() {
logBackupSuccessInternal(WALLPAPER_IMG_LOCK, /* liveComponentWallpaperInfo */ null);
}
void onSystemLiveWallpaperBackedUp(WallpaperInfo wallpaperInfo) {
logBackupSuccessInternal(WALLPAPER_LIVE_SYSTEM, wallpaperInfo);
}
void onLockLiveWallpaperBackedUp(WallpaperInfo wallpaperInfo) {
logBackupSuccessInternal(WALLPAPER_LIVE_LOCK, wallpaperInfo);
}
void onSystemImageWallpaperBackupFailed(@BackupRestoreError String error) {
logBackupFailureInternal(WALLPAPER_IMG_SYSTEM, error);
}
void onLockImageWallpaperBackupFailed(@BackupRestoreError String error) {
logBackupFailureInternal(WALLPAPER_IMG_LOCK, error);
}
void onSystemLiveWallpaperBackupFailed(@BackupRestoreError String error) {
logBackupFailureInternal(WALLPAPER_LIVE_SYSTEM, error);
}
void onLockLiveWallpaperBackupFailed(@BackupRestoreError String error) {
logBackupFailureInternal(WALLPAPER_LIVE_LOCK, error);
}
/**
* Called when the whole backup flow is interrupted by an exception.
*/
void onBackupException(Exception exception) {
String error = exception.getClass().getName();
if (!mProcessedDataTypes.contains(WALLPAPER_IMG_SYSTEM) && !mProcessedDataTypes.contains(
WALLPAPER_LIVE_SYSTEM)) {
mLogger.logItemsBackupFailed(WALLPAPER_IMG_SYSTEM, /* count */ 1, error);
}
if (!mProcessedDataTypes.contains(WALLPAPER_IMG_LOCK) && !mProcessedDataTypes.contains(
WALLPAPER_LIVE_LOCK)) {
mLogger.logItemsBackupFailed(WALLPAPER_IMG_LOCK, /* count */ 1, error);
}
}
private void logBackupSuccessInternal(@BackupRestoreDataType String which,
@Nullable WallpaperInfo liveComponentWallpaperInfo) {
mLogger.logItemsBackedUp(which, /* count */ 1);
logLiveWallpaperNameIfPresent(which, liveComponentWallpaperInfo);
mProcessedDataTypes.add(which);
}
private void logBackupFailureInternal(@BackupRestoreDataType String which,
@BackupRestoreError String error) {
mLogger.logItemsBackupFailed(which, /* count */ 1, error);
mProcessedDataTypes.add(which);
}
private void logLiveWallpaperNameIfPresent(@BackupRestoreDataType String wallpaperType,
WallpaperInfo wallpaperInfo) {
if (wallpaperInfo != null) {
mLogger.logBackupMetadata(wallpaperType, wallpaperInfo.getComponent().getClassName());
}
}
}

View File

@@ -4,6 +4,21 @@
<application android:label="WallpaperBackup Tests">
<uses-library android:name="android.test.runner" />
<service android:name="com.android.wallpaperbackup.utils.TestWallpaperService"
android:enabled="true"
android:directBootAware="true"
android:label="Test wallpaper"
android:permission="android.permission.BIND_WALLPAPER"
android:exported="true">
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService"/>
</intent-filter>
<!-- Link to XML that defines the wallpaper info. -->
<meta-data android:name="android.service.wallpaper"
android:resource="@xml/livewallpaper"/>
</service>
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2023 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
-->
<wallpaper/>

View File

@@ -23,22 +23,40 @@ import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
import static com.android.wallpaperbackup.WallpaperBackupAgent.LOCK_WALLPAPER_STAGE;
import static com.android.wallpaperbackup.WallpaperBackupAgent.SYSTEM_WALLPAPER_STAGE;
import static com.android.wallpaperbackup.WallpaperBackupAgent.WALLPAPER_INFO_STAGE;
import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_INELIGIBLE;
import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_NO_WALLPAPER;
import static com.android.wallpaperbackup.WallpaperEventLogger.ERROR_QUOTA_EXCEEDED;
import static com.android.wallpaperbackup.WallpaperEventLogger.WALLPAPER_IMG_LOCK;
import static com.android.wallpaperbackup.WallpaperEventLogger.WALLPAPER_IMG_SYSTEM;
import static com.android.wallpaperbackup.WallpaperEventLogger.WALLPAPER_LIVE_LOCK;
import static com.android.wallpaperbackup.WallpaperEventLogger.WALLPAPER_LIVE_SYSTEM;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.WallpaperInfo;
import android.app.WallpaperManager;
import android.app.backup.BackupAnnotations;
import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
import android.app.backup.FullBackupDataOutput;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.service.wallpaper.WallpaperService;
import androidx.test.InstrumentationRegistry;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.runner.AndroidJUnit4;
@@ -69,12 +87,18 @@ public class WallpaperBackupAgentTest {
private static final int TEST_SYSTEM_WALLPAPER_ID = 1;
private static final int TEST_LOCK_WALLPAPER_ID = 2;
private static final int NO_LOCK_WALLPAPER_ID = -1;
// An arbitrary user.
private static final UserHandle USER_HANDLE = new UserHandle(15);
@Mock private FullBackupDataOutput mOutput;
@Mock private WallpaperManager mWallpaperManager;
@Mock private Context mMockContext;
@Mock
private FullBackupDataOutput mOutput;
@Mock
private WallpaperManager mWallpaperManager;
@Mock
private Context mMockContext;
@Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
@Rule
public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
private ContextWithServiceOverrides mContext;
private IsolatedWallpaperBackupAgent mWallpaperBackupAgent;
@@ -90,9 +114,10 @@ public class WallpaperBackupAgentTest {
mContext = new ContextWithServiceOverrides(ApplicationProvider.getApplicationContext());
mContext.injectSystemService(WallpaperManager.class, mWallpaperManager);
mWallpaperBackupAgent = new IsolatedWallpaperBackupAgent(mTemporaryFolder.getRoot());
mWallpaperBackupAgent = new IsolatedWallpaperBackupAgent();
mWallpaperBackupAgent.attach(mContext);
mWallpaperBackupAgent.onCreate();
mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
BackupAnnotations.OperationType.BACKUP);
mWallpaperComponent = new ComponentName(TEST_WALLPAPER_PACKAGE, "");
}
@@ -388,6 +413,185 @@ public class WallpaperBackupAgentTest {
verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK));
}
@Test
public void testOnFullBackup_systemWallpaperImgSuccess_logsSuccess() throws Exception {
mockSystemWallpaperFileWithContents("system wallpaper");
mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, NO_LOCK_WALLPAPER_ID);
mWallpaperBackupAgent.onFullBackup(mOutput);
DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
assertThat(result).isNotNull();
assertThat(result.getSuccessCount()).isEqualTo(1);
}
@Test
public void testOnFullBackup_systemWallpaperImgIneligible_logsFailure() throws Exception {
when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_SYSTEM))).thenReturn(false);
mockSystemWallpaperFileWithContents("system wallpaper");
mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
mWallpaperBackupAgent.onFullBackup(mOutput);
DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
assertThat(result).isNotNull();
assertThat(result.getFailCount()).isEqualTo(1);
assertThat(result.getErrors()).containsKey(ERROR_INELIGIBLE);
}
@Test
public void testOnFullBackup_systemWallpaperImgMissing_logsFailure() throws Exception {
mWallpaperBackupAgent.onFullBackup(mOutput);
DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
assertThat(result).isNotNull();
assertThat(result.getFailCount()).isEqualTo(1);
assertThat(result.getErrors()).containsKey(ERROR_NO_WALLPAPER);
}
@Test
public void testOnFullBackup_systemWallpaperImgMissingButHasLiveComponent_logsLiveSuccess()
throws Exception {
mockWallpaperInfoFileWithContents("info file");
when(mWallpaperManager.getWallpaperInfo(anyInt())).thenReturn(getFakeWallpaperInfo());
mWallpaperBackupAgent.onFullBackup(mOutput);
DataTypeResult result = getLoggingResult(WALLPAPER_LIVE_SYSTEM,
mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
assertThat(result).isNotNull();
assertThat(result.getSuccessCount()).isEqualTo(1);
assertThat(result.getMetadataHash()).isNotNull();
}
@Test
public void testOnFullBackup_systemWallpaperImgMissingButHasLiveComponent_logsNothingForImg()
throws Exception {
mockWallpaperInfoFileWithContents("info file");
when(mWallpaperManager.getWallpaperInfo(anyInt())).thenReturn(getFakeWallpaperInfo());
mWallpaperBackupAgent.onFullBackup(mOutput);
DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
assertThat(result).isNull();
}
@Test
public void testOnFullBackup_lockWallpaperImgSuccess_logsSuccess() throws Exception {
mockLockWallpaperFileWithContents("lock wallpaper");
mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
mWallpaperBackupAgent.onFullBackup(mOutput);
DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
assertThat(result).isNotNull();
assertThat(result.getSuccessCount()).isEqualTo(1);
}
@Test
public void testOnFullBackup_lockWallpaperImgIneligible_logsFailure() throws Exception {
when(mWallpaperManager.isWallpaperBackupEligible(eq(FLAG_LOCK))).thenReturn(false);
mockLockWallpaperFileWithContents("lock wallpaper");
mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
mWallpaperBackupAgent.onFullBackup(mOutput);
DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
assertThat(result).isNotNull();
assertThat(result.getFailCount()).isEqualTo(1);
assertThat(result.getErrors()).containsKey(ERROR_INELIGIBLE);
}
@Test
public void testOnFullBackup_lockWallpaperImgMissing_logsFailure() throws Exception {
mWallpaperBackupAgent.onFullBackup(mOutput);
DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
assertThat(result).isNotNull();
assertThat(result.getFailCount()).isEqualTo(1);
assertThat(result.getErrors()).containsKey(ERROR_NO_WALLPAPER);
}
@Test
public void testOnFullBackup_lockWallpaperImgMissingButHasLiveComponent_logsLiveSuccess()
throws Exception {
mockWallpaperInfoFileWithContents("info file");
when(mWallpaperManager.getWallpaperInfo(anyInt())).thenReturn(getFakeWallpaperInfo());
mWallpaperBackupAgent.onFullBackup(mOutput);
DataTypeResult result = getLoggingResult(WALLPAPER_LIVE_LOCK,
mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
assertThat(result).isNotNull();
assertThat(result.getSuccessCount()).isEqualTo(1);
assertThat(result.getMetadataHash()).isNotNull();
}
@Test
public void testOnFullBackup_lockWallpaperImgMissingButHasLiveComponent_logsNothingForImg()
throws Exception {
mockWallpaperInfoFileWithContents("info file");
when(mWallpaperManager.getWallpaperInfo(anyInt())).thenReturn(getFakeWallpaperInfo());
mWallpaperBackupAgent.onFullBackup(mOutput);
DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
assertThat(result).isNull();
}
@Test
public void testOnFullBackup_exceptionThrown_logsException() throws Exception {
when(mWallpaperManager.isWallpaperBackupEligible(anyInt())).thenThrow(
new RuntimeException());
mWallpaperBackupAgent.onFullBackup(mOutput);
DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
assertThat(result).isNotNull();
assertThat(result.getFailCount()).isEqualTo(1);
assertThat(result.getErrors()).containsKey(RuntimeException.class.getName());
}
@Test
public void testOnFullBackup_lastBackupOverQuota_logsLockFailure() throws Exception {
mockSystemWallpaperFileWithContents("system wallpaper");
mockLockWallpaperFileWithContents("lock wallpaper");
mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
markAgentAsOverQuota();
mWallpaperBackupAgent.onFullBackup(mOutput);
DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
assertThat(result).isNotNull();
assertThat(result.getFailCount()).isEqualTo(1);
assertThat(result.getErrors()).containsKey(ERROR_QUOTA_EXCEEDED);
}
@Test
public void testOnFullBackup_lastBackupOverQuota_logsSystemSuccess() throws Exception {
mockSystemWallpaperFileWithContents("system wallpaper");
mockLockWallpaperFileWithContents("lock wallpaper");
mockCurrentWallpaperIds(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
markAgentAsOverQuota();
mWallpaperBackupAgent.onFullBackup(mOutput);
DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
assertThat(result).isNotNull();
assertThat(result.getSuccessCount()).isEqualTo(1);
}
private void mockCurrentWallpaperIds(int systemWallpaperId, int lockWallpaperId) {
when(mWallpaperManager.getWallpaperId(eq(FLAG_SYSTEM))).thenReturn(systemWallpaperId);
when(mWallpaperManager.getWallpaperId(eq(FLAG_LOCK))).thenReturn(lockWallpaperId);
@@ -432,16 +636,41 @@ public class WallpaperBackupAgentTest {
ParcelFileDescriptor.open(fakeLockWallpaperFile, MODE_READ_ONLY));
}
private WallpaperInfo getFakeWallpaperInfo() throws Exception {
Context context = InstrumentationRegistry.getTargetContext();
Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
intent.setPackage("com.android.wallpaperbackup.tests");
PackageManager pm = context.getPackageManager();
List<ResolveInfo> result = pm.queryIntentServices(intent, PackageManager.GET_META_DATA);
assertEquals(1, result.size());
ResolveInfo info = result.get(0);
return new WallpaperInfo(context, info);
}
private void markAgentAsOverQuota() throws Exception {
// Create over quota file to indicate the last backup was over quota
File quotaFile = new File(mContext.getFilesDir(), WallpaperBackupAgent.QUOTA_SENTINEL);
quotaFile.createNewFile();
// Now redo the setup of the agent to pick up the over quota
mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
BackupAnnotations.OperationType.BACKUP);
}
private static DataTypeResult getLoggingResult(String dataType, List<DataTypeResult> results) {
for (DataTypeResult result : results) {
if ((result.getDataType()).equals(dataType)) {
return result;
}
}
return null;
}
private class IsolatedWallpaperBackupAgent extends WallpaperBackupAgent {
File mWallpaperBaseDirectory;
List<File> mBackedUpFiles = new ArrayList<>();
PackageMonitor mWallpaperPackageMonitor;
boolean mIsDeviceInRestore = false;
IsolatedWallpaperBackupAgent(File wallpaperBaseDirectory) {
mWallpaperBaseDirectory = wallpaperBaseDirectory;
}
@Override
protected void backupFile(File file, FullBackupDataOutput data) {
mBackedUpFiles.add(file);

View File

@@ -0,0 +1,204 @@
/*
* Copyright (C) 2023 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;
import static com.android.wallpaperbackup.WallpaperEventLogger.WALLPAPER_IMG_LOCK;
import static com.android.wallpaperbackup.WallpaperEventLogger.WALLPAPER_IMG_SYSTEM;
import static com.android.wallpaperbackup.WallpaperEventLogger.WALLPAPER_LIVE_LOCK;
import static com.android.wallpaperbackup.WallpaperEventLogger.WALLPAPER_LIVE_SYSTEM;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.WallpaperInfo;
import android.app.backup.BackupManager;
import android.app.backup.BackupRestoreEventLogger;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.service.wallpaper.WallpaperService;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.wallpaperbackup.utils.TestWallpaperService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class WallpaperEventLoggerTest {
@Mock
private BackupRestoreEventLogger mMockLogger;
@Mock
private BackupManager mMockBackupManager;
@Mock
private WallpaperBackupAgent mMockBackupAgent;
private static final String WALLPAPER_ERROR = "some_error";
private WallpaperEventLogger mWallpaperEventLogger;
private WallpaperInfo mWallpaperInfo;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mMockBackupAgent.getBackupRestoreEventLogger()).thenReturn(mMockLogger);
when(mMockBackupManager.getBackupRestoreEventLogger(any())).thenReturn(mMockLogger);
mWallpaperInfo = getWallpaperInfo();
mWallpaperEventLogger = new WallpaperEventLogger(mMockBackupManager, mMockBackupAgent);
}
@Test
public void onSystemImgWallpaperBackedUp_logsSuccess() {
mWallpaperEventLogger.onSystemImageWallpaperBackedUp();
verify(mMockLogger).logItemsBackedUp(eq(WALLPAPER_IMG_SYSTEM), eq(1));
}
@Test
public void onLockImgWallpaperBackedUp_logsSuccess() {
mWallpaperEventLogger.onLockImageWallpaperBackedUp();
verify(mMockLogger).logItemsBackedUp(eq(WALLPAPER_IMG_LOCK), eq(1));
}
@Test
public void onSystemLiveWallpaperBackedUp_logsSuccess() {
mWallpaperEventLogger.onSystemLiveWallpaperBackedUp(mWallpaperInfo);
verify(mMockLogger).logItemsBackedUp(eq(WALLPAPER_LIVE_SYSTEM), eq(1));
}
@Test
public void onLockLiveWallpaperBackedUp_logsSuccess() {
mWallpaperEventLogger.onLockLiveWallpaperBackedUp(mWallpaperInfo);
verify(mMockLogger).logItemsBackedUp(eq(WALLPAPER_LIVE_LOCK), eq(1));
}
@Test
public void onImgWallpaperBackedUp_nullInfo_doesNotLogMetadata() {
mWallpaperEventLogger.onSystemImageWallpaperBackedUp();
verify(mMockLogger, never()).logBackupMetadata(eq(WALLPAPER_IMG_SYSTEM), anyString());
}
@Test
public void onLiveWallpaperBackedUp_logsMetadata() {
mWallpaperEventLogger.onSystemLiveWallpaperBackedUp(mWallpaperInfo);
verify(mMockLogger).logBackupMetadata(eq(WALLPAPER_LIVE_SYSTEM),
eq(TestWallpaperService.class.getName()));
}
@Test
public void onSystemImgWallpaperBackupFailed_logsFail() {
mWallpaperEventLogger.onSystemImageWallpaperBackupFailed(WALLPAPER_ERROR);
verify(mMockLogger).logItemsBackupFailed(eq(WALLPAPER_IMG_SYSTEM), eq(1),
eq(WALLPAPER_ERROR));
}
@Test
public void onLockImgWallpaperBackupFailed_logsFail() {
mWallpaperEventLogger.onLockImageWallpaperBackupFailed(WALLPAPER_ERROR);
verify(mMockLogger).logItemsBackupFailed(eq(WALLPAPER_IMG_LOCK), eq(1),
eq(WALLPAPER_ERROR));
}
@Test
public void onSystemLiveWallpaperBackupFailed_logsFail() {
mWallpaperEventLogger.onSystemLiveWallpaperBackupFailed(WALLPAPER_ERROR);
verify(mMockLogger).logItemsBackupFailed(eq(WALLPAPER_LIVE_SYSTEM), eq(1),
eq(WALLPAPER_ERROR));
}
@Test
public void onLockLiveWallpaperBackupFailed_logsFail() {
mWallpaperEventLogger.onLockLiveWallpaperBackupFailed(WALLPAPER_ERROR);
verify(mMockLogger).logItemsBackupFailed(eq(WALLPAPER_LIVE_LOCK), eq(1),
eq(WALLPAPER_ERROR));
}
@Test
public void onWallpaperBackupException_someProcessed_doesNotLogErrorForProcessedType() {
mWallpaperEventLogger.onSystemImageWallpaperBackedUp();
mWallpaperEventLogger.onBackupException(new Exception());
verify(mMockLogger, never()).logItemsBackupFailed(eq(WALLPAPER_IMG_SYSTEM), anyInt(),
anyString());
}
@Test
public void onWallpaperBackupException_someProcessed_logsErrorForUnprocessedType() {
mWallpaperEventLogger.onSystemImageWallpaperBackedUp();
mWallpaperEventLogger.onBackupException(new Exception());
verify(mMockLogger).logItemsBackupFailed(eq(WALLPAPER_IMG_LOCK), eq(1),
eq(Exception.class.getName()));
}
@Test
public void onWallpaperBackupException_liveTypeProcessed_doesNotLogErrorForSameImgType() {
mWallpaperEventLogger.onSystemLiveWallpaperBackedUp(mWallpaperInfo);
mWallpaperEventLogger.onBackupException(new Exception());
verify(mMockLogger, never()).logItemsBackupFailed(eq(WALLPAPER_IMG_SYSTEM), anyInt(),
anyString());
}
private WallpaperInfo getWallpaperInfo() throws Exception {
Context context = InstrumentationRegistry.getTargetContext();
Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
intent.setPackage("com.android.wallpaperbackup.tests");
PackageManager pm = context.getPackageManager();
List<ResolveInfo> result = pm.queryIntentServices(intent, PackageManager.GET_META_DATA);
assertEquals(1, result.size());
ResolveInfo info = result.get(0);
return new WallpaperInfo(context, info);
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2023 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.service.wallpaper.WallpaperService;
/**
* Empty wallpaper service used for wallpaper backup tests
*/
public class TestWallpaperService extends WallpaperService {
@Override
public Engine onCreateEngine() {
return new Engine();
}
}