DelayedSyncController.java revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5package org.chromium.chrome.browser.sync; 6 7import android.accounts.Account; 8import android.content.ContentResolver; 9import android.content.Context; 10import android.content.SharedPreferences; 11import android.os.AsyncTask; 12import android.os.Bundle; 13import android.preference.PreferenceManager; 14import android.util.Log; 15 16import org.chromium.base.ApplicationStatus; 17import org.chromium.base.VisibleForTesting; 18import org.chromium.sync.notifier.SyncStatusHelper; 19import org.chromium.sync.signin.AccountManagerHelper; 20 21/** 22 * A class for controlling when a sync should be performed immediately, and when it should be 23 * delayed until Chrome comes to the foreground again. 24 */ 25public class DelayedSyncController { 26 private static final String TAG = "DelayedSyncController"; 27 private static final String DELAYED_ACCOUNT_NAME = "delayed_account"; 28 29 private static class LazyHolder { 30 private static final DelayedSyncController INSTANCE = new DelayedSyncController(); 31 } 32 33 public static DelayedSyncController getInstance() { 34 return LazyHolder.INSTANCE; 35 } 36 37 @VisibleForTesting 38 DelayedSyncController() {} 39 40 /** 41 * Resume any syncs that were delayed while Chromium was backgrounded. 42 */ 43 public boolean resumeDelayedSyncs(final Context context) { 44 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 45 String accountName = prefs.getString(DELAYED_ACCOUNT_NAME, null); 46 if (accountName == null) { 47 Log.d(TAG, "No delayed sync."); 48 return false; 49 } else { 50 Log.d(TAG, "Handling delayed sync."); 51 Account account = AccountManagerHelper.createAccountFromName(accountName); 52 requestSyncOnBackgroundThread(context, account); 53 return true; 54 } 55 } 56 57 /** 58 * Calls ContentResolver.requestSync() in a separate thread as it performs some blocking 59 * IO operations. 60 */ 61 @VisibleForTesting 62 void requestSyncOnBackgroundThread(final Context context, final Account account) { 63 new AsyncTask<Void, Void, Void>() { 64 @Override 65 protected Void doInBackground(Void... unused) { 66 String contractAuthority = 67 SyncStatusHelper.get(context).getContractAuthority(); 68 ContentResolver.requestSync(account, contractAuthority, new Bundle()); 69 return null; 70 } 71 }.execute(); 72 } 73 74 /** 75 * Stores preferences to indicate that an invalidation has arrived, but dropped on the floor. 76 */ 77 void setDelayedSync(Context ctx, String accountName) { 78 SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(ctx).edit(); 79 editor.putString(DELAYED_ACCOUNT_NAME, accountName); 80 editor.apply(); 81 } 82 83 /** 84 * If there is a delayed sync, it will be cleared. 85 */ 86 @VisibleForTesting 87 void clearDelayedSyncs(Context context) { 88 setDelayedSync(context, null); 89 } 90 91 @VisibleForTesting 92 boolean shouldPerformSync(Context ctx, Bundle extras, Account account) { 93 boolean manualSync = isManualSync(extras); 94 95 if (manualSync || ApplicationStatus.hasVisibleActivities()) { 96 clearDelayedSyncs(ctx); 97 return true; 98 } else { 99 Log.d(TAG, "Delaying sync."); 100 setDelayedSync(ctx, account.name); 101 return false; 102 } 103 } 104 105 private static boolean isManualSync(Bundle extras) { 106 boolean manualSync = false; 107 if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)) { 108 manualSync = true; 109 Log.d(TAG, "Manual sync requested."); 110 } 111 return manualSync; 112 } 113} 114