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

Commit 454f1466 authored by Christopher Tate's avatar Christopher Tate Committed by android-build-merger
Browse files

Merge "Use normal API for legacy wallpaper restore" into oc-mr1-dev

am: 4204f165

Change-Id: I2621dcbb5b727a5420095223f36d3e6e5784799d
parents 662282b2 4204f165
Loading
Loading
Loading
Loading
+27 −126
Original line number Original line Diff line number Diff line
@@ -18,20 +18,19 @@ package android.app.backup;


import android.app.WallpaperManager;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.os.Environment;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.os.UserHandle;
import android.util.Slog;
import android.util.Slog;
import android.view.Display;
import android.view.WindowManager;


import java.io.File;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;


/**
/**
 * Helper for backing up / restoring wallpapers.  Basically an AbsoluteFileBackupHelper,
 * We no longer back up wallpapers with this helper, but we do need to process restores
 * but with logic for deciding what to do with restored wallpaper images.
 * of legacy backup payloads.  We just take the restored image as-is and apply it as the
 * system wallpaper using the public "set the wallpaper" API.
 *
 *
 * @hide
 * @hide
 */
 */
@@ -39,83 +38,34 @@ public class WallpaperBackupHelper extends FileBackupHelperBase implements Backu
    private static final String TAG = "WallpaperBackupHelper";
    private static final String TAG = "WallpaperBackupHelper";
    private static final boolean DEBUG = false;
    private static final boolean DEBUG = false;


    // If 'true', then apply an acceptable-size heuristic at restore time, dropping back
    // Key that legacy wallpaper imagery was stored under
    // to the factory default wallpaper if the restored one differs "too much" from the
    // device's preferred wallpaper image dimensions.
    private static final boolean REJECT_OUTSIZED_RESTORE = false;

    // When outsized restore rejection is enabled, this is the maximum ratio between the
    // source and target image heights that will be permitted.  The ratio is checked both
    // ways (i.e. >= MAX, or <= 1/MAX) to validate restores from both largeer-than-target
    // and smaller-than-target sources.
    private static final double MAX_HEIGHT_RATIO = 1.35;

    // The height ratio check when applying larger images on smaller screens is separate;
    // in current policy we accept any such restore regardless of the relative dimensions.
    private static final double MIN_HEIGHT_RATIO = 0;

    // This path must match what the WallpaperManagerService uses
    // TODO: Will need to change if backing up non-primary user's wallpaper
    // http://b/22388012
    public static final String WALLPAPER_IMAGE =
            new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM),
                    "wallpaper").getAbsolutePath();
    public static final String WALLPAPER_ORIG_IMAGE =
            new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM),
                    "wallpaper_orig").getAbsolutePath();
    public static final String WALLPAPER_INFO =
            new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM),
                    "wallpaper_info.xml").getAbsolutePath();
    // Use old keys to keep legacy data compatibility and avoid writing two wallpapers
    public static final String WALLPAPER_IMAGE_KEY =
    public static final String WALLPAPER_IMAGE_KEY =
            "/data/data/com.android.settings/files/wallpaper";
            "/data/data/com.android.settings/files/wallpaper";
    public static final String WALLPAPER_INFO_KEY = "/data/system/wallpaper_info.xml";
    public static final String WALLPAPER_INFO_KEY = "/data/system/wallpaper_info.xml";


    // Stage file - should be adjacent to the WALLPAPER_IMAGE location.  The wallpapers
    // Stage file that the restored imagery is stored to prior to being applied
    // will be saved to this file from the restore stream, then renamed to the proper
    // as the system wallpaper.
    // location if it's deemed suitable.
    // TODO: Will need to change if backing up non-primary user's wallpaper
    // http://b/22388012
    private static final String STAGE_FILE =
    private static final String STAGE_FILE =
            new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM),
            new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM),
                    "wallpaper-tmp").getAbsolutePath();
                    "wallpaper-tmp").getAbsolutePath();


    Context mContext;
    private final String[] mKeys;
    String[] mFiles;
    private final WallpaperManager mWpm;
    String[] mKeys;
    double mDesiredMinWidth;
    double mDesiredMinHeight;


    /**
    /**
     * Construct a helper for backing up / restoring the files at the given absolute locations
     * Legacy wallpaper restores, from back when the imagery was stored under the
     * within the file system.
     * "android" system package as file key/value entities.
     *
     *
     * @param context
     * @param context
     * @param files
     * @param files
     */
     */
    public WallpaperBackupHelper(Context context, String[] files, String[] keys) {
    public WallpaperBackupHelper(Context context, String[] keys) {
        super(context);
        super(context);


        mContext = context;
        mContext = context;
        mFiles = files;
        mKeys = keys;
        mKeys = keys;


        final WindowManager wm =
        mWpm = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
                (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        final WallpaperManager wpm =
                (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
        final Display d = wm.getDefaultDisplay();
        final Point size = new Point();
        d.getSize(size);
        mDesiredMinWidth = Math.min(size.x, size.y);
        mDesiredMinHeight = (double) wpm.getDesiredMinimumHeight();
        if (mDesiredMinHeight <= 0) {
            mDesiredMinHeight = size.y;
        }

        if (DEBUG) {
            Slog.d(TAG, "dmW=" + mDesiredMinWidth + " dmH=" + mDesiredMinHeight);
        }
    }
    }


    /**
    /**
@@ -126,13 +76,12 @@ public class WallpaperBackupHelper extends FileBackupHelperBase implements Backu
    @Override
    @Override
    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
            ParcelFileDescriptor newState) {
            ParcelFileDescriptor newState) {
        performBackup_checked(oldState, data, newState, mFiles, mKeys);
        // Intentionally no-op; we don't back up the wallpaper this way any more.
    }
    }


    /**
    /**
     * Restore one absolute file entity from the restore stream.  If we're restoring the
     * Restore one absolute file entity from the restore stream.  If we're restoring the
     * magic wallpaper file, take specific action to determine whether it is suitable for
     * magic wallpaper file, apply it as the system wallpaper.
     * the current device.
     */
     */
    @Override
    @Override
    public void restoreEntity(BackupDataInputStream data) {
    public void restoreEntity(BackupDataInputStream data) {
@@ -140,69 +89,21 @@ public class WallpaperBackupHelper extends FileBackupHelperBase implements Backu
        if (isKeyInList(key, mKeys)) {
        if (isKeyInList(key, mKeys)) {
            if (key.equals(WALLPAPER_IMAGE_KEY)) {
            if (key.equals(WALLPAPER_IMAGE_KEY)) {
                // restore the file to the stage for inspection
                // restore the file to the stage for inspection
                File f = new File(STAGE_FILE);
                File stage = new File(STAGE_FILE);
                if (writeFile(f, data)) {
                try {

                    if (writeFile(stage, data)) {
                    // Preflight the restored image's dimensions without loading it
                        try (FileInputStream in = new FileInputStream(stage)) {
                    BitmapFactory.Options options = new BitmapFactory.Options();
                            mWpm.setStream(in);
                    options.inJustDecodeBounds = true;
                        } catch (IOException e) {
                    BitmapFactory.decodeFile(STAGE_FILE, options);
                            Slog.e(TAG, "Unable to set restored wallpaper: " + e.getMessage());

                    if (DEBUG) Slog.d(TAG, "Restoring wallpaper image w=" + options.outWidth
                            + " h=" + options.outHeight);

                    if (REJECT_OUTSIZED_RESTORE) {
                        // We accept any wallpaper that is at least as wide as our preference
                        // (i.e. wide enough to fill the screen), and is within a comfortable
                        // factor of the target height, to avoid significant clipping/scaling/
                        // letterboxing.  At this point we know that mDesiredMinWidth is the
                        // smallest dimension, regardless of current orientation, so we can
                        // safely require that the candidate's width and height both exceed
                        // that hard minimum.
                        final double heightRatio = mDesiredMinHeight / options.outHeight;
                        if (options.outWidth < mDesiredMinWidth
                                || options.outHeight < mDesiredMinWidth
                                || heightRatio >= MAX_HEIGHT_RATIO
                                || heightRatio <= MIN_HEIGHT_RATIO) {
                            // Not wide enough for the screen, or too short/tall to be a good fit
                            // for the height of the screen, broken image file, or the system's
                            // desires for wallpaper size are in a bad state.  Probably one of the
                            // first two.
                            Slog.i(TAG, "Restored image dimensions (w="
                                    + options.outWidth + ", h=" + options.outHeight
                                    + ") too far off target (tw="
                                    + mDesiredMinWidth + ", th=" + mDesiredMinHeight
                                    + "); falling back to default wallpaper.");
                            f.delete();
                            return;
                        }
                        }
                    } else {
                        Slog.e(TAG, "Unable to save restored wallpaper");
                    }
                    }

                } finally {
                    // We passed the acceptable-dimensions test (if any), so we're going to
                    stage.delete();
                    // use the restored image.  That comes last, when we are done restoring
                    // both the pixels and the metadata.
                }
            } else if (key.equals(WALLPAPER_INFO_KEY)) {
                // XML file containing wallpaper info
                File f = new File(WALLPAPER_INFO);
                writeFile(f, data);
                }
                }
            }
            }
        }
        }

    /**
     * Hook for the agent to call this helper upon completion of the restore.  We do this
     * upon completion so that we know both the imagery and the wallpaper info have
     * been emplaced without requiring either or relying on ordering.
     */
    public void onRestoreFinished() {
        final File f = new File(STAGE_FILE);
        if (f.exists()) {
            // TODO: spin a service to copy the restored image to sd/usb storage,
            // since it does not exist anywhere other than the private wallpaper
            // file.
            Slog.d(TAG, "Applying restored wallpaper image.");
            f.renameTo(new File(WALLPAPER_ORIG_IMAGE));
        }
    }
    }
}
}
+13 −34
Original line number Original line Diff line number Diff line
@@ -35,7 +35,8 @@ import java.io.File;
import java.io.IOException;
import java.io.IOException;


/**
/**
 * Backup agent for various system-managed data, currently just the system wallpaper
 * Backup agent for various system-managed data.  Wallpapers are now handled by a
 * separate package, but we still process restores from legacy datasets here.
 */
 */
public class SystemBackupAgent extends BackupAgentHelper {
public class SystemBackupAgent extends BackupAgentHelper {
    private static final String TAG = "SystemBackupAgent";
    private static final String TAG = "SystemBackupAgent";
@@ -61,16 +62,19 @@ public class SystemBackupAgent extends BackupAgentHelper {
    // TODO: http://b/22388012
    // TODO: http://b/22388012
    private static final String WALLPAPER_IMAGE_DIR =
    private static final String WALLPAPER_IMAGE_DIR =
            Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM).getAbsolutePath();
            Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM).getAbsolutePath();
    private static final String WALLPAPER_IMAGE = WallpaperBackupHelper.WALLPAPER_IMAGE;
    public static final String WALLPAPER_IMAGE =
            new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM),
                    "wallpaper").getAbsolutePath();


    // TODO: Will need to change if backing up non-primary user's wallpaper
    // TODO: Will need to change if backing up non-primary user's wallpaper
    // TODO: http://b/22388012
    // TODO: http://b/22388012
    private static final String WALLPAPER_INFO_DIR =
    private static final String WALLPAPER_INFO_DIR =
            Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM).getAbsolutePath();
            Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM).getAbsolutePath();
    private static final String WALLPAPER_INFO = WallpaperBackupHelper.WALLPAPER_INFO;
    public static final String WALLPAPER_INFO =
            new File(Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM),
                    "wallpaper_info.xml").getAbsolutePath();
    // Use old keys to keep legacy data compatibility and avoid writing two wallpapers
    // Use old keys to keep legacy data compatibility and avoid writing two wallpapers
    private static final String WALLPAPER_IMAGE_KEY = WallpaperBackupHelper.WALLPAPER_IMAGE_KEY;
    private static final String WALLPAPER_IMAGE_KEY = WallpaperBackupHelper.WALLPAPER_IMAGE_KEY;
    private static final String WALLPAPER_INFO_KEY = WallpaperBackupHelper.WALLPAPER_INFO_KEY;


    private WallpaperBackupHelper mWallpaperHelper = null;
    private WallpaperBackupHelper mWallpaperHelper = null;


