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

Commit 00105805 authored by Sunny Goyal's avatar Sunny Goyal Committed by Android (Google) Code Review
Browse files

Merge "Updating backup restore logic" into ub-now-queens

parents f659c985 33d44389
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -37,12 +37,36 @@ message CheckedMessage {
  required int64 checksum = 2;
}

message DeviceProfieData {
  required float desktop_rows = 1;
  required float desktop_cols = 2;
  required float hotseat_count = 3;
  required int32 allapps_rank = 4;
}

message Journal {
  required int32 app_version = 1;

  // Time when the backup was created
  required int64 t = 2;

  // Total bytes written during the last backup
  // OBSOLETE: A state may contain entries which are already present in the backup
  // and were not written in the last backup
  optional int64 bytes = 3;

  // Total entries written during the last backup
  // OBSOLETE: A state may contain entries which are already present in the backup
  // and were not written in the last backup
  optional int32 rows = 4;

  // Valid keys for this state
  repeated Key key = 5;

  // Backup format version.
  optional int32 backup_version = 6 [default = 1];

  optional DeviceProfieData profile = 7;
}

message Favorite {
+1 −16
Original line number Diff line number Diff line
@@ -53,7 +53,6 @@ import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -71,7 +70,6 @@ import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.method.TextKeyListener;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
@@ -418,22 +416,9 @@ public class Launcher extends Activity
        LauncherAppState.setApplicationContext(getApplicationContext());
        LauncherAppState app = LauncherAppState.getInstance();
        LauncherAppState.getLauncherProvider().setLauncherProviderChangeListener(this);
        // Determine the dynamic grid properties
        Point smallestSize = new Point();
        Point largestSize = new Point();
        Point realSize = new Point();
        Display display = getWindowManager().getDefaultDisplay();
        display.getCurrentSizeRange(smallestSize, largestSize);
        display.getRealSize(realSize);
        DisplayMetrics dm = new DisplayMetrics();
        display.getMetrics(dm);

        // Lazy-initialize the dynamic grid
        DeviceProfile grid = app.initDynamicGrid(this,
                Math.min(smallestSize.x, smallestSize.y),
                Math.min(largestSize.x, largestSize.y),
                realSize.x, realSize.y,
                dm.widthPixels, dm.heightPixels);
        DeviceProfile grid = app.initDynamicGrid(this);

        // the LauncherApplication should call this, but in case of Instrumentation it might not be present yet
        mSharedPrefs = getSharedPreferences(LauncherAppState.getSharedPreferencesKey(),
+25 −7
Original line number Diff line number Diff line
@@ -25,8 +25,12 @@ import android.content.IntentFilter;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Point;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;

import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat;
@@ -190,21 +194,35 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
        return LauncherFiles.SHARED_PREFERENCES_KEY;
    }

    DeviceProfile initDynamicGrid(Context context, int minWidth, int minHeight,
                                  int width, int height,
                                  int availableWidth, int availableHeight) {
    DeviceProfile initDynamicGrid(Context context) {
        // Determine the dynamic grid properties
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();

        Point realSize = new Point();
        display.getRealSize(realSize);
        DisplayMetrics dm = new DisplayMetrics();
        display.getMetrics(dm);

        if (mDynamicGrid == null) {
            Point smallestSize = new Point();
            Point largestSize = new Point();
            display.getCurrentSizeRange(smallestSize, largestSize);

            mDynamicGrid = new DynamicGrid(context,
                    context.getResources(),
                    minWidth, minHeight, width, height,
                    availableWidth, availableHeight);
                    Math.min(smallestSize.x, smallestSize.y),
                    Math.min(largestSize.x, largestSize.y),
                    realSize.x, realSize.y,
                    dm.widthPixels, dm.heightPixels);
            mDynamicGrid.getDeviceProfile().addCallback(this);
        }

        // Update the icon size
        DeviceProfile grid = mDynamicGrid.getDeviceProfile();
        grid.updateFromConfiguration(context, context.getResources(), width, height,
                availableWidth, availableHeight);
        grid.updateFromConfiguration(context, context.getResources(),
                realSize.x, realSize.y,
                dm.widthPixels, dm.heightPixels);
        return grid;
    }
    public DynamicGrid getDynamicGrid() {
+11 −23
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import android.app.backup.BackupManager;
import android.content.Context;
import android.database.Cursor;
import android.os.ParcelFileDescriptor;
import android.provider.Settings;
import android.util.Log;

import java.io.IOException;
@@ -30,13 +29,14 @@ import java.io.IOException;
public class LauncherBackupAgentHelper extends BackupAgentHelper {

    private static final String TAG = "LauncherBackupAgentHelper";

    private static final String LAUNCHER_DATA_PREFIX = "L";

    static final boolean VERBOSE = true;
    static final boolean DEBUG = false;

    private static BackupManager sBackupManager;

    protected static final String SETTING_RESTORE_ENABLED = "launcher_restore_enabled";

    /**
     * Notify the backup manager that out database is dirty.
     *
@@ -51,28 +51,13 @@ public class LauncherBackupAgentHelper extends BackupAgentHelper {
        sBackupManager.dataChanged();
    }

    @Override
    public void onDestroy() {
        // There is only one process accessing this preference file, but the restore
        // modifies the file outside the normal codepaths, so it looks like another
        // process.  This forces a reload of the file, in case this process persists.
        String spKey = LauncherAppState.getSharedPreferencesKey();
        getSharedPreferences(spKey, Context.MODE_MULTI_PROCESS);
        super.onDestroy();
    }
    private LauncherBackupHelper mHelper;

    @Override
    public void onCreate() {
        boolean restoreEnabled = 0 != Settings.Secure.getInt(
                getContentResolver(), SETTING_RESTORE_ENABLED, 1);
        if (VERBOSE) Log.v(TAG, "restore is " + (restoreEnabled ? "enabled" : "disabled"));

        addHelper(LauncherBackupHelper.LAUNCHER_PREFS_PREFIX,
                new LauncherPreferencesBackupHelper(this,
                        LauncherAppState.getSharedPreferencesKey(),
                        restoreEnabled));
        addHelper(LauncherBackupHelper.LAUNCHER_PREFIX,
                new LauncherBackupHelper(this, restoreEnabled));
        super.onCreate();
        mHelper = new LauncherBackupHelper(this);
        addHelper(LAUNCHER_DATA_PREFIX, mHelper);
    }

    @Override
@@ -92,7 +77,10 @@ public class LauncherBackupAgentHelper extends BackupAgentHelper {
        boolean hasData = c.moveToNext();
        c.close();

        if (!hasData) {
        if (hasData && mHelper.restoreSuccessful) {
            LauncherAppState.getLauncherProvider().clearFlagEmptyDbCreated();
            LauncherClings.synchonouslyMarkFirstRunClingDismissed(this);
        } else {
            if (VERBOSE) Log.v(TAG, "Nothing was restored, clearing DB");
            LauncherAppState.getLauncherProvider().createEmptyDB();
        }
+77 −11
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.LauncherSettings.WorkspaceScreens;
import com.android.launcher3.backup.BackupProtos;
import com.android.launcher3.backup.BackupProtos.CheckedMessage;
import com.android.launcher3.backup.BackupProtos.DeviceProfieData;
import com.android.launcher3.backup.BackupProtos.Favorite;
import com.android.launcher3.backup.BackupProtos.Journal;
import com.android.launcher3.backup.BackupProtos.Key;
@@ -66,24 +67,24 @@ import java.util.zip.CRC32;
 * Persist the launcher home state across calamities.
 */
public class LauncherBackupHelper implements BackupHelper {

    private static final String TAG = "LauncherBackupHelper";
    private static final boolean VERBOSE = LauncherBackupAgentHelper.VERBOSE;
    private static final boolean DEBUG = LauncherBackupAgentHelper.DEBUG;

    private static final int BACKUP_VERSION = 2;
    private static final int MAX_JOURNAL_SIZE = 1000000;

    // Journal key is such that it is always smaller than any dynamically generated
    // key (any Base64 encoded string).
    private static final String JOURNAL_KEY = "#";

    /** icons are large, dribble them out */
    private static final int MAX_ICONS_PER_PASS = 10;

    /** widgets contain previews, which are very large, dribble them out */
    private static final int MAX_WIDGETS_PER_PASS = 5;

    public static final int IMAGE_COMPRESSION_QUALITY = 75;

    public static final String LAUNCHER_PREFIX = "L";

    public static final String LAUNCHER_PREFS_PREFIX = "LP";
    private static final int IMAGE_COMPRESSION_QUALITY = 75;

    private static final Bitmap.CompressFormat IMAGE_FORMAT =
            android.graphics.Bitmap.CompressFormat.PNG;
@@ -145,10 +146,13 @@ public class LauncherBackupHelper implements BackupHelper {
    private byte[] mBuffer = new byte[512];
    private long mLastBackupRestoreTime;

    public LauncherBackupHelper(Context context, boolean restoreEnabled) {
    boolean restoreSuccessful;

    public LauncherBackupHelper(Context context) {
        mContext = context;
        mExistingKeys = new HashSet<String>();
        mKeys = new ArrayList<Key>();
        restoreSuccessful = true;
    }

    private void dataChanged() {
@@ -178,7 +182,6 @@ public class LauncherBackupHelper implements BackupHelper {
     * @param oldState notes from the last backup
     * @param data incremental key/value pairs to persist off-device
     * @param newState notes for the next backup
     * @throws IOException
     */
    @Override
    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
@@ -220,6 +223,12 @@ public class LauncherBackupHelper implements BackupHelper {

            mExistingKeys.clear();
            mLastBackupRestoreTime = newBackupTime;

            // We store the journal at two places.
            //   1) Storing it in newState allows us to do partial backups by comparing old state
            //   2) Storing it in backup data allows us to validate keys during restore
            Journal state = getCurrentStateJournal();
            writeRowToBackup(JOURNAL_KEY, state, data);
        } catch (IOException e) {
            Log.e(TAG, "launcher backup has failed", e);
        }
@@ -227,15 +236,27 @@ public class LauncherBackupHelper implements BackupHelper {
        writeNewStateDescription(newState);
    }

    /**
     * @return true if the backup corresponding to oldstate can be successfully applied
     * to this device.
     */
    private boolean isBackupCompatible(Journal oldState) {
        return true;
    }

    /**
     * Restore launcher configuration from the restored data stream.
     *
     * <P>Keys may arrive in any order.
     * It assumes that the keys will arrive in lexical order. So if the journal was present in the
     * backup, it should arrive first.
     *
     * @param data the key/value pair from the server
     */
    @Override
    public void restoreEntity(BackupDataInputStream data) {
        if (!restoreSuccessful) {
            return;
        }

        int dataSize = data.size();
        if (mBuffer.length < dataSize) {
            mBuffer = new byte[dataSize];
@@ -244,6 +265,27 @@ public class LauncherBackupHelper implements BackupHelper {
            int bytesRead = data.read(mBuffer, 0, dataSize);
            if (DEBUG) Log.d(TAG, "read " + bytesRead + " of " + dataSize + " available");
            String backupKey = data.getKey();

            if (JOURNAL_KEY.equals(backupKey)) {
                if (VERBOSE) Log.v(TAG, "Journal entry restored");
                if (!mKeys.isEmpty()) {
                    // We received the journal key after a restore key.
                    Log.wtf(TAG, keyToBackupKey(mKeys.get(0)) + " received after " + JOURNAL_KEY);
                    restoreSuccessful = false;
                    return;
                }

                Journal journal = new Journal();
                MessageNano.mergeFrom(journal, readCheckedBytes(mBuffer, dataSize));
                applyJournal(journal);
                restoreSuccessful = isBackupCompatible(journal);
                return;
            }

            if (!mExistingKeys.isEmpty() && !mExistingKeys.contains(backupKey)) {
                if (DEBUG) Log.e(TAG, "Ignoring key not present in the backup state " + backupKey);
                return;
            }
            Key key = backupKeyToKey(backupKey);
            mKeys.add(key);
            switch (key.type) {
@@ -288,6 +330,8 @@ public class LauncherBackupHelper implements BackupHelper {
        journal.t = mLastBackupRestoreTime;
        journal.key = mKeys.toArray(new BackupProtos.Key[mKeys.size()]);
        journal.appVersion = getAppVersion();
        journal.backupVersion = BACKUP_VERSION;
        journal.profile = getDeviceProfieData();
        return journal;
    }

@@ -300,6 +344,29 @@ public class LauncherBackupHelper implements BackupHelper {
        }
    }

    /**
     * @return the current device profile information.
     */
    private DeviceProfieData getDeviceProfieData() {
        LauncherAppState.setApplicationContext(mContext.getApplicationContext());
        LauncherAppState app = LauncherAppState.getInstance();

        DeviceProfile profile;
        if (app.getDynamicGrid() == null) {
            // Initialize the grid
            profile = app.initDynamicGrid(mContext);
        } else {
            profile = app.getDynamicGrid().getDeviceProfile();
        }

        DeviceProfieData data = new DeviceProfieData();
        data.desktopRows = profile.numRows;
        data.desktopCols = profile.numColumns;
        data.hotseatCount = profile.numHotseatIcons;
        data.allappsRank = profile.hotseatAllAppsRank;
        return data;
    }

    /**
     * Write all modified favorites to the data stream.
     *
@@ -902,7 +969,6 @@ public class LauncherBackupHelper implements BackupHelper {
        return journal;
    }


    private void writeRowToBackup(Key key, MessageNano proto, BackupDataOutput data)
            throws IOException {
        writeRowToBackup(keyToBackupKey(key), proto, data);
Loading