Loading protos/backup.proto +24 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading src/com/android/launcher3/Launcher.java +1 −16 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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(), Loading src/com/android/launcher3/LauncherAppState.java +25 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() { Loading src/com/android/launcher3/LauncherBackupAgentHelper.java +11 −23 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. * Loading @@ -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 Loading @@ -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(); } Loading src/com/android/launcher3/LauncherBackupHelper.java +77 −11 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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() { Loading Loading @@ -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, Loading Loading @@ -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); } Loading @@ -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]; Loading @@ -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) { Loading Loading @@ -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; } Loading @@ -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. * Loading Loading @@ -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 Loading
protos/backup.proto +24 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading
src/com/android/launcher3/Launcher.java +1 −16 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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(), Loading
src/com/android/launcher3/LauncherAppState.java +25 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() { Loading
src/com/android/launcher3/LauncherBackupAgentHelper.java +11 −23 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. * Loading @@ -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 Loading @@ -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(); } Loading
src/com/android/launcher3/LauncherBackupHelper.java +77 −11 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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() { Loading Loading @@ -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, Loading Loading @@ -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); } Loading @@ -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]; Loading @@ -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) { Loading Loading @@ -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; } Loading @@ -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. * Loading Loading @@ -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