Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1750ca34 authored by Niamh Walsh's avatar Niamh Walsh Committed by Automerger Merge Worker
Browse files

Merge "Add backup logging to WallpaperBackupAgent" into udc-dev am: 002adab4

parents c48c12c8 002adab4
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -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"],
}
+61 −0
Original line number Diff line number Diff line
@@ -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);
    }

    /**
+139 −0
Original line number Diff line number Diff line
/*
 * 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());
        }
    }
}
+15 −0
Original line number Diff line number Diff line
@@ -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"
+17 −0
Original line number Diff line number Diff line
<?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/>
Loading