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

Commit 853ed1ca authored by Makoto Onuki's avatar Makoto Onuki Committed by Android (Google) Code Review
Browse files

Merge "Clean up sync manager and fix the lock screen blocked sync issue."

parents 4cc78204 3ab7781d
Loading
Loading
Loading
Loading
+90 −81
Original line number Original line Diff line number Diff line
@@ -16,12 +16,10 @@


package com.android.server.content;
package com.android.server.content;


import android.annotation.Nullable;
import android.app.job.JobParameters;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.app.job.JobService;
import android.content.Intent;
import android.os.Message;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemClock;
import android.util.Log;
import android.util.Log;
import android.util.Slog;
import android.util.Slog;
@@ -34,78 +32,86 @@ import com.android.internal.annotations.GuardedBy;
public class SyncJobService extends JobService {
public class SyncJobService extends JobService {
    private static final String TAG = "SyncManager";
    private static final String TAG = "SyncManager";


    public static final String EXTRA_MESSENGER = "messenger";
    private static final Object sLock = new Object();


    private Messenger mMessenger;
    @GuardedBy("sLock")
    private static SyncJobService sInstance;


    private final Object mLock = new Object();
    @GuardedBy("sLock")
    private static final SparseArray<JobParameters> sJobParamsMap = new SparseArray<>();


    @GuardedBy("mLock")
    @GuardedBy("sLock")
    private final SparseArray<JobParameters> mJobParamsMap = new SparseArray<>();
    private static final SparseBooleanArray sStartedSyncs = new SparseBooleanArray();


    @GuardedBy("mLock")
    @GuardedBy("sLock")
    private final SparseBooleanArray mStartedSyncs = new SparseBooleanArray();
    private static final SparseLongArray sJobStartUptimes = new SparseLongArray();


    @GuardedBy("mLock")
    private static final SyncLogger sLogger = SyncLogger.getInstance();
    private final SparseLongArray mJobStartUptimes = new SparseLongArray();


    private final SyncLogger mLogger = SyncLogger.getInstance();
    private void updateInstance() {

        synchronized (SyncJobService.class) {
    /**
            sInstance = this;
     * This service is started by the SyncManager which passes a messenger object to
        }
     * communicate back with it. It never stops while the device is running.
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mMessenger = intent.getParcelableExtra(EXTRA_MESSENGER);
        Message m = Message.obtain();
        m.what = SyncManager.SyncHandler.MESSAGE_JOBSERVICE_OBJECT;
        m.obj = this;
        sendMessage(m);

        return START_NOT_STICKY;
    }
    }


    private void sendMessage(Message message) {
    @Nullable
        if (mMessenger == null) {
    private static SyncJobService getInstance() {
            Slog.e(TAG, "Messenger not initialized.");
        synchronized (sLock) {
            return;
            if (sInstance == null) {
                Slog.wtf(TAG, "sInstance == null");
            }
            }
        try {
            return sInstance;
            mMessenger.send(message);
        }
        } catch (RemoteException e) {
    }
            Slog.e(TAG, e.toString());

    public static boolean isReady() {
        synchronized (sLock) {
            return sInstance != null;
        }
        }
    }
    }


    @Override
    @Override
    public boolean onStartJob(JobParameters params) {
    public boolean onStartJob(JobParameters params) {
        updateInstance();


        mLogger.purgeOldLogs();
        sLogger.purgeOldLogs();

        SyncOperation op = SyncOperation.maybeCreateFromJobExtras(params.getExtras());

        if (op == null) {
            Slog.wtf(TAG, "Got invalid job " + params.getJobId());
            return false;
        }

        final boolean readyToSync = SyncManager.readyToSync(op.target.userId);

        sLogger.log("onStartJob() jobid=", params.getJobId(), " op=", op,
                " readyToSync", readyToSync);

        if (!readyToSync) {
            // If the user isn't unlocked or the device has been provisioned yet, just stop the job
            // at this point. If it's a non-periodic sync, ask the job scheduler to reschedule it.
            // If it's a periodic sync, then just wait until the next cycle.
            final boolean wantsReschedule = !op.isPeriodic;
            jobFinished(params, wantsReschedule);
            return true;
        }


        boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
        boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
        synchronized (mLock) {
        synchronized (sLock) {
            final int jobId = params.getJobId();
            final int jobId = params.getJobId();
            mJobParamsMap.put(jobId, params);
            sJobParamsMap.put(jobId, params);


            mStartedSyncs.delete(jobId);
            sStartedSyncs.delete(jobId);
            mJobStartUptimes.put(jobId, SystemClock.uptimeMillis());
            sJobStartUptimes.put(jobId, SystemClock.uptimeMillis());
        }
        }
        Message m = Message.obtain();
        Message m = Message.obtain();
        m.what = SyncManager.SyncHandler.MESSAGE_START_SYNC;
        m.what = SyncManager.SyncHandler.MESSAGE_START_SYNC;
        SyncOperation op = SyncOperation.maybeCreateFromJobExtras(params.getExtras());

        mLogger.log("onStartJob() jobid=", params.getJobId(), " op=", op);

        if (op == null) {
            Slog.e(TAG, "Got invalid job " + params.getJobId());
            return false;
        }
        if (isLoggable) {
        if (isLoggable) {
            Slog.v(TAG, "Got start job message " + op.target);
            Slog.v(TAG, "Got start job message " + op.target);
        }
        }
        m.obj = op;
        m.obj = op;
        sendMessage(m);
        SyncManager.sendMessage(m);
        return true;
        return true;
    }
    }


@@ -115,15 +121,22 @@ public class SyncJobService extends JobService {
            Slog.v(TAG, "onStopJob called " + params.getJobId() + ", reason: "
            Slog.v(TAG, "onStopJob called " + params.getJobId() + ", reason: "
                    + params.getStopReason());
                    + params.getStopReason());
        }
        }
        final boolean readyToSync = SyncManager.readyToSync();
        final SyncOperation op = SyncOperation.maybeCreateFromJobExtras(params.getExtras());
        if (op == null) {
            Slog.wtf(TAG, "Got invalid job " + params.getJobId());
            return false;
        }

        final boolean readyToSync = SyncManager.readyToSync(op.target.userId);


        mLogger.log("onStopJob() ", mLogger.jobParametersToString(params),
        sLogger.log("onStopJob() ", sLogger.jobParametersToString(params),
                " readyToSync=", readyToSync);
                " readyToSync=", readyToSync);
        synchronized (mLock) {

        synchronized (sLock) {
            final int jobId = params.getJobId();
            final int jobId = params.getJobId();
            mJobParamsMap.remove(jobId);
            sJobParamsMap.remove(jobId);


            final long startUptime = mJobStartUptimes.get(jobId);
            final long startUptime = sJobStartUptimes.get(jobId);
            final long nowUptime = SystemClock.uptimeMillis();
            final long nowUptime = SystemClock.uptimeMillis();
            final long runtime = nowUptime - startUptime;
            final long runtime = nowUptime - startUptime;


@@ -135,61 +148,57 @@ public class SyncJobService extends JobService {
                // WTF if startSyncH() hasn't happened, *unless* onStopJob() was called too soon.
                // WTF if startSyncH() hasn't happened, *unless* onStopJob() was called too soon.
                // (1 minute threshold.)
                // (1 minute threshold.)
                // Also don't wtf when it's not ready to sync.
                // Also don't wtf when it's not ready to sync.
                if (readyToSync && !mStartedSyncs.get(jobId)) {
                if (readyToSync && !sStartedSyncs.get(jobId)) {
                    wtf("Job " + jobId + " didn't start: "
                    wtf("Job " + jobId + " didn't start: "
                            + " startUptime=" + startUptime
                            + " startUptime=" + startUptime
                            + " nowUptime=" + nowUptime
                            + " nowUptime=" + nowUptime
                            + " params=" + jobParametersToString(params));
                            + " params=" + jobParametersToString(params));
                }
                }
            } else if (runtime < 10 * 1000) {
                // This happens too in a normal case too, and it's rather too often.
                // Disable it for now.
//                // Job stopped too soon. WTF.
//                wtf("Job " + jobId + " stopped in " + runtime + " ms: "
//                        + " startUptime=" + startUptime
//                        + " nowUptime=" + nowUptime
//                        + " params=" + jobParametersToString(params));
            }
            }


            mStartedSyncs.delete(jobId);
            sStartedSyncs.delete(jobId);
            mJobStartUptimes.delete(jobId);
            sJobStartUptimes.delete(jobId);
        }
        }
        Message m = Message.obtain();
        Message m = Message.obtain();
        m.what = SyncManager.SyncHandler.MESSAGE_STOP_SYNC;
        m.what = SyncManager.SyncHandler.MESSAGE_STOP_SYNC;
        m.obj = SyncOperation.maybeCreateFromJobExtras(params.getExtras());
        m.obj = op;
        if (m.obj == null) {
            return false;
        }


        // Reschedule if this job was NOT explicitly canceled.
        // Reschedule if this job was NOT explicitly canceled.
        m.arg1 = params.getStopReason() != JobParameters.REASON_CANCELED ? 1 : 0;
        m.arg1 = params.getStopReason() != JobParameters.REASON_CANCELED ? 1 : 0;
        // Apply backoff only if stop is called due to timeout.
        // Apply backoff only if stop is called due to timeout.
        m.arg2 = params.getStopReason() == JobParameters.REASON_TIMEOUT ? 1 : 0;
        m.arg2 = params.getStopReason() == JobParameters.REASON_TIMEOUT ? 1 : 0;


        sendMessage(m);
        SyncManager.sendMessage(m);
        return false;
        return false;
    }
    }


    public void callJobFinished(int jobId, boolean needsReschedule, String why) {
    public static void callJobFinished(int jobId, boolean needsReschedule, String why) {
        synchronized (mLock) {
        final SyncJobService instance = getInstance();
            JobParameters params = mJobParamsMap.get(jobId);
        if (instance != null) {
            mLogger.log("callJobFinished()",
            instance.callJobFinishedInner(jobId, needsReschedule, why);
        }
    }

    public void callJobFinishedInner(int jobId, boolean needsReschedule, String why) {
        synchronized (sLock) {
            JobParameters params = sJobParamsMap.get(jobId);
            sLogger.log("callJobFinished()",
                    " jobid=", jobId,
                    " jobid=", jobId,
                    " needsReschedule=", needsReschedule,
                    " needsReschedule=", needsReschedule,
                    " ", mLogger.jobParametersToString(params),
                    " ", sLogger.jobParametersToString(params),
                    " why=", why);
                    " why=", why);
            if (params != null) {
            if (params != null) {
                jobFinished(params, needsReschedule);
                jobFinished(params, needsReschedule);
                mJobParamsMap.remove(jobId);
                sJobParamsMap.remove(jobId);
            } else {
            } else {
                Slog.e(TAG, "Job params not found for " + String.valueOf(jobId));
                Slog.e(TAG, "Job params not found for " + String.valueOf(jobId));
            }
            }
        }
        }
    }
    }


    public void markSyncStarted(int jobId) {
    public static void markSyncStarted(int jobId) {
        synchronized (mLock) {
        synchronized (sLock) {
            mStartedSyncs.put(jobId, true);
            sStartedSyncs.put(jobId, true);
        }
        }
    }
    }


@@ -203,8 +212,8 @@ public class SyncJobService extends JobService {
        }
        }
    }
    }


    private void wtf(String message) {
    private static void wtf(String message) {
        mLogger.log(message);
        sLogger.log(message);
        Slog.wtf(TAG, message);
        Slog.wtf(TAG, message);
    }
    }
}
}
+80 −149

File changed.

Preview size limit exceeded, changes collapsed.

+5 −3
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.content;
import android.accounts.Account;
import android.accounts.Account;
import android.accounts.AccountAndUser;
import android.accounts.AccountAndUser;
import android.accounts.AccountManager;
import android.accounts.AccountManager;
import android.annotation.Nullable;
import android.app.backup.BackupManager;
import android.app.backup.BackupManager;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentResolver;
@@ -1005,7 +1006,7 @@ public class SyncStorageEngine {
     * Called when the set of account has changed, given the new array of
     * Called when the set of account has changed, given the new array of
     * active accounts.
     * active accounts.
     */
     */
    public void doDatabaseCleanup(Account[] accounts, int userId) {
    public void removeStaleAccounts(@Nullable Account[] accounts, int userId) {
        synchronized (mAuthorities) {
        synchronized (mAuthorities) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Slog.v(TAG, "Updating for new accounts...");
                Slog.v(TAG, "Updating for new accounts...");
@@ -1014,8 +1015,9 @@ public class SyncStorageEngine {
            Iterator<AccountInfo> accIt = mAccounts.values().iterator();
            Iterator<AccountInfo> accIt = mAccounts.values().iterator();
            while (accIt.hasNext()) {
            while (accIt.hasNext()) {
                AccountInfo acc = accIt.next();
                AccountInfo acc = accIt.next();
                if (!ArrayUtils.contains(accounts, acc.accountAndUser.account)
                if ((accounts == null) || (
                        && acc.accountAndUser.userId == userId) {
                        (acc.accountAndUser.userId == userId)
                        && !ArrayUtils.contains(accounts, acc.accountAndUser.account))) {
                    // This account no longer exists...
                    // This account no longer exists...
                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        Slog.v(TAG, "Account removed: " + acc.accountAndUser);
                        Slog.v(TAG, "Account removed: " + acc.accountAndUser);
+2 −1
Original line number Original line Diff line number Diff line
@@ -974,7 +974,8 @@ public class UsageStatsService extends SystemService implements
            final long token = Binder.clearCallingIdentity();
            final long token = Binder.clearCallingIdentity();
            try {
            try {
                final int packageUid = mPackageManagerInternal.getPackageUid(packageName,
                final int packageUid = mPackageManagerInternal.getPackageUid(packageName,
                        PackageManager.MATCH_ANY_USER, userId);
                        PackageManager.MATCH_ANY_USER | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                        | PackageManager.MATCH_DIRECT_BOOT_AWARE, userId);
                // Caller cannot set their own standby state
                // Caller cannot set their own standby state
                if (packageUid == callingUid) {
                if (packageUid == callingUid) {
                    throw new IllegalArgumentException("Cannot set your own standby bucket");
                    throw new IllegalArgumentException("Cannot set your own standby bucket");