/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.content;

import android.accounts.Account;
import android.accounts.AccountAndUser;
import android.accounts.AccountManager;
import android.accounts.AccountManagerInternal;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentResolver.SyncExemption;
import android.content.Context;
import android.content.ISyncAdapter;
import android.content.ISyncAdapterUnsyncableAccountCallback;
import android.content.ISyncContext;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.PeriodicSync;
import android.content.ServiceConnection;
import android.content.SyncActivityTooManyDeletes;
import android.content.SyncAdapterType;
import android.content.SyncAdaptersCache;
import android.content.SyncInfo;
import android.content.SyncResult;
import android.content.SyncStatusInfo;
import android.content.SyncStatusInfo.Stats;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ProviderInfo;
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.net.TrafficStats;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.WorkSource;
import android.provider.Settings;
import android.text.format.Time;
import android.util.EventLog;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseBooleanArray;

import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.function.QuadConsumer;
import com.android.server.DeviceIdleController;
import com.android.server.LocalServices;
import com.android.server.SystemService;
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.android.server.job.JobSchedulerInternal;

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.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
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;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * Implementation details:
 * All scheduled syncs will be passed on to JobScheduler as jobs
 * (See {@link #scheduleSyncOperationH(SyncOperation, long)}. This function schedules a job
 * with JobScheduler with appropriate delay and constraints (according to backoffs and extras).
 * The scheduleSyncOperationH function also assigns a unique jobId to each
 * SyncOperation.
 *
 * Periodic Syncs:
 * Each periodic sync is scheduled as a periodic job. If a periodic sync fails, we create a new
 * one off SyncOperation and set its {@link SyncOperation#sourcePeriodicId} field to the jobId of the
 * periodic sync. We don't allow the periodic job to run while any job initiated by it is pending.
 *
 * Backoffs:
 * Each {@link EndPoint} has a backoff associated with it. When a SyncOperation fails, we increase
 * the backoff on the authority. Then we reschedule all syncs associated with that authority to
 * run at a later time. Similarly, when a sync succeeds, backoff is cleared and all associated syncs
 * are rescheduled. A rescheduled sync will get a new jobId.
 *
 * @hide
 */
public class SyncManager {
    static final String TAG = "SyncManager";

    private static final boolean DEBUG_ACCOUNT_ACCESS = false;

    // Only do the check on a debuggable build.
    private static final boolean ENABLE_SUSPICIOUS_CHECK = Build.IS_DEBUGGABLE;

    /** Delay a sync due to local changes this long. In milliseconds */
    private static final long LOCAL_SYNC_DELAY;

    static {
        LOCAL_SYNC_DELAY =
                SystemProperties.getLong("sync.local_sync_delay", 30 * 1000 /* 30 seconds */);
    }

    /**
     * How long to wait before retrying a sync that failed due to one already being in progress.
     */
    private static final int DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS = 10;

    /**
     * How often to periodically poll network traffic for an adapter performing a sync to determine
     * whether progress is being made.
     */
    private static final long SYNC_MONITOR_WINDOW_LENGTH_MILLIS = 60 * 1000; // 60 seconds

    /**
     * How many bytes must be transferred (Tx + Rx) over the period of time defined by
     * {@link #SYNC_MONITOR_WINDOW_LENGTH_MILLIS} for the sync to be considered to be making
     * progress.
     */
    private static final int SYNC_MONITOR_PROGRESS_THRESHOLD_BYTES = 10; // 10 bytes

    /**
     * If a previously scheduled sync becomes ready and we are low on storage, it gets
     * pushed back for this amount of time.
     */
    private static final long SYNC_DELAY_ON_LOW_STORAGE = 60*60*1000;   // 1 hour

    /**
     * If a sync becomes ready and it conflicts with an already running sync, it gets
     * pushed back for this amount of time.
     */
    private static final long SYNC_DELAY_ON_CONFLICT = 10*1000; // 10 seconds

    /**
     * Generate job ids in the range [MIN_SYNC_JOB_ID, MAX_SYNC_JOB_ID) to avoid conflicts with
     * other jobs scheduled by the system process.
     */
    private static final int MIN_SYNC_JOB_ID = 100000;
    private static final int MAX_SYNC_JOB_ID = 110000;

    private static final String SYNC_WAKE_LOCK_PREFIX = "*sync*/";
    private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarm";
    private static final String SYNC_LOOP_WAKE_LOCK = "SyncLoopWakeLock";


    private static final int SYNC_OP_STATE_VALID = 0;
    private static final int SYNC_OP_STATE_INVALID = 1;
    private static final int SYNC_OP_STATE_INVALID_NO_ACCOUNT_ACCESS = 2;

    /** Flags used when connecting to a sync adapter service */
    private static final int SYNC_ADAPTER_CONNECTION_FLAGS = Context.BIND_AUTO_CREATE
            | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT;

    /** Singleton instance. */
    @GuardedBy("SyncManager.class")
    private static SyncManager sInstance;

    private Context mContext;

    private static final AccountAndUser[] INITIAL_ACCOUNTS_ARRAY = new AccountAndUser[0];

    // TODO: add better locking around mRunningAccounts
    private volatile AccountAndUser[] mRunningAccounts = INITIAL_ACCOUNTS_ARRAY;

    volatile private PowerManager.WakeLock mSyncManagerWakeLock;
    volatile private boolean mDataConnectionIsConnected = false;
    volatile private boolean mStorageIsLow = false;
    volatile private boolean mDeviceIsIdle = false;
    volatile private boolean mReportedSyncActive = false;

    private final NotificationManager mNotificationMgr;
    private final IBatteryStats mBatteryStats;
    private JobScheduler mJobScheduler;
    private JobSchedulerInternal mJobSchedulerInternal;

    private SyncStorageEngine mSyncStorageEngine;

    protected final ArrayList<ActiveSyncContext> mActiveSyncContexts = Lists.newArrayList();

    // Synchronized on "this". Instead of using this directly one should instead call
    // its accessor, getConnManager().
    private ConnectivityManager mConnManagerDoNotUseDirectly;

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

    protected final SyncAdaptersCache mSyncAdapters;

    private final Random mRand;

    private final SyncLogger mLogger;

    private boolean isJobIdInUseLockedH(int jobId, List<JobInfo> pendingJobs) {
        for (JobInfo job: pendingJobs) {
            if (job.getId() == jobId) {
                return true;
            }
        }
        for (ActiveSyncContext asc: mActiveSyncContexts) {
            if (asc.mSyncOperation.jobId == jobId) {
                return true;
            }
        }
        return false;
    }

    private int getUnusedJobIdH() {
        int newJobId;
        do {
            newJobId = MIN_SYNC_JOB_ID + mRand.nextInt(MAX_SYNC_JOB_ID - MIN_SYNC_JOB_ID);
        } while (isJobIdInUseLockedH(newJobId,
                mJobSchedulerInternal.getSystemScheduledPendingJobs()));
        return newJobId;
    }

    private List<SyncOperation> getAllPendingSyncs() {
        verifyJobScheduler();
        List<JobInfo> pendingJobs = mJobSchedulerInternal.getSystemScheduledPendingJobs();
        List<SyncOperation> pendingSyncs = new ArrayList<SyncOperation>(pendingJobs.size());
        for (JobInfo job: pendingJobs) {
            SyncOperation op = SyncOperation.maybeCreateFromJobExtras(job.getExtras());
            if (op != null) {
                pendingSyncs.add(op);
            }
        }
        return pendingSyncs;
    }

    private final BroadcastReceiver mStorageIntentReceiver =
            new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    String action = intent.getAction();
                    if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(action)) {
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                            Slog.v(TAG, "Internal storage is low.");
                        }
                        mStorageIsLow = true;
                        cancelActiveSync(
                                SyncStorageEngine.EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL,
                                null /* any sync */,
                                "storage low");
                    } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                            Slog.v(TAG, "Internal storage is ok.");
                        }
                        mStorageIsLow = false;
                        rescheduleSyncs(EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL,
                                "storage ok");
                    }
                }
            };

    private final BroadcastReceiver mAccountsUpdatedReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            EndPoint target = new EndPoint(null, null, getSendingUserId());
            updateRunningAccounts(target /* sync targets for user */);
        }
    };

    private final PowerManager mPowerManager;

    private final UserManager mUserManager;

    private final AccountManager mAccountManager;

    private final AccountManagerInternal mAccountManagerInternal;

    private final PackageManagerInternal mPackageManagerInternal;

    private List<UserInfo> getAllUsers() {
        return mUserManager.getUsers();
    }

    private boolean containsAccountAndUser(AccountAndUser[] accounts, Account account, int userId) {
        boolean found = false;
        for (int i = 0; i < accounts.length; i++) {
            if (accounts[i].userId == userId
                    && accounts[i].account.equals(account)) {
                found = true;
                break;
            }
        }
        return found;
    }

    /** target indicates endpoints that should be synced after account info is updated. */
    private void updateRunningAccounts(EndPoint target) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) Slog.v(TAG, "sending MESSAGE_ACCOUNTS_UPDATED");
        // Update accounts in handler thread.
        Message m = mSyncHandler.obtainMessage(SyncHandler.MESSAGE_ACCOUNTS_UPDATED);
        m.obj = target;
        m.sendToTarget();
    }

    private void removeStaleAccounts() {
        for (UserInfo user : mUserManager.getUsers(true)) {
            // Skip any partially created/removed users
            if (user.partial) continue;
            Account[] accountsForUser = AccountManagerService.getSingleton().getAccounts(
                    user.id, mContext.getOpPackageName());

            mSyncStorageEngine.removeStaleAccounts(accountsForUser, user.id);
        }
    }

    private BroadcastReceiver mConnectivityIntentReceiver =
            new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    final boolean wasConnected = mDataConnectionIsConnected;

                    // Don't use the intent to figure out if network is connected, just check
                    // ConnectivityManager directly.
                    mDataConnectionIsConnected = readDataConnectionState();
                    if (mDataConnectionIsConnected) {
                        if (!wasConnected) {
                            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                                Slog.v(TAG, "Reconnection detected: clearing all backoffs");
                            }
                            // Note the location of this code was wrong from nyc to oc; fixed in DR.
                            clearAllBackoffs("network reconnect");
                        }
                    }
                }
            };

    private void clearAllBackoffs(String why) {
        mSyncStorageEngine.clearAllBackoffsLocked();
        rescheduleSyncs(EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL, why);
    }

    private boolean readDataConnectionState() {
        NetworkInfo networkInfo = getConnectivityManager().getActiveNetworkInfo();
        return (networkInfo != null) && networkInfo.isConnected();
    }

    private String getJobStats() {
        JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class);
        return "JobStats: "
                + ((js == null) ? "(JobSchedulerInternal==null)"
                : js.getPersistStats().toString());
    }

    private BroadcastReceiver mShutdownIntentReceiver =
            new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    Log.w(TAG, "Writing sync state before shutdown...");
                    getSyncStorageEngine().writeAllState();

                    mLogger.log(getJobStats());
                    mLogger.log("Shutting down.");
                }
            };

    private final BroadcastReceiver mOtherIntentsReceiver =
            new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
                        mSyncStorageEngine.setClockValid();
                        return;
                    }
                }
            };

    private BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
            if (userId == UserHandle.USER_NULL) return;

            if (Intent.ACTION_USER_REMOVED.equals(action)) {
                onUserRemoved(userId);
            } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
                onUserUnlocked(userId);
            } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
                onUserStopped(userId);
            }
        }
    };

    private final HandlerThread mThread;
    private final SyncHandler mSyncHandler;
    private final SyncManagerConstants mConstants;

    @GuardedBy("mUnlockedUsers")
    private final SparseBooleanArray mUnlockedUsers = new SparseBooleanArray();

    private ConnectivityManager getConnectivityManager() {
        synchronized (this) {
            if (mConnManagerDoNotUseDirectly == null) {
                mConnManagerDoNotUseDirectly = (ConnectivityManager)mContext.getSystemService(
                        Context.CONNECTIVITY_SERVICE);
            }
            return mConnManagerDoNotUseDirectly;
        }
    }

    /**
     * Cancel all unnecessary jobs. This function will be run once after every boot.
     */
    private void cleanupJobs() {
        // O(n^2) in number of jobs, so we run this on the background thread.
        mSyncHandler.postAtFrontOfQueue(new Runnable() {
            @Override
            public void run() {
                List<SyncOperation> ops = getAllPendingSyncs();
                Set<String> cleanedKeys = new HashSet<String>();
                for (SyncOperation opx: ops) {
                    if (cleanedKeys.contains(opx.key)) {
                        continue;
                    }
                    cleanedKeys.add(opx.key);
                    for (SyncOperation opy: ops) {
                        if (opx == opy) {
                            continue;
                        }
                        if (opx.key.equals(opy.key)) {
                            mLogger.log("Removing duplicate sync: ", opy);
                            cancelJob(opy, "cleanupJobs() x=" + opx + " y=" + opy);
                        }
                    }
                }
            }
        });
    }

    private synchronized void verifyJobScheduler() {
        if (mJobScheduler != null) {
            return;
        }
        final long token = Binder.clearCallingIdentity();
        try {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.d(TAG, "initializing JobScheduler object.");
            }
            mJobScheduler = (JobScheduler) mContext.getSystemService(
                    Context.JOB_SCHEDULER_SERVICE);
            mJobSchedulerInternal = LocalServices.getService(JobSchedulerInternal.class);
            // Get all persisted syncs from JobScheduler
            List<JobInfo> pendingJobs = mJobScheduler.getAllPendingJobs();

            int numPersistedPeriodicSyncs = 0;
            int numPersistedOneshotSyncs = 0;
            for (JobInfo job : pendingJobs) {
                SyncOperation op = SyncOperation.maybeCreateFromJobExtras(job.getExtras());
                if (op != null) {
                    if (op.isPeriodic) {
                        numPersistedPeriodicSyncs++;
                    } else {
                        numPersistedOneshotSyncs++;
                        // Set the pending status of this EndPoint to true. Pending icon is
                        // shown on the settings activity.
                        mSyncStorageEngine.markPending(op.target, true);
                    }
                }
            }
            final String summary = "Loaded persisted syncs: "
                    + numPersistedPeriodicSyncs + " periodic syncs, "
                    + numPersistedOneshotSyncs + " oneshot syncs, "
                    + (pendingJobs.size()) + " total system server jobs, "
                    + getJobStats();
            Slog.i(TAG, summary);
            mLogger.log(summary);

            cleanupJobs();

            if (ENABLE_SUSPICIOUS_CHECK &&
                    (numPersistedPeriodicSyncs == 0) && likelyHasPeriodicSyncs()) {
                Slog.wtf(TAG, "Device booted with no persisted periodic syncs: " + summary);
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    /**
     * @return whether the device most likely has some periodic syncs.
     */
    private boolean likelyHasPeriodicSyncs() {
        try {
            // Each sync adapter has a daily periodic sync by default, but sync adapters can remove
            // them by themselves. So here, we use an arbitrary threshold. If there are more than
            // this many sync endpoints, surely one of them should have a periodic sync...
            return mSyncStorageEngine.getAuthorityCount() >= 6;
        } catch (Throwable th) {
            // Just in case.
        }
        return false;
    }

    private JobScheduler getJobScheduler() {
        verifyJobScheduler();
        return mJobScheduler;
    }

    public SyncManager(Context context, boolean factoryTest) {
        synchronized (SyncManager.class) {
            if (sInstance == null) {
                sInstance = this;
            } else {
                Slog.wtf(TAG, "SyncManager instantiated multiple times");
            }
        }

        // Initialize the SyncStorageEngine first, before registering observers
        // and creating threads and so on; it may fail if the disk is full.
        mContext = context;

        mLogger = SyncLogger.getInstance();

        SyncStorageEngine.init(context, BackgroundThread.get().getLooper());
        mSyncStorageEngine = SyncStorageEngine.getSingleton();
        mSyncStorageEngine.setOnSyncRequestListener(new OnSyncRequestListener() {
            @Override
            public void onSyncRequest(SyncStorageEngine.EndPoint info, int reason, Bundle extras,
                    @SyncExemption int syncExemptionFlag, int callingUid, int callingPid) {
                scheduleSync(info.account, info.userId, reason, info.provider, extras,
                        AuthorityInfo.UNDEFINED, syncExemptionFlag, callingUid, callingPid, null);
            }
        });

        mSyncStorageEngine.setPeriodicSyncAddedListener(
                new SyncStorageEngine.PeriodicSyncAddedListener() {
                    @Override
                    public void onPeriodicSyncAdded(EndPoint target, Bundle extras, long pollFrequency,
                            long flex) {
                        updateOrAddPeriodicSync(target, pollFrequency, flex, extras);
                    }
                });

        mSyncStorageEngine.setOnAuthorityRemovedListener(new SyncStorageEngine.OnAuthorityRemovedListener() {
            @Override
            public void onAuthorityRemoved(EndPoint removedAuthority) {
                removeSyncsForAuthority(removedAuthority, "onAuthorityRemoved");
            }
        });

        mSyncAdapters = new SyncAdaptersCache(mContext);

        mThread = new HandlerThread("SyncManager", android.os.Process.THREAD_PRIORITY_BACKGROUND);
        mThread.start();
        mSyncHandler = new SyncHandler(mThread.getLooper());

        mSyncAdapters.setListener(new RegisteredServicesCacheListener<SyncAdapterType>() {
            @Override
            public void onServiceChanged(SyncAdapterType type, int userId, boolean removed) {
                if (!removed) {
                    scheduleSync(null, UserHandle.USER_ALL,
                            SyncOperation.REASON_SERVICE_CHANGED,
                            type.authority, null, AuthorityInfo.UNDEFINED,
                            ContentResolver.SYNC_EXEMPTION_NONE,
                            Process.myUid(), -1, null);
                }
            }
        }, mSyncHandler);

        mRand = new Random(System.currentTimeMillis());
        mConstants = new SyncManagerConstants(context);

        IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        context.registerReceiver(mConnectivityIntentReceiver, intentFilter);

        intentFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW);
        intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
        context.registerReceiver(mStorageIntentReceiver, intentFilter);

        intentFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
        intentFilter.setPriority(100);
        context.registerReceiver(mShutdownIntentReceiver, intentFilter);

        intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_USER_REMOVED);
        intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
        intentFilter.addAction(Intent.ACTION_USER_STOPPED);
        mContext.registerReceiverAsUser(
                mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);

        intentFilter = new IntentFilter(Intent.ACTION_TIME_CHANGED);
        context.registerReceiver(mOtherIntentsReceiver, intentFilter);

        if (!factoryTest) {
            mNotificationMgr = (NotificationManager)
                    context.getSystemService(Context.NOTIFICATION_SERVICE);
        } else {
            mNotificationMgr = null;
        }
        mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        mAccountManager = (AccountManager) mContext.getSystemService(Context.ACCOUNT_SERVICE);
        mAccountManagerInternal = LocalServices.getService(AccountManagerInternal.class);
        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);

        mAccountManagerInternal.addOnAppPermissionChangeListener((Account account, int uid) -> {
            // If the UID gained access to the account kick-off syncs lacking account access
            if (mAccountManagerInternal.hasAccountAccess(account, uid)) {
                scheduleSync(account, UserHandle.getUserId(uid),
                        SyncOperation.REASON_ACCOUNTS_UPDATED,
                        null, null, AuthorityInfo.SYNCABLE_NO_ACCOUNT_ACCESS,
                        ContentResolver.SYNC_EXEMPTION_NONE,
                        Process.myUid(), -2, null);
            }
        });

        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
                BatteryStats.SERVICE_NAME));

        // This WakeLock is used to ensure that we stay awake while running the sync loop
        // message handler. Normally we will hold a sync adapter wake lock while it is being
        // synced but during the execution of the sync loop it might finish a sync for
        // one sync adapter before starting the sync for the other sync adapter and we
        // don't want the device to go to sleep during that window.
        mSyncManagerWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                SYNC_LOOP_WAKE_LOCK);
        mSyncManagerWakeLock.setReferenceCounted(false);

        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) {
                                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,
                    UserHandle.ALL,
                    new IntentFilter(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION),
                    null, null);
        }

        // Sync adapters were able to access the synced account without the accounts
        // permission which circumvents our permission model. Therefore, we require
        // sync adapters that don't have access to the account to get user consent.
        // This can be noisy, therefore we will white-list sync adapters installed
        // before we started checking for account access because they already know
        // the account (they run before) which is the genie is out of the bottle.
        whiteListExistingSyncAdaptersIfNeeded();

        mLogger.log("Sync manager initialized: " + Build.FINGERPRINT);
    }

    public void onStartUser(int userId) {
        // Log on the handler to avoid slowing down device boot.
        mSyncHandler.post(() -> mLogger.log("onStartUser: user=", userId));
    }

    public void onUnlockUser(int userId) {
        synchronized (mUnlockedUsers) {
            mUnlockedUsers.put(userId, true);
        }
        // Log on the handler to avoid slowing down device boot.
        mSyncHandler.post(() -> mLogger.log("onUnlockUser: user=", userId));
    }

    public void onStopUser(int userId) {
        synchronized (mUnlockedUsers) {
            mUnlockedUsers.put(userId, false);
        }
        // Log on the handler to avoid slowing down user switch.
        mSyncHandler.post(() -> mLogger.log("onStopUser: user=", userId));
    }

    private boolean isUserUnlocked(int userId) {
        synchronized (mUnlockedUsers) {
            return mUnlockedUsers.get(userId);
        }
    }

    public void onBootPhase(int phase) {
        // Note SyncManager only receives PHASE_ACTIVITY_MANAGER_READY and after.
        switch (phase) {
            case SystemService.PHASE_ACTIVITY_MANAGER_READY:
                mConstants.start();
                break;
        }
    }

    private void whiteListExistingSyncAdaptersIfNeeded() {
        if (!mSyncStorageEngine.shouldGrantSyncAdaptersAccountAccess()) {
            return;
        }
        List<UserInfo> users = mUserManager.getUsers(true);
        final int userCount = users.size();
        for (int i = 0; i < userCount; i++) {
            UserHandle userHandle = users.get(i).getUserHandle();
            final int userId = userHandle.getIdentifier();
            for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> service
                    : mSyncAdapters.getAllServices(userId)) {
                String packageName = service.componentName.getPackageName();
                for (Account account : mAccountManager.getAccountsByTypeAsUser(
                        service.type.accountType, userHandle)) {
                    if (!canAccessAccount(account, packageName, userId)) {
                        mAccountManager.updateAppPermission(account,
                                AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, service.uid, true);
                    }
                }
            }
        }
    }

    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.
     */
    private long jitterize(long minValue, long maxValue) {
        Random random = new Random(SystemClock.elapsedRealtime());
        long spread = maxValue - minValue;
        if (spread > Integer.MAX_VALUE) {
            throw new IllegalArgumentException("the difference between the maxValue and the "
                    + "minValue must be less than " + Integer.MAX_VALUE);
        }
        return minValue + random.nextInt((int)spread);
    }

    public SyncStorageEngine getSyncStorageEngine() {
        return mSyncStorageEngine;
    }

    private int getIsSyncable(Account account, int userId, String providerName) {
        int isSyncable = mSyncStorageEngine.getIsSyncable(account, userId, providerName);
        UserInfo userInfo = UserManager.get(mContext).getUserInfo(userId);

        // If it's not a restricted user, return isSyncable.
        if (userInfo == null || !userInfo.isRestricted()) return isSyncable;

        // Else check if the sync adapter has opted-in or not.
        RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
                mSyncAdapters.getServiceInfo(
                        SyncAdapterType.newKey(providerName, account.type), userId);
        if (syncAdapterInfo == null) return AuthorityInfo.NOT_SYNCABLE;

        PackageInfo pInfo = null;
        try {
            pInfo = AppGlobals.getPackageManager().getPackageInfo(
                    syncAdapterInfo.componentName.getPackageName(), 0, userId);
            if (pInfo == null) return AuthorityInfo.NOT_SYNCABLE;
        } catch (RemoteException re) {
            // Shouldn't happen.
            return AuthorityInfo.NOT_SYNCABLE;
        }
        if (pInfo.restrictedAccountType != null
                && pInfo.restrictedAccountType.equals(account.type)) {
            return isSyncable;
        } else {
            return AuthorityInfo.NOT_SYNCABLE;
        }
    }

    private void setAuthorityPendingState(EndPoint info) {
        List<SyncOperation> ops = getAllPendingSyncs();
        for (SyncOperation op: ops) {
            if (!op.isPeriodic && op.target.matchesSpec(info)) {
                getSyncStorageEngine().markPending(info, true);
                return;
            }
        }
        getSyncStorageEngine().markPending(info, false);
    }

    /**
     * Initiate a sync. This can start a sync for all providers
     * (pass null to url, set onlyTicklable to false), only those
     * providers that are marked as ticklable (pass null to url,
     * set onlyTicklable to true), or a specific provider (set url
     * to the content url of the provider).
     *
     * <p>If the ContentResolver.SYNC_EXTRAS_UPLOAD boolean in extras is
     * true then initiate a sync that just checks for local changes to send
     * to the server, otherwise initiate a sync that first gets any
     * changes from the server before sending local changes back to
     * the server.
     *
     * <p>If a specific provider is being synced (the url is non-null)
     * then the extras can contain SyncAdapter-specific information
     * to control what gets synced (e.g. which specific feed to sync).
     *
     * <p>You'll start getting callbacks after this.
     *
     * @param requestedAccount the account to sync, may be null to signify all accounts
     * @param userId the id of the user whose accounts are to be synced. If userId is USER_ALL,
     *          then all users' accounts are considered.
     * @param reason for sync request. If this is a positive integer, it is the Linux uid
     * assigned to the process that requested the sync. If it's negative, the sync was requested by
     * the SyncManager itself and could be one of the following:
     *      {@link SyncOperation#REASON_BACKGROUND_DATA_SETTINGS_CHANGED}
     *      {@link SyncOperation#REASON_ACCOUNTS_UPDATED}
     *      {@link SyncOperation#REASON_SERVICE_CHANGED}
     *      {@link SyncOperation#REASON_PERIODIC}
     *      {@link SyncOperation#REASON_IS_SYNCABLE}
     *      {@link SyncOperation#REASON_SYNC_AUTO}
     *      {@link SyncOperation#REASON_MASTER_SYNC_AUTO}
     *      {@link SyncOperation#REASON_USER_START}
     * @param requestedAuthority the authority to sync, may be null to indicate all authorities
     * @param extras a Map of SyncAdapter-specific information to control
     *          syncs of a specific provider. Can be null. Is ignored
     *          if the url is null.
     * @param targetSyncState Only sync authorities that have the specified sync state.
     *           Use {@link AuthorityInfo#UNDEFINED} to sync all authorities.
     */
    public void scheduleSync(Account requestedAccount, int userId, int reason,
            String requestedAuthority, Bundle extras, int targetSyncState,
            @SyncExemption int syncExemptionFlag, int callingUid, int callingPid,
            String callingPackage) {
        scheduleSync(requestedAccount, userId, reason, requestedAuthority, extras, targetSyncState,
                0 /* min delay */, true /* checkIfAccountReady */, syncExemptionFlag,
                callingUid, callingPid, callingPackage);
    }

    /**
     * @param minDelayMillis The sync can't land before this delay expires.
     */
    private void scheduleSync(Account requestedAccount, int userId, int reason,
            String requestedAuthority, Bundle extras, int targetSyncState,
            final long minDelayMillis, boolean checkIfAccountReady,
            @SyncExemption int syncExemptionFlag,
            int callingUid, int callingPid, String callingPackage) {
        if (extras == null) {
            extras = new Bundle();
        }
        extras.size(); // Force unpacel.
        mLogger.log("scheduleSync: account=", requestedAccount,
                " u", userId,
                " authority=", requestedAuthority,
                " reason=", reason,
                " extras=", extras,
                " cuid=", callingUid, " cpid=", callingPid, " cpkg=", callingPackage,
                " mdm=", minDelayMillis,
                " ciar=", checkIfAccountReady,
                " sef=", syncExemptionFlag);

        AccountAndUser[] accounts = null;
        if (requestedAccount != null) {
            if (userId != UserHandle.USER_ALL) {
                accounts = new AccountAndUser[]{new AccountAndUser(requestedAccount, userId)};
            } else {
                for (AccountAndUser runningAccount : mRunningAccounts) {
                    if (requestedAccount.equals(runningAccount.account)) {
                        accounts = ArrayUtils.appendElement(AccountAndUser.class,
                                accounts, runningAccount);
                    }
                }
            }
        } else {
            accounts = mRunningAccounts;
        }

        if (ArrayUtils.isEmpty(accounts)) {
            mLogger.log("scheduleSync: no accounts configured, dropping");
            return;
        }

        final boolean uploadOnly = extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false);
        final boolean manualSync = extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
        if (manualSync) {
            extras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true);
            extras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
        }
        final boolean ignoreSettings =
                extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);

        int source;
        if (uploadOnly) {
            source = SyncStorageEngine.SOURCE_LOCAL;
        } else if (manualSync) {
            source = SyncStorageEngine.SOURCE_USER;
        } else if (requestedAuthority == null) {
            source = SyncStorageEngine.SOURCE_POLL;
        } else {
            if (extras.containsKey("feed")) {
                source = SyncStorageEngine.SOURCE_FEED;
            } else{
                // This isn't strictly server, since arbitrary callers can (and do) request
                // a non-forced two-way sync on a specific url.
                source = SyncStorageEngine.SOURCE_OTHER;
            }
        }

        for (AccountAndUser account : accounts) {
            // If userId is specified, do not sync accounts of other users
            if (userId >= UserHandle.USER_SYSTEM && account.userId >= UserHandle.USER_SYSTEM
                    && userId != account.userId) {
                continue;
            }
            // Compile a list of authorities that have sync adapters.
            // For each authority sync each account that matches a sync adapter.
            final HashSet<String> syncableAuthorities = new HashSet<String>();
            for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter :
                    mSyncAdapters.getAllServices(account.userId)) {
                syncableAuthorities.add(syncAdapter.type.authority);
            }

            // If the url was specified then replace the list of authorities
            // with just this authority or clear it if this authority isn't
            // syncable.
            if (requestedAuthority != null) {
                final boolean hasSyncAdapter = syncableAuthorities.contains(requestedAuthority);
                syncableAuthorities.clear();
                if (hasSyncAdapter) syncableAuthorities.add(requestedAuthority);
            }

            for (String authority : syncableAuthorities) {
                int isSyncable = computeSyncable(account.account, account.userId, authority,
                        !checkIfAccountReady);

                if (isSyncable == AuthorityInfo.NOT_SYNCABLE) {
                    continue;
                }

                final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
                        mSyncAdapters.getServiceInfo(SyncAdapterType.newKey(authority,
                                account.account.type), account.userId);
                if (syncAdapterInfo == null) {
                    continue;
                }

                final int owningUid = syncAdapterInfo.uid;

                if (isSyncable == AuthorityInfo.SYNCABLE_NO_ACCOUNT_ACCESS) {
                    mLogger.log("scheduleSync: Not scheduling sync operation: "
                                + "isSyncable == SYNCABLE_NO_ACCOUNT_ACCESS");
                    Bundle finalExtras = new Bundle(extras);
                    String packageName = syncAdapterInfo.componentName.getPackageName();
                    // If the app did not run and has no account access, done
                    if (!wasPackageEverLaunched(packageName, userId)) {
                        continue;
                    }
                    mAccountManagerInternal.requestAccountAccess(account.account,
                            packageName, userId,
                            new RemoteCallback((Bundle result) -> {
                                if (result != null
                                        && result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT)) {
                                    scheduleSync(account.account, userId, reason, authority,
                                            finalExtras, targetSyncState, minDelayMillis,
                                            true /* checkIfAccountReady */,
                                            syncExemptionFlag, callingUid, callingPid,
                                            callingPackage);
                                }
                            }
                        ));
                    continue;
                }

                final boolean allowParallelSyncs = syncAdapterInfo.type.allowParallelSyncs();
                final boolean isAlwaysSyncable = syncAdapterInfo.type.isAlwaysSyncable();
                if (!checkIfAccountReady && isSyncable < 0 && isAlwaysSyncable) {
                    mSyncStorageEngine.setIsSyncable(
                            account.account, account.userId, authority, AuthorityInfo.SYNCABLE,
                            callingUid, callingPid);
                    isSyncable = AuthorityInfo.SYNCABLE;
                }

                if (targetSyncState != AuthorityInfo.UNDEFINED && targetSyncState != isSyncable) {
                    continue;
                }

                if (!syncAdapterInfo.type.supportsUploading() && uploadOnly) {
                    continue;
                }

                boolean syncAllowed =
                        (isSyncable < 0) // Always allow if the isSyncable state is unknown.
                                || ignoreSettings
                                || (mSyncStorageEngine.getMasterSyncAutomatically(account.userId)
                                && mSyncStorageEngine.getSyncAutomatically(account.account,
                                account.userId, authority));
                if (!syncAllowed) {
                    mLogger.log("scheduleSync: sync of ", account, " ", authority,
                            " is not allowed, dropping request");
                    continue;
                }
                SyncStorageEngine.EndPoint info =
                        new SyncStorageEngine.EndPoint(
                                account.account, authority, account.userId);
                long delayUntil =
                        mSyncStorageEngine.getDelayUntilTime(info);

                final String owningPackage = syncAdapterInfo.componentName.getPackageName();

                if (isSyncable == AuthorityInfo.NOT_INITIALIZED) {
                    if (checkIfAccountReady) {
                        Bundle finalExtras = new Bundle(extras);

                        sendOnUnsyncableAccount(mContext, syncAdapterInfo, account.userId,
                                () -> scheduleSync(account.account, account.userId, reason,
                                        authority, finalExtras, targetSyncState, minDelayMillis,
                                        false, syncExemptionFlag, callingUid, callingPid,
                                        callingPackage));
                    } else {
                        // Initialisation sync.
                        Bundle newExtras = new Bundle();
                        newExtras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);

                        mLogger.log("scheduleSync: schedule initialisation sync ",
                                account, " ", authority);

                        postScheduleSyncMessage(
                                new SyncOperation(account.account, account.userId,
                                        owningUid, owningPackage, reason, source,
                                        authority, newExtras, allowParallelSyncs,
                                        syncExemptionFlag),
                                minDelayMillis
                        );
                    }
                } else if (targetSyncState == AuthorityInfo.UNDEFINED
                        || targetSyncState == isSyncable) {
                    mLogger.log("scheduleSync: scheduling sync ",
                            account, " ", authority);
                    postScheduleSyncMessage(
                            new SyncOperation(account.account, account.userId,
                                    owningUid, owningPackage, reason, source,
                                    authority, extras, allowParallelSyncs, syncExemptionFlag),
                            minDelayMillis
                    );
                } else {
                    mLogger.log("scheduleSync: not handling ",
                            account, " ", authority);
                }
            }
        }
    }

    public int computeSyncable(Account account, int userId, String authority,
            boolean checkAccountAccess) {
        final int status = getIsSyncable(account, userId, authority);
        if (status == AuthorityInfo.NOT_SYNCABLE) {
            return AuthorityInfo.NOT_SYNCABLE;
        }
        final SyncAdapterType type = SyncAdapterType.newKey(authority, account.type);
        final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
                mSyncAdapters.getServiceInfo(type, userId);
        if (syncAdapterInfo == null) {
            return AuthorityInfo.NOT_SYNCABLE;
        }
        final int owningUid = syncAdapterInfo.uid;
        final String owningPackage = syncAdapterInfo.componentName.getPackageName();
        try {
            if (ActivityManager.getService().isAppStartModeDisabled(owningUid, owningPackage)) {
                Slog.w(TAG, "Not scheduling job " + syncAdapterInfo.uid + ":"
                        + syncAdapterInfo.componentName
                        + " -- package not allowed to start");
                return AuthorityInfo.NOT_SYNCABLE;
            }
        } catch (RemoteException e) {
            /* ignore - local call */
        }
        if (checkAccountAccess && !canAccessAccount(account, owningPackage, owningUid)) {
            Log.w(TAG, "Access to " + account + " denied for package "
                    + owningPackage + " in UID " + syncAdapterInfo.uid);
            return AuthorityInfo.SYNCABLE_NO_ACCOUNT_ACCESS;
        }

        return status;
    }

    private boolean canAccessAccount(Account account, String packageName, int uid) {
        if (mAccountManager.hasAccountAccess(account, packageName,
                UserHandle.getUserHandleForUid(uid))) {
            return true;
        }
        // We relax the account access rule to also include the system apps as
        // they are trusted and we want to minimize the cases where the user
        // involvement is required to grant access to the synced account.
        try {
            mContext.getPackageManager().getApplicationInfoAsUser(packageName,
                    PackageManager.MATCH_SYSTEM_ONLY, UserHandle.getUserId(uid));
            return true;
        } catch (NameNotFoundException e) {
            return false;
        }
    }

    private void removeSyncsForAuthority(EndPoint info, String why) {
        mLogger.log("removeSyncsForAuthority: ", info);
        verifyJobScheduler();
        List<SyncOperation> ops = getAllPendingSyncs();
        for (SyncOperation op: ops) {
            if (op.target.matchesSpec(info)) {
                mLogger.log("canceling: ", op);
                cancelJob(op, why);
            }
        }
    }

    /**
     * Remove a specific periodic sync identified by its target and extras.
     */
    public void removePeriodicSync(EndPoint target, Bundle extras, String why) {
        Message m = mSyncHandler.obtainMessage(mSyncHandler.MESSAGE_REMOVE_PERIODIC_SYNC,
                Pair.create(target, why));
        m.setData(extras);
        m.sendToTarget();
    }

    /**
     * Add a periodic sync. If a sync with same target and extras exists, its period and
     * flexMillis will be updated.
     */
    public void updateOrAddPeriodicSync(EndPoint target, long pollFrequency, long flex,
            Bundle extras) {
        UpdatePeriodicSyncMessagePayload payload = new UpdatePeriodicSyncMessagePayload(target,
                pollFrequency, flex, extras);
        mSyncHandler.obtainMessage(SyncHandler.MESSAGE_UPDATE_PERIODIC_SYNC, payload)
                .sendToTarget();
    }

    /**
     * Get a list of periodic syncs corresponding to the given target.
     */
    public List<PeriodicSync> getPeriodicSyncs(EndPoint target) {
        List<SyncOperation> ops = getAllPendingSyncs();
        List<PeriodicSync> periodicSyncs = new ArrayList<PeriodicSync>();

        for (SyncOperation op: ops) {
            if (op.isPeriodic && op.target.matchesSpec(target)) {
                periodicSyncs.add(new PeriodicSync(op.target.account, op.target.provider,
                        op.extras, op.periodMillis / 1000, op.flexMillis / 1000));
            }
        }

        return periodicSyncs;
    }

    /**
     * Schedule sync based on local changes to a provider. We wait for at least LOCAL_SYNC_DELAY
     * ms to batch syncs.
     */
    public void scheduleLocalSync(Account account, int userId, int reason, String authority,
            @SyncExemption int syncExemptionFlag,
            int callingUid, int callingPid, String callingPackage) {
        final Bundle extras = new Bundle();
        extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
        scheduleSync(account, userId, reason, authority, extras,
                AuthorityInfo.UNDEFINED, LOCAL_SYNC_DELAY, true /* checkIfAccountReady */,
                syncExemptionFlag, callingUid, callingPid, callingPackage);
    }

    public SyncAdapterType[] getSyncAdapterTypes(int userId) {
        final Collection<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> serviceInfos;
        serviceInfos = mSyncAdapters.getAllServices(userId);
        SyncAdapterType[] types = new SyncAdapterType[serviceInfos.size()];
        int i = 0;
        for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> serviceInfo : serviceInfos) {
            types[i] = serviceInfo.type;
            ++i;
        }
        return types;
    }

    public String[] getSyncAdapterPackagesForAuthorityAsUser(String authority, int userId) {
        return mSyncAdapters.getSyncAdapterPackagesForAuthority(authority, userId);
    }

    private void sendSyncFinishedOrCanceledMessage(ActiveSyncContext syncContext,
            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;
        msg.obj = new SyncFinishedOrCancelledMessagePayload(syncContext, syncResult);
        mSyncHandler.sendMessage(msg);
    }

    private void sendCancelSyncsMessage(final SyncStorageEngine.EndPoint info, Bundle extras,
            String why) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) Slog.v(TAG, "sending MESSAGE_CANCEL");

        mLogger.log("sendCancelSyncsMessage() ep=", info, " why=", why);

        Message msg = mSyncHandler.obtainMessage();
        msg.what = SyncHandler.MESSAGE_CANCEL;
        msg.setData(extras);
        msg.obj = info;
        mSyncHandler.sendMessage(msg);
    }

    /**
     * Post a delayed message that will monitor the given sync context by periodically checking how
     * much network has been used by the uid.
     */
    private void postMonitorSyncProgressMessage(ActiveSyncContext activeSyncContext) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Slog.v(TAG, "posting MESSAGE_SYNC_MONITOR in " +
                    (SYNC_MONITOR_WINDOW_LENGTH_MILLIS/1000) + "s");
        }

        activeSyncContext.mBytesTransferredAtLastPoll =
                getTotalBytesTransferredByUid(activeSyncContext.mSyncAdapterUid);
        activeSyncContext.mLastPolledTimeElapsed = SystemClock.elapsedRealtime();
        Message monitorMessage =
                mSyncHandler.obtainMessage(
                        SyncHandler.MESSAGE_MONITOR_SYNC,
                        activeSyncContext);
        mSyncHandler.sendMessageDelayed(monitorMessage, SYNC_MONITOR_WINDOW_LENGTH_MILLIS);
    }

    private void postScheduleSyncMessage(SyncOperation syncOperation, long minDelayMillis) {
        ScheduleSyncMessagePayload payload =
                new ScheduleSyncMessagePayload(syncOperation, minDelayMillis);
        mSyncHandler.obtainMessage(mSyncHandler.MESSAGE_SCHEDULE_SYNC, payload).sendToTarget();
    }

    /**
     * Monitor sync progress by calculating how many bytes it is managing to send to and fro.
     */
    private long getTotalBytesTransferredByUid(int uid) {
        return (TrafficStats.getUidRxBytes(uid) + TrafficStats.getUidTxBytes(uid));
    }

    /**
     * Convenience class for passing parameters for a finished or cancelled sync to the handler
     * to be processed.
     */
    private class SyncFinishedOrCancelledMessagePayload {
        public final ActiveSyncContext activeSyncContext;
        public final SyncResult syncResult;

        SyncFinishedOrCancelledMessagePayload(ActiveSyncContext syncContext,
                SyncResult syncResult) {
            this.activeSyncContext = syncContext;
            this.syncResult = syncResult;
        }
    }

    private class UpdatePeriodicSyncMessagePayload {
        public final EndPoint target;
        public final long pollFrequency;
        public final long flex;
        public final Bundle extras;

        UpdatePeriodicSyncMessagePayload(EndPoint target, long pollFrequency, long flex,
                Bundle extras) {
            this.target = target;
            this.pollFrequency = pollFrequency;
            this.flex = flex;
            this.extras = extras;
        }
    }

    private static class ScheduleSyncMessagePayload {
        final SyncOperation syncOperation;
        final long minDelayMillis;

        ScheduleSyncMessagePayload(SyncOperation syncOperation, long minDelayMillis) {
            this.syncOperation = syncOperation;
            this.minDelayMillis = minDelayMillis;
        }
    }

    private void clearBackoffSetting(EndPoint target, String why) {
        Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(target);
        if (backoff != null && backoff.first == SyncStorageEngine.NOT_IN_BACKOFF_MODE &&
                backoff.second == SyncStorageEngine.NOT_IN_BACKOFF_MODE) {
            return;
        }
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Slog.v(TAG, "Clearing backoffs for " + target);
        }
        mSyncStorageEngine.setBackoff(target,
                SyncStorageEngine.NOT_IN_BACKOFF_MODE,
                SyncStorageEngine.NOT_IN_BACKOFF_MODE);

        rescheduleSyncs(target, why);
    }

    private void increaseBackoffSetting(EndPoint target) {
        final long now = SystemClock.elapsedRealtime();

        final Pair<Long, Long> previousSettings =
                mSyncStorageEngine.getBackoff(target);
        long newDelayInMs = -1;
        if (previousSettings != null) {
            // Don't increase backoff before current backoff is expired. This will happen for op's
            // with ignoreBackoff set.
            if (now < previousSettings.first) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Slog.v(TAG, "Still in backoff, do not increase it. "
                            + "Remaining: " + ((previousSettings.first - now) / 1000) + " seconds.");
                }
                return;
            }
            // Subsequent delays are the double of the previous delay.
            newDelayInMs =
                    (long) (previousSettings.second * mConstants.getRetryTimeIncreaseFactor());
        }
        if (newDelayInMs <= 0) {
            // The initial delay is the jitterized INITIAL_SYNC_RETRY_TIME_IN_MS.
            final long initialRetryMs = mConstants.getInitialSyncRetryTimeInSeconds() * 1000;
            newDelayInMs = jitterize(initialRetryMs, (long)(initialRetryMs * 1.1));
        }

        // Cap the delay.
        final long maxSyncRetryTimeInSeconds = mConstants.getMaxSyncRetryTimeInSeconds();

        if (newDelayInMs > maxSyncRetryTimeInSeconds * 1000) {
            newDelayInMs = maxSyncRetryTimeInSeconds * 1000;
        }

        final long backoff = now + newDelayInMs;
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Slog.v(TAG, "Backoff until: " + backoff + ", delayTime: " + newDelayInMs);
        }
        mSyncStorageEngine.setBackoff(target, backoff, newDelayInMs);
        rescheduleSyncs(target, "increaseBackoffSetting");
    }

    /**
     * Reschedule all scheduled syncs for this EndPoint. The syncs will be scheduled according
     * to current backoff and delayUntil values of this EndPoint.
     */
    private void rescheduleSyncs(EndPoint target, String why) {
        mLogger.log("rescheduleSyncs() ep=", target, " why=", why);

        List<SyncOperation> ops = getAllPendingSyncs();
        int count = 0;
        for (SyncOperation op: ops) {
            if (!op.isPeriodic && op.target.matchesSpec(target)) {
                count++;
                cancelJob(op, why);
                postScheduleSyncMessage(op, 0 /* min delay */);
            }
        }
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Slog.v(TAG, "Rescheduled " + count + " syncs for " + target);
        }
    }

    private void setDelayUntilTime(EndPoint target, long delayUntilSeconds) {
        final long delayUntil = delayUntilSeconds * 1000;
        final long absoluteNow = System.currentTimeMillis();
        long newDelayUntilTime;
        if (delayUntil > absoluteNow) {
            newDelayUntilTime = SystemClock.elapsedRealtime() + (delayUntil - absoluteNow);
        } else {
            newDelayUntilTime = 0;
        }
        mSyncStorageEngine.setDelayUntilTime(target, newDelayUntilTime);
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Slog.v(TAG, "Delay Until time set to " + newDelayUntilTime + " for " + target);
        }
        rescheduleSyncs(target, "delayUntil newDelayUntilTime: " + newDelayUntilTime);
    }

    private boolean isAdapterDelayed(EndPoint target) {
        long now = SystemClock.elapsedRealtime();
        Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(target);
        if (backoff != null && backoff.first != SyncStorageEngine.NOT_IN_BACKOFF_MODE
                && backoff.first > now) {
            return true;
        }
        if (mSyncStorageEngine.getDelayUntilTime(target) > now) {
            return true;
        }
        return false;
    }

    /**
     * Cancel the active sync if it matches the target.
     * @param info object containing info about which syncs to cancel. The target can
     * have null account/provider info to specify all accounts/providers.
     * @param extras if non-null, specifies the exact sync to remove.
     */
    public void cancelActiveSync(SyncStorageEngine.EndPoint info, Bundle extras, String why) {
        sendCancelSyncsMessage(info, extras, why);
    }

    /**
     * Schedule a sync operation with JobScheduler.
     */
    private void scheduleSyncOperationH(SyncOperation syncOperation) {
        scheduleSyncOperationH(syncOperation, 0L);
    }

    private void scheduleSyncOperationH(SyncOperation syncOperation, long minDelay) {
        final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
        if (syncOperation == null) {
            Slog.e(TAG, "Can't schedule null sync operation.");
            return;
        }
        if (!syncOperation.ignoreBackoff()) {
            Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(syncOperation.target);
            if (backoff == null) {
                Slog.e(TAG, "Couldn't find backoff values for " + syncOperation.target);
                backoff = new Pair<Long, Long>(SyncStorageEngine.NOT_IN_BACKOFF_MODE,
                        SyncStorageEngine.NOT_IN_BACKOFF_MODE);
            }
            long now = SystemClock.elapsedRealtime();
            long backoffDelay = backoff.first == SyncStorageEngine.NOT_IN_BACKOFF_MODE ? 0
                    : backoff.first - now;
            long delayUntil = mSyncStorageEngine.getDelayUntilTime(syncOperation.target);
            long delayUntilDelay = delayUntil > now ? delayUntil - now : 0;
            if (isLoggable) {
                Slog.v(TAG, "backoff delay:" + backoffDelay
                        + " delayUntil delay:" + delayUntilDelay);
            }
            minDelay = Math.max(minDelay, Math.max(backoffDelay, delayUntilDelay));
        }

        if (minDelay < 0) {
            minDelay = 0;
        }

        // Check if duplicate syncs are pending. If found, keep one with least expected run time.

        // If any of the duplicate ones has exemption, then we inherit it.
        if (!syncOperation.isPeriodic) {
            int inheritedSyncExemptionFlag = ContentResolver.SYNC_EXEMPTION_NONE;

            // Check currently running syncs
            for (ActiveSyncContext asc: mActiveSyncContexts) {
                if (asc.mSyncOperation.key.equals(syncOperation.key)) {
                    if (isLoggable) {
                        Log.v(TAG, "Duplicate sync is already running. Not scheduling "
                                + syncOperation);
                    }
                    return;
                }
            }

            int duplicatesCount = 0;
            long now = SystemClock.elapsedRealtime();
            syncOperation.expectedRuntime = now + minDelay;
            List<SyncOperation> pending = getAllPendingSyncs();
            SyncOperation syncToRun = syncOperation;
            for (SyncOperation op : pending) {
                if (op.isPeriodic) {
                    continue;
                }
                if (op.key.equals(syncOperation.key)) {
                    if (syncToRun.expectedRuntime > op.expectedRuntime) {
                        syncToRun = op;
                    }
                    duplicatesCount++;
                }
            }
            if (duplicatesCount > 1) {
                Slog.e(TAG, "FATAL ERROR! File a bug if you see this.");
            }

            if (syncOperation != syncToRun) {
                // If there's a duplicate with an earlier run time that's not exempted,
                // and if the current operation is exempted with no minDelay,
                // cancel the duplicate one and keep the current one.
                //
                // This means the duplicate one has a negative expected run time, but it hasn't
                // been executed possibly because of app-standby.

                if ((minDelay == 0)
                        && (syncToRun.syncExemptionFlag < syncOperation.syncExemptionFlag)) {
                    syncToRun = syncOperation;
                    inheritedSyncExemptionFlag =
                            Math.max(inheritedSyncExemptionFlag, syncToRun.syncExemptionFlag);
                }
            }

            // Cancel all other duplicate syncs.
            for (SyncOperation op : pending) {
                if (op.isPeriodic) {
                    continue;
                }
                if (op.key.equals(syncOperation.key)) {
                    if (op != syncToRun) {
                        if (isLoggable) {
                            Slog.v(TAG, "Cancelling duplicate sync " + op);
                        }
                        inheritedSyncExemptionFlag =
                                Math.max(inheritedSyncExemptionFlag, op.syncExemptionFlag);
                        cancelJob(op, "scheduleSyncOperationH-duplicate");
                    }
                }
            }
            if (syncToRun != syncOperation) {
                // Don't schedule because a duplicate sync with earlier expected runtime exists.
                if (isLoggable) {
                    Slog.v(TAG, "Not scheduling because a duplicate exists.");
                }

                // TODO Should we give the winning one SYNC_EXTRAS_APP_STANDBY_EXEMPTED
                // if the current one has it?
                return;
            }

            // If any of the duplicates had exemption, we exempt the current one.
            //
            if (inheritedSyncExemptionFlag > ContentResolver.SYNC_EXEMPTION_NONE) {
                syncOperation.syncExemptionFlag = inheritedSyncExemptionFlag;
            }
        }

        // Syncs that are re-scheduled shouldn't get a new job id.
        if (syncOperation.jobId == SyncOperation.NO_JOB_ID) {
            syncOperation.jobId = getUnusedJobIdH();
        }

        if (isLoggable) {
            Slog.v(TAG, "scheduling sync operation " + syncOperation.toString());
        }

        int priority = syncOperation.findPriority();

        final int networkType = syncOperation.isNotAllowedOnMetered() ?
                JobInfo.NETWORK_TYPE_UNMETERED : JobInfo.NETWORK_TYPE_ANY;

        // Note this logic means when an exempted sync fails,
        // the back-off one will inherit it too, and will be exempted from app-standby.
        final int jobFlags = syncOperation.isAppStandbyExempted()
                ? JobInfo.FLAG_EXEMPT_FROM_APP_STANDBY : 0;

        JobInfo.Builder b = new JobInfo.Builder(syncOperation.jobId,
                new ComponentName(mContext, SyncJobService.class))
                .setExtras(syncOperation.toJobInfoExtras())
                .setRequiredNetworkType(networkType)
                .setPersisted(true)
                .setPriority(priority)
                .setFlags(jobFlags);

        if (syncOperation.isPeriodic) {
            b.setPeriodic(syncOperation.periodMillis, syncOperation.flexMillis);
        } else {
            if (minDelay > 0) {
                b.setMinimumLatency(minDelay);
            }
            getSyncStorageEngine().markPending(syncOperation.target, true);
        }

        if (syncOperation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_REQUIRE_CHARGING)) {
            b.setRequiresCharging(true);
        }

        if (syncOperation.syncExemptionFlag
                == ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP) {
            DeviceIdleController.LocalService dic =
                    LocalServices.getService(DeviceIdleController.LocalService.class);
            if (dic != null) {
                dic.addPowerSaveTempWhitelistApp(Process.SYSTEM_UID,
                        syncOperation.owningPackage,
                        mConstants.getKeyExemptionTempWhitelistDurationInSeconds() * 1000,
                        UserHandle.getUserId(syncOperation.owningUid),
                        /* sync=*/ false, "sync by top app");
            }
        }

        if (syncOperation.isAppStandbyExempted()) {
            final UsageStatsManagerInternal usmi = LocalServices.getService(
                    UsageStatsManagerInternal.class);
            if (usmi != null) {
                usmi.reportExemptedSyncScheduled(syncOperation.owningPackage,
                        UserHandle.getUserId(syncOperation.owningUid));
            }
        }

        getJobScheduler().scheduleAsPackage(b.build(), syncOperation.owningPackage,
                syncOperation.target.userId, syncOperation.wakeLockName());
    }

    /**
     * Remove scheduled sync operations.
     * @param info limit the removals to operations that match this target. The target can
     * have null account/provider info to specify all accounts/providers.
     */
    public void clearScheduledSyncOperations(SyncStorageEngine.EndPoint info) {
        List<SyncOperation> ops = getAllPendingSyncs();
        for (SyncOperation op: ops) {
            if (!op.isPeriodic && op.target.matchesSpec(info)) {
                cancelJob(op, "clearScheduledSyncOperations");
                getSyncStorageEngine().markPending(op.target, false);
            }
        }
        mSyncStorageEngine.setBackoff(info,
                SyncStorageEngine.NOT_IN_BACKOFF_MODE, SyncStorageEngine.NOT_IN_BACKOFF_MODE);
    }

    /**
     * Remove a specified sync, if it exists.
     * @param info Authority for which the sync is to be removed.
     * @param extras extras bundle to uniquely identify sync.
     */
    public void cancelScheduledSyncOperation(SyncStorageEngine.EndPoint info, Bundle extras) {
        List<SyncOperation> ops = getAllPendingSyncs();
        for (SyncOperation op: ops) {
            if (!op.isPeriodic && op.target.matchesSpec(info)
                    && syncExtrasEquals(extras, op.extras, false)) {
                cancelJob(op, "cancelScheduledSyncOperation");
            }
        }
        setAuthorityPendingState(info);
        // Reset the back-off if there are no more syncs pending.
        if (!mSyncStorageEngine.isSyncPending(info)) {
            mSyncStorageEngine.setBackoff(info,
                    SyncStorageEngine.NOT_IN_BACKOFF_MODE, SyncStorageEngine.NOT_IN_BACKOFF_MODE);
        }
    }

    private void maybeRescheduleSync(SyncResult syncResult, SyncOperation operation) {
        final boolean isLoggable = Log.isLoggable(TAG, Log.DEBUG);
        if (isLoggable) {
            Log.d(TAG, "encountered error(s) during the sync: " + syncResult + ", " + operation);
        }

        // The SYNC_EXTRAS_IGNORE_BACKOFF only applies to the first attempt to sync a given
        // request. Retries of the request will always honor the backoff, so clear the
        // flag in case we retry this request.
        if (operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false)) {
            operation.extras.remove(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF);
        }

        if (operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false)
                && !syncResult.syncAlreadyInProgress) {
            // syncAlreadyInProgress flag is set by AbstractThreadedSyncAdapter. The sync adapter
            // has no way of knowing that a sync error occured. So we DO retry if the error is
            // syncAlreadyInProgress.
            if (isLoggable) {
                Log.d(TAG, "not retrying sync operation because SYNC_EXTRAS_DO_NOT_RETRY was specified "
                        + operation);
            }
        } else if (operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false)
                && !syncResult.syncAlreadyInProgress) {
            // If this was an upward sync then schedule a two-way sync immediately.
            operation.extras.remove(ContentResolver.SYNC_EXTRAS_UPLOAD);
            if (isLoggable) {
                Log.d(TAG, "retrying sync operation as a two-way sync because an upload-only sync "
                        + "encountered an error: " + operation);
            }
            scheduleSyncOperationH(operation);
        } else if (syncResult.tooManyRetries) {
            // If this sync aborted because the internal sync loop retried too many times then
            //   don't reschedule. Otherwise we risk getting into a retry loop.
            if (isLoggable) {
                Log.d(TAG, "not retrying sync operation because it retried too many times: "
                        + operation);
            }
        } else if (syncResult.madeSomeProgress()) {
            // If the operation succeeded to some extent then retry immediately.
            if (isLoggable) {
                Log.d(TAG, "retrying sync operation because even though it had an error "
                        + "it achieved some success");
            }
            scheduleSyncOperationH(operation);
        } else if (syncResult.syncAlreadyInProgress) {
            if (isLoggable) {
                Log.d(TAG, "retrying sync operation that failed because there was already a "
                        + "sync in progress: " + operation);
            }
            scheduleSyncOperationH(operation, DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS * 1000);
        } else if (syncResult.hasSoftError()) {
            // If this was a two-way sync then retry soft errors with an exponential backoff.
            if (isLoggable) {
                Log.d(TAG, "retrying sync operation because it encountered a soft error: "
                        + operation);
            }
            scheduleSyncOperationH(operation);
        } else {
            // Otherwise do not reschedule.
            Log.d(TAG, "not retrying sync operation because the error is a hard error: "
                    + operation);
        }
    }

    private void onUserUnlocked(int userId) {
        // Make sure that accounts we're about to use are valid.
        AccountManagerService.getSingleton().validateAccounts(userId);

        mSyncAdapters.invalidateCache(userId);

        EndPoint target = new EndPoint(null, null, userId);
        updateRunningAccounts(target);

        // Schedule sync for any accounts under started user, but only the NOT_INITIALIZED adapters.
        final Account[] accounts = AccountManagerService.getSingleton().getAccounts(userId,
                mContext.getOpPackageName());
        for (Account account : accounts) {
            scheduleSync(account, userId, SyncOperation.REASON_USER_START, null, null,
                    AuthorityInfo.NOT_INITIALIZED, ContentResolver.SYNC_EXEMPTION_NONE,
                    Process.myUid(), -3, null);
        }
    }

    private void onUserStopped(int userId) {
        updateRunningAccounts(null /* Don't sync any target */);

        cancelActiveSync(
                new SyncStorageEngine.EndPoint(
                        null /* any account */,
                        null /* any authority */,
                        userId),
                null /* any sync. */,
                "onUserStopped"
        );
    }

    private void onUserRemoved(int userId) {
        mLogger.log("onUserRemoved: u", userId);
        updateRunningAccounts(null /* Don't sync any target */);

        // Clean up the storage engine database
        mSyncStorageEngine.removeStaleAccounts(null, userId);
        List<SyncOperation> ops = getAllPendingSyncs();
        for (SyncOperation op: ops) {
            if (op.target.userId == userId) {
                cancelJob(op, "user removed u" + userId);
            }
        }
    }

    /**
     * Construct intent used to bind to an adapter.
     *
     * @param context Context to create intent for
     * @param syncAdapterComponent The adapter description
     * @param userId The user the adapter belongs to
     *
     * @return The intent required to bind to the adapter
     */
    static @NonNull Intent getAdapterBindIntent(@NonNull Context context,
            @NonNull ComponentName syncAdapterComponent, @UserIdInt int userId) {
        final Intent intent = new Intent();
        intent.setAction("android.content.SyncAdapter");
        intent.setComponent(syncAdapterComponent);
        intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
                com.android.internal.R.string.sync_binding_label);
        intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(context, 0,
                new Intent(Settings.ACTION_SYNC_SETTINGS), 0, null, UserHandle.of(userId)));

        return intent;
    }

    /**
     * @hide
     */
    class ActiveSyncContext extends ISyncContext.Stub
            implements ServiceConnection, IBinder.DeathRecipient {
        final SyncOperation mSyncOperation;
        final long mHistoryRowId;
        ISyncAdapter mSyncAdapter;
        final long mStartTime;
        long mTimeoutStartTime;
        boolean mBound;
        final PowerManager.WakeLock mSyncWakeLock;
        final int mSyncAdapterUid;
        SyncInfo mSyncInfo;
        boolean mIsLinkedToDeath = false;
        String mEventName;

        /** Total bytes transferred, counted at {@link #mLastPolledTimeElapsed} */
        long mBytesTransferredAtLastPoll;
        /**
         * Last point in {@link SystemClock#elapsedRealtime()} at which we checked the # of bytes
         * transferred to/fro by this adapter.
         */
        long mLastPolledTimeElapsed;

        /**
         * Create an ActiveSyncContext for an impending sync and grab the wakelock for that
         * sync adapter. Since this grabs the wakelock you need to be sure to call
         * close() when you are done with this ActiveSyncContext, whether the sync succeeded
         * or not.
         * @param syncOperation the SyncOperation we are about to sync
         * @param historyRowId the row in which to record the history info for this sync
         * @param syncAdapterUid the UID of the application that contains the sync adapter
         * for this sync. This is used to attribute the wakelock hold to that application.
         */
        public ActiveSyncContext(SyncOperation syncOperation, long historyRowId,
                int syncAdapterUid) {
            super();
            mSyncAdapterUid = syncAdapterUid;
            mSyncOperation = syncOperation;
            mHistoryRowId = historyRowId;
            mSyncAdapter = null;
            mStartTime = SystemClock.elapsedRealtime();
            mTimeoutStartTime = mStartTime;
            mSyncWakeLock = mSyncHandler.getSyncWakeLock(mSyncOperation);
            mSyncWakeLock.setWorkSource(new WorkSource(syncAdapterUid));
            mSyncWakeLock.acquire();
        }

        public void sendHeartbeat() {
            // Heartbeats are no longer used.
        }

        public void onFinished(SyncResult result) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) Slog.v(TAG, "onFinished: " + this);
            // Include "this" in the message so that the handler can ignore it if this
            // ActiveSyncContext is no longer the mActiveSyncContext at message handling
            // time.
            mLogger.log("onFinished result=", result, " endpoint=",
                    (mSyncOperation == null ? "null" : mSyncOperation.target));
            sendSyncFinishedOrCanceledMessage(this, result);
        }

        public void toString(StringBuilder sb) {
            sb.append("startTime ").append(mStartTime)
                    .append(", mTimeoutStartTime ").append(mTimeoutStartTime)
                    .append(", mHistoryRowId ").append(mHistoryRowId)
                    .append(", syncOperation ").append(mSyncOperation);
        }

        public void onServiceConnected(ComponentName name, IBinder service) {
            Message msg = mSyncHandler.obtainMessage();
            msg.what = SyncHandler.MESSAGE_SERVICE_CONNECTED;
            msg.obj = new ServiceConnectionData(this, service);
            mSyncHandler.sendMessage(msg);
        }

        public void onServiceDisconnected(ComponentName name) {
            Message msg = mSyncHandler.obtainMessage();
            msg.what = SyncHandler.MESSAGE_SERVICE_DISCONNECTED;
            msg.obj = new ServiceConnectionData(this, null);
            mSyncHandler.sendMessage(msg);
        }

        boolean bindToSyncAdapter(ComponentName serviceComponent, int userId) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.d(TAG, "bindToSyncAdapter: " + serviceComponent + ", connection " + this);
            }
            Intent intent = getAdapterBindIntent(mContext, serviceComponent, userId);

            mBound = true;
            final boolean bindResult = mContext.bindServiceAsUser(intent, this,
                    SYNC_ADAPTER_CONNECTION_FLAGS, new UserHandle(mSyncOperation.target.userId));
            mLogger.log("bindService() returned=", mBound, " for ", this);
            if (!bindResult) {
                mBound = false;
            } else {
                try {
                    mEventName = mSyncOperation.wakeLockName();
                    mBatteryStats.noteSyncStart(mEventName, mSyncAdapterUid);
                } catch (RemoteException e) {
                }
            }
            return bindResult;
        }

        /**
         * Performs the required cleanup, which is the releasing of the wakelock and
         * unbinding from the sync adapter (if actually bound).
         */
        protected void close() {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.d(TAG, "unBindFromSyncAdapter: connection " + this);
            }
            if (mBound) {
                mBound = false;
                mLogger.log("unbindService for ", this);
                mContext.unbindService(this);
                try {
                    mBatteryStats.noteSyncFinish(mEventName, mSyncAdapterUid);
                } catch (RemoteException e) {
                }
            }
            mSyncWakeLock.release();
            mSyncWakeLock.setWorkSource(null);
        }

        public String toString() {
            StringBuilder sb = new StringBuilder();
            toString(sb);
            return sb.toString();
        }

        @Override
        public void binderDied() {
            sendSyncFinishedOrCanceledMessage(this, null);
        }
    }

    protected void dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll) {
        final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");

        final SyncAdapterStateFetcher buckets = new SyncAdapterStateFetcher();

        dumpSyncState(ipw, buckets);
        mConstants.dump(pw, "");
        dumpSyncAdapters(ipw);

        if (dumpAll) {
            ipw.println("Detailed Sync History");
            mLogger.dumpAll(pw);
        }
    }

    static String formatTime(long time) {
        if (time == 0) {
            return "N/A";
        }
        Time tobj = new Time();
        tobj.set(time);
        return tobj.format("%Y-%m-%d %H:%M:%S");
    }

    private final static Comparator<SyncOperation> sOpDumpComparator = (op1, op2) -> {
        int res = Integer.compare(op1.target.userId, op2.target.userId);
        if (res != 0) return res;

        final Comparator<String> stringComparator = String.CASE_INSENSITIVE_ORDER;

        res = stringComparator.compare(op1.target.account.type, op2.target.account.type);
        if (res != 0) return res;

        res = stringComparator.compare(op1.target.account.name, op2.target.account.name);
        if (res != 0) return res;

        res = stringComparator.compare(op1.target.provider, op2.target.provider);
        if (res != 0) return res;

        res = Integer.compare(op1.reason, op2.reason);
        if (res != 0) return res;

        res = Long.compare(op1.periodMillis, op2.periodMillis);
        if (res != 0) return res;

        res = Long.compare(op1.expectedRuntime, op2.expectedRuntime);
        if (res != 0) return res;

        res = Long.compare(op1.jobId, op2.jobId);
        if (res != 0) return res;

        return 0;
    };

    private final static Comparator<SyncOperation> sOpRuntimeComparator = (op1, op2) -> {
        int res = Long.compare(op1.expectedRuntime, op2.expectedRuntime);
        if (res != 0) return res;

        return sOpDumpComparator.compare(op1, op2);
    };

    private static <T> int countIf(Collection<T> col, Predicate<T> p) {
        int ret = 0;
        for (T item : col) {
            if (p.test(item)) ret++;
        }
        return ret;
    }

    protected void dumpPendingSyncs(PrintWriter pw, SyncAdapterStateFetcher buckets) {
        List<SyncOperation> pendingSyncs = getAllPendingSyncs();

        pw.print("Pending Syncs: ");
        pw.println(countIf(pendingSyncs, op -> !op.isPeriodic));

        Collections.sort(pendingSyncs, sOpRuntimeComparator);
        int count = 0;
        for (SyncOperation op: pendingSyncs) {
            if (!op.isPeriodic) {
                pw.println(op.dump(null, false, buckets));
                count++;
            }
        }
        pw.println();
    }

    protected void dumpPeriodicSyncs(PrintWriter pw, SyncAdapterStateFetcher buckets) {
        List<SyncOperation> pendingSyncs = getAllPendingSyncs();

        pw.print("Periodic Syncs: ");
        pw.println(countIf(pendingSyncs, op -> op.isPeriodic));

        Collections.sort(pendingSyncs, sOpDumpComparator);
        int count = 0;
        for (SyncOperation op: pendingSyncs) {
            if (op.isPeriodic) {
                pw.println(op.dump(null, false, buckets));
                count++;
            }
        }
        pw.println();
    }

    /**
     * Similar to {@link android.util.TimeUtils#formatDuration}, but it's more suitable and concise
     * for the sync manager dumpsys.  (Don't add the leading + sign, don't show milliseconds.)
     */
    public static StringBuilder formatDurationHMS(StringBuilder sb, long duration) {
        duration /= 1000;
        if (duration < 0) {
            sb.append('-');
            duration = -duration;
        }
        final long seconds = duration % 60;
        duration /= 60;

        final long minutes = duration % 60;
        duration /= 60;

        final long hours = duration % 24;
        duration /= 24;

        final long days = duration;

        boolean print = false;
        if (days > 0) {
            sb.append(days);
            sb.append('d');
            print = true;
        }
        print = printTwoDigitNumber(sb, hours, 'h', print);
        print = printTwoDigitNumber(sb, minutes, 'm', print);
        print = printTwoDigitNumber(sb, seconds, 's', print);
        if (!print) {
            sb.append("0s");
        }

        return sb;
    }

    private static boolean printTwoDigitNumber(StringBuilder sb, long value, char unit,
            boolean always) {
        if (!always && (value == 0)) {
            return false;
        }
        if (always && (value < 10)) {
            sb.append('0');
        }
        sb.append(value);
        sb.append(unit);
        return true;
    }

    protected void dumpSyncState(PrintWriter pw, SyncAdapterStateFetcher buckets) {
        final StringBuilder sb = new StringBuilder();

        pw.print("Data connected: "); pw.println(mDataConnectionIsConnected);
        pw.print("Battery saver: ");
        pw.println((mPowerManager != null) && mPowerManager.isPowerSaveMode());

        pw.print("Background network restriction: ");
        {
            final ConnectivityManager cm = getConnectivityManager();
            final int status = (cm == null) ? -1 : cm.getRestrictBackgroundStatus();
            switch (status) {
                case ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED:
                    pw.println(" disabled");
                    break;
                case ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED:
                    pw.println(" whitelisted");
                    break;
                case ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED:
                    pw.println(" enabled");
                    break;
                default:
                    pw.print("Unknown(");
                    pw.print(status);
                    pw.println(")");
                    break;
            }
        }

        pw.print("Auto sync: ");
        List<UserInfo> users = getAllUsers();
        if (users != null) {
            for (UserInfo user : users) {
                pw.print("u" + user.id + "="
                        + mSyncStorageEngine.getMasterSyncAutomatically(user.id) + " ");
            }
            pw.println();
        }
        pw.print("Memory low: "); pw.println(mStorageIsLow);
        pw.print("Device idle: "); pw.println(mDeviceIsIdle);
        pw.print("Reported active: "); pw.println(mReportedSyncActive);
        pw.print("Clock valid: "); pw.println(mSyncStorageEngine.isClockValid());

        final AccountAndUser[] accounts = AccountManagerService.getSingleton().getAllAccounts();

        pw.print("Accounts: ");
        if (accounts != INITIAL_ACCOUNTS_ARRAY) {
            pw.println(accounts.length);
        } else {
            pw.println("not known yet");
        }
        final long now = SystemClock.elapsedRealtime();
        pw.print("Now: "); pw.print(now);
        pw.println(" (" + formatTime(System.currentTimeMillis()) + ")");

        sb.setLength(0);
        pw.print("Uptime: "); pw.print(formatDurationHMS(sb, now));
        pw.println();
        pw.print("Time spent syncing: ");

        sb.setLength(0);
        pw.print(formatDurationHMS(sb,
                mSyncHandler.mSyncTimeTracker.timeSpentSyncing()));
        pw.print(", sync ");
        pw.print(mSyncHandler.mSyncTimeTracker.mLastWasSyncing ? "" : "not ");
        pw.println("in progress");

        pw.println();
        pw.println("Active Syncs: " + mActiveSyncContexts.size());
        final PackageManager pm = mContext.getPackageManager();
        for (SyncManager.ActiveSyncContext activeSyncContext : mActiveSyncContexts) {
            final long durationInSeconds = (now - activeSyncContext.mStartTime);
            pw.print("  ");
            sb.setLength(0);
            pw.print(formatDurationHMS(sb, durationInSeconds));
            pw.print(" - ");
            pw.print(activeSyncContext.mSyncOperation.dump(pm, false, buckets));
            pw.println();
        }
        pw.println();

        dumpPendingSyncs(pw, buckets);
        dumpPeriodicSyncs(pw, buckets);

        // Join the installed sync adapter with the accounts list and emit for everything.
        pw.println("Sync Status");

        final ArrayList<Pair<EndPoint, SyncStatusInfo>> statuses = new ArrayList<>();

        mSyncStorageEngine.resetTodayStats(/* force=*/ false);

        for (AccountAndUser account : accounts) {
            final boolean unlocked;
            synchronized (mUnlockedUsers) {
                unlocked = mUnlockedUsers.get(account.userId);
            }
            pw.printf("Account %s u%d %s%s\n",
                    account.account.name, account.userId, account.account.type,
                    (unlocked ? "" : " (locked)"));

            pw.println("=======================================================================");
            final PrintTable table = new PrintTable(16);
            table.set(0, 0,
                    "Authority", // 0
                    "Syncable",  // 1
                    "Enabled",   // 2

                    "Stats",     // 3 "Total", "Today" or "Yesterday".

                    "Loc",       // 4 # of syncs with local sources. (including failures/cancels. )
                    "Poll",      // 5 "poll" syncs.
                    "Per",       // 6 Periodic syncs.
                    "Feed",      // 7 Syncs with a "feed" extra. (subscribedfeeds?)
                    "User",      // 8 User-initiated
                    "Othr",      // 9 Other sources.

                    "Tot",       // 10 Total syncs (including failures / cancels)
                    "Fail",      // 11 (Failure)
                    "Can",       // 12 (Cancel)

                    "Time",      // 13 Total time
                    "Last Sync", // 14
                    "Backoff"    // 15
            );

            final List<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> sorted =
                    Lists.newArrayList();
            sorted.addAll(mSyncAdapters.getAllServices(account.userId));
            Collections.sort(sorted,
                    new Comparator<RegisteredServicesCache.ServiceInfo<SyncAdapterType>>() {
                        @Override
                        public int compare(RegisteredServicesCache.ServiceInfo<SyncAdapterType> lhs,
                                RegisteredServicesCache.ServiceInfo<SyncAdapterType> rhs) {
                            return lhs.type.authority.compareTo(rhs.type.authority);
                        }
                    });
            for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterType : sorted) {
                if (!syncAdapterType.type.accountType.equals(account.account.type)) {
                    continue;
                }
                int row = table.getNumRows();
                Pair<AuthorityInfo, SyncStatusInfo> syncAuthoritySyncStatus =
                        mSyncStorageEngine.getCopyOfAuthorityWithSyncStatus(
                                new SyncStorageEngine.EndPoint(
                                        account.account,
                                        syncAdapterType.type.authority,
                                        account.userId));
                SyncStorageEngine.AuthorityInfo settings = syncAuthoritySyncStatus.first;
                SyncStatusInfo status = syncAuthoritySyncStatus.second;
                statuses.add(Pair.create(settings.target, status));
                String authority = settings.target.provider;
                if (authority.length() > 50) {
                    authority = authority.substring(authority.length() - 50);
                }
                table.set(row, 0, authority, settings.syncable, settings.enabled);

                QuadConsumer<String, Stats, Function<Integer, String>, Integer> c =
                        (label, stats, filter, r) -> {
                    sb.setLength(0);
                    table.set(r, 3,
                            label,
                            filter.apply(stats.numSourceLocal),
                            filter.apply(stats.numSourcePoll),
                            filter.apply(stats.numSourcePeriodic),
                            filter.apply(stats.numSourceFeed),
                            filter.apply(stats.numSourceUser),
                            filter.apply(stats.numSourceOther),
                            filter.apply(stats.numSyncs),
                            filter.apply(stats.numFailures),
                            filter.apply(stats.numCancels),
                            formatDurationHMS(sb, stats.totalElapsedTime));
                };
                c.accept("Total", status.totalStats, (i) -> Integer.toString(i), row);
                c.accept("Today", status.todayStats, this::zeroToEmpty, row + 1);
                c.accept("Yestr", status.yesterdayStats, this::zeroToEmpty, row + 2);

                final int LAST_SYNC = 14;
                final int BACKOFF = LAST_SYNC + 1;

                int row1 = row;
                if (settings.delayUntil > now) {
                    table.set(row1++, BACKOFF, "D: " + (settings.delayUntil - now) / 1000);
                    if (settings.backoffTime > now) {
                        table.set(row1++, BACKOFF, "B: " + (settings.backoffTime - now) / 1000);
                        table.set(row1++, BACKOFF, settings.backoffDelay / 1000);
                    }
                }

                row1 = row;
                if (status.lastSuccessTime != 0) {
                    table.set(row1++, LAST_SYNC, SyncStorageEngine.SOURCES[status.lastSuccessSource]
                            + " " + "SUCCESS");
                    table.set(row1++, LAST_SYNC, formatTime(status.lastSuccessTime));
                }
                if (status.lastFailureTime != 0) {
                    table.set(row1++, LAST_SYNC, SyncStorageEngine.SOURCES[status.lastFailureSource]
                            + " " + "FAILURE");
                    table.set(row1++, LAST_SYNC, formatTime(status.lastFailureTime));
                    //noinspection UnusedAssignment
                    table.set(row1++, LAST_SYNC, status.lastFailureMesg);
                }
            }
            table.writeTo(pw);
        }

        dumpSyncHistory(pw);

        pw.println();
        pw.println("Per Adapter History");
        pw.println("(SERVER is now split up to FEED and OTHER)");

        for (int i = 0; i < statuses.size(); i++) {
            final Pair<EndPoint, SyncStatusInfo> event = statuses.get(i);

            pw.print("  ");
            pw.print(event.first.account.name);
            pw.print('/');
            pw.print(event.first.account.type);
            pw.print(" u");
            pw.print(event.first.userId);
            pw.print(" [");
            pw.print(event.first.provider);
            pw.print("]");
            pw.println();

            pw.println("    Per source last syncs:");
            for (int j = 0; j < SyncStorageEngine.SOURCES.length; j++) {
                pw.print("      ");
                pw.print(String.format("%8s", SyncStorageEngine.SOURCES[j]));
                pw.print("  Success: ");
                pw.print(formatTime(event.second.perSourceLastSuccessTimes[j]));

                pw.print("  Failure: ");
                pw.println(formatTime(event.second.perSourceLastFailureTimes[j]));
            }

            pw.println("    Last syncs:");
            for (int j = 0; j < event.second.getEventCount(); j++) {
                pw.print("      ");
                pw.print(formatTime(event.second.getEventTime(j)));
                pw.print(' ');
                pw.print(event.second.getEvent(j));
                pw.println();
            }
            if (event.second.getEventCount() == 0) {
                pw.println("      N/A");
            }
        }
    }

    private String zeroToEmpty(int value) {
        return (value != 0) ? Integer.toString(value) : "";
    }

    private void dumpTimeSec(PrintWriter pw, long time) {
        pw.print(time/1000); pw.print('.'); pw.print((time/100)%10);
        pw.print('s');
    }

    private void dumpDayStatistic(PrintWriter pw, SyncStorageEngine.DayStats ds) {
        pw.print("Success ("); pw.print(ds.successCount);
        if (ds.successCount > 0) {
            pw.print(" for "); dumpTimeSec(pw, ds.successTime);
            pw.print(" avg="); dumpTimeSec(pw, ds.successTime/ds.successCount);
        }
        pw.print(") Failure ("); pw.print(ds.failureCount);
        if (ds.failureCount > 0) {
            pw.print(" for "); dumpTimeSec(pw, ds.failureTime);
            pw.print(" avg="); dumpTimeSec(pw, ds.failureTime/ds.failureCount);
        }
        pw.println(")");
    }

    protected void dumpSyncHistory(PrintWriter pw) {
        dumpRecentHistory(pw);
        dumpDayStatistics(pw);
    }

    private void dumpRecentHistory(PrintWriter pw) {
        final ArrayList<SyncStorageEngine.SyncHistoryItem> items
                = mSyncStorageEngine.getSyncHistory();
        if (items != null && items.size() > 0) {
            final Map<String, AuthoritySyncStats> authorityMap = Maps.newHashMap();
            long totalElapsedTime = 0;
            long totalTimes = 0;
            final int N = items.size();

            int maxAuthority = 0;
            int maxAccount = 0;
            for (SyncStorageEngine.SyncHistoryItem item : items) {
                SyncStorageEngine.AuthorityInfo authorityInfo
                        = mSyncStorageEngine.getAuthority(item.authorityId);
                final String authorityName;
                final String accountKey;
                if (authorityInfo != null) {
                    authorityName = authorityInfo.target.provider;
                    accountKey = authorityInfo.target.account.name + "/"
                            + authorityInfo.target.account.type
                            + " u" + authorityInfo.target.userId;
                } else {
                    authorityName = "Unknown";
                    accountKey = "Unknown";
                }

                int length = authorityName.length();
                if (length > maxAuthority) {
                    maxAuthority = length;
                }
                length = accountKey.length();
                if (length > maxAccount) {
                    maxAccount = length;
                }

                final long elapsedTime = item.elapsedTime;
                totalElapsedTime += elapsedTime;
                totalTimes++;
                AuthoritySyncStats authoritySyncStats = authorityMap.get(authorityName);
                if (authoritySyncStats == null) {
                    authoritySyncStats = new AuthoritySyncStats(authorityName);
                    authorityMap.put(authorityName, authoritySyncStats);
                }
                authoritySyncStats.elapsedTime += elapsedTime;
                authoritySyncStats.times++;
                final Map<String, AccountSyncStats> accountMap = authoritySyncStats.accountMap;
                AccountSyncStats accountSyncStats = accountMap.get(accountKey);
                if (accountSyncStats == null) {
                    accountSyncStats = new AccountSyncStats(accountKey);
                    accountMap.put(accountKey, accountSyncStats);
                }
                accountSyncStats.elapsedTime += elapsedTime;
                accountSyncStats.times++;

            }

            if (totalElapsedTime > 0) {
                pw.println();
                pw.printf("Detailed Statistics (Recent history):  "
                                + "%d (# of times) %ds (sync time)\n",
                        totalTimes, totalElapsedTime / 1000);

                final List<AuthoritySyncStats> sortedAuthorities =
                        new ArrayList<AuthoritySyncStats>(authorityMap.values());
                Collections.sort(sortedAuthorities, new Comparator<AuthoritySyncStats>() {
                    @Override
                    public int compare(AuthoritySyncStats lhs, AuthoritySyncStats rhs) {
                        // reverse order
                        int compare = Integer.compare(rhs.times, lhs.times);
                        if (compare == 0) {
                            compare = Long.compare(rhs.elapsedTime, lhs.elapsedTime);
                        }
                        return compare;
                    }
                });

                final int maxLength = Math.max(maxAuthority, maxAccount + 3);
                final int padLength = 2 + 2 + maxLength + 2 + 10 + 11;
                final char chars[] = new char[padLength];
                Arrays.fill(chars, '-');
                final String separator = new String(chars);

                final String authorityFormat =
                        String.format("  %%-%ds: %%-9s  %%-11s\n", maxLength + 2);
                final String accountFormat =
                        String.format("    %%-%ds:   %%-9s  %%-11s\n", maxLength);

                pw.println(separator);
                for (AuthoritySyncStats authoritySyncStats : sortedAuthorities) {
                    String name = authoritySyncStats.name;
                    long elapsedTime;
                    int times;
                    String timeStr;
                    String timesStr;

                    elapsedTime = authoritySyncStats.elapsedTime;
                    times = authoritySyncStats.times;
                    timeStr = String.format("%ds/%d%%",
                            elapsedTime / 1000,
                            elapsedTime * 100 / totalElapsedTime);
                    timesStr = String.format("%d/%d%%",
                            times,
                            times * 100 / totalTimes);
                    pw.printf(authorityFormat, name, timesStr, timeStr);

                    final List<AccountSyncStats> sortedAccounts =
                            new ArrayList<AccountSyncStats>(
                                    authoritySyncStats.accountMap.values());
                    Collections.sort(sortedAccounts, new Comparator<AccountSyncStats>() {
                        @Override
                        public int compare(AccountSyncStats lhs, AccountSyncStats rhs) {
                            // reverse order
                            int compare = Integer.compare(rhs.times, lhs.times);
                            if (compare == 0) {
                                compare = Long.compare(rhs.elapsedTime, lhs.elapsedTime);
                            }
                            return compare;
                        }
                    });
                    for (AccountSyncStats stats: sortedAccounts) {
                        elapsedTime = stats.elapsedTime;
                        times = stats.times;
                        timeStr = String.format("%ds/%d%%",
                                elapsedTime / 1000,
                                elapsedTime * 100 / totalElapsedTime);
                        timesStr = String.format("%d/%d%%",
                                times,
                                times * 100 / totalTimes);
                        pw.printf(accountFormat, stats.name, timesStr, timeStr);
                    }
                    pw.println(separator);
                }
            }

            pw.println();
            pw.println("Recent Sync History");
            pw.println("(SERVER is now split up to FEED and OTHER)");
            final String format = "  %-" + maxAccount + "s  %-" + maxAuthority + "s %s\n";
            final Map<String, Long> lastTimeMap = Maps.newHashMap();
            final PackageManager pm = mContext.getPackageManager();
            for (int i = 0; i < N; i++) {
                SyncStorageEngine.SyncHistoryItem item = items.get(i);
                SyncStorageEngine.AuthorityInfo authorityInfo
                        = mSyncStorageEngine.getAuthority(item.authorityId);
                final String authorityName;
                final String accountKey;
                if (authorityInfo != null) {
                    authorityName = authorityInfo.target.provider;
                    accountKey = authorityInfo.target.account.name + "/"
                            + authorityInfo.target.account.type
                            + " u" + authorityInfo.target.userId;
                } else {
                    authorityName = "Unknown";
                    accountKey = "Unknown";
                }
                final long elapsedTime = item.elapsedTime;
                final Time time = new Time();
                final long eventTime = item.eventTime;
                time.set(eventTime);

                final String key = authorityName + "/" + accountKey;
                final Long lastEventTime = lastTimeMap.get(key);
                final String diffString;
                if (lastEventTime == null) {
                    diffString = "";
                } else {
                    final long diff = (lastEventTime - eventTime) / 1000;
                    if (diff < 60) {
                        diffString = String.valueOf(diff);
                    } else if (diff < 3600) {
                        diffString = String.format("%02d:%02d", diff / 60, diff % 60);
                    } else {
                        final long sec = diff % 3600;
                        diffString = String.format("%02d:%02d:%02d",
                                diff / 3600, sec / 60, sec % 60);
                    }
                }
                lastTimeMap.put(key, eventTime);

                pw.printf("  #%-3d: %s %8s  %5.1fs  %8s",
                        i + 1,
                        formatTime(eventTime),
                        SyncStorageEngine.SOURCES[item.source],
                        ((float) elapsedTime) / 1000,
                        diffString);
                pw.printf(format, accountKey, authorityName,
                        SyncOperation.reasonToString(pm, item.reason));

                if (item.event != SyncStorageEngine.EVENT_STOP
                        || item.upstreamActivity != 0
                        || item.downstreamActivity != 0) {
                    pw.printf("    event=%d upstreamActivity=%d downstreamActivity=%d\n",
                            item.event,
                            item.upstreamActivity,
                            item.downstreamActivity);
                }
                if (item.mesg != null
                        && !SyncStorageEngine.MESG_SUCCESS.equals(item.mesg)) {
                    pw.printf("    mesg=%s\n", item.mesg);
                }
            }
            pw.println();
            pw.println("Recent Sync History Extras");
            pw.println("(SERVER is now split up to FEED and OTHER)");
            for (int i = 0; i < N; i++) {
                final SyncStorageEngine.SyncHistoryItem item = items.get(i);
                final Bundle extras = item.extras;
                if (extras == null || extras.size() == 0) {
                    continue;
                }
                final SyncStorageEngine.AuthorityInfo authorityInfo
                        = mSyncStorageEngine.getAuthority(item.authorityId);
                final String authorityName;
                final String accountKey;
                if (authorityInfo != null) {
                    authorityName = authorityInfo.target.provider;
                    accountKey = authorityInfo.target.account.name + "/"
                            + authorityInfo.target.account.type
                            + " u" + authorityInfo.target.userId;
                } else {
                    authorityName = "Unknown";
                    accountKey = "Unknown";
                }
                final Time time = new Time();
                final long eventTime = item.eventTime;
                time.set(eventTime);

                pw.printf("  #%-3d: %s %8s ",
                        i + 1,
                        formatTime(eventTime),
                        SyncStorageEngine.SOURCES[item.source]);

                pw.printf(format, accountKey, authorityName, extras);
            }
        }
    }

    private void dumpDayStatistics(PrintWriter pw) {
        SyncStorageEngine.DayStats dses[] = mSyncStorageEngine.getDayStatistics();
        if (dses != null && dses[0] != null) {
            pw.println();
            pw.println("Sync Statistics");
            pw.print("  Today:  "); dumpDayStatistic(pw, dses[0]);
            int today = dses[0].day;
            int i;
            SyncStorageEngine.DayStats ds;

            // Print each day in the current week.
            for (i=1; i<=6 && i < dses.length; i++) {
                ds = dses[i];
                if (ds == null) break;
                int delta = today-ds.day;
                if (delta > 6) break;

                pw.print("  Day-"); pw.print(delta); pw.print(":  ");
                dumpDayStatistic(pw, ds);
            }

            // Aggregate all following days into weeks and print totals.
            int weekDay = today;
            while (i < dses.length) {
                SyncStorageEngine.DayStats aggr = null;
                weekDay -= 7;
                while (i < dses.length) {
                    ds = dses[i];
                    if (ds == null) {
                        i = dses.length;
                        break;
                    }
                    int delta = weekDay-ds.day;
                    if (delta > 6) break;
                    i++;

                    if (aggr == null) {
                        aggr = new SyncStorageEngine.DayStats(weekDay);
                    }
                    aggr.successCount += ds.successCount;
                    aggr.successTime += ds.successTime;
                    aggr.failureCount += ds.failureCount;
                    aggr.failureTime += ds.failureTime;
                }
                if (aggr != null) {
                    pw.print("  Week-"); pw.print((today-weekDay)/7); pw.print(": ");
                    dumpDayStatistic(pw, aggr);
                }
            }
        }
    }

    private void dumpSyncAdapters(IndentingPrintWriter pw) {
        pw.println();
        final List<UserInfo> users = getAllUsers();
        if (users != null) {
            for (UserInfo user : users) {
                pw.println("Sync adapters for " + user + ":");
                pw.increaseIndent();
                for (RegisteredServicesCache.ServiceInfo<?> info :
                        mSyncAdapters.getAllServices(user.id)) {
                    pw.println(info);
                }
                pw.decreaseIndent();
                pw.println();
            }
        }
    }

    private static class AuthoritySyncStats {
        String name;
        long elapsedTime;
        int times;
        Map<String, AccountSyncStats> accountMap = Maps.newHashMap();

        private AuthoritySyncStats(String name) {
            this.name = name;
        }
    }

    private static class AccountSyncStats {
        String name;
        long elapsedTime;
        int times;

        private AccountSyncStats(String name) {
            this.name = name;
        }
    }

    interface OnReadyCallback {
        void onReady();
    }

    static void sendOnUnsyncableAccount(@NonNull Context context,
            @NonNull RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo,
            @UserIdInt int userId, @NonNull OnReadyCallback onReadyCallback) {
        OnUnsyncableAccountCheck connection = new OnUnsyncableAccountCheck(syncAdapterInfo,
                onReadyCallback);

        boolean isBound = context.bindServiceAsUser(
                getAdapterBindIntent(context, syncAdapterInfo.componentName, userId),
                connection, SYNC_ADAPTER_CONNECTION_FLAGS, UserHandle.of(userId));

        if (isBound) {
            // Unbind after SERVICE_BOUND_TIME_MILLIS to not leak the connection.
            (new Handler(Looper.getMainLooper())).postDelayed(
                    () -> context.unbindService(connection),
                    OnUnsyncableAccountCheck.SERVICE_BOUND_TIME_MILLIS);
        } else {
                /*
                 * The default implementation of adapter.onUnsyncableAccount returns true. Hence if
                 * there the service cannot be bound, assume the default behavior.
                 */
            connection.onReady();
        }
    }


    /**
     * Helper class for calling ISyncAdapter.onUnsyncableAccountDone.
     *
     * If this returns {@code true} the onReadyCallback is called. Otherwise nothing happens.
     */
    private static class OnUnsyncableAccountCheck implements ServiceConnection {
        static final long SERVICE_BOUND_TIME_MILLIS = 5000;

        private final @NonNull OnReadyCallback mOnReadyCallback;
        private final @NonNull RegisteredServicesCache.ServiceInfo<SyncAdapterType>
                mSyncAdapterInfo;

        OnUnsyncableAccountCheck(
                @NonNull RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo,
                @NonNull OnReadyCallback onReadyCallback) {
            mSyncAdapterInfo = syncAdapterInfo;
            mOnReadyCallback = onReadyCallback;
        }

        private void onReady() {
            long identity = Binder.clearCallingIdentity();
            try {
                mOnReadyCallback.onReady();
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            final ISyncAdapter adapter = ISyncAdapter.Stub.asInterface(service);

            try {
                adapter.onUnsyncableAccount(new ISyncAdapterUnsyncableAccountCallback.Stub() {
                    @Override
                    public void onUnsyncableAccountDone(boolean isReady) {
                        if (isReady) {
                            onReady();
                        }
                    }
                });
            } catch (RemoteException e) {
                Slog.e(TAG, "Could not call onUnsyncableAccountDone " + mSyncAdapterInfo, e);
                /*
                 * The default implementation of adapter.onUnsyncableAccount returns true. Hence if
                 * there is a crash in the implementation, assume the default behavior.
                 */
                onReady();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // Wait until the service connects again
        }
    }

    /**
     * A helper object to keep track of the time we have spent syncing since the last boot
     */
    private class SyncTimeTracker {
        /** True if a sync was in progress on the most recent call to update() */
        boolean mLastWasSyncing = false;
        /** Used to track when lastWasSyncing was last set */
        long mWhenSyncStarted = 0;
        /** The cumulative time we have spent syncing */
        private long mTimeSpentSyncing;

        /** Call to let the tracker know that the sync state may have changed */
        public synchronized void update() {
            final boolean isSyncInProgress = !mActiveSyncContexts.isEmpty();
            if (isSyncInProgress == mLastWasSyncing) return;
            final long now = SystemClock.elapsedRealtime();
            if (isSyncInProgress) {
                mWhenSyncStarted = now;
            } else {
                mTimeSpentSyncing += now - mWhenSyncStarted;
            }
            mLastWasSyncing = isSyncInProgress;
        }

        /** Get how long we have been syncing, in ms */
        public synchronized long timeSpentSyncing() {
            if (!mLastWasSyncing) return mTimeSpentSyncing;

            final long now = SystemClock.elapsedRealtime();
            return mTimeSpentSyncing + (now - mWhenSyncStarted);
        }
    }

    class ServiceConnectionData {
        public final ActiveSyncContext activeSyncContext;
        public final IBinder adapter;

        ServiceConnectionData(ActiveSyncContext activeSyncContext, IBinder adapter) {
            this.activeSyncContext = activeSyncContext;
            this.adapter = adapter;
        }
    }

    @Nullable
    private static SyncManager getInstance() {
        synchronized (SyncManager.class) {
            if (sInstance == null) {
                Slog.wtf(TAG, "sInstance == null"); // Maybe called too early?
            }
            return sInstance;
        }
    }

    /**
     * @return whether the device is ready to run sync jobs for a given user.
     */
    public static boolean readyToSync(int userId) {
        final SyncManager instance = getInstance();
        return (instance != null) && SyncJobService.isReady()
                && instance.mProvisioned && instance.isUserUnlocked(userId);
    }

    public static void sendMessage(Message message) {
        final SyncManager instance = getInstance();
        if (instance != null) {
            instance.mSyncHandler.sendMessage(message);
        }
    }

    /**
     * Handles SyncOperation Messages that are posted to the associated
     * HandlerThread.
     */
    class SyncHandler extends Handler {
        // Messages that can be sent on mHandler.
        private static final int MESSAGE_SYNC_FINISHED = 1;
        private static final int MESSAGE_SERVICE_CONNECTED = 4;
        private static final int MESSAGE_SERVICE_DISCONNECTED = 5;
        private static final int MESSAGE_CANCEL = 6;
        static final int MESSAGE_START_SYNC = 10;
        static final int MESSAGE_STOP_SYNC = 11;
        static final int MESSAGE_SCHEDULE_SYNC = 12;
        static final int MESSAGE_UPDATE_PERIODIC_SYNC = 13;
        static final int MESSAGE_REMOVE_PERIODIC_SYNC = 14;

        /**
         * Posted periodically to monitor network process for long-running syncs.
         * obj: {@link com.android.server.content.SyncManager.ActiveSyncContext}
         */
        private static final int MESSAGE_MONITOR_SYNC = 8;
        private static final int MESSAGE_ACCOUNTS_UPDATED = 9;

        public final SyncTimeTracker mSyncTimeTracker = new SyncTimeTracker();
        private final HashMap<String, PowerManager.WakeLock> mWakeLocks = Maps.newHashMap();

        public SyncHandler(Looper looper) {
            super(looper);
        }

        public void handleMessage(Message msg) {
            // TODO Do we really need this wake lock?? If we actually needed it, this is probably
            // not the best place to acquire the lock -- it's probably too late, because the device
            // could have gone to sleep before we reach here.
            mSyncManagerWakeLock.acquire();
            try {
                handleSyncMessage(msg);
            } finally {
                mSyncManagerWakeLock.release();
            }
        }

        private void handleSyncMessage(Message msg) {
            final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);

            try {
                mDataConnectionIsConnected = readDataConnectionState();
                switch (msg.what) {
                    case MESSAGE_ACCOUNTS_UPDATED:
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                            Slog.v(TAG, "handleSyncHandlerMessage: MESSAGE_ACCOUNTS_UPDATED");
                        }
                        EndPoint targets = (EndPoint) msg.obj;
                        updateRunningAccountsH(targets);
                        break;
                    case MESSAGE_SCHEDULE_SYNC:
                        ScheduleSyncMessagePayload syncPayload =
                                (ScheduleSyncMessagePayload) msg.obj;
                        SyncOperation op = syncPayload.syncOperation;
                        scheduleSyncOperationH(op, syncPayload.minDelayMillis);
                        break;

                    case MESSAGE_START_SYNC:
                        op = (SyncOperation) msg.obj;
                        startSyncH(op);
                        break;

                    case MESSAGE_STOP_SYNC:
                        op = (SyncOperation) msg.obj;
                        if (isLoggable) {
                            Slog.v(TAG, "Stop sync received.");
                        }
                        ActiveSyncContext asc = findActiveSyncContextH(op.jobId);
                        if (asc != null) {
                            runSyncFinishedOrCanceledH(null /* no result */, asc);
                            boolean reschedule = msg.arg1 != 0;
                            boolean applyBackoff = msg.arg2 != 0;
                            if (isLoggable) {
                                Slog.v(TAG, "Stopping sync. Reschedule: " + reschedule
                                        + "Backoff: " + applyBackoff);
                            }
                            if (applyBackoff) {
                                increaseBackoffSetting(op.target);
                            }
                            if (reschedule) {
                                deferStoppedSyncH(op, 0);
                            }
                        }
                        break;

                    case MESSAGE_UPDATE_PERIODIC_SYNC:
                        UpdatePeriodicSyncMessagePayload data =
                                (UpdatePeriodicSyncMessagePayload) msg.obj;
                        updateOrAddPeriodicSyncH(data.target, data.pollFrequency,
                                data.flex, data.extras);
                        break;
                    case MESSAGE_REMOVE_PERIODIC_SYNC:
                        Pair<EndPoint, String> args = (Pair<EndPoint, String>) (msg.obj);
                        removePeriodicSyncH(args.first, msg.getData(), args.second);
                        break;

                    case SyncHandler.MESSAGE_CANCEL:
                        SyncStorageEngine.EndPoint endpoint = (SyncStorageEngine.EndPoint) msg.obj;
                        Bundle extras = msg.peekData();
                        if (Log.isLoggable(TAG, Log.DEBUG)) {
                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_CANCEL: "
                                    + endpoint + " bundle: " + extras);
                        }
                        cancelActiveSyncH(endpoint, extras, "MESSAGE_CANCEL");
                        break;

                    case SyncHandler.MESSAGE_SYNC_FINISHED:
                        SyncFinishedOrCancelledMessagePayload payload =
                                (SyncFinishedOrCancelledMessagePayload) msg.obj;
                        if (!isSyncStillActiveH(payload.activeSyncContext)) {
                            Log.d(TAG, "handleSyncHandlerMessage: dropping since the "
                                    + "sync is no longer active: "
                                    + payload.activeSyncContext);
                            break;
                        }
                        if (isLoggable) {
                            Slog.v(TAG, "syncFinished" + payload.activeSyncContext.mSyncOperation);
                        }
                        SyncJobService.callJobFinished(
                                payload.activeSyncContext.mSyncOperation.jobId, false,
                                "sync finished");
                        runSyncFinishedOrCanceledH(payload.syncResult,
                                payload.activeSyncContext);
                        break;

                    case SyncHandler.MESSAGE_SERVICE_CONNECTED: {
                        ServiceConnectionData msgData = (ServiceConnectionData) msg.obj;
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SERVICE_CONNECTED: "
                                    + msgData.activeSyncContext);
                        }
                        // Check that this isn't an old message.
                        if (isSyncStillActiveH(msgData.activeSyncContext)) {
                            runBoundToAdapterH(
                                    msgData.activeSyncContext,
                                    msgData.adapter);
                        }
                        break;
                    }

                    case SyncHandler.MESSAGE_SERVICE_DISCONNECTED: {
                        final ActiveSyncContext currentSyncContext =
                                ((ServiceConnectionData) msg.obj).activeSyncContext;
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SERVICE_DISCONNECTED: "
                                    + currentSyncContext);
                        }
                        // Check that this isn't an old message.
                        if (isSyncStillActiveH(currentSyncContext)) {
                            // cancel the sync if we have a syncadapter, which means one is
                            // outstanding
                            try {
                                if (currentSyncContext.mSyncAdapter != null) {
                                    mLogger.log("Calling cancelSync for SERVICE_DISCONNECTED ",
                                            currentSyncContext,
                                            " adapter=", currentSyncContext.mSyncAdapter);
                                    currentSyncContext.mSyncAdapter.cancelSync(currentSyncContext);
                                    mLogger.log("Canceled");
                                }
                            } catch (RemoteException e) {
                                mLogger.log("RemoteException ", Log.getStackTraceString(e));
                                // We don't need to retry this in this case.
                            }

                            // Pretend that the sync failed with an IOException,
                            // which is a soft error.
                            SyncResult syncResult = new SyncResult();
                            syncResult.stats.numIoExceptions++;
                            SyncJobService.callJobFinished(
                                    currentSyncContext.mSyncOperation.jobId, false,
                                    "service disconnected");
                            runSyncFinishedOrCanceledH(syncResult, currentSyncContext);
                        }
                        break;
                    }

                    case SyncHandler.MESSAGE_MONITOR_SYNC:
                        ActiveSyncContext monitoredSyncContext = (ActiveSyncContext) msg.obj;
                        if (Log.isLoggable(TAG, Log.DEBUG)) {
                            Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_MONITOR_SYNC: " +
                                    monitoredSyncContext.mSyncOperation.target);
                        }

                        if (isSyncNotUsingNetworkH(monitoredSyncContext)) {
                            Log.w(TAG, String.format(
                                    "Detected sync making no progress for %s. cancelling.",
                                    monitoredSyncContext));
                            SyncJobService.callJobFinished(
                                    monitoredSyncContext.mSyncOperation.jobId, false,
                                    "no network activity");
                            runSyncFinishedOrCanceledH(
                                    null /* cancel => no result */, monitoredSyncContext);
                        } else {
                            // Repost message to check again.
                            postMonitorSyncProgressMessage(monitoredSyncContext);
                        }
                        break;

                }
            } finally {
                mSyncTimeTracker.update();
            }
        }

        private PowerManager.WakeLock getSyncWakeLock(SyncOperation operation) {
            final String wakeLockKey = operation.wakeLockName();
            PowerManager.WakeLock wakeLock = mWakeLocks.get(wakeLockKey);
            if (wakeLock == null) {
                final String name = SYNC_WAKE_LOCK_PREFIX + wakeLockKey;
                wakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name);
                wakeLock.setReferenceCounted(false);
                mWakeLocks.put(wakeLockKey, wakeLock);
            }
            return wakeLock;
        }

        /**
         * Defer the specified SyncOperation by rescheduling it on the JobScheduler with some
         * delay. This is equivalent to a failure. If this is a periodic sync, a delayed one-off
         * sync will be scheduled.
         */
        private void deferSyncH(SyncOperation op, long delay, String why) {
            mLogger.log("deferSyncH() ", (op.isPeriodic ? "periodic " : ""),
                    "sync.  op=", op, " delay=", delay, " why=", why);
            SyncJobService.callJobFinished(op.jobId, false, why);
            if (op.isPeriodic) {
                scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay);
            } else {
                // mSyncJobService.callJobFinished is async, so cancel the job to ensure we don't
                // find the this job in the pending jobs list while looking for duplicates
                // before scheduling it at a later time.
                cancelJob(op, "deferSyncH()");
                scheduleSyncOperationH(op, delay);
            }
        }

        /* Same as deferSyncH, but assumes that job is no longer running on JobScheduler. */
        private void deferStoppedSyncH(SyncOperation op, long delay) {
            if (op.isPeriodic) {
                scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay);
            } else {
                scheduleSyncOperationH(op, delay);
            }
        }

        /**
         * Cancel an active sync and reschedule it on the JobScheduler with some delay.
         */
        private void deferActiveSyncH(ActiveSyncContext asc, String why) {
            SyncOperation op = asc.mSyncOperation;
            runSyncFinishedOrCanceledH(null, asc);
            deferSyncH(op, SYNC_DELAY_ON_CONFLICT, why);
        }

        private void startSyncH(SyncOperation op) {
            final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
            if (isLoggable) Slog.v(TAG, op.toString());

            // At this point, we know the device has been connected to the server, so
            // assume the clock is correct.
            mSyncStorageEngine.setClockValid();

            SyncJobService.markSyncStarted(op.jobId);

            if (mStorageIsLow) {
                deferSyncH(op, SYNC_DELAY_ON_LOW_STORAGE, "storage low");
                return;
            }

            if (op.isPeriodic) {
                // Don't allow this periodic to run if a previous instance failed and is currently
                // scheduled according to some backoff criteria.
                List<SyncOperation> ops = getAllPendingSyncs();
                for (SyncOperation syncOperation: ops) {
                    if (syncOperation.sourcePeriodicId == op.jobId) {
                        SyncJobService.callJobFinished(op.jobId, false,
                                "periodic sync, pending");
                        return;
                    }
                }
                // Don't allow this periodic to run if a previous instance failed and is currently
                // executing according to some backoff criteria.
                for (ActiveSyncContext asc: mActiveSyncContexts) {
                    if (asc.mSyncOperation.sourcePeriodicId == op.jobId) {
                        SyncJobService.callJobFinished(op.jobId, false,
                                "periodic sync, already running");
                        return;
                    }
                }
                // Check for adapter delays.
                if (isAdapterDelayed(op.target)) {
                    deferSyncH(op, 0 /* No minimum delay */, "backing off");
                    return;
                }
            }

            // Check for conflicting syncs.
            for (ActiveSyncContext asc: mActiveSyncContexts) {
                if (asc.mSyncOperation.isConflict(op)) {
                    // If the provided SyncOperation conflicts with a running one, the lower
                    // priority sync is pre-empted.
                    if (asc.mSyncOperation.findPriority() >= op.findPriority()) {
                        if (isLoggable) {
                            Slog.v(TAG, "Rescheduling sync due to conflict " + op.toString());
                        }
                        deferSyncH(op, SYNC_DELAY_ON_CONFLICT, "delay on conflict");
                        return;
                    } else {
                        if (isLoggable) {
                            Slog.v(TAG, "Pushing back running sync due to a higher priority sync");
                        }
                        deferActiveSyncH(asc, "preempted");
                        break;
                    }
                }
            }

            final int syncOpState = computeSyncOpState(op);
            switch (syncOpState) {
                case SYNC_OP_STATE_INVALID_NO_ACCOUNT_ACCESS:
                case SYNC_OP_STATE_INVALID: {
                    SyncJobService.callJobFinished(op.jobId, false,
                            "invalid op state: " + syncOpState);
                } return;
            }

            if (!dispatchSyncOperation(op)) {
                SyncJobService.callJobFinished(op.jobId, false, "dispatchSyncOperation() failed");
            }

            setAuthorityPendingState(op.target);
        }

        private ActiveSyncContext findActiveSyncContextH(int jobId) {
            for (ActiveSyncContext asc: mActiveSyncContexts) {
                SyncOperation op = asc.mSyncOperation;
                if (op != null && op.jobId == jobId) {
                    return asc;
                }
            }
            return null;
        }

        private void updateRunningAccountsH(EndPoint syncTargets) {
            AccountAndUser[] oldAccounts = mRunningAccounts;
            mRunningAccounts = AccountManagerService.getSingleton().getRunningAccounts();
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Slog.v(TAG, "Accounts list: ");
                for (AccountAndUser acc : mRunningAccounts) {
                    Slog.v(TAG, acc.toString());
                }
            }
            if (mLogger.enabled()) {
                mLogger.log("updateRunningAccountsH: ", Arrays.toString(mRunningAccounts));
            }
            removeStaleAccounts();

            AccountAndUser[] accounts = mRunningAccounts;
            for (ActiveSyncContext currentSyncContext : mActiveSyncContexts) {
                if (!containsAccountAndUser(accounts,
                        currentSyncContext.mSyncOperation.target.account,
                        currentSyncContext.mSyncOperation.target.userId)) {
                    Log.d(TAG, "canceling sync since the account is no longer running");
                    sendSyncFinishedOrCanceledMessage(currentSyncContext,
                            null /* no result since this is a cancel */);
                }
            }

            // 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;
                }
            }

            // Cancel all jobs from non-existent accounts.
            AccountAndUser[] allAccounts = AccountManagerService.getSingleton().getAllAccounts();
            List<SyncOperation> ops = getAllPendingSyncs();
            for (SyncOperation op: ops) {
                if (!containsAccountAndUser(allAccounts, op.target.account, op.target.userId)) {
                    mLogger.log("canceling: ", op);
                    cancelJob(op, "updateRunningAccountsH()");
                }
            }

            if (syncTargets != null) {
                scheduleSync(syncTargets.account, syncTargets.userId,
                        SyncOperation.REASON_ACCOUNTS_UPDATED, syncTargets.provider,
                        null, AuthorityInfo.NOT_INITIALIZED,
                        ContentResolver.SYNC_EXEMPTION_NONE, Process.myUid(), -4, null);
            }
        }

        /**
         * The given SyncOperation will be removed and a new one scheduled in its place if
         * an updated period or flex is specified.
         * @param syncOperation SyncOperation whose period and flex is to be updated.
         * @param pollFrequencyMillis new period in milliseconds.
         * @param flexMillis new flex time in milliseconds.
         */
        private void maybeUpdateSyncPeriodH(SyncOperation syncOperation, long pollFrequencyMillis,
                long flexMillis) {
            if (!(pollFrequencyMillis == syncOperation.periodMillis
                    && flexMillis == syncOperation.flexMillis)) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Slog.v(TAG, "updating period " + syncOperation + " to " + pollFrequencyMillis
                            + " and flex to " + flexMillis);
                }
                SyncOperation newOp = new SyncOperation(syncOperation, pollFrequencyMillis,
                        flexMillis);
                newOp.jobId = syncOperation.jobId;
                scheduleSyncOperationH(newOp);
            }
        }

        private void updateOrAddPeriodicSyncH(EndPoint target, long pollFrequency, long flex,
                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;
            final long flexMillis = flex * 1000L;
            if (isLoggable) {
                Slog.v(TAG, "Addition to periodic syncs requested: " + target
                        + " period: " + pollFrequency
                        + " flexMillis: " + flex
                        + " extras: " + extras.toString());
            }
            List<SyncOperation> ops = getAllPendingSyncs();
            for (SyncOperation op: ops) {
                if (op.isPeriodic && op.target.matchesSpec(target)
                        && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) {
                    maybeUpdateSyncPeriodH(op, pollFrequencyMillis, flexMillis);
                    return;
                }
            }

            if (isLoggable) {
                Slog.v(TAG, "Adding new periodic sync: " + target
                        + " period: " + pollFrequency
                        + " flexMillis: " + flex
                        + " extras: " + extras.toString());
            }

            final RegisteredServicesCache.ServiceInfo<SyncAdapterType>
                    syncAdapterInfo = mSyncAdapters.getServiceInfo(
                    SyncAdapterType.newKey(
                            target.provider, target.account.type),
                    target.userId);
            if (syncAdapterInfo == null) {
                return;
            }

            SyncOperation op = new SyncOperation(target, syncAdapterInfo.uid,
                    syncAdapterInfo.componentName.getPackageName(), SyncOperation.REASON_PERIODIC,
                    SyncStorageEngine.SOURCE_PERIODIC, extras,
                    syncAdapterInfo.type.allowParallelSyncs(), true, SyncOperation.NO_JOB_ID,
                    pollFrequencyMillis, flexMillis, ContentResolver.SYNC_EXEMPTION_NONE);

            final int syncOpState = computeSyncOpState(op);
            switch (syncOpState) {
                case SYNC_OP_STATE_INVALID_NO_ACCOUNT_ACCESS: {
                    String packageName = op.owningPackage;
                    final int userId = UserHandle.getUserId(op.owningUid);
                    // If the app did not run and has no account access, done
                    if (!wasPackageEverLaunched(packageName, userId)) {
                        return;
                    }
                    mAccountManagerInternal.requestAccountAccess(op.target.account,
                            packageName, userId, new RemoteCallback((Bundle result) -> {
                                if (result != null
                                        && result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT)) {
                                    updateOrAddPeriodicSync(target, pollFrequency, flex, extras);
                                }
                            }
                        ));
                } return;

                case SYNC_OP_STATE_INVALID: {
                    return;
                }
            }

            scheduleSyncOperationH(op);
            mSyncStorageEngine.reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
        }

        /**
         * Remove this periodic sync operation and all one-off operations initiated by it.
         */
        private void removePeriodicSyncInternalH(SyncOperation syncOperation, String why) {
            // Remove this periodic sync and all one-off syncs initiated by it.
            List<SyncOperation> ops = getAllPendingSyncs();
            for (SyncOperation op: ops) {
                if (op.sourcePeriodicId == syncOperation.jobId || op.jobId == syncOperation.jobId) {
                    ActiveSyncContext asc = findActiveSyncContextH(syncOperation.jobId);
                    if (asc != null) {
                        SyncJobService.callJobFinished(syncOperation.jobId, false,
                                "removePeriodicSyncInternalH");
                        runSyncFinishedOrCanceledH(null, asc);
                    }
                    mLogger.log("removePeriodicSyncInternalH-canceling: ", op);
                    cancelJob(op, why);
                }
            }
        }

        private void removePeriodicSyncH(EndPoint target, Bundle extras, String why) {
            verifyJobScheduler();
            List<SyncOperation> ops = getAllPendingSyncs();
            for (SyncOperation op: ops) {
                if (op.isPeriodic && op.target.matchesSpec(target)
                        && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) {
                    removePeriodicSyncInternalH(op, why);
                }
            }
        }

        private boolean isSyncNotUsingNetworkH(ActiveSyncContext activeSyncContext) {
            final long bytesTransferredCurrent =
                    getTotalBytesTransferredByUid(activeSyncContext.mSyncAdapterUid);
            final long deltaBytesTransferred =
                    bytesTransferredCurrent - activeSyncContext.mBytesTransferredAtLastPoll;

            if (Log.isLoggable(TAG, Log.DEBUG)) {
                // Bytes transferred
                long remainder = deltaBytesTransferred;
                long mb = remainder / (1024 * 1024);
                remainder %= 1024 * 1024;
                long kb = remainder / 1024;
                remainder %= 1024;
                long b = remainder;
                Log.d(TAG, String.format(
                        "Time since last update: %ds. Delta transferred: %dMBs,%dKBs,%dBs",
                        (SystemClock.elapsedRealtime()
                                - activeSyncContext.mLastPolledTimeElapsed)/1000,
                        mb, kb, b)
                );
            }
            return (deltaBytesTransferred <= SYNC_MONITOR_PROGRESS_THRESHOLD_BYTES);
        }

        /**
         * Determine if a sync is no longer valid and should be dropped.
         */
        private int computeSyncOpState(SyncOperation op) {
            final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
            int state;
            final EndPoint target = op.target;

            // Drop the sync if the account of this operation no longer exists.
            AccountAndUser[] accounts = mRunningAccounts;
            if (!containsAccountAndUser(accounts, target.account, target.userId)) {
                if (isLoggable) {
                    Slog.v(TAG, "    Dropping sync operation: account doesn't exist.");
                }
                return SYNC_OP_STATE_INVALID;
            }
            // Drop this sync request if it isn't syncable.
            state = computeSyncable(target.account, target.userId, target.provider, true);
            if (state == AuthorityInfo.SYNCABLE_NO_ACCOUNT_ACCESS) {
                if (isLoggable) {
                    Slog.v(TAG, "    Dropping sync operation: "
                            + "isSyncable == SYNCABLE_NO_ACCOUNT_ACCESS");
                }
                return SYNC_OP_STATE_INVALID_NO_ACCOUNT_ACCESS;
            }
            if (state == AuthorityInfo.NOT_SYNCABLE) {
                if (isLoggable) {
                    Slog.v(TAG, "    Dropping sync operation: isSyncable == NOT_SYNCABLE");
                }
                return SYNC_OP_STATE_INVALID;
            }

            final boolean syncEnabled = mSyncStorageEngine.getMasterSyncAutomatically(target.userId)
                    && mSyncStorageEngine.getSyncAutomatically(target.account,
                            target.userId, target.provider);

            // We ignore system settings that specify the sync is invalid if:
            // 1) It's manual - we try it anyway. When/if it fails it will be rescheduled.
            //      or
            // 2) it's an initialisation sync - we just need to connect to it.
            final boolean ignoreSystemConfiguration = op.isIgnoreSettings() || (state < 0);

            // Sync not enabled.
            if (!syncEnabled && !ignoreSystemConfiguration) {
                if (isLoggable) {
                    Slog.v(TAG, "    Dropping sync operation: disallowed by settings/network.");
                }
                return SYNC_OP_STATE_INVALID;
            }
            return SYNC_OP_STATE_VALID;
        }

        private boolean dispatchSyncOperation(SyncOperation op) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Slog.v(TAG, "dispatchSyncOperation: we are going to sync " + op);
                Slog.v(TAG, "num active syncs: " + mActiveSyncContexts.size());
                for (ActiveSyncContext syncContext : mActiveSyncContexts) {
                    Slog.v(TAG, syncContext.toString());
                }
            }
            if (op.isAppStandbyExempted()) {
                final UsageStatsManagerInternal usmi = LocalServices.getService(
                        UsageStatsManagerInternal.class);
                if (usmi != null) {
                    usmi.reportExemptedSyncStart(op.owningPackage,
                            UserHandle.getUserId(op.owningUid));
                }
            }

            // Connect to the sync adapter.
            int targetUid;
            ComponentName targetComponent;
            final SyncStorageEngine.EndPoint info = op.target;
            SyncAdapterType syncAdapterType =
                    SyncAdapterType.newKey(info.provider, info.account.type);
            final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
            syncAdapterInfo = mSyncAdapters.getServiceInfo(syncAdapterType, info.userId);
            if (syncAdapterInfo == null) {
                mLogger.log("dispatchSyncOperation() failed: no sync adapter info for ",
                        syncAdapterType);
                Log.d(TAG, "can't find a sync adapter for " + syncAdapterType
                        + ", removing settings for it");
                mSyncStorageEngine.removeAuthority(info);
                return false;
            }
            targetUid = syncAdapterInfo.uid;
            targetComponent = syncAdapterInfo.componentName;
            ActiveSyncContext activeSyncContext =
                    new ActiveSyncContext(op, insertStartSyncEvent(op), targetUid);
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Slog.v(TAG, "dispatchSyncOperation: starting " + activeSyncContext);
            }

            activeSyncContext.mSyncInfo = mSyncStorageEngine.addActiveSync(activeSyncContext);
            mActiveSyncContexts.add(activeSyncContext);

            // Post message to begin monitoring this sync's progress.
            postMonitorSyncProgressMessage(activeSyncContext);

            if (!activeSyncContext.bindToSyncAdapter(targetComponent, info.userId)) {
                mLogger.log("dispatchSyncOperation() failed: bind failed. target: ",
                        targetComponent);
                Slog.e(TAG, "Bind attempt failed - target: " + targetComponent);
                closeActiveSyncContext(activeSyncContext);
                return false;
            }

            return true;
        }

        private void runBoundToAdapterH(final ActiveSyncContext activeSyncContext,
                IBinder syncAdapter) {
            final SyncOperation syncOperation = activeSyncContext.mSyncOperation;
            try {
                activeSyncContext.mIsLinkedToDeath = true;
                syncAdapter.linkToDeath(activeSyncContext, 0);

                mLogger.log("Sync start: account=" + syncOperation.target.account,
                        " authority=", syncOperation.target.provider,
                        " reason=", SyncOperation.reasonToString(null, syncOperation.reason),
                        " extras=", SyncOperation.extrasToString(syncOperation.extras),
                        " adapter=", activeSyncContext.mSyncAdapter);

                activeSyncContext.mSyncAdapter = ISyncAdapter.Stub.asInterface(syncAdapter);
                activeSyncContext.mSyncAdapter
                        .startSync(activeSyncContext, syncOperation.target.provider,
                                syncOperation.target.account, syncOperation.extras);

                mLogger.log("Sync is running now...");
            } catch (RemoteException remoteExc) {
                mLogger.log("Sync failed with RemoteException: ", remoteExc.toString());
                Log.d(TAG, "maybeStartNextSync: caught a RemoteException, rescheduling", remoteExc);
                closeActiveSyncContext(activeSyncContext);
                increaseBackoffSetting(syncOperation.target);
                scheduleSyncOperationH(syncOperation);
            } catch (RuntimeException exc) {
                mLogger.log("Sync failed with RuntimeException: ", exc.toString());
                closeActiveSyncContext(activeSyncContext);
                Slog.e(TAG, "Caught RuntimeException while starting the sync " + syncOperation, exc);
            }
        }

        /**
         * Cancel the sync for the provided target that matches the given bundle.
         * @param info Can have null fields to indicate all the active syncs for that field.
         * @param extras Can be null to indicate <strong>all</strong> syncs for the given endpoint.
         */
        private void cancelActiveSyncH(SyncStorageEngine.EndPoint info, Bundle extras,
                String why) {
            ArrayList<ActiveSyncContext> activeSyncs =
                    new ArrayList<ActiveSyncContext>(mActiveSyncContexts);
            for (ActiveSyncContext activeSyncContext : activeSyncs) {
                if (activeSyncContext != null) {
                    final SyncStorageEngine.EndPoint opInfo =
                            activeSyncContext.mSyncOperation.target;
                    if (!opInfo.matchesSpec(info)) {
                        continue;
                    }
                    if (extras != null &&
                            !syncExtrasEquals(activeSyncContext.mSyncOperation.extras,
                                    extras,
                                    false /* no config settings */)) {
                        continue;
                    }
                    SyncJobService.callJobFinished(activeSyncContext.mSyncOperation.jobId, false,
                            why);
                    runSyncFinishedOrCanceledH(null /* cancel => no result */, activeSyncContext);
                }
            }
        }

        /**
         * Should be called when a one-off instance of a periodic sync completes successfully.
         */
        private void reschedulePeriodicSyncH(SyncOperation syncOperation) {
            // Ensure that the periodic sync wasn't removed.
            SyncOperation periodicSync = null;
            List<SyncOperation> ops = getAllPendingSyncs();
            for (SyncOperation op: ops) {
                if (op.isPeriodic && syncOperation.matchesPeriodicOperation(op)) {
                    periodicSync = op;
                    break;
                }
            }
            if (periodicSync == null) {
                return;
            }
            scheduleSyncOperationH(periodicSync);
        }

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

            final SyncOperation syncOperation = activeSyncContext.mSyncOperation;
            final SyncStorageEngine.EndPoint info = syncOperation.target;

            if (activeSyncContext.mIsLinkedToDeath) {
                activeSyncContext.mSyncAdapter.asBinder().unlinkToDeath(activeSyncContext, 0);
                activeSyncContext.mIsLinkedToDeath = false;
            }
            final long elapsedTime = SystemClock.elapsedRealtime() - activeSyncContext.mStartTime;
            String historyMessage;
            int downstreamActivity;
            int upstreamActivity;

            mLogger.log("runSyncFinishedOrCanceledH() op=", syncOperation, " result=", syncResult);

            if (syncResult != null) {
                if (isLoggable) {
                    Slog.v(TAG, "runSyncFinishedOrCanceled [finished]: "
                            + syncOperation + ", result " + syncResult);
                }

                // In the non-canceled case, close the active sync context before doing the rest
                // of the stuff.
                closeActiveSyncContext(activeSyncContext);

                // Note this part is probably okay to do before closeActiveSyncContext()...
                // But moved here to restore OC-dev's behavior.  See b/64597061.
                if (!syncOperation.isPeriodic) {
                    cancelJob(syncOperation, "runSyncFinishedOrCanceledH()-finished");
                }

                if (!syncResult.hasError()) {
                    historyMessage = SyncStorageEngine.MESG_SUCCESS;
                    // TODO: set these correctly when the SyncResult is extended to include it
                    downstreamActivity = 0;
                    upstreamActivity = 0;
                    clearBackoffSetting(syncOperation.target, "sync success");

                    // If the operation completes successfully and it was scheduled due to
                    // a periodic operation failing, we reschedule the periodic operation to
                    // start from now.
                    if (syncOperation.isDerivedFromFailedPeriodicSync()) {
                        reschedulePeriodicSyncH(syncOperation);
                    }
                } else {
                    Log.w(TAG, "failed sync operation " + syncOperation + ", " + syncResult);

                    syncOperation.retries++;
                    if (syncOperation.retries > mConstants.getMaxRetriesWithAppStandbyExemption()) {
                        syncOperation.syncExemptionFlag = ContentResolver.SYNC_EXEMPTION_NONE;
                    }

                    // the operation failed so increase the backoff time
                    increaseBackoffSetting(syncOperation.target);
                    if (!syncOperation.isPeriodic) {
                        // reschedule the sync if so indicated by the syncResult
                        maybeRescheduleSync(syncResult, syncOperation);
                    } else {
                        // create a normal sync instance that will respect adapter backoffs
                        postScheduleSyncMessage(syncOperation.createOneTimeSyncOperation(),
                                0 /* min delay */);
                    }
                    historyMessage = ContentResolver.syncErrorToString(
                            syncResultToErrorNumber(syncResult));
                    // TODO: set these correctly when the SyncResult is extended to include it
                    downstreamActivity = 0;
                    upstreamActivity = 0;
                }
                setDelayUntilTime(syncOperation.target, syncResult.delayUntil);
            } else {
                if (isLoggable) {
                    Slog.v(TAG, "runSyncFinishedOrCanceled [canceled]: " + syncOperation);
                }

                if (!syncOperation.isPeriodic) {
                    cancelJob(syncOperation, "runSyncFinishedOrCanceledH()-canceled");
                }

                if (activeSyncContext.mSyncAdapter != null) {
                    try {
                        mLogger.log("Calling cancelSync for runSyncFinishedOrCanceled ",
                                activeSyncContext, "  adapter=", activeSyncContext.mSyncAdapter);
                        activeSyncContext.mSyncAdapter.cancelSync(activeSyncContext);
                        mLogger.log("Canceled");
                    } catch (RemoteException e) {
                        mLogger.log("RemoteException ", Log.getStackTraceString(e));
                        // we don't need to retry this in this case
                    }
                }
                historyMessage = SyncStorageEngine.MESG_CANCELED;
                downstreamActivity = 0;
                upstreamActivity = 0;

                // In the cancel sync case, close it after calling cancelSync().
                closeActiveSyncContext(activeSyncContext);
            }

            stopSyncEvent(activeSyncContext.mHistoryRowId, syncOperation, historyMessage,
                    upstreamActivity, downstreamActivity, elapsedTime);
            // Check for full-resync and schedule it after closing off the last sync.
            if (syncResult != null && syncResult.tooManyDeletions) {
                installHandleTooManyDeletesNotification(info.account,
                        info.provider, syncResult.stats.numDeletes,
                        info.userId);
            } else {
                mNotificationMgr.cancelAsUser(
                        Integer.toString(info.account.hashCode() ^ info.provider.hashCode()),
                        SystemMessage.NOTE_SYNC_ERROR,
                        new UserHandle(info.userId));
            }
            if (syncResult != null && syncResult.fullSyncRequested) {
                scheduleSyncOperationH(
                        new SyncOperation(info.account, info.userId,
                                syncOperation.owningUid, syncOperation.owningPackage,
                                syncOperation.reason,
                                syncOperation.syncSource, info.provider, new Bundle(),
                                syncOperation.allowParallelSyncs,
                                syncOperation.syncExemptionFlag));
            }
        }

        private void closeActiveSyncContext(ActiveSyncContext activeSyncContext) {
            activeSyncContext.close();
            mActiveSyncContexts.remove(activeSyncContext);
            mSyncStorageEngine.removeActiveSync(activeSyncContext.mSyncInfo,
                    activeSyncContext.mSyncOperation.target.userId);

            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Slog.v(TAG, "removing all MESSAGE_MONITOR_SYNC & MESSAGE_SYNC_EXPIRED for "
                        + activeSyncContext.toString());
            }
            mSyncHandler.removeMessages(SyncHandler.MESSAGE_MONITOR_SYNC, activeSyncContext);

            mLogger.log("closeActiveSyncContext: ", activeSyncContext);
        }

        /**
         * Convert the error-containing SyncResult into the Sync.History error number. Since
         * the SyncResult may indicate multiple errors at once, this method just returns the
         * most "serious" error.
         * @param syncResult the SyncResult from which to read
         * @return the most "serious" error set in the SyncResult
         * @throws IllegalStateException if the SyncResult does not indicate any errors.
         *   If SyncResult.error() is true then it is safe to call this.
         */
        private int syncResultToErrorNumber(SyncResult syncResult) {
            if (syncResult.syncAlreadyInProgress)
                return ContentResolver.SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS;
            if (syncResult.stats.numAuthExceptions > 0)
                return ContentResolver.SYNC_ERROR_AUTHENTICATION;
            if (syncResult.stats.numIoExceptions > 0)
                return ContentResolver.SYNC_ERROR_IO;
            if (syncResult.stats.numParseExceptions > 0)
                return ContentResolver.SYNC_ERROR_PARSE;
            if (syncResult.stats.numConflictDetectedExceptions > 0)
                return ContentResolver.SYNC_ERROR_CONFLICT;
            if (syncResult.tooManyDeletions)
                return ContentResolver.SYNC_ERROR_TOO_MANY_DELETIONS;
            if (syncResult.tooManyRetries)
                return ContentResolver.SYNC_ERROR_TOO_MANY_RETRIES;
            if (syncResult.databaseError)
                return ContentResolver.SYNC_ERROR_INTERNAL;
            throw new IllegalStateException("we are not in an error state, " + syncResult);
        }

        private void installHandleTooManyDeletesNotification(Account account, String authority,
                long numDeletes, int userId) {
            if (mNotificationMgr == null) return;

            final ProviderInfo providerInfo = mContext.getPackageManager().resolveContentProvider(
                    authority, 0 /* flags */);
            if (providerInfo == null) {
                return;
            }
            CharSequence authorityName = providerInfo.loadLabel(mContext.getPackageManager());

            Intent clickIntent = new Intent(mContext, SyncActivityTooManyDeletes.class);
            clickIntent.putExtra("account", account);
            clickIntent.putExtra("authority", authority);
            clickIntent.putExtra("provider", authorityName.toString());
            clickIntent.putExtra("numDeletes", numDeletes);

            if (!isActivityAvailable(clickIntent)) {
                Log.w(TAG, "No activity found to handle too many deletes.");
                return;
            }

            UserHandle user = new UserHandle(userId);
            final PendingIntent pendingIntent = PendingIntent
                    .getActivityAsUser(mContext, 0, clickIntent,
                            PendingIntent.FLAG_CANCEL_CURRENT, null, user);

            CharSequence tooManyDeletesDescFormat = mContext.getResources().getText(
                    R.string.contentServiceTooManyDeletesNotificationDesc);

            Context contextForUser = getContextForUser(user);
            Notification notification =
                    new Notification.Builder(contextForUser, SystemNotificationChannels.ACCOUNT)
                    .setSmallIcon(R.drawable.stat_notify_sync_error)
                    .setTicker(mContext.getString(R.string.contentServiceSync))
                    .setWhen(System.currentTimeMillis())
                    .setColor(contextForUser.getColor(
                            com.android.internal.R.color.system_notification_accent_color))
                    .setContentTitle(contextForUser.getString(
                            R.string.contentServiceSyncNotificationTitle))
                    .setContentText(
                            String.format(tooManyDeletesDescFormat.toString(), authorityName))
                    .setContentIntent(pendingIntent)
                    .build();
            notification.flags |= Notification.FLAG_ONGOING_EVENT;
            mNotificationMgr.notifyAsUser(
                    Integer.toString(account.hashCode() ^ authority.hashCode()),
                    SystemMessage.NOTE_SYNC_ERROR,
                    notification, user);
        }

        /**
         * Checks whether an activity exists on the system image for the given intent.
         *
         * @param intent The intent for an activity.
         * @return Whether or not an activity exists.
         */
        private boolean isActivityAvailable(Intent intent) {
            PackageManager pm = mContext.getPackageManager();
            List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
            int listSize = list.size();
            for (int i = 0; i < listSize; i++) {
                ResolveInfo resolveInfo = list.get(i);
                if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
                        != 0) {
                    return true;
                }
            }

            return false;
        }

        public long insertStartSyncEvent(SyncOperation syncOperation) {
            final long now = System.currentTimeMillis();
            EventLog.writeEvent(2720,
                    syncOperation.toEventLog(SyncStorageEngine.EVENT_START));
            return mSyncStorageEngine.insertStartSyncEvent(syncOperation, now);
        }

        public void stopSyncEvent(long rowId, SyncOperation syncOperation, String resultMessage,
                int upstreamActivity, int downstreamActivity, long elapsedTime) {
            EventLog.writeEvent(2720,
                    syncOperation.toEventLog(SyncStorageEngine.EVENT_STOP));
            mSyncStorageEngine.stopSyncEvent(rowId, elapsedTime,
                    resultMessage, downstreamActivity, upstreamActivity);
        }
    }

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

    /**
     * Sync extra comparison function.
     * @param b1 bundle to compare
     * @param b2 other bundle to compare
     * @param includeSyncSettings if false, ignore system settings in bundle.
     */
    public static boolean syncExtrasEquals(Bundle b1, Bundle b2, boolean includeSyncSettings) {
        if (b1 == b2) {
            return true;
        }
        // Exit early if we can.
        if (includeSyncSettings && b1.size() != b2.size()) {
            return false;
        }
        Bundle bigger = b1.size() > b2.size() ? b1 : b2;
        Bundle smaller = b1.size() > b2.size() ? b2 : b1;
        for (String key : bigger.keySet()) {
            if (!includeSyncSettings && isSyncSetting(key)) {
                continue;
            }
            if (!smaller.containsKey(key)) {
                return false;
            }
            if (!Objects.equals(bigger.get(key), smaller.get(key))) {
                return false;
            }
        }
        return true;
    }

    /**
     * @return true if the provided key is used by the SyncManager in scheduling the sync.
     */
    private static boolean isSyncSetting(String key) {
        if (key.equals(ContentResolver.SYNC_EXTRAS_EXPEDITED)) {
            return true;
        }
        if (key.equals(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS)) {
            return true;
        }
        if (key.equals(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF)) {
            return true;
        }
        if (key.equals(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY)) {
            return true;
        }
        if (key.equals(ContentResolver.SYNC_EXTRAS_MANUAL)) {
            return true;
        }
        if (key.equals(ContentResolver.SYNC_EXTRAS_UPLOAD)) {
            return true;
        }
        if (key.equals(ContentResolver.SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS)) {
            return true;
        }
        if (key.equals(ContentResolver.SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS)) {
            return true;
        }
        if (key.equals(ContentResolver.SYNC_EXTRAS_EXPECTED_UPLOAD)) {
            return true;
        }
        if (key.equals(ContentResolver.SYNC_EXTRAS_EXPECTED_DOWNLOAD)) {
            return true;
        }
        if (key.equals(ContentResolver.SYNC_EXTRAS_PRIORITY)) {
            return true;
        }
        if (key.equals(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED)) {
            return true;
        }
        if (key.equals(ContentResolver.SYNC_EXTRAS_INITIALIZE)) {
            return true;
        }
//        if (key.equals(ContentResolver.SYNC_EXTRAS_APP_STANDBY_EXEMPTED)) {
//            return true;
//        }
        // No need to check virtual flags such as SYNC_VIRTUAL_EXTRAS_FORCE_FG_SYNC.
        return false;
    }

    static class PrintTable {
        private ArrayList<String[]> mTable = Lists.newArrayList();
        private final int mCols;

        PrintTable(int cols) {
            mCols = cols;
        }

        void set(int row, int col, Object... values) {
            if (col + values.length > mCols) {
                throw new IndexOutOfBoundsException("Table only has " + mCols +
                        " columns. can't set " + values.length + " at column " + col);
            }
            for (int i = mTable.size(); i <= row; i++) {
                final String[] list = new String[mCols];
                mTable.add(list);
                for (int j = 0; j < mCols; j++) {
                    list[j] = "";
                }
            }
            final String[] rowArray = mTable.get(row);
            for (int i = 0; i < values.length; i++) {
                final Object value = values[i];
                rowArray[col + i] = (value == null) ? "" : value.toString();
            }
        }

        void writeTo(PrintWriter out) {
            final String[] formats = new String[mCols];
            int totalLength = 0;
            for (int col = 0; col < mCols; ++col) {
                int maxLength = 0;
                for (Object[] row : mTable) {
                    final int length = row[col].toString().length();
                    if (length > maxLength) {
                        maxLength = length;
                    }
                }
                totalLength += maxLength;
                formats[col] = String.format("%%-%ds", maxLength);
            }
            formats[mCols - 1] = "%s";
            printRow(out, formats, mTable.get(0));
            totalLength += (mCols - 1) * 2;
            for (int i = 0; i < totalLength; ++i) {
                out.print("-");
            }
            out.println();
            for (int i = 1, mTableSize = mTable.size(); i < mTableSize; i++) {
                Object[] row = mTable.get(i);
                printRow(out, formats, row);
            }
        }

        private void printRow(PrintWriter out, String[] formats, Object[] row) {
            for (int j = 0, rowLength = row.length; j < rowLength; j++) {
                out.printf(String.format(formats[j], row[j].toString()));
                out.print("  ");
            }
            out.println();
        }

        public int getNumRows() {
            return mTable.size();
        }
    }

    private Context getContextForUser(UserHandle user) {
        try {
            return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user);
        } catch (NameNotFoundException e) {
            // Default to mContext, not finding the package system is running as is unlikely.
            return mContext;
        }
    }

    private void cancelJob(SyncOperation op, String why) {
        if (op == null) {
            Slog.wtf(TAG, "Null sync operation detected.");
            return;
        }
        if (op.isPeriodic) {
            mLogger.log("Removing periodic sync ", op, " for ", why);
        }
        getJobScheduler().cancel(op.jobId);
    }

    private void wtfWithLog(String message) {
        Slog.wtf(TAG, message);
        mLogger.log("WTF: ", message);
    }

    public void resetTodayStats() {
        mSyncStorageEngine.resetTodayStats(/*force=*/ true);
    }

    private boolean wasPackageEverLaunched(String packageName, int userId) {
        try {
            return mPackageManagerInternal.wasPackageEverLaunched(packageName, userId);
        } catch (IllegalArgumentException e) {
            return false; // Package has been removed.
        }
    }
}