@@ -98,13 +102,11 @@ public class SystemBackupAgent extends BackupAgentHelper {
        // Slot in a restore helper for the older wallpaper backup schema to support restore
        // Slot in a restore helper for the older wallpaper backup schema to support restore
        // from devices still generating data in that format.
        // from devices still generating data in that format.
        mWallpaperHelper = new WallpaperBackupHelper(this,
        mWallpaperHelper = new WallpaperBackupHelper(this,
                new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO },
                new String[] { WALLPAPER_IMAGE_KEY} );
                new String[] { WALLPAPER_IMAGE_KEY, WALLPAPER_INFO_KEY} );
        addHelper(WALLPAPER_HELPER, mWallpaperHelper);
        addHelper(WALLPAPER_HELPER, mWallpaperHelper);


        // On restore, we also support a long-ago wallpaper data schema "system_files"
        // On restore, we also support a long-ago wallpaper data schema "system_files"
        addHelper("system_files", new WallpaperBackupHelper(this,
        addHelper("system_files", new WallpaperBackupHelper(this,
                new String[] { WALLPAPER_IMAGE },
                new String[] { WALLPAPER_IMAGE_KEY} ));
                new String[] { WALLPAPER_IMAGE_KEY} ));


        addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this));
        addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this));
@@ -115,27 +117,12 @@ public class SystemBackupAgent extends BackupAgentHelper {
        addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper());
        addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper());
        addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper());
        addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper());


        try {
        super.onRestore(data, appVersionCode, newState);
        super.onRestore(data, appVersionCode, newState);

            IWallpaperManager wallpaper = (IWallpaperManager) ServiceManager.getService(
                    Context.WALLPAPER_SERVICE);
            if (wallpaper != null) {
                try {
                    wallpaper.settingsRestored();
                } catch (RemoteException re) {
                    Slog.e(TAG, "Couldn't restore settings\n" + re);
                }
            }
        } catch (IOException ex) {
            // If there was a failure, delete everything for the wallpaper, this is too aggressive,
            // but this is hopefully a rare failure.
            Slog.d(TAG, "restore failed", ex);
            (new File(WALLPAPER_IMAGE)).delete();
            (new File(WALLPAPER_INFO)).delete();
        }
    }
    }


    /**
     * Support for 'adb restore' of legacy archives
     */
    @Override
    @Override
    public void onRestoreFile(ParcelFileDescriptor data, long size,
    public void onRestoreFile(ParcelFileDescriptor data, long size,
            int type, String domain, String path, long mode, long mtime)
            int type, String domain, String path, long mode, long mtime)
@@ -183,12 +170,4 @@ public class SystemBackupAgent extends BackupAgentHelper {
            }
            }
        }
        }
    }
    }

    @Override
    public void onRestoreFinished() {
        // helper will be null following 'adb restore' or other full-data operation
        if (mWallpaperHelper != null) {
            mWallpaperHelper.onRestoreFinished();
        }
    }
}
}
+33 −13
Original line number Original line Diff line number Diff line
@@ -2307,16 +2307,36 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
    }
    }


    private void migrateFromOld() {
    private void migrateFromOld() {
        File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
        // Pre-N, what existed is the one we're now using as the display crop
        File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
        File preNWallpaper = new File(getWallpaperDir(0), WALLPAPER_CROP);
        if (oldWallpaper.exists()) {
        // In the very-long-ago, imagery lived with the settings app
        File originalWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
        File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
        File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
            oldWallpaper.renameTo(newWallpaper);

        // Migrations from earlier wallpaper image storage schemas
        if (preNWallpaper.exists()) {
            if (!newWallpaper.exists()) {
                // we've got the 'wallpaper' crop file but not the nominal source image,
                // so do the simple "just take everything" straight copy of legacy data
                if (DEBUG) {
                    Slog.i(TAG, "Migrating wallpaper schema");
                }
                }
                FileUtils.copyFile(preNWallpaper, newWallpaper);
            } // else we're in the usual modern case: both source & crop exist
        } else if (originalWallpaper.exists()) {
            // VERY old schema; make sure things exist and are in the right place
            if (DEBUG) {
                Slog.i(TAG, "Migrating antique wallpaper schema");
            }
            File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
            if (oldInfo.exists()) {
            if (oldInfo.exists()) {
                File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
                File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
                oldInfo.renameTo(newInfo);
                oldInfo.renameTo(newInfo);
            }
            }

            FileUtils.copyFile(originalWallpaper, preNWallpaper);
            originalWallpaper.renameTo(newWallpaper);
        }
    }
    }


    private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
    private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
@@ -2376,12 +2396,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
        JournaledFile journal = makeJournaledFile(userId);
        JournaledFile journal = makeJournaledFile(userId);
        FileInputStream stream = null;
        FileInputStream stream = null;
        File file = journal.chooseForRead();
        File file = journal.chooseForRead();
        if (!file.exists()) {

            // This should only happen one time, when upgrading from a legacy system
            migrateFromOld();
        }
        WallpaperData wallpaper = mWallpaperMap.get(userId);
        WallpaperData wallpaper = mWallpaperMap.get(userId);
        if (wallpaper == null) {
        if (wallpaper == null) {
            // Do this once per boot
            migrateFromOld();

            wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
            wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP);
            wallpaper.allowBackup = true;
            wallpaper.allowBackup = true;
            mWallpaperMap.put(userId, wallpaper);
            mWallpaperMap.put(userId, wallpaper);