Loading core/java/com/android/server/backup/AccountSyncSettingsBackupHelper.java +88 −25 Original line number Diff line number Diff line Loading @@ -16,10 +16,6 @@ package com.android.server.backup; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.accounts.Account; import android.accounts.AccountManager; import android.app.backup.BackupDataInputStream; Loading @@ -28,14 +24,21 @@ import android.app.backup.BackupHelper; import android.content.ContentResolver; import android.content.Context; import android.content.SyncAdapterType; import android.os.Environment; import android.os.ParcelFileDescriptor; import android.util.Log; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.security.MessageDigest; Loading Loading @@ -73,6 +76,8 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { private static final String KEY_AUTHORITY_NAME = "name"; private static final String KEY_AUTHORITY_SYNC_STATE = "syncState"; private static final String KEY_AUTHORITY_SYNC_ENABLED = "syncEnabled"; private static final String STASH_FILE = Environment.getDataDirectory() + "/backup/unadded_account_syncsettings.json"; private Context mContext; private AccountManager mAccountManager; Loading Loading @@ -256,33 +261,91 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { } try { HashSet<Account> currentAccounts = getAccountsHashSet(); restoreFromJsonArray(accountJSONArray); } finally { // Set the master sync preference to the value from the backup set. ContentResolver.setMasterSyncAutomatically(masterSyncEnabled); } Log.i(TAG, "Restore successful."); } catch (IOException | JSONException e) { Log.e(TAG, "Couldn't restore account sync settings\n" + e); } } private void restoreFromJsonArray(JSONArray accountJSONArray) throws JSONException { HashSet<Account> currentAccounts = getAccounts(); JSONArray unaddedAccountsJSONArray = new JSONArray(); for (int i = 0; i < accountJSONArray.length(); i++) { JSONObject accountJSON = (JSONObject) accountJSONArray.get(i); String accountName = accountJSON.getString(KEY_ACCOUNT_NAME); String accountType = accountJSON.getString(KEY_ACCOUNT_TYPE); Account account = new Account(accountName, accountType); Account account = null; try { account = new Account(accountName, accountType); } catch (IllegalArgumentException iae) { continue; } // Check if the account already exists. Accounts that don't exist on the device // yet won't be restored. if (currentAccounts.contains(account)) { if (DEBUG) Log.i(TAG, "Restoring Sync Settings for" + accountName); restoreExistingAccountSyncSettingsFromJSON(accountJSON); } else { // TODO: // Stash the data to a file that the SyncManager can read from to restore // settings at a later date. unaddedAccountsJSONArray.put(accountJSON); } } } finally { // Set the master sync preference to the value from the backup set. ContentResolver.setMasterSyncAutomatically(masterSyncEnabled); if (unaddedAccountsJSONArray.length() > 0) { try (FileOutputStream fOutput = new FileOutputStream(STASH_FILE)) { String jsonString = unaddedAccountsJSONArray.toString(); DataOutputStream out = new DataOutputStream(fOutput); out.writeUTF(jsonString); } catch (IOException ioe) { // Error in writing to stash file Log.e(TAG, "unable to write the sync settings to the stash file", ioe); } } else { File stashFile = new File(STASH_FILE); if (stashFile.exists()) stashFile.delete(); } } Log.i(TAG, "Restore successful."); } catch (IOException | JSONException e) { Log.e(TAG, "Couldn't restore account sync settings\n" + e); /** * Restore SyncSettings for all existing accounts from a stashed backup-set */ private void accountAddedInternal() { String jsonString; try (FileInputStream fIn = new FileInputStream(new File(STASH_FILE))) { DataInputStream in = new DataInputStream(fIn); jsonString = in.readUTF(); } catch (FileNotFoundException fnfe) { // This is expected to happen when there is no accounts info stashed if (DEBUG) Log.d(TAG, "unable to find the stash file", fnfe); return; } catch (IOException ioe) { if (DEBUG) Log.d(TAG, "could not read sync settings from stash file", ioe); return; } try { JSONArray unaddedAccountsJSONArray = new JSONArray(jsonString); restoreFromJsonArray(unaddedAccountsJSONArray); } catch (JSONException jse) { // Malformed jsonString Log.e(TAG, "there was an error with the stashed sync settings", jse); } } /** * Restore SyncSettings for all existing accounts from a stashed backup-set */ public static void accountAdded(Context context) { AccountSyncSettingsBackupHelper helper = new AccountSyncSettingsBackupHelper(context); helper.accountAddedInternal(); } /** Loading @@ -290,7 +353,7 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { * * @return Accounts in a HashSet. */ private HashSet<Account> getAccountsHashSet() { private HashSet<Account> getAccounts() { Account[] accounts = mAccountManager.getAccounts(); HashSet<Account> accountHashSet = new HashSet<Account>(); for (Account account : accounts) { Loading services/core/java/com/android/server/content/SyncManager.java +47 −33 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; Loading @@ -70,41 +71,42 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.WorkSource; import android.os.Messenger; import android.provider.Settings; import android.text.format.DateUtils; import android.text.format.Time; import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import com.google.android.collect.Lists; import com.google.android.collect.Maps; import com.android.internal.R; import com.android.internal.app.IBatteryStats; import com.android.internal.os.BackgroundThread; import com.android.internal.util.IndentingPrintWriter; import com.android.server.accounts.AccountManagerService; import com.android.server.backup.AccountSyncSettingsBackupHelper; import com.android.server.content.SyncStorageEngine.AuthorityInfo; import com.android.server.content.SyncStorageEngine.EndPoint; import com.android.server.content.SyncStorageEngine.OnSyncRequestListener; import com.google.android.collect.Lists; import com.google.android.collect.Maps; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Random; import java.util.List; import java.util.Set; import java.util.HashSet; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Map; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Random; import java.util.Set; /** * Implementation details: Loading Loading @@ -2572,6 +2574,7 @@ public class SyncManager { } private void updateRunningAccountsH(EndPoint syncTargets) { AccountAndUser[] oldAccounts = mRunningAccounts; mRunningAccounts = AccountManagerService.getSingleton().getRunningAccounts(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Slog.v(TAG, "Accounts list: "); Loading @@ -2595,6 +2598,17 @@ public class SyncManager { } } // On account add, check if there are any settings to be restored. for (AccountAndUser aau : mRunningAccounts) { if (!containsAccountAndUser(oldAccounts, aau.account, aau.userId)) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Account " + aau.account + " added, checking sync restore data"); } AccountSyncSettingsBackupHelper.accountAdded(mContext); break; } } List<SyncOperation> ops = getAllPendingSyncsFromCache(); for (SyncOperation op: ops) { if (!containsAccountAndUser(accounts, op.target.account, op.target.userId)) { Loading Loading
core/java/com/android/server/backup/AccountSyncSettingsBackupHelper.java +88 −25 Original line number Diff line number Diff line Loading @@ -16,10 +16,6 @@ package com.android.server.backup; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.accounts.Account; import android.accounts.AccountManager; import android.app.backup.BackupDataInputStream; Loading @@ -28,14 +24,21 @@ import android.app.backup.BackupHelper; import android.content.ContentResolver; import android.content.Context; import android.content.SyncAdapterType; import android.os.Environment; import android.os.ParcelFileDescriptor; import android.util.Log; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.security.MessageDigest; Loading Loading @@ -73,6 +76,8 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { private static final String KEY_AUTHORITY_NAME = "name"; private static final String KEY_AUTHORITY_SYNC_STATE = "syncState"; private static final String KEY_AUTHORITY_SYNC_ENABLED = "syncEnabled"; private static final String STASH_FILE = Environment.getDataDirectory() + "/backup/unadded_account_syncsettings.json"; private Context mContext; private AccountManager mAccountManager; Loading Loading @@ -256,33 +261,91 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { } try { HashSet<Account> currentAccounts = getAccountsHashSet(); restoreFromJsonArray(accountJSONArray); } finally { // Set the master sync preference to the value from the backup set. ContentResolver.setMasterSyncAutomatically(masterSyncEnabled); } Log.i(TAG, "Restore successful."); } catch (IOException | JSONException e) { Log.e(TAG, "Couldn't restore account sync settings\n" + e); } } private void restoreFromJsonArray(JSONArray accountJSONArray) throws JSONException { HashSet<Account> currentAccounts = getAccounts(); JSONArray unaddedAccountsJSONArray = new JSONArray(); for (int i = 0; i < accountJSONArray.length(); i++) { JSONObject accountJSON = (JSONObject) accountJSONArray.get(i); String accountName = accountJSON.getString(KEY_ACCOUNT_NAME); String accountType = accountJSON.getString(KEY_ACCOUNT_TYPE); Account account = new Account(accountName, accountType); Account account = null; try { account = new Account(accountName, accountType); } catch (IllegalArgumentException iae) { continue; } // Check if the account already exists. Accounts that don't exist on the device // yet won't be restored. if (currentAccounts.contains(account)) { if (DEBUG) Log.i(TAG, "Restoring Sync Settings for" + accountName); restoreExistingAccountSyncSettingsFromJSON(accountJSON); } else { // TODO: // Stash the data to a file that the SyncManager can read from to restore // settings at a later date. unaddedAccountsJSONArray.put(accountJSON); } } } finally { // Set the master sync preference to the value from the backup set. ContentResolver.setMasterSyncAutomatically(masterSyncEnabled); if (unaddedAccountsJSONArray.length() > 0) { try (FileOutputStream fOutput = new FileOutputStream(STASH_FILE)) { String jsonString = unaddedAccountsJSONArray.toString(); DataOutputStream out = new DataOutputStream(fOutput); out.writeUTF(jsonString); } catch (IOException ioe) { // Error in writing to stash file Log.e(TAG, "unable to write the sync settings to the stash file", ioe); } } else { File stashFile = new File(STASH_FILE); if (stashFile.exists()) stashFile.delete(); } } Log.i(TAG, "Restore successful."); } catch (IOException | JSONException e) { Log.e(TAG, "Couldn't restore account sync settings\n" + e); /** * Restore SyncSettings for all existing accounts from a stashed backup-set */ private void accountAddedInternal() { String jsonString; try (FileInputStream fIn = new FileInputStream(new File(STASH_FILE))) { DataInputStream in = new DataInputStream(fIn); jsonString = in.readUTF(); } catch (FileNotFoundException fnfe) { // This is expected to happen when there is no accounts info stashed if (DEBUG) Log.d(TAG, "unable to find the stash file", fnfe); return; } catch (IOException ioe) { if (DEBUG) Log.d(TAG, "could not read sync settings from stash file", ioe); return; } try { JSONArray unaddedAccountsJSONArray = new JSONArray(jsonString); restoreFromJsonArray(unaddedAccountsJSONArray); } catch (JSONException jse) { // Malformed jsonString Log.e(TAG, "there was an error with the stashed sync settings", jse); } } /** * Restore SyncSettings for all existing accounts from a stashed backup-set */ public static void accountAdded(Context context) { AccountSyncSettingsBackupHelper helper = new AccountSyncSettingsBackupHelper(context); helper.accountAddedInternal(); } /** Loading @@ -290,7 +353,7 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper { * * @return Accounts in a HashSet. */ private HashSet<Account> getAccountsHashSet() { private HashSet<Account> getAccounts() { Account[] accounts = mAccountManager.getAccounts(); HashSet<Account> accountHashSet = new HashSet<Account>(); for (Account account : accounts) { Loading
services/core/java/com/android/server/content/SyncManager.java +47 −33 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; Loading @@ -70,41 +71,42 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.WorkSource; import android.os.Messenger; import android.provider.Settings; import android.text.format.DateUtils; import android.text.format.Time; import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import com.google.android.collect.Lists; import com.google.android.collect.Maps; import com.android.internal.R; import com.android.internal.app.IBatteryStats; import com.android.internal.os.BackgroundThread; import com.android.internal.util.IndentingPrintWriter; import com.android.server.accounts.AccountManagerService; import com.android.server.backup.AccountSyncSettingsBackupHelper; import com.android.server.content.SyncStorageEngine.AuthorityInfo; import com.android.server.content.SyncStorageEngine.EndPoint; import com.android.server.content.SyncStorageEngine.OnSyncRequestListener; import com.google.android.collect.Lists; import com.google.android.collect.Maps; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Random; import java.util.List; import java.util.Set; import java.util.HashSet; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Map; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Random; import java.util.Set; /** * Implementation details: Loading Loading @@ -2572,6 +2574,7 @@ public class SyncManager { } private void updateRunningAccountsH(EndPoint syncTargets) { AccountAndUser[] oldAccounts = mRunningAccounts; mRunningAccounts = AccountManagerService.getSingleton().getRunningAccounts(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Slog.v(TAG, "Accounts list: "); Loading @@ -2595,6 +2598,17 @@ public class SyncManager { } } // On account add, check if there are any settings to be restored. for (AccountAndUser aau : mRunningAccounts) { if (!containsAccountAndUser(oldAccounts, aau.account, aau.userId)) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Account " + aau.account + " added, checking sync restore data"); } AccountSyncSettingsBackupHelper.accountAdded(mContext); break; } } List<SyncOperation> ops = getAllPendingSyncsFromCache(); for (SyncOperation op: ops) { if (!containsAccountAndUser(accounts, op.target.account, op.target.userId)) { Loading