下面列出了怎么用android.app.backup.BackupDataOutput的API类实例代码及写法,或者点击链接到github查看源代码。
private long writeIfChanged(long oldChecksum, String key, byte[] data,
BackupDataOutput output) {
CRC32 checkSummer = new CRC32();
checkSummer.update(data);
long newChecksum = checkSummer.getValue();
if (oldChecksum == newChecksum) {
return oldChecksum;
}
try {
output.writeEntityHeader(key, data.length);
output.writeEntityData(data, data.length);
} catch (IOException ioe) {
// Bail
}
return newChecksum;
}
private long writeIfChanged(long oldChecksum, String key, byte[] data,
BackupDataOutput output) {
CRC32 checkSummer = new CRC32();
checkSummer.update(data);
long newChecksum = checkSummer.getValue();
if (oldChecksum == newChecksum) {
return oldChecksum;
}
try {
if (DEBUG_BACKUP) {
Log.v(TAG, "Writing entity " + key + " of size " + data.length);
}
output.writeEntityHeader(key, data.length);
output.writeEntityData(data, data.length);
} catch (IOException ioe) {
// Bail
}
return newChecksum;
}
/**
* Write all modified screens to the data stream.
*
* @param data output stream for key/value pairs
* @throws IOException
*/
private void backupScreens(BackupDataOutput data) throws IOException {
// persist things that have changed since the last backup
ContentResolver cr = mContext.getContentResolver();
Cursor cursor = cr.query(WorkspaceScreens.CONTENT_URI, SCREEN_PROJECTION,
null, null, null);
try {
cursor.moveToPosition(-1);
if (DEBUG) Log.d(TAG, "dumping screens after: " + mLastBackupRestoreTime);
while(cursor.moveToNext()) {
final long id = cursor.getLong(ID_INDEX);
final long updateTime = cursor.getLong(ID_MODIFIED);
Key key = getKey(Key.SCREEN, id);
mKeys.add(key);
final String backupKey = keyToBackupKey(key);
if (!mExistingKeys.contains(backupKey) || updateTime >= mLastBackupRestoreTime) {
writeRowToBackup(key, packScreen(cursor), data);
} else {
if (VERBOSE) Log.v(TAG, "screen already backup up " + id);
}
}
} finally {
cursor.close();
}
}
private void writeRowToBackup(Key key, byte[] blob, Journal out,
BackupDataOutput data) throws IOException {
String backupKey = keyToBackupKey(key);
data.writeEntityHeader(backupKey, blob.length);
data.writeEntityData(blob, blob.length);
out.rows++;
out.bytes += blob.length;
if (VERBOSE) Log.v(TAG, "saving " + geKeyType(key) + " " + backupKey + ": " +
getKeyName(key) + "/" + blob.length);
if(DEBUG_PAYLOAD) {
String encoded = Base64.encodeToString(blob, 0, blob.length, Base64.NO_WRAP);
final int chunkSize = 1024;
for (int offset = 0; offset < encoded.length(); offset += chunkSize) {
int end = offset + chunkSize;
end = Math.min(end, encoded.length());
Log.w(TAG, "wrote " + encoded.substring(offset, end));
}
}
}
/**
* Write all modified favorites to the data stream.
*
* @param data output stream for key/value pairs
* @throws IOException
*/
private void backupFavorites(BackupDataOutput data) throws IOException {
// persist things that have changed since the last backup
ContentResolver cr = mContext.getContentResolver();
// Don't backup apps in other profiles for now.
Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
getUserSelectionArg(), null, null);
try {
cursor.moveToPosition(-1);
while(cursor.moveToNext()) {
final long id = cursor.getLong(ID_INDEX);
final long updateTime = cursor.getLong(ID_MODIFIED);
Key key = getKey(Key.FAVORITE, id);
mKeys.add(key);
final String backupKey = keyToBackupKey(key);
if (!mExistingKeys.contains(backupKey) || updateTime >= mLastBackupRestoreTime) {
writeRowToBackup(key, packFavorite(cursor), data);
} else {
if (DEBUG) Log.d(TAG, "favorite already backup up: " + id);
}
}
} finally {
cursor.close();
}
}
/**
* Write all modified screens to the data stream.
*
* @param data output stream for key/value pairs
* @throws IOException
*/
private void backupScreens(BackupDataOutput data) throws IOException {
// persist things that have changed since the last backup
ContentResolver cr = mContext.getContentResolver();
Cursor cursor = cr.query(WorkspaceScreens.CONTENT_URI, SCREEN_PROJECTION,
null, null, null);
try {
cursor.moveToPosition(-1);
if (DEBUG) Log.d(TAG, "dumping screens after: " + mLastBackupRestoreTime);
while(cursor.moveToNext()) {
final long id = cursor.getLong(ID_INDEX);
final long updateTime = cursor.getLong(ID_MODIFIED);
Key key = getKey(Key.SCREEN, id);
mKeys.add(key);
final String backupKey = keyToBackupKey(key);
if (!mExistingKeys.contains(backupKey) || updateTime >= mLastBackupRestoreTime) {
writeRowToBackup(key, packScreen(cursor), data);
} else {
if (VERBOSE) Log.v(TAG, "screen already backup up " + id);
}
}
} finally {
cursor.close();
}
}
@Override
public void onCreate() {
// The name of the SharedPreferences file
final String prefs = getPackageName() + "_preferences"; // getPackageName() cannot be used in final
SharedPreferencesBackupHelper prefsHelper = new SharedPreferencesBackupHelper(this, prefs) {
@Override
public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) {
if (new WorkTimeTrackerBackupManager(WorkTimeTrackerBackupAgentHelper.this).isEnabled()) {
super.performBackup(oldState, data, newState);
}
}
};
addHelper(PREFS_BACKUP_KEY, prefsHelper);
DbBackupHelper dbHelper = new DbBackupHelper(this);
addHelper(DB_BACKUP_KEY, dbHelper);
}
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) throws IOException {
// Hold the lock while the FileBackupHelper performs the backup operation
synchronized (sDataLock) {
super.onBackup(oldState, data, newState);
}
}
private void writeData(BackupDataOutput data, String value) throws IOException {
// Create buffer stream and data output stream for our data
ByteArrayOutputStream bufStream = new ByteArrayOutputStream();
DataOutputStream outWriter = new DataOutputStream(bufStream);
// Write structured data
outWriter.writeUTF(value);
// Send the data to the Backup Manager via the BackupDataOutput
byte[] buffer = bufStream.toByteArray();
int len = buffer.length;
data.writeEntityHeader(ACCOUNTS_BACKUP_KEY, len);
data.writeEntityData(buffer, len);
}
private void writeData(BackupDataOutput data, String value) throws IOException {
// Create buffer stream and data output stream for our data
ByteArrayOutputStream bufStream = new ByteArrayOutputStream();
DataOutputStream outWriter = new DataOutputStream(bufStream);
// Write structured data
outWriter.writeUTF(value);
// Send the data to the Backup Manager via the BackupDataOutput
byte[] buffer = bufStream.toByteArray();
int len = buffer.length;
data.writeEntityHeader(SETTINGS_BACKUP_KEY, len);
data.writeEntityData(buffer, len);
}
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException {
Settings settings = new Settings(this);
if(settings.getAndroidBackupServiceEnabled()) {
synchronized (DatabaseHelper.DatabaseFileLock) {
super.onBackup(oldState, data, newState);
}
}
}
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) throws IOException {
Log.i(TAG, "Performing backup");
SharedPreferences preferences = this.getSharedPreferences(
Constants.SETTINGS_NAME, Context.MODE_PRIVATE);
backupPreferences(data, preferences);
Log.i(TAG, "Backup complete");
}
private void backupPreferences(BackupDataOutput data,
SharedPreferences preferences) throws IOException {
PreferenceBackupHelper preferenceDumper = createPreferenceBackupHelper();
byte[] dumpedContents = preferenceDumper.exportPreferences(preferences);
data.writeEntityHeader(PREFERENCES_ENTITY, dumpedContents.length);
data.writeEntityData(dumpedContents, dumpedContents.length);
}
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) throws IOException {
byte[] systemSettingsData = getSystemSettings();
byte[] secureSettingsData = getSecureSettings();
byte[] globalSettingsData = getGlobalSettings();
byte[] locale = mSettingsHelper.getLocaleData();
byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
byte[] wifiConfigData = getFileData(mWifiConfigFile);
long[] stateChecksums = readOldChecksums(oldState);
stateChecksums[STATE_SYSTEM] =
writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
stateChecksums[STATE_SECURE] =
writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
stateChecksums[STATE_GLOBAL] =
writeIfChanged(stateChecksums[STATE_GLOBAL], KEY_GLOBAL, globalSettingsData, data);
stateChecksums[STATE_LOCALE] =
writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
stateChecksums[STATE_WIFI_SUPPLICANT] =
writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT,
wifiSupplicantData, data);
stateChecksums[STATE_WIFI_CONFIG] =
writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData,
data);
writeNewChecksums(stateChecksums, newState);
}
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) throws IOException {
byte[] systemSettingsData = getSystemSettings();
byte[] secureSettingsData = getSecureSettings();
byte[] globalSettingsData = getGlobalSettings();
byte[] lockSettingsData = getLockSettings();
byte[] locale = mSettingsHelper.getLocaleData();
byte[] softApConfigData = getSoftAPConfiguration();
byte[] netPoliciesData = getNetworkPolicies();
byte[] wifiFullConfigData = getNewWifiConfigData();
long[] stateChecksums = readOldChecksums(oldState);
stateChecksums[STATE_SYSTEM] =
writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
stateChecksums[STATE_SECURE] =
writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
stateChecksums[STATE_GLOBAL] =
writeIfChanged(stateChecksums[STATE_GLOBAL], KEY_GLOBAL, globalSettingsData, data);
stateChecksums[STATE_LOCALE] =
writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
stateChecksums[STATE_WIFI_SUPPLICANT] = 0;
stateChecksums[STATE_WIFI_CONFIG] = 0;
stateChecksums[STATE_LOCK_SETTINGS] =
writeIfChanged(stateChecksums[STATE_LOCK_SETTINGS], KEY_LOCK_SETTINGS,
lockSettingsData, data);
stateChecksums[STATE_SOFTAP_CONFIG] =
writeIfChanged(stateChecksums[STATE_SOFTAP_CONFIG], KEY_SOFTAP_CONFIG,
softApConfigData, data);
stateChecksums[STATE_NETWORK_POLICIES] =
writeIfChanged(stateChecksums[STATE_NETWORK_POLICIES], KEY_NETWORK_POLICIES,
netPoliciesData, data);
stateChecksums[STATE_WIFI_NEW_CONFIG] =
writeIfChanged(stateChecksums[STATE_WIFI_NEW_CONFIG], KEY_WIFI_NEW_CONFIG,
wifiFullConfigData, data);
writeNewChecksums(stateChecksums, newState);
}
/**
* Write all modified favorites to the data stream.
*
* @param data output stream for key/value pairs
* @throws IOException
*/
private void backupFavorites(BackupDataOutput data) throws IOException {
// persist things that have changed since the last backup
ContentResolver cr = mContext.getContentResolver();
// Don't backup apps in other profiles for now.
Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
getUserSelectionArg(), null, null);
try {
cursor.moveToPosition(-1);
while(cursor.moveToNext()) {
final long id = cursor.getLong(ID_INDEX);
final long updateTime = cursor.getLong(ID_MODIFIED);
Key key = getKey(Key.FAVORITE, id);
mKeys.add(key);
final String backupKey = keyToBackupKey(key);
// Favorite proto changed in v4. Backup again if the version is old.
if (!mExistingKeys.contains(backupKey) || updateTime >= mLastBackupRestoreTime
|| restoredBackupVersion < 4) {
writeRowToBackup(key, packFavorite(cursor), data);
} else {
if (DEBUG) Log.d(TAG, "favorite already backup up: " + id);
}
}
} finally {
cursor.close();
}
}
private void writeRowToBackup(String backupKey, MessageNano proto,
BackupDataOutput data) throws IOException {
byte[] blob = writeCheckedBytes(proto);
data.writeEntityHeader(backupKey, blob.length);
data.writeEntityData(blob, blob.length);
mBackupDataWasUpdated = true;
if (VERBOSE) Log.v(TAG, "Writing New entry " + backupKey);
}
/**
* Back up launcher data so we can restore the user's state on a new device.
*
* <P>The journal is a timestamp and a list of keys that were saved as of that time.
*
* <P>Keys may come back in any order, so each key/value is one complete row of the database.
*
* @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,
ParcelFileDescriptor newState) {
if (VERBOSE) Log.v(TAG, "onBackup");
Journal in = readJournal(oldState);
Journal out = new Journal();
long lastBackupTime = in.t;
out.t = System.currentTimeMillis();
out.rows = 0;
out.bytes = 0;
Log.v(TAG, "lastBackupTime = " + lastBackupTime);
ArrayList<Key> keys = new ArrayList<Key>();
if (launcherIsReady()) {
try {
backupFavorites(in, data, out, keys);
backupScreens(in, data, out, keys);
backupIcons(in, data, out, keys);
backupWidgets(in, data, out, keys);
} catch (IOException e) {
Log.e(TAG, "launcher backup has failed", e);
}
out.key = keys.toArray(new BackupProtos.Key[keys.size()]);
} else {
out = in;
}
writeJournal(newState, out);
Log.v(TAG, "onBackup: wrote " + out.bytes + "b in " + out.rows + " rows.");
}
/**
* Write all modified favorites to the data stream.
*
*
* @param in notes from last backup
* @param data output stream for key/value pairs
* @param out notes about this backup
* @param keys keys to mark as clean in the notes for next backup
* @throws IOException
*/
private void backupFavorites(Journal in, BackupDataOutput data, Journal out,
ArrayList<Key> keys)
throws IOException {
// read the old ID set
Set<String> savedIds = getSavedIdsByType(Key.FAVORITE, in);
if (DEBUG) Log.d(TAG, "favorite savedIds.size()=" + savedIds.size());
// persist things that have changed since the last backup
ContentResolver cr = mContext.getContentResolver();
Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
null, null, null);
Set<String> currentIds = new HashSet<String>(cursor.getCount());
try {
cursor.moveToPosition(-1);
while(cursor.moveToNext()) {
final long id = cursor.getLong(ID_INDEX);
final long updateTime = cursor.getLong(ID_MODIFIED);
Key key = getKey(Key.FAVORITE, id);
keys.add(key);
final String backupKey = keyToBackupKey(key);
currentIds.add(backupKey);
if (!savedIds.contains(backupKey) || updateTime >= in.t) {
byte[] blob = packFavorite(cursor);
writeRowToBackup(key, blob, out, data);
} else {
if (VERBOSE) Log.v(TAG, "favorite " + id + " was too old: " + updateTime);
}
}
} finally {
cursor.close();
}
if (DEBUG) Log.d(TAG, "favorite currentIds.size()=" + currentIds.size());
// these IDs must have been deleted
savedIds.removeAll(currentIds);
out.rows += removeDeletedKeysFromBackup(savedIds, data);
}
/**
* Write all modified screens to the data stream.
*
*
* @param in notes from last backup
* @param data output stream for key/value pairs
* @param out notes about this backup
* @param keys keys to mark as clean in the notes for next backup
* @throws IOException
*/
private void backupScreens(Journal in, BackupDataOutput data, Journal out,
ArrayList<Key> keys)
throws IOException {
// read the old ID set
Set<String> savedIds = getSavedIdsByType(Key.SCREEN, in);
if (DEBUG) Log.d(TAG, "screen savedIds.size()=" + savedIds.size());
// persist things that have changed since the last backup
ContentResolver cr = mContext.getContentResolver();
Cursor cursor = cr.query(WorkspaceScreens.CONTENT_URI, SCREEN_PROJECTION,
null, null, null);
Set<String> currentIds = new HashSet<String>(cursor.getCount());
try {
cursor.moveToPosition(-1);
if (DEBUG) Log.d(TAG, "dumping screens after: " + in.t);
while(cursor.moveToNext()) {
final long id = cursor.getLong(ID_INDEX);
final long updateTime = cursor.getLong(ID_MODIFIED);
Key key = getKey(Key.SCREEN, id);
keys.add(key);
final String backupKey = keyToBackupKey(key);
currentIds.add(backupKey);
if (!savedIds.contains(backupKey) || updateTime >= in.t) {
byte[] blob = packScreen(cursor);
writeRowToBackup(key, blob, out, data);
} else {
if (VERBOSE) Log.v(TAG, "screen " + id + " was too old: " + updateTime);
}
}
} finally {
cursor.close();
}
if (DEBUG) Log.d(TAG, "screen currentIds.size()=" + currentIds.size());
// these IDs must have been deleted
savedIds.removeAll(currentIds);
out.rows += removeDeletedKeysFromBackup(savedIds, data);
}
private int removeDeletedKeysFromBackup(Set<String> deletedIds, BackupDataOutput data)
throws IOException {
int rows = 0;
for(String deleted: deletedIds) {
if (VERBOSE) Log.v(TAG, "dropping deleted item " + deleted);
data.writeEntityHeader(deleted, -1);
rows++;
}
return rows;
}
private void writeRowToBackup(String backupKey, MessageNano proto,
BackupDataOutput data) throws IOException {
byte[] blob = writeCheckedBytes(proto);
data.writeEntityHeader(backupKey, blob.length);
data.writeEntityData(blob, blob.length);
if (VERBOSE) Log.v(TAG, "Writing New entry " + backupKey);
}
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) throws IOException {
// Hold the lock while the FileBackupHelper performs backup
synchronized (UserData.sFileBackupLock) {
super.onBackup(oldState, data, newState);
}
}
@Override
public void onBackup(
ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) {
// Doesn't do incremental backup/restore
}
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) throws IOException {
// No implementation needed for Android 6.0 Auto Backup. Used only on older versions of
// Android Backup
}
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException {
synchronized (DbHelper.sLock) {
super.onBackup(oldState, data, newState);
}
}
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) throws IOException {
final ChromeBackupAgent backupAgent = this;
final ArrayList<String> backupNames = new ArrayList<>();
final ArrayList<byte[]> backupValues = new ArrayList<>();
// The native preferences can only be read on the UI thread.
if (!ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean>() {
@Override
public Boolean call() {
// Start the browser if necessary, so that Chrome can access the native
// preferences. Although Chrome requests the backup, it doesn't happen
// immediately, so by the time it does Chrome may not be running.
if (!initializeBrowser(backupAgent)) return false;
String[] nativeBackupNames = nativeGetBoolBackupNames();
boolean[] nativeBackupValues = nativeGetBoolBackupValues();
assert nativeBackupNames.length == nativeBackupValues.length;
for (String name : nativeBackupNames) {
backupNames.add(NATIVE_PREF_PREFIX + name);
}
for (boolean val : nativeBackupValues) {
backupValues.add(booleanToBytes(val));
}
return true;
}
})) {
// Something went wrong reading the native preferences, skip the backup.
return;
}
// Add the Android boolean prefs.
SharedPreferences sharedPrefs = ContextUtils.getAppSharedPreferences();
for (String prefName : BACKUP_ANDROID_BOOL_PREFS) {
if (sharedPrefs.contains(prefName)) {
backupNames.add(ANDROID_DEFAULT_PREFIX + prefName);
backupValues.add(booleanToBytes(sharedPrefs.getBoolean(prefName, false)));
}
}
// Finally add the user id.
backupNames.add(ANDROID_DEFAULT_PREFIX + ChromeSigninController.SIGNED_IN_ACCOUNT_KEY);
backupValues.add(
sharedPrefs.getString(ChromeSigninController.SIGNED_IN_ACCOUNT_KEY, "").getBytes());
BackupState newBackupState = new BackupState(backupNames, backupValues);
// Check if a backup is actually needed.
try {
BackupState oldBackupState = new BackupState(oldState);
if (newBackupState.equals(oldBackupState)) {
Log.i(TAG, "Nothing has changed since the last backup. Backup skipped.");
newBackupState.save(newState);
return;
}
} catch (IOException e) {
// This will happen if Chrome has never written backup data, or if the backup status is
// corrupt. Create a new backup in either case.
Log.i(TAG, "Can't read backup status file");
}
// Write the backup data
for (int i = 0; i < backupNames.size(); i++) {
data.writeEntityHeader(backupNames.get(i), backupValues.get(i).length);
data.writeEntityData(backupValues.get(i), backupValues.get(i).length);
}
// Remember the backup state.
newBackupState.save(newState);
Log.i(TAG, "Backup complete");
}
/**
* Back up launcher data so we can restore the user's state on a new device.
*
* <P>The journal is a timestamp and a list of keys that were saved as of that time.
*
* <P>Keys may come back in any order, so each key/value is one complete row of the database.
*
* @param oldState notes from the last backup
* @param data incremental key/value pairs to persist off-device
* @param newState notes for the next backup
*/
@Override
public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
ParcelFileDescriptor newState) {
if (VERBOSE) Log.v(TAG, "onBackup");
Journal in = readJournal(oldState);
if (!launcherIsReady()) {
dataChanged();
// Perform backup later.
writeJournal(newState, in);
return;
}
if (mDeviceProfileData == null) {
LauncherAppState app = LauncherAppState.getInstance();
mIdp = app.getInvariantDeviceProfile();
mDeviceProfileData = initDeviceProfileData(mIdp);
mIconCache = app.getIconCache();
}
Log.v(TAG, "lastBackupTime = " + in.t);
mKeys.clear();
applyJournal(in);
// Record the time before performing backup so that entries edited while the backup
// was going on, do not get missed in next backup.
long newBackupTime = System.currentTimeMillis();
mBackupDataWasUpdated = false;
try {
backupFavorites(data);
backupScreens(data);
backupIcons(data);
backupWidgets(data);
// Delete any key which still exist in the old backup, but is not valid anymore.
HashSet<String> validKeys = new HashSet<String>();
for (Key key : mKeys) {
validKeys.add(keyToBackupKey(key));
}
mExistingKeys.removeAll(validKeys);
// Delete anything left in the existing keys.
for (String deleted: mExistingKeys) {
if (VERBOSE) Log.v(TAG, "dropping deleted item " + deleted);
data.writeEntityHeader(deleted, -1);
mBackupDataWasUpdated = true;
}
mExistingKeys.clear();
if (!mBackupDataWasUpdated) {
// Check if any metadata has changed
mBackupDataWasUpdated = (in.profile == null)
|| !Arrays.equals(DeviceProfieData.toByteArray(in.profile),
DeviceProfieData.toByteArray(mDeviceProfileData))
|| (in.backupVersion != BACKUP_VERSION)
|| (in.appVersion != getAppVersion());
}
if (mBackupDataWasUpdated) {
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);
} else {
if (DEBUG) Log.d(TAG, "Nothing was written during backup");
}
} catch (IOException e) {
Log.e(TAG, "launcher backup has failed", e);
}
writeNewStateDescription(newState);
}
/**
* Write all the static widget resources we need to render placeholders
* for a package that is not installed.
*
* @param data output stream for key/value pairs
* @throws IOException
*/
private void backupWidgets(BackupDataOutput data) throws IOException {
// persist static widget info that hasn't been persisted yet
final ContentResolver cr = mContext.getContentResolver();
final int dpi = mContext.getResources().getDisplayMetrics().densityDpi;
int backupWidgetCount = 0;
String where = Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_APPWIDGET + " AND "
+ getUserSelectionArg();
Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
where, null, null);
try {
cursor.moveToPosition(-1);
while(cursor.moveToNext()) {
final long id = cursor.getLong(ID_INDEX);
final String providerName = cursor.getString(APPWIDGET_PROVIDER_INDEX);
final ComponentName provider = ComponentName.unflattenFromString(providerName);
Key key = null;
String backupKey = null;
if (provider != null) {
key = getKey(Key.WIDGET, providerName);
backupKey = keyToBackupKey(key);
} else {
Log.w(TAG, "empty intent on appwidget: " + id);
}
// Widget backup proto changed in v3. So add it again if the original backup is old.
if (mExistingKeys.contains(backupKey) && restoredBackupVersion >= 3) {
if (DEBUG) Log.d(TAG, "already saved widget " + backupKey);
// remember that we already backed this up previously
mKeys.add(key);
} else if (backupKey != null) {
if (DEBUG) Log.d(TAG, "I can count this high: " + backupWidgetCount);
if (backupWidgetCount < MAX_WIDGETS_PER_PASS) {
if (DEBUG) Log.d(TAG, "saving widget " + backupKey);
UserHandleCompat user = UserHandleCompat.myUserHandle();
writeRowToBackup(key, packWidget(dpi, provider, user), data);
mKeys.add(key);
backupWidgetCount ++;
} else {
if (VERBOSE) Log.v(TAG, "deferring widget backup " + backupKey);
// too many widgets for this pass, request another.
dataChanged();
}
}
}
} finally {
cursor.close();
}
}
private void writeRowToBackup(Key key, MessageNano proto, BackupDataOutput data)
throws IOException {
writeRowToBackup(keyToBackupKey(key), proto, data);
}