Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 41fe5292 authored by Matthew Williams's avatar Matthew Williams Committed by Android (Google) Code Review
Browse files

Merge "Delay all syncing until the device is provisioned" into mnc-dev

parents 6402dc7e 8b76d20c
Loading
Loading
Loading
Loading
+104 −34
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import android.content.pm.RegisteredServicesCache;
import android.content.pm.RegisteredServicesCacheListener;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.BatteryStats;
@@ -99,6 +100,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
@@ -157,7 +159,19 @@ public class SyncManager {
    /**
     * How long to wait before considering an active sync to have timed-out, and cancelling it.
     */
    private static final long ACTIVE_SYNC_TIMEOUT_MILLIS = 30L * 60 * 1000;  // 30 mins.
    private static final long ACTIVE_SYNC_TIMEOUT_MILLIS = 30L * 60 * 1000;  // 30 mins

    /**
     * How long to delay each queued {@link SyncHandler} message that may have occurred before boot
     * or befor the device became provisioned.
     */
    private static final long PER_SYNC_BOOT_DELAY_MILLIS = 3000L;  // 3 seconds

    /**
     * The maximum amount of time we're willing to delay syncs out of boot, after device has been
     * provisioned, etc.
     */
    private static final long MAX_SYNC_BOOT_DELAY_MILLIS = 120000L;  // 2 minutes

    private static final String SYNC_WAKE_LOCK_PREFIX = "*sync*/";
    private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarm";
@@ -198,6 +212,9 @@ public class SyncManager {
    // its accessor, getConnManager().
    private ConnectivityManager mConnManagerDoNotUseDirectly;

    /** Track whether the device has already been provisioned. */
    private boolean mProvisioned;

    protected SyncAdaptersCache mSyncAdapters;

    private final AppIdleMonitor mAppIdleMonitor;
@@ -242,6 +259,7 @@ public class SyncManager {
    private BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            mBootCompleted = true;
            mSyncHandler.onBootCompleted();
        }
    };
@@ -498,6 +516,35 @@ public class SyncManager {
                    }
                });

        mProvisioned = isDeviceProvisioned();
        if (!mProvisioned) {
            final ContentResolver resolver = context.getContentResolver();
            ContentObserver provisionedObserver =
                    new ContentObserver(null /* current thread */) {
                        public void onChange(boolean selfChange) {
                            mProvisioned |= isDeviceProvisioned();
                            if (mProvisioned) {
                                mSyncHandler.onDeviceProvisioned();
                                resolver.unregisterContentObserver(this);
                            }
                        }
                    };

            synchronized (mSyncHandler) {
                resolver.registerContentObserver(
                        Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
                        false /* notifyForDescendents */,
                        provisionedObserver);

                // The device *may* have been provisioned while we were registering above observer.
                // Check again to make sure.
                mProvisioned |= isDeviceProvisioned();
                if (mProvisioned) {
                    resolver.unregisterContentObserver(provisionedObserver);
                }
            }
        }

        if (!factoryTest) {
            // Register for account list updates for all users
            mContext.registerReceiverAsUser(mAccountsUpdatedReceiver,
@@ -510,6 +557,10 @@ public class SyncManager {
        mSyncRandomOffsetMillis = mSyncStorageEngine.getSyncRandomOffset() * 1000;
    }

    private boolean isDeviceProvisioned() {
        final ContentResolver resolver = mContext.getContentResolver();
        return (Settings.Global.getInt(resolver, Settings.Global.DEVICE_PROVISIONED, 0) != 0);
    }
    /**
     * Return a random value v that satisfies minValue <= v < maxValue. The difference between
     * maxValue and minValue must be less than Integer.MAX_VALUE.
@@ -2000,20 +2051,36 @@ public class SyncManager {
        public final SyncTimeTracker mSyncTimeTracker = new SyncTimeTracker();
        private final HashMap<String, PowerManager.WakeLock> mWakeLocks = Maps.newHashMap();

        private List<Message> mBootQueue = new ArrayList<Message>();
        private List<Message> mUnreadyQueue = new ArrayList<Message>();

      public void onBootCompleted() {
        void onBootCompleted() {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "Boot completed, clearing boot queue.");
            }
            doDatabaseCleanup();
            synchronized(this) {
                // Dispatch any stashed messages.
                for (Message message : mBootQueue) {
                    sendMessage(message);
                maybeEmptyUnreadyQueueLocked();
            }
                mBootQueue = null;
                mBootCompleted = true;
        }

        void onDeviceProvisioned() {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "mProvisioned=" + mProvisioned);
            }
            synchronized (this) {
                maybeEmptyUnreadyQueueLocked();
            }
        }

        private void maybeEmptyUnreadyQueueLocked() {
            if (mProvisioned && mBootCompleted) {
                // Dispatch any stashed messages.
                for (int i=0; i<mUnreadyQueue.size(); i++) {
                    sendMessageDelayed(mUnreadyQueue.get(i),
                            Math.max(PER_SYNC_BOOT_DELAY_MILLIS * i, MAX_SYNC_BOOT_DELAY_MILLIS));
                }
                mUnreadyQueue = null;
            }
        }

@@ -2030,22 +2097,25 @@ public class SyncManager {
        }

        /**
         * Stash any messages that come to the handler before boot is complete.
         * {@link #onBootCompleted()} will disable this and dispatch all the messages collected.
         * Stash any messages that come to the handler before boot is complete or before the device
         * is properly provisioned (i.e. out of set-up wizard).
         * {@link #onBootCompleted()} and {@link #onDeviceProvisioned(boolean)} both need to come
         * in before we start syncing.
         * @param msg Message to dispatch at a later point.
         * @return true if a message was enqueued, false otherwise. This is to avoid losing the
         * message if we manage to acquire the lock but by the time we do boot has completed.
         */
        private boolean tryEnqueueMessageUntilReadyToRun(Message msg) {
            synchronized (this) {
                if (!mBootCompleted) {
                if (!mBootCompleted || !mProvisioned) {
                    // Need to copy the message bc looper will recycle it.
                    mBootQueue.add(Message.obtain(msg));
                    mUnreadyQueue.add(Message.obtain(msg));
                    return true;
                }
                } else {
                    return false;
                }
            }
        }

        /**
         * Used to keep track of whether a sync notification is active and who it is for.
@@ -2100,7 +2170,7 @@ public class SyncManager {
                        }
                        cancelActiveSync(expiredContext.mSyncOperation.target,
                                expiredContext.mSyncOperation.extras);
                        nextPendingSyncTime = maybeStartNextSyncLocked();
                        nextPendingSyncTime = maybeStartNextSyncH();
                        break;

                    case SyncHandler.MESSAGE_CANCEL: {
@@ -2111,7 +2181,7 @@ public class SyncManager {
                                    + payload + " bundle: " + extras);
                        }
                        cancelActiveSyncLocked(payload, extras);
                        nextPendingSyncTime = maybeStartNextSyncLocked();
                        nextPendingSyncTime = maybeStartNextSyncH();
                        break;
                    }

@@ -2120,17 +2190,17 @@ public class SyncManager {
                            Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_SYNC_FINISHED");
                        }
                        SyncHandlerMessagePayload payload = (SyncHandlerMessagePayload) msg.obj;
                        if (!isSyncStillActive(payload.activeSyncContext)) {
                        if (!isSyncStillActiveH(payload.activeSyncContext)) {
                            Log.d(TAG, "handleSyncHandlerMessage: dropping since the "
                                    + "sync is no longer active: "
                                    + payload.activeSyncContext);
                            break;
                        }
                        runSyncFinishedOrCanceledLocked(payload.syncResult,
                        runSyncFinishedOrCanceledH(payload.syncResult,
                                payload.activeSyncContext);

                        // since a sync just finished check if it is time to start a new sync
                        nextPendingSyncTime = maybeStartNextSyncLocked();
                        nextPendingSyncTime = maybeStartNextSyncH();
                        break;

                    case SyncHandler.MESSAGE_SERVICE_CONNECTED: {
@@ -2140,7 +2210,7 @@ public class SyncManager {
                                    + msgData.activeSyncContext);
                        }
                        // check that this isn't an old message
                        if (isSyncStillActive(msgData.activeSyncContext)) {
                        if (isSyncStillActiveH(msgData.activeSyncContext)) {
                            runBoundToAdapter(
                                    msgData.activeSyncContext,
                                    msgData.adapter);
@@ -2156,7 +2226,7 @@ public class SyncManager {
                                    + currentSyncContext);
                        }
                        // check that this isn't an old message
                        if (isSyncStillActive(currentSyncContext)) {
                        if (isSyncStillActiveH(currentSyncContext)) {
                            // cancel the sync if we have a syncadapter, which means one is
                            // outstanding
                            try {
@@ -2174,10 +2244,10 @@ public class SyncManager {
                            // which is a soft error
                            SyncResult syncResult = new SyncResult();
                            syncResult.stats.numIoExceptions++;
                            runSyncFinishedOrCanceledLocked(syncResult, currentSyncContext);
                            runSyncFinishedOrCanceledH(syncResult, currentSyncContext);

                            // since a sync just finished check if it is time to start a new sync
                            nextPendingSyncTime = maybeStartNextSyncLocked();
                            nextPendingSyncTime = maybeStartNextSyncH();
                        }

                        break;
@@ -2190,7 +2260,7 @@ public class SyncManager {
                        }
                        mAlarmScheduleTime = null;
                        try {
                            nextPendingSyncTime = maybeStartNextSyncLocked();
                            nextPendingSyncTime = maybeStartNextSyncH();
                        } finally {
                            mHandleAlarmWakeLock.release();
                        }
@@ -2201,7 +2271,7 @@ public class SyncManager {
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                            Log.v(TAG, "handleSyncHandlerMessage: MESSAGE_CHECK_ALARMS");
                        }
                        nextPendingSyncTime = maybeStartNextSyncLocked();
                        nextPendingSyncTime = maybeStartNextSyncH();
                        break;
                }
            } finally {
@@ -2393,7 +2463,7 @@ public class SyncManager {
                    0 : (earliestFuturePollTime - nowAbsolute));
        }

        private long maybeStartNextSyncLocked() {
        private long maybeStartNextSyncH() {
            final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
            if (isLoggable) Log.v(TAG, "maybeStartNextSync");

@@ -2612,7 +2682,7 @@ public class SyncManager {
                }

                if (toReschedule != null) {
                    runSyncFinishedOrCanceledLocked(null, toReschedule);
                    runSyncFinishedOrCanceledH(null, toReschedule);
                    scheduleSyncOperation(toReschedule.mSyncOperation);
                }
                synchronized (mSyncQueue) {
@@ -2845,13 +2915,13 @@ public class SyncManager {
                                    false /* no config settings */)) {
                        continue;
                    }
                    runSyncFinishedOrCanceledLocked(null /* no result since this is a cancel */,
                    runSyncFinishedOrCanceledH(null /* no result since this is a cancel */,
                            activeSyncContext);
                }
            }
        }

        private void runSyncFinishedOrCanceledLocked(SyncResult syncResult,
        private void runSyncFinishedOrCanceledH(SyncResult syncResult,
                                                ActiveSyncContext activeSyncContext) {
            boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);

@@ -3257,7 +3327,7 @@ public class SyncManager {
        }
    }

    private boolean isSyncStillActive(ActiveSyncContext activeSyncContext) {
    private boolean isSyncStillActiveH(ActiveSyncContext activeSyncContext) {
        for (ActiveSyncContext sync : mActiveSyncContexts) {
            if (sync == activeSyncContext) {
                return true;