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

Commit a48c085e authored by [CSarp Misoglu's avatar [CSarp Misoglu Committed by Sarp Misoglu
Browse files

Support wallpaper backup for non-system users

Wallpaper backup happens through a separate package 'com.android.wallpaperbackup' which shares the system uid. For the system user, WallpaperBackupAgent copies the wallpaper files from /data/system/users/0 and backs them up (explained more in the javadoc of WallpaperBackupAgent). However, for non-system users it will run in the non-system user's 'system' process and it doesn't have access to /data/system.

As a workaround, this CL uses WallpaperManager APIs to access the files rather than directly reading them.

I decided not to keep the old way of backing up for the system user in WallpaperBackupAgent. Instead all users use the APIs now. There is a small amount of risk with this approach since we change the mechanism for backups for the system user as well but the new approach is arguably more correct than reading system data directories directly.

Also, I've refactored WallpaperBackupAgent's backup flow to be more readable. The functionality (and the ordering of logic) should be exactly the same as before, except for using the APIs instead of reading files directly.

The restore side remains untouched. The backup bytes that are stored in the cloud or transferred by cable are exactly the same as before, so there shouldn't be any backwards compatibility issues.

Bug: 259848850
Test: atest WallpaperBackupAgentTest.java
  atest WallpaperManagerServiceTests.java
  Manual testing by backing up and restoring static/live wallpaper between two devices.
Change-Id: I9f825da4adc8f9dcd69abe6c99056df6e54cceb2
parent c6346aa1
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -177,6 +177,11 @@ final class DisabledWallpaperManager extends WallpaperManager {
        return unsupported();
    }

    @Override
    public ParcelFileDescriptor getWallpaperFile(int which, boolean getCropped) {
        return unsupported();
    }

    @Override
    public void forgetLoadedWallpaper() {
        unsupported();
@@ -187,6 +192,11 @@ final class DisabledWallpaperManager extends WallpaperManager {
        return unsupported();
    }

    @Override
    public ParcelFileDescriptor getWallpaperInfoFile() {
        return unsupported();
    }

    @Override
    public WallpaperInfo getWallpaperInfoForUser(int userId) {
        return unsupported();
+8 −1
Original line number Diff line number Diff line
@@ -74,7 +74,8 @@ interface IWallpaperManager {
     * Get the wallpaper for a given user.
     */
    ParcelFileDescriptor getWallpaperWithFeature(String callingPkg, String callingFeatureId,
            IWallpaperManagerCallback cb, int which, out Bundle outParams, int userId);
            IWallpaperManagerCallback cb, int which, out Bundle outParams, int userId,
            boolean getCropped);

    /**
     * Retrieve the given user's current wallpaper ID of the given kind.
@@ -95,6 +96,12 @@ interface IWallpaperManager {
     */
    WallpaperInfo getWallpaperInfoWithFlags(int which, int userId);

    /**
     * Return a file descriptor for the file that contains metadata about the given user's
     * wallpaper.
     */
    ParcelFileDescriptor getWallpaperInfoFile(int userId);

    /**
     * Clear the system wallpaper.
     */
+47 −3
Original line number Diff line number Diff line
@@ -640,7 +640,7 @@ public class WallpaperManager {
                Bundle params = new Bundle();
                try (ParcelFileDescriptor pfd = mService.getWallpaperWithFeature(
                        context.getOpPackageName(), context.getAttributionTag(), this, which,
                        params, userId)) {
                        params, userId, /* getCropped = */ true)) {
                    // Let's peek user wallpaper first.
                    if (pfd != null) {
                        BitmapFactory.Options options = new BitmapFactory.Options();
@@ -690,7 +690,7 @@ public class WallpaperManager {
                Bundle params = new Bundle();
                ParcelFileDescriptor pfd = mService.getWallpaperWithFeature(
                        context.getOpPackageName(), context.getAttributionTag(), this, which,
                        params, userId);
                        params, userId, /* getCropped = */ true);

                if (pfd != null) {
                    try (BufferedInputStream bis = new BufferedInputStream(
@@ -1437,6 +1437,27 @@ public class WallpaperManager {
     */
    @UnsupportedAppUsage
    public ParcelFileDescriptor getWallpaperFile(@SetWallpaperFlags int which, int userId) {
        return getWallpaperFile(which, userId, /* getCropped = */ true);
    }

    /**
     * Version of {@link #getWallpaperFile(int)} that allows specifying whether to get the
     * cropped version of the wallpaper file or the original.
     *
     * @param which The wallpaper whose image file is to be retrieved.  Must be a single
     *    defined kind of wallpaper, either {@link #FLAG_SYSTEM} or {@link #FLAG_LOCK}.
     * @param getCropped If true the cropped file will be retrieved, if false the original will
     *                   be retrieved.
     *
     * @hide
     */
    @Nullable
    public ParcelFileDescriptor getWallpaperFile(@SetWallpaperFlags int which, boolean getCropped) {
        return getWallpaperFile(which, mContext.getUserId(), getCropped);
    }

    private ParcelFileDescriptor getWallpaperFile(@SetWallpaperFlags int which, int userId,
            boolean getCropped) {
        checkExactlyOneWallpaperFlagSet(which);

        if (sGlobals.mService == null) {
@@ -1446,7 +1467,8 @@ public class WallpaperManager {
            try {
                Bundle outParams = new Bundle();
                return sGlobals.mService.getWallpaperWithFeature(mContext.getOpPackageName(),
                        mContext.getAttributionTag(), null, which, outParams, userId);
                        mContext.getAttributionTag(), null, which, outParams,
                        userId, getCropped);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            } catch (SecurityException e) {
@@ -1529,6 +1551,28 @@ public class WallpaperManager {
        }
    }

    /**
     * Get an open, readable file descriptor for the file that contains metadata about the
     * context user's wallpaper.
     *
     * The caller is responsible for closing the file descriptor when done ingesting the file.
     *
     * @hide
     */
    @Nullable
    public ParcelFileDescriptor getWallpaperInfoFile() {
        if (sGlobals.mService == null) {
            Log.w(TAG, "WallpaperService not running");
            throw new RuntimeException(new DeadSystemException());
        } else {
            try {
                return sGlobals.mService.getWallpaperInfoFile(mContext.getUserId());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

    /**
     * Get the ID of the current wallpaper of the given kind.  If there is no
     * such wallpaper configured, returns a negative number.
+172 −123
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import android.content.SharedPreferences;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.graphics.Rect;
import android.os.Environment;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -43,8 +42,6 @@ import android.util.Xml;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;

import libcore.io.IoUtils;

import org.xmlpull.v1.XmlPullParser;

import java.io.File;
@@ -52,39 +49,60 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Backs up and restores wallpaper and metadata related to it.
 *
 * This agent has its own package because it does full backup as opposed to SystemBackupAgent
 * which does key/value backup.
 *
 * This class stages wallpaper files for backup by copying them into its own directory because of
 * the following reasons:
 *
 * <ul>
 *     <li>Non-system users don't have permission to read the directory that the system stores
 *     the wallpaper files in</li>
 *     <li>{@link BackupAgent} enforces that backed up files must live inside the package's
 *     {@link Context#getFilesDir()}</li>
 * </ul>
 *
 * There are 3 files to back up:
 * <ul>
 *     <li>The "wallpaper info"  file which contains metadata like the crop applied to the
 *     wallpaper or the live wallpaper component name.</li>
 *     <li>The "system" wallpaper file.</li>
 *     <li>An optional "lock" wallpaper, which is shown on the lockscreen instead of the system
 *     wallpaper if set.</li>
 * </ul>
 *
 * On restore, the metadata file is parsed and {@link WallpaperManager} APIs are used to set the
 * wallpaper. Note that if there's a live wallpaper, the live wallpaper package name will be
 * part of the metadata file and the wallpaper will be applied when the package it's installed.
 */
public class WallpaperBackupAgent extends BackupAgent {
    private static final String TAG = "WallpaperBackup";
    private static final boolean DEBUG = false;

    // NB: must be kept in sync with WallpaperManagerService but has no
    // compile-time visibility.

    // Target filenames within the system's wallpaper directory
    static final String WALLPAPER = "wallpaper_orig";
    static final String WALLPAPER_LOCK = "wallpaper_lock_orig";
    static final String WALLPAPER_INFO = "wallpaper_info.xml";
    // Names of our local-data stage files
    @VisibleForTesting
    static final String SYSTEM_WALLPAPER_STAGE = "wallpaper-stage";
    @VisibleForTesting
    static final String LOCK_WALLPAPER_STAGE = "wallpaper-lock-stage";
    @VisibleForTesting
    static final String WALLPAPER_INFO_STAGE = "wallpaper-info-stage";

    // Names of our local-data stage files/links
    static final String IMAGE_STAGE = "wallpaper-stage";
    static final String LOCK_IMAGE_STAGE = "wallpaper-lock-stage";
    static final String INFO_STAGE = "wallpaper-info-stage";
    static final String EMPTY_SENTINEL = "empty";
    static final String QUOTA_SENTINEL = "quota";

    // Not-for-backup bookkeeping
    // Shared preferences constants.
    static final String PREFS_NAME = "wbprefs.xml";
    static final String SYSTEM_GENERATION = "system_gen";
    static final String LOCK_GENERATION = "lock_gen";

    private File mWallpaperInfo;        // wallpaper metadata file
    private File mWallpaperFile;        // primary wallpaper image file
    private File mLockWallpaperFile;    // lock wallpaper image file

    // If this file exists, it means we exceeded our quota last time
    private File mQuotaFile;
    private boolean mQuotaExceeded;

    private WallpaperManager mWm;
    private WallpaperManager mWallpaperManager;

    @Override
    public void onCreate() {
@@ -92,11 +110,7 @@ public class WallpaperBackupAgent extends BackupAgent {
            Slog.v(TAG, "onCreate()");
        }

        File wallpaperDir = getWallpaperDir();
        mWallpaperInfo = new File(wallpaperDir, WALLPAPER_INFO);
        mWallpaperFile = new File(wallpaperDir, WALLPAPER);
        mLockWallpaperFile = new File(wallpaperDir, WALLPAPER_LOCK);
        mWm = (WallpaperManager) getSystemService(Context.WALLPAPER_SERVICE);
        mWallpaperManager = getSystemService(WallpaperManager.class);

        mQuotaFile = new File(getFilesDir(), QUOTA_SENTINEL);
        mQuotaExceeded = mQuotaFile.exists();
@@ -105,120 +119,156 @@ public class WallpaperBackupAgent extends BackupAgent {
        }
    }

    @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.
        final File filesDir = getFilesDir();
        final File infoStage = new File(filesDir, INFO_STAGE);
        final File imageStage = new File (filesDir, IMAGE_STAGE);
        final File lockImageStage = new File (filesDir, LOCK_IMAGE_STAGE);
        final File empty = new File (filesDir, EMPTY_SENTINEL);

        try {
            // We always back up this 'empty' file to ensure that the absence of
            // storable wallpaper imagery still produces a non-empty backup data
            // stream, otherwise it'd simply be ignored in preflight.
            final File empty = new File(getFilesDir(), EMPTY_SENTINEL);
            if (!empty.exists()) {
                FileOutputStream touch = new FileOutputStream(empty);
                touch.close();
            }
            backupFile(empty, data);

            SharedPreferences prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
            final int lastSysGeneration = prefs.getInt(SYSTEM_GENERATION, -1);
            final int lastLockGeneration = prefs.getInt(LOCK_GENERATION, -1);
            SharedPreferences sharedPrefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);

            final int sysGeneration =
                    mWm.getWallpaperIdForUser(FLAG_SYSTEM, UserHandle.USER_SYSTEM);
            final int lockGeneration =
                    mWm.getWallpaperIdForUser(FLAG_LOCK, UserHandle.USER_SYSTEM);
            // Check the IDs of the wallpapers that we backed up last time. If they haven't
            // changed, we won't re-stage them for backup and use the old staged versions to avoid
            // disk churn.
            final int lastSysGeneration = sharedPrefs.getInt(SYSTEM_GENERATION, /* defValue= */ -1);
            final int lastLockGeneration = sharedPrefs.getInt(LOCK_GENERATION, /* defValue= */ -1);
            final int sysGeneration = mWallpaperManager.getWallpaperId(FLAG_SYSTEM);
            final int lockGeneration = mWallpaperManager.getWallpaperId(FLAG_LOCK);
            final boolean sysChanged = (sysGeneration != lastSysGeneration);
            final boolean lockChanged = (lockGeneration != lastLockGeneration);

            final boolean sysEligible = mWm.isWallpaperBackupEligible(FLAG_SYSTEM);
            final boolean lockEligible = mWm.isWallpaperBackupEligible(FLAG_LOCK);

                // There might be a latent lock wallpaper file present but unused: don't
                // include it in the backup if that's the case.
                ParcelFileDescriptor lockFd = mWm.getWallpaperFile(FLAG_LOCK, UserHandle.USER_SYSTEM);
                final boolean hasLockWallpaper = (lockFd != null);
                IoUtils.closeQuietly(lockFd);

            if (DEBUG) {
                Slog.v(TAG, "sysGen=" + sysGeneration + " : sysChanged=" + sysChanged);
                Slog.v(TAG, "lockGen=" + lockGeneration + " : lockChanged=" + lockChanged);
                Slog.v(TAG, "sysEligble=" + sysEligible);
                Slog.v(TAG, "lockEligible=" + lockEligible);
                Slog.v(TAG, "hasLockWallpaper=" + hasLockWallpaper);
            }

            // only back up the wallpapers if we've been told they're eligible
            if (mWallpaperInfo.exists()) {
                if (sysChanged || lockChanged || !infoStage.exists()) {
            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);
        } 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
            // between "try both" and "only store the primary image" until either there
            // is no lock image to store, or the quota is raised, or both fit under the
            // quota.
            mQuotaFile.delete();
        }
    }

    private void backupWallpaperInfoFile(boolean sysOrLockChanged, FullBackupDataOutput data)
            throws IOException {
        final ParcelFileDescriptor wallpaperInfoFd = mWallpaperManager.getWallpaperInfoFile();

        if (wallpaperInfoFd == null) {
            Slog.w(TAG, "Wallpaper metadata file doesn't exist");
            return;
        }

        final File infoStage = new File(getFilesDir(), WALLPAPER_INFO_STAGE);

        if (sysOrLockChanged || !infoStage.exists()) {
            if (DEBUG) Slog.v(TAG, "New wallpaper configuration; copying");
                    FileUtils.copyFileOrThrow(mWallpaperInfo, infoStage);
            copyFromPfdToFileAndClosePfd(wallpaperInfoFd, infoStage);
        }

        if (DEBUG) Slog.v(TAG, "Storing wallpaper metadata");
        backupFile(infoStage, data);
            } else {
                Slog.w(TAG, "Wallpaper metadata file doesn't exist: " +
                        mWallpaperFile.getPath());
    }
            if (sysEligible && mWallpaperFile.exists()) {

    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");
            return;
        }

        final ParcelFileDescriptor systemWallpaperImageFd = mWallpaperManager.getWallpaperFile(
                FLAG_SYSTEM,
                /* getCropped= */ false);

        if (systemWallpaperImageFd == null) {
            Slog.w(TAG, "System wallpaper doesn't exist");
            return;
        }

        final File imageStage = new File(getFilesDir(), SYSTEM_WALLPAPER_STAGE);

        if (sysChanged || !imageStage.exists()) {
            if (DEBUG) Slog.v(TAG, "New system wallpaper; copying");
                    FileUtils.copyFileOrThrow(mWallpaperFile, imageStage);
            copyFromPfdToFileAndClosePfd(systemWallpaperImageFd, imageStage);
        }

        if (DEBUG) Slog.v(TAG, "Storing system wallpaper image");
        backupFile(imageStage, data);
                prefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply();
            } else {
                Slog.w(TAG, "Not backing up wallpaper as one of conditions is not "
                        + "met: sysEligible = " + sysEligible + " wallpaperFileExists = "
                        + mWallpaperFile.exists());
        sharedPrefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply();
    }

            // If there's no lock wallpaper, then we have nothing to add to the backup.
    private void backupLockWallpaperFileIfItExists(SharedPreferences sharedPrefs,
            boolean lockChanged, int lockGeneration, FullBackupDataOutput data) throws IOException {
        final File lockImageStage = new File(getFilesDir(), LOCK_WALLPAPER_STAGE);

        // This means there's no lock wallpaper set by the user.
        if (lockGeneration == -1) {
            if (lockChanged && lockImageStage.exists()) {
                if (DEBUG) Slog.v(TAG, "Removed lock wallpaper; deleting");
                lockImageStage.delete();
            }
            Slog.d(TAG, "No lockscreen wallpaper set, add nothing to backup");
                prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
            sharedPrefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
            return;
        }

        if (!mWallpaperManager.isWallpaperBackupEligible(FLAG_LOCK)) {
            Slog.d(TAG, "Lock screen wallpaper ineligible for backup");
            return;
        }

        final ParcelFileDescriptor lockWallpaperFd = mWallpaperManager.getWallpaperFile(
                FLAG_LOCK, /* getCropped= */ false);

        // If we get to this point, that means lockGeneration != -1 so there's a lock wallpaper
        // set, but we can't find it.
        if (lockWallpaperFd == null) {
            Slog.w(TAG, "Lock wallpaper doesn't exist");
            return;
        }

        if (mQuotaExceeded) {
            Slog.w(TAG, "Not backing up lock screen wallpaper. Quota was exceeded last time");
            return;
        }

            // Don't try to store the lock image if we overran our quota last time
            if (lockEligible && hasLockWallpaper && mLockWallpaperFile.exists() && !mQuotaExceeded) {
        if (lockChanged || !lockImageStage.exists()) {
            if (DEBUG) Slog.v(TAG, "New lock wallpaper; copying");
                    FileUtils.copyFileOrThrow(mLockWallpaperFile, lockImageStage);
            copyFromPfdToFileAndClosePfd(lockWallpaperFd, lockImageStage);
        }

        if (DEBUG) Slog.v(TAG, "Storing lock wallpaper image");
        backupFile(lockImageStage, data);
                prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
            } else {
                Slog.w(TAG, "Not backing up lockscreen wallpaper as one of conditions is not "
                        + "met: lockEligible = " + lockEligible + " hasLockWallpaper = "
                        + hasLockWallpaper + " lockWallpaperFileExists = "
                        + mLockWallpaperFile.exists() + " quotaExceeded (last time) = "
                        + mQuotaExceeded);
        sharedPrefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
    }
        } catch (Exception e) {
            Slog.e(TAG, "Unable to back up wallpaper", 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
            // between "try both" and "only store the primary image" until either there
            // is no lock image to store, or the quota is raised, or both fit under the
            // quota.
            mQuotaFile.delete();

    /**
     * Copies the contents of the given {@code pfd} to the given {@code file}.
     *
     * All resources used in the process including the {@code pfd} will be closed.
     */
    private static void copyFromPfdToFileAndClosePfd(ParcelFileDescriptor pfd, File file)
            throws IOException {
        try (ParcelFileDescriptor.AutoCloseInputStream inputStream =
                     new ParcelFileDescriptor.AutoCloseInputStream(pfd);
             FileOutputStream outputStream = new FileOutputStream(file)
        ) {
            FileUtils.copy(inputStream, outputStream);
        }
    }

@@ -244,9 +294,9 @@ public class WallpaperBackupAgent extends BackupAgent {
    public void onRestoreFinished() {
        Slog.v(TAG, "onRestoreFinished()");
        final File filesDir = getFilesDir();
        final File infoStage = new File(filesDir, INFO_STAGE);
        final File imageStage = new File (filesDir, IMAGE_STAGE);
        final File lockImageStage = new File (filesDir, LOCK_IMAGE_STAGE);
        final File infoStage = new File(filesDir, WALLPAPER_INFO_STAGE);
        final File imageStage = new File(filesDir, SYSTEM_WALLPAPER_STAGE);
        final File lockImageStage = new File(filesDir, LOCK_WALLPAPER_STAGE);

        // If we restored separate lock imagery, the system wallpaper should be
        // applied as system-only; but if there's no separate lock image, make
@@ -283,11 +333,11 @@ public class WallpaperBackupAgent extends BackupAgent {
    void updateWallpaperComponent(ComponentName wpService, boolean applyToLock) throws IOException {
        if (servicePackageExists(wpService)) {
            Slog.i(TAG, "Using wallpaper service " + wpService);
            mWm.setWallpaperComponent(wpService, UserHandle.USER_SYSTEM);
            mWallpaperManager.setWallpaperComponent(wpService);
            if (applyToLock) {
                // We have a live wallpaper and no static lock image,
                // allow live wallpaper to show "through" on lock screen.
                mWm.clear(FLAG_LOCK);
                mWallpaperManager.clear(FLAG_LOCK);
            }
        } else {
            // If we've restored a live wallpaper, but the component doesn't exist,
@@ -311,8 +361,9 @@ public class WallpaperBackupAgent extends BackupAgent {
                Slog.i(TAG, "Got restored wallpaper; applying which=" + which
                        + "; cropHint = " + cropHint);
                try (FileInputStream in = new FileInputStream(stage)) {
                    mWm.setStream(in, cropHint.isEmpty() ? null : cropHint, true, which);
                } finally {} // auto-closes 'in'
                    mWallpaperManager.setStream(in, cropHint.isEmpty() ? null : cropHint, true,
                            which);
                }
            }
        } else {
            Slog.d(TAG, "Restore data doesn't exist for file " + stage.getPath());
@@ -384,7 +435,7 @@ public class WallpaperBackupAgent extends BackupAgent {
            if (comp != null) {
                final IPackageManager pm = AppGlobals.getPackageManager();
                final PackageInfo info = pm.getPackageInfo(comp.getPackageName(),
                        0, UserHandle.USER_SYSTEM);
                        0, getUserId());
                return (info != null);
            }
        } catch (RemoteException e) {
@@ -393,16 +444,14 @@ public class WallpaperBackupAgent extends BackupAgent {
        return false;
    }

    //
    // Key/value API: abstract, therefore required; but not used
    //

    /** Unused Key/Value API. */
    @Override
    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
            ParcelFileDescriptor newState) throws IOException {
        // Intentionally blank
    }

    /** Unused Key/Value API. */
    @Override
    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
            throws IOException {
@@ -427,10 +476,10 @@ public class WallpaperBackupAgent extends BackupAgent {

                if (componentName.getPackageName().equals(packageName)) {
                    Slog.d(TAG, "Applying component " + componentName);
                    mWm.setWallpaperComponent(componentName);
                    mWallpaperManager.setWallpaperComponent(componentName);
                    if (applyToLock) {
                        try {
                            mWm.clear(FLAG_LOCK);
                            mWallpaperManager.clear(FLAG_LOCK);
                        } catch (IOException e) {
                            Slog.w(TAG, "Failed to apply live wallpaper to lock screen: " + e);
                        }
+264 −74

File changed.

Preview size limit exceeded, changes collapsed.

Loading