Merge "Stashing SyncSettings for accounts added aft SUW" into nyc-dev

am: 9ca8ed9302

* commit '9ca8ed9302f7d257ad3779d6dab34da645bc16b7':
  Stashing SyncSettings for accounts added aft SUW
This commit is contained in:
Ritesh Reddy
2016-02-12 16:34:20 +00:00
committed by android-build-merger
2 changed files with 135 additions and 58 deletions

View File

@@ -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;
@@ -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;
@@ -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;
@@ -256,41 +261,99 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper {
}
try {
HashSet<Account> currentAccounts = getAccountsHashSet();
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);
// Check if the account already exists. Accounts that don't exist on the device
// yet won't be restored.
if (currentAccounts.contains(account)) {
restoreExistingAccountSyncSettingsFromJSON(accountJSON);
} else {
// TODO:
// Stash the data to a file that the SyncManager can read from to restore
// settings at a later date.
}
}
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 = 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 {
unaddedAccountsJSONArray.put(accountJSON);
}
}
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();
}
}
/**
* 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();
}
/**
* Helper method - fetch accounts and return them as a HashSet.
*
* @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) {
@@ -359,4 +422,4 @@ public class AccountSyncSettingsBackupHelper implements BackupHelper {
public void writeNewStateDescription(ParcelFileDescriptor newState) {
}
}
}

View File

@@ -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;
@@ -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:
@@ -510,12 +512,12 @@ public class SyncManager {
mSyncStorageEngine.setPeriodicSyncAddedListener(
new SyncStorageEngine.PeriodicSyncAddedListener() {
@Override
public void onPeriodicSyncAdded(EndPoint target, Bundle extras, long pollFrequency,
long flex) {
updateOrAddPeriodicSync(target, pollFrequency, flex, extras);
}
});
@Override
public void onPeriodicSyncAdded(EndPoint target, Bundle extras, long pollFrequency,
long flex) {
updateOrAddPeriodicSync(target, pollFrequency, flex, extras);
}
});
mSyncStorageEngine.setOnAuthorityRemovedListener(new SyncStorageEngine.OnAuthorityRemovedListener() {
@Override
@@ -750,8 +752,8 @@ public class SyncManager {
* @param onlyThoseWithUnkownSyncableState Only sync authorities that have unknown state.
*/
public void scheduleSync(Account requestedAccount, int userId, int reason,
String requestedAuthority, Bundle extras, long beforeRuntimeMillis,
long runtimeMillis, boolean onlyThoseWithUnkownSyncableState) {
String requestedAuthority, Bundle extras, long beforeRuntimeMillis,
long runtimeMillis, boolean onlyThoseWithUnkownSyncableState) {
final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
if (extras == null) {
extras = new Bundle();
@@ -941,7 +943,7 @@ public class SyncManager {
* flexMillis will be updated.
*/
public void updateOrAddPeriodicSync(EndPoint target, long pollFrequency, long flex,
Bundle extras) {
Bundle extras) {
UpdatePeriodicSyncMessagePayload payload = new UpdatePeriodicSyncMessagePayload(target,
pollFrequency, flex, extras);
mSyncHandler.obtainMessage(SyncHandler.MESSAGE_UPDATE_PERIODIC_SYNC, payload)
@@ -995,7 +997,7 @@ public class SyncManager {
}
private void sendSyncFinishedOrCanceledMessage(ActiveSyncContext syncContext,
SyncResult syncResult) {
SyncResult syncResult) {
if (Log.isLoggable(TAG, Log.VERBOSE)) Slog.v(TAG, "sending MESSAGE_SYNC_FINISHED");
Message msg = mSyncHandler.obtainMessage();
msg.what = SyncHandler.MESSAGE_SYNC_FINISHED;
@@ -1053,7 +1055,7 @@ public class SyncManager {
public final SyncResult syncResult;
SyncFinishedOrCancelledMessagePayload(ActiveSyncContext syncContext,
SyncResult syncResult) {
SyncResult syncResult) {
this.activeSyncContext = syncContext;
this.syncResult = syncResult;
}
@@ -1066,7 +1068,7 @@ public class SyncManager {
public final Bundle extras;
UpdatePeriodicSyncMessagePayload(EndPoint target, long pollFrequency, long flex,
Bundle extras) {
Bundle extras) {
this.target = target;
this.pollFrequency = pollFrequency;
this.flex = flex;
@@ -1297,7 +1299,7 @@ public class SyncManager {
JobInfo.NETWORK_TYPE_UNMETERED : JobInfo.NETWORK_TYPE_ANY;
JobInfo.Builder b = new JobInfo.Builder(syncOperation.jobId,
new ComponentName(mContext, SyncJobService.class))
new ComponentName(mContext, SyncJobService.class))
.setExtras(syncOperation.toJobInfoExtras())
.setRequiredNetworkType(networkType)
.setPersisted(true)
@@ -1502,7 +1504,7 @@ public class SyncManager {
* for this sync. This is used to attribute the wakelock hold to that application.
*/
public ActiveSyncContext(SyncOperation syncOperation, long historyRowId,
int syncAdapterUid) {
int syncAdapterUid) {
super();
mSyncAdapterUid = syncAdapterUid;
mSyncOperation = syncOperation;
@@ -1731,7 +1733,7 @@ public class SyncManager {
new Comparator<RegisteredServicesCache.ServiceInfo<SyncAdapterType>>() {
@Override
public int compare(RegisteredServicesCache.ServiceInfo<SyncAdapterType> lhs,
RegisteredServicesCache.ServiceInfo<SyncAdapterType> rhs) {
RegisteredServicesCache.ServiceInfo<SyncAdapterType> rhs) {
return lhs.type.authority.compareTo(rhs.type.authority);
}
});
@@ -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: ");
@@ -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)) {
@@ -2618,7 +2632,7 @@ public class SyncManager {
* @param flexMillis new flex time in milliseconds.
*/
private void maybeUpdateSyncPeriodH(SyncOperation syncOperation, long pollFrequencyMillis,
long flexMillis) {
long flexMillis) {
if (!(pollFrequencyMillis == syncOperation.periodMillis
&& flexMillis == syncOperation.flexMillis)) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -2633,7 +2647,7 @@ public class SyncManager {
}
private void updateOrAddPeriodicSyncH(EndPoint target, long pollFrequency, long flex,
Bundle extras) {
Bundle extras) {
final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
verifyJobScheduler(); // Will fill in mScheduledSyncs cache if it is not already filled.
final long pollFrequencyMillis = pollFrequency * 1000L;
@@ -2821,7 +2835,7 @@ public class SyncManager {
}
private void runBoundToAdapterH(final ActiveSyncContext activeSyncContext,
IBinder syncAdapter) {
IBinder syncAdapter) {
final SyncOperation syncOperation = activeSyncContext.mSyncOperation;
try {
activeSyncContext.mIsLinkedToDeath = true;
@@ -2889,7 +2903,7 @@ public class SyncManager {
}
private void runSyncFinishedOrCanceledH(SyncResult syncResult,
ActiveSyncContext activeSyncContext) {
ActiveSyncContext activeSyncContext) {
final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
final SyncOperation syncOperation = activeSyncContext.mSyncOperation;
@@ -3023,7 +3037,7 @@ public class SyncManager {
}
private void installHandleTooManyDeletesNotification(Account account, String authority,
long numDeletes, int userId) {
long numDeletes, int userId) {
if (mNotificationMgr == null) return;
final ProviderInfo providerInfo = mContext.getPackageManager().resolveContentProvider(
@@ -3099,7 +3113,7 @@ public class SyncManager {
}
public void stopSyncEvent(long rowId, SyncOperation syncOperation, String resultMessage,
int upstreamActivity, int downstreamActivity, long elapsedTime) {
int upstreamActivity, int downstreamActivity, long elapsedTime) {
EventLog.writeEvent(2720,
syncOperation.toEventLog(SyncStorageEngine.EVENT_STOP));
mSyncStorageEngine.stopSyncEvent(rowId, elapsedTime,
@@ -3263,4 +3277,4 @@ public class SyncManager {
return mContext;
}
}
}
}