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

Commit 92837e86 authored by Niamh Walsh's avatar Niamh Walsh
Browse files

Add restore logging to WallpaperBackupAgent

This also includes rewriting some of the tests, since the event logger was made final and we cant mock it any more

Bug: 268471749
Test: atest WallpaperEventLoggerTest WallpaperBackupAgentTest
Change-Id: I411733b24fa1e0d628d1340b36921e37c249bedf
parent 77ea277f
Loading
Loading
Loading
Loading
+33 −1
Original line number Diff line number Diff line
@@ -365,6 +365,11 @@ public class WallpaperBackupAgent extends BackupAgent {
        final int sysWhich = FLAG_SYSTEM | (lockImageStage.exists() ? 0 : FLAG_LOCK);

        try {
            // First parse the live component name so that we know for logging if we care about
            // logging errors with the image restore.
            ComponentName wpService = parseWallpaperComponent(infoStage, "wp");
            mSystemHasLiveComponent = wpService != null;

            // It is valid for the imagery to be absent; it means that we were not permitted
            // to back up the original image on the source device, or there was no user-supplied
            // wallpaper image present.
@@ -372,10 +377,10 @@ public class WallpaperBackupAgent extends BackupAgent {
            restoreFromStage(lockImageStage, infoStage, "kwp", FLAG_LOCK);

            // And reset to the wallpaper service we should be using
            ComponentName wpService = parseWallpaperComponent(infoStage, "wp");
            updateWallpaperComponent(wpService, !lockImageStage.exists());
        } catch (Exception e) {
            Slog.e(TAG, "Unable to restore wallpaper: " + e.getMessage());
            mEventLogger.onRestoreException(e);
        } finally {
            Slog.v(TAG, "Restore finished; clearing backup bookkeeping");
            infoStage.delete();
@@ -399,12 +404,15 @@ public class WallpaperBackupAgent extends BackupAgent {
                // We have a live wallpaper and no static lock image,
                // allow live wallpaper to show "through" on lock screen.
                mWallpaperManager.clear(FLAG_LOCK);
                mEventLogger.onLockLiveWallpaperRestored(wpService);
            }
            mEventLogger.onSystemLiveWallpaperRestored(wpService);
        } else {
            // If we've restored a live wallpaper, but the component doesn't exist,
            // we should log it as an error so we can easily identify the problem
            // in reports from users
            if (wpService != null) {
                // TODO(b/268471749): Handle delayed case
                applyComponentAtInstall(wpService, applyToLock);
                Slog.w(TAG, "Wallpaper service " + wpService + " isn't available. "
                        + " Will try to apply later");
@@ -424,13 +432,37 @@ public class WallpaperBackupAgent extends BackupAgent {
                try (FileInputStream in = new FileInputStream(stage)) {
                    mWallpaperManager.setStream(in, cropHint.isEmpty() ? null : cropHint, true,
                            which);

                    // And log the success
                    if ((which & FLAG_SYSTEM) > 0) {
                        mEventLogger.onSystemImageWallpaperRestored();
                    } else {
                        mEventLogger.onLockImageWallpaperRestored();
                    }
                }
            } else {
                logRestoreError(which, ERROR_NO_METADATA);
            }
        } else {
            Slog.d(TAG, "Restore data doesn't exist for file " + stage.getPath());
            logRestoreErrorIfNoLiveComponent(which, ERROR_NO_WALLPAPER);
        }
    }

    private void logRestoreErrorIfNoLiveComponent(int which, String error) {
        if (mSystemHasLiveComponent) {
            return;
        }
        logRestoreError(which, error);
    }

    private void logRestoreError(int which, String error) {
        if ((which & FLAG_SYSTEM) == FLAG_SYSTEM) {
            mEventLogger.onSystemImageWallpaperRestoreFailed(error);
        } else if ((which & FLAG_LOCK) == FLAG_LOCK) {
            mEventLogger.onLockImageWallpaperRestoreFailed(error);
        }
    }
    private Rect parseCropHint(File wallpaperInfo, String sectionTag) {
        Rect cropHint = new Rect();
        try (FileInputStream stream = new FileInputStream(wallpaperInfo)) {
+68 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.app.backup.BackupManager;
import android.app.backup.BackupRestoreEventLogger;
import android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType;
import android.app.backup.BackupRestoreEventLogger.BackupRestoreError;
import android.content.ComponentName;

import com.android.internal.annotations.VisibleForTesting;

@@ -101,6 +102,39 @@ public class WallpaperEventLogger {
        logBackupFailureInternal(WALLPAPER_LIVE_LOCK, error);
    }

    void onSystemImageWallpaperRestored() {
        logRestoreSuccessInternal(WALLPAPER_IMG_SYSTEM, /* liveComponentWallpaperInfo */ null);
    }

    void onLockImageWallpaperRestored() {
        logRestoreSuccessInternal(WALLPAPER_IMG_LOCK, /* liveComponentWallpaperInfo */ null);
    }

    void onSystemLiveWallpaperRestored(ComponentName wpService) {
        logRestoreSuccessInternal(WALLPAPER_LIVE_SYSTEM, wpService);
    }

    void onLockLiveWallpaperRestored(ComponentName wpService) {
        logRestoreSuccessInternal(WALLPAPER_LIVE_LOCK, wpService);
    }

    void onSystemImageWallpaperRestoreFailed(@BackupRestoreError String error) {
        logRestoreFailureInternal(WALLPAPER_IMG_SYSTEM, error);
    }

    void onLockImageWallpaperRestoreFailed(@BackupRestoreError String error) {
        logRestoreFailureInternal(WALLPAPER_IMG_LOCK, error);
    }

    void onSystemLiveWallpaperRestoreFailed(@BackupRestoreError String error) {
        logRestoreFailureInternal(WALLPAPER_LIVE_SYSTEM, error);
    }

    void onLockLiveWallpaperRestoreFailed(@BackupRestoreError String error) {
        logRestoreFailureInternal(WALLPAPER_LIVE_LOCK, error);
    }



    /**
     * Called when the whole backup flow is interrupted by an exception.
@@ -117,6 +151,20 @@ public class WallpaperEventLogger {
        }
    }

    /**
     * Called when the whole restore flow is interrupted by an exception.
     */
    void onRestoreException(Exception exception) {
        String error = exception.getClass().getName();
        if (!mProcessedDataTypes.contains(WALLPAPER_IMG_SYSTEM) && !mProcessedDataTypes.contains(
                WALLPAPER_LIVE_SYSTEM)) {
            mLogger.logItemsRestoreFailed(WALLPAPER_IMG_SYSTEM, /* count */ 1, error);
        }
        if (!mProcessedDataTypes.contains(WALLPAPER_IMG_LOCK) && !mProcessedDataTypes.contains(
                WALLPAPER_LIVE_LOCK)) {
            mLogger.logItemsRestoreFailed(WALLPAPER_IMG_LOCK, /* count */ 1, error);
        }
    }
    private void logBackupSuccessInternal(@BackupRestoreDataType String which,
            @Nullable WallpaperInfo liveComponentWallpaperInfo) {
        mLogger.logItemsBackedUp(which, /* count */ 1);
@@ -130,10 +178,30 @@ public class WallpaperEventLogger {
        mProcessedDataTypes.add(which);
    }

    private void logRestoreSuccessInternal(@BackupRestoreDataType String which,
            @Nullable ComponentName liveComponentWallpaperInfo) {
        mLogger.logItemsRestored(which, /* count */ 1);
        logRestoredLiveWallpaperNameIfPresent(which, liveComponentWallpaperInfo);
        mProcessedDataTypes.add(which);
    }

    private void logRestoreFailureInternal(@BackupRestoreDataType String which,
            @BackupRestoreError String error) {
        mLogger.logItemsRestoreFailed(which, /* count */ 1, error);
        mProcessedDataTypes.add(which);
    }

    private void logLiveWallpaperNameIfPresent(@BackupRestoreDataType String wallpaperType,
            WallpaperInfo wallpaperInfo) {
        if (wallpaperInfo != null) {
            mLogger.logBackupMetadata(wallpaperType, wallpaperInfo.getComponent().getClassName());
        }
    }

    private void logRestoredLiveWallpaperNameIfPresent(@BackupRestoreDataType String wallpaperType,
            ComponentName wpService) {
        if (wpService != null) {
            mLogger.logRestoreMetadata(wallpaperType, wpService.getClassName());
        }
    }
}
+143 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static com.android.wallpaperbackup.WallpaperBackupAgent.LOCK_WALLPAPER_ST
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_METADATA;
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;
@@ -34,6 +35,8 @@ import static com.android.wallpaperbackup.WallpaperEventLogger.WALLPAPER_LIVE_SY
import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
@@ -55,12 +58,14 @@ import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.service.wallpaper.WallpaperService;
import android.util.Xml;

import androidx.test.InstrumentationRegistry;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.runner.AndroidJUnit4;

import com.android.internal.content.PackageMonitor;
import com.android.modules.utils.TypedXmlSerializer;
import com.android.wallpaperbackup.utils.ContextWithServiceOverrides;

import org.junit.After;
@@ -592,6 +597,123 @@ public class WallpaperBackupAgentTest {
        assertThat(result.getSuccessCount()).isEqualTo(1);
    }

    @Test
    public void testOnRestore_systemWallpaperImgSuccess_logsSuccess() throws Exception {
        mockStagedWallpaperFile(WALLPAPER_INFO_STAGE);
        mockStagedWallpaperFile(SYSTEM_WALLPAPER_STAGE);
        mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
                BackupAnnotations.OperationType.RESTORE);

        mWallpaperBackupAgent.onRestoreFinished();

        DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
                mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
        assertThat(result).isNotNull();
        assertThat(result.getSuccessCount()).isEqualTo(1);
    }

    @Test
    public void testOnRestore_lockWallpaperImgSuccess_logsSuccess() throws Exception {
        mockStagedWallpaperFile(WALLPAPER_INFO_STAGE);
        mockStagedWallpaperFile(LOCK_WALLPAPER_STAGE);
        mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
                BackupAnnotations.OperationType.RESTORE);

        mWallpaperBackupAgent.onRestoreFinished();

        DataTypeResult result = getLoggingResult(WALLPAPER_IMG_LOCK,
                mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
        assertThat(result).isNotNull();
        assertThat(result.getSuccessCount()).isEqualTo(1);
    }

    @Test
    public void testOnRestore_systemWallpaperImgMissingAndNoLive_logsFailure() throws Exception {
        mockStagedWallpaperFile(WALLPAPER_INFO_STAGE);
        mockStagedWallpaperFile(LOCK_WALLPAPER_STAGE);
        mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
                BackupAnnotations.OperationType.RESTORE);

        mWallpaperBackupAgent.onRestoreFinished();

        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 testOnRestore_lockWallpaperImgMissingAndNoLive_logsFailure() throws Exception {
        mockStagedWallpaperFile(WALLPAPER_INFO_STAGE);
        mockStagedWallpaperFile(SYSTEM_WALLPAPER_STAGE);
        mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
                BackupAnnotations.OperationType.RESTORE);

        mWallpaperBackupAgent.onRestoreFinished();

        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 testOnRestore_wallpaperInfoMissing_logsFailure() throws Exception {
        mockStagedWallpaperFile(SYSTEM_WALLPAPER_STAGE);
        mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
                BackupAnnotations.OperationType.RESTORE);

        mWallpaperBackupAgent.onRestoreFinished();

        DataTypeResult result = getLoggingResult(WALLPAPER_IMG_SYSTEM,
                mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
        assertThat(result).isNotNull();
        assertThat(result.getFailCount()).isEqualTo(1);
        assertThat(result.getErrors()).containsKey(ERROR_NO_METADATA);
    }

    @Test
    public void testOnRestore_imgMissingButWallpaperInfoHasLive_doesNotLogImg() throws Exception {
        mockRestoredLiveWallpaperFile();
        mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
                BackupAnnotations.OperationType.RESTORE);

        mWallpaperBackupAgent.onRestoreFinished();

        DataTypeResult system = getLoggingResult(WALLPAPER_IMG_SYSTEM,
                mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
        DataTypeResult lock = getLoggingResult(WALLPAPER_IMG_LOCK,
                mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
        assertThat(system).isNull();
        assertThat(lock).isNull();
    }

    @Test
    public void testOnRestore_throwsException_logsErrors() throws Exception {
        when(mWallpaperManager.setStream(any(), any(), anyBoolean(), anyInt())).thenThrow(
                new RuntimeException());
        mockStagedWallpaperFile(SYSTEM_WALLPAPER_STAGE);
        mockStagedWallpaperFile(WALLPAPER_INFO_STAGE);
        mWallpaperBackupAgent.onCreate(USER_HANDLE, BackupAnnotations.BackupDestination.CLOUD,
                BackupAnnotations.OperationType.RESTORE);

        mWallpaperBackupAgent.onRestoreFinished();

        DataTypeResult system = getLoggingResult(WALLPAPER_IMG_SYSTEM,
                mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
        DataTypeResult lock = getLoggingResult(WALLPAPER_IMG_LOCK,
                mWallpaperBackupAgent.getBackupRestoreEventLogger().getLoggingResults());
        assertThat(system).isNotNull();
        assertThat(system.getFailCount()).isEqualTo(1);
        assertThat(system.getErrors()).containsKey(RuntimeException.class.getName());
        assertThat(lock).isNotNull();
        assertThat(lock.getFailCount()).isEqualTo(1);
        assertThat(lock.getErrors()).containsKey(RuntimeException.class.getName());
    }

    private void mockCurrentWallpaperIds(int systemWallpaperId, int lockWallpaperId) {
        when(mWallpaperManager.getWallpaperId(eq(FLAG_SYSTEM))).thenReturn(systemWallpaperId);
        when(mWallpaperManager.getWallpaperId(eq(FLAG_LOCK))).thenReturn(lockWallpaperId);
@@ -636,6 +758,27 @@ public class WallpaperBackupAgentTest {
                ParcelFileDescriptor.open(fakeLockWallpaperFile, MODE_READ_ONLY));
    }

    private void mockStagedWallpaperFile(String location) throws Exception {
        File wallpaperFile = new File(mContext.getFilesDir(), location);
        wallpaperFile.createNewFile();
    }

    private void mockRestoredLiveWallpaperFile() throws Exception {
        File wallpaperFile = new File(mContext.getFilesDir(), WALLPAPER_INFO_STAGE);
        wallpaperFile.createNewFile();
        FileOutputStream fstream = new FileOutputStream(wallpaperFile, false);
        TypedXmlSerializer out = Xml.resolveSerializer(fstream);
        out.startDocument(null, true);
        out.startTag(null, "wp");
        out.attribute(null, "component",
                getFakeWallpaperInfo().getComponent().flattenToShortString());
        out.endTag(null, "wp");
        out.endDocument();
        fstream.flush();
        FileUtils.sync(fstream);
        fstream.close();
    }

    private WallpaperInfo getFakeWallpaperInfo() throws Exception {
        Context context = InstrumentationRegistry.getTargetContext();
        Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
+253 −34

File changed.

Preview size limit exceeded, changes collapsed.