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

Commit e738c13d authored by Georgi Nikolov's avatar Georgi Nikolov Committed by Android (Google) Code Review
Browse files

Merge "Bugfix 9373708 JBMR2 runtime restart (system process crash in the sync...

Merge "Bugfix 9373708 JBMR2 runtime restart (system process crash in the sync manager) during setup"
parents 46eadae1 dbe846b0
Loading
Loading
Loading
Loading
+47 −18
Original line number Diff line number Diff line
@@ -42,7 +42,10 @@ public class SyncStatusInfo implements Parcelable {
    public long initialFailureTime;
    public boolean pending;
    public boolean initialize;
    public ArrayList<Long> periodicSyncTimes;
    
  // Warning: It is up to the external caller to ensure there are
  // no race conditions when accessing this list
  private ArrayList<Long> periodicSyncTimes;

    private static final String TAG = "Sync";

@@ -126,35 +129,48 @@ public class SyncStatusInfo implements Parcelable {
        }
    }

    public void setPeriodicSyncTime(int index, long when) {
        ensurePeriodicSyncTimeSize(index);
        periodicSyncTimes.set(index, when);
    public SyncStatusInfo(SyncStatusInfo other) {
        authorityId = other.authorityId;
        totalElapsedTime = other.totalElapsedTime;
        numSyncs = other.numSyncs;
        numSourcePoll = other.numSourcePoll;
        numSourceServer = other.numSourceServer;
        numSourceLocal = other.numSourceLocal;
        numSourceUser = other.numSourceUser;
        numSourcePeriodic = other.numSourcePeriodic;
        lastSuccessTime = other.lastSuccessTime;
        lastSuccessSource = other.lastSuccessSource;
        lastFailureTime = other.lastFailureTime;
        lastFailureSource = other.lastFailureSource;
        lastFailureMesg = other.lastFailureMesg;
        initialFailureTime = other.initialFailureTime;
        pending = other.pending;
        initialize = other.initialize;
        if (other.periodicSyncTimes != null) {
            periodicSyncTimes = new ArrayList<Long>(other.periodicSyncTimes);
        }

    private void ensurePeriodicSyncTimeSize(int index) {
        if (periodicSyncTimes == null) {
            periodicSyncTimes = new ArrayList<Long>(0);
    }

        final int requiredSize = index + 1;
        if (periodicSyncTimes.size() < requiredSize) {
            for (int i = periodicSyncTimes.size(); i < requiredSize; i++) {
                periodicSyncTimes.add((long) 0);
            }
        }
    public void setPeriodicSyncTime(int index, long when) {
        // The list is initialized lazily when scheduling occurs so we need to make sure
        // we initialize elements < index to zero (zero is ignore for scheduling purposes)
        ensurePeriodicSyncTimeSize(index);
        periodicSyncTimes.set(index, when);
    }

    public long getPeriodicSyncTime(int index) {
        if (periodicSyncTimes == null || periodicSyncTimes.size() < (index + 1)) {
        if (periodicSyncTimes != null && index < periodicSyncTimes.size()) {
            return periodicSyncTimes.get(index);
        } else {
            return 0;
        }
        return periodicSyncTimes.get(index);
    }

    public void removePeriodicSyncTime(int index) {
        ensurePeriodicSyncTimeSize(index);
        if (periodicSyncTimes != null && index < periodicSyncTimes.size()) {
            periodicSyncTimes.remove(index);
        }
    }

    public static final Creator<SyncStatusInfo> CREATOR = new Creator<SyncStatusInfo>() {
        public SyncStatusInfo createFromParcel(Parcel in) {
@@ -165,4 +181,17 @@ public class SyncStatusInfo implements Parcelable {
            return new SyncStatusInfo[size];
        }
    };

    private void ensurePeriodicSyncTimeSize(int index) {
        if (periodicSyncTimes == null) {
            periodicSyncTimes = new ArrayList<Long>(0);
        }

        final int requiredSize = index + 1;
        if (periodicSyncTimes.size() < requiredSize) {
            for (int i = periodicSyncTimes.size(); i < requiredSize; i++) {
                periodicSyncTimes.add((long) 0);
            }
        }
    }
}
 No newline at end of file
+57 −44
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.accounts.AccountManagerService;
import com.android.server.content.SyncStorageEngine.AuthorityInfo;
import com.android.server.content.SyncStorageEngine.OnSyncRequestListener;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -1248,10 +1249,11 @@ public class SyncManager {
                    continue;
                }
                int row = table.getNumRows();
                SyncStorageEngine.AuthorityInfo settings =
                        mSyncStorageEngine.getOrCreateAuthority(
                Pair<AuthorityInfo, SyncStatusInfo> syncAuthoritySyncStatus = 
                        mSyncStorageEngine.getCopyOfAuthorityWithSyncStatus(
                                account.account, account.userId, syncAdapterType.type.authority);
                SyncStatusInfo status = mSyncStorageEngine.getOrCreateSyncStatus(settings);
                SyncStorageEngine.AuthorityInfo settings = syncAuthoritySyncStatus.first;
                SyncStatusInfo status = syncAuthoritySyncStatus.second;

                String authority = settings.authority;
                if (authority.length() > 50) {
@@ -1269,10 +1271,10 @@ public class SyncManager {


                for (int i = 0; i < settings.periodicSyncs.size(); i++) {
                    final Pair<Bundle, Long> pair = settings.periodicSyncs.get(0);
                    final Pair<Bundle, Long> pair = settings.periodicSyncs.get(i);
                    final String period = String.valueOf(pair.second);
                    final String extras = pair.first.size() > 0 ? pair.first.toString() : "";
                    final String next = formatTime(status.getPeriodicSyncTime(0)
                    final String next = formatTime(status.getPeriodicSyncTime(i)
                            + pair.second * 1000);
                    table.set(row + i * 2, 12, period + extras);
                    table.set(row + i * 2 + 1, 12, next);
@@ -1945,28 +1947,34 @@ public class SyncManager {
            final long shiftedNowAbsolute = (0 < nowAbsolute - mSyncRandomOffsetMillis)
                    ? (nowAbsolute - mSyncRandomOffsetMillis) : 0;

            ArrayList<SyncStorageEngine.AuthorityInfo> infos = mSyncStorageEngine.getAuthorities();
            for (SyncStorageEngine.AuthorityInfo info : infos) {
                // skip the sync if the account of this operation no longer exists
                if (!containsAccountAndUser(accounts, info.account, info.userId)) {
            ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> infos = mSyncStorageEngine
                    .getCopyOfAllAuthoritiesWithSyncStatus();
            for (Pair<AuthorityInfo, SyncStatusInfo> info : infos) {
                final AuthorityInfo authorityInfo = info.first;
                final SyncStatusInfo status = info.second;
                // skip the sync if the account of this operation no longer
                // exists
                if (!containsAccountAndUser(
                        accounts, authorityInfo.account, authorityInfo.userId)) {
                    continue;
                }

                if (!mSyncStorageEngine.getMasterSyncAutomatically(info.userId)
                        || !mSyncStorageEngine.getSyncAutomatically(info.account, info.userId,
                                info.authority)) {
                if (!mSyncStorageEngine.getMasterSyncAutomatically(authorityInfo.userId)
                        || !mSyncStorageEngine.getSyncAutomatically(
                                authorityInfo.account, authorityInfo.userId,
                                authorityInfo.authority)) {
                    continue;
                }

                if (getIsSyncable(info.account, info.userId, info.authority)
                if (getIsSyncable(
                        authorityInfo.account, authorityInfo.userId, authorityInfo.authority)
                        == 0) {
                    continue;
                }

                SyncStatusInfo status = mSyncStorageEngine.getOrCreateSyncStatus(info);
                for (int i = 0, N = info.periodicSyncs.size(); i < N; i++) {
                    final Bundle extras = info.periodicSyncs.get(i).first;
                    final Long periodInMillis = info.periodicSyncs.get(i).second * 1000;
                for (int i = 0, N = authorityInfo.periodicSyncs.size(); i < N; i++) {
                    final Bundle extras = authorityInfo.periodicSyncs.get(i).first;
                    final Long periodInMillis = authorityInfo.periodicSyncs.get(i).second * 1000;
                    // Skip if the period is invalid
                    if (periodInMillis <= 0) {
                        continue;
@@ -1978,18 +1986,18 @@ public class SyncManager {
                    = periodInMillis - (shiftedNowAbsolute % periodInMillis);

                    /*
                     * Sync scheduling strategy:
                     *    Set the next periodic sync based on a random offset (in seconds).
                     *
                     *    Also sync right now if any of the following cases hold
                     *    and mark it as having been scheduled
                     *
                     * Case 1:  This sync is ready to run now.
                     * Case 2:  If the lastPollTimeAbsolute is in the future,
                     *          sync now and reinitialize. This can happen for
                     *          example if the user changed the time, synced and
                     *          changed back.
                     * Case 3:  If we failed to sync at the last scheduled time
                     * Sync scheduling strategy: Set the next periodic sync
                     * based on a random offset (in seconds). Also sync right
                     * now if any of the following cases hold and mark it as
                     * having been scheduled
                     * Case 1: This sync is ready to run
                     * now.
                     * Case 2: If the lastPollTimeAbsolute is in the
                     * future, sync now and reinitialize. This can happen for
                     * example if the user changed the time, synced and changed
                     * back.
                     * Case 3: If we failed to sync at the last scheduled
                     * time
                     */
                    if (remainingMillis == periodInMillis // Case 1
                            || lastPollTimeAbsolute > nowAbsolute // Case 2
@@ -1997,29 +2005,34 @@ public class SyncManager {
                                    >= periodInMillis)) { // Case 3
                        // Sync now
                        final Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(
                                info.account, info.userId, info.authority);
                                authorityInfo.account, authorityInfo.userId,
                                authorityInfo.authority);
                        final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
                        syncAdapterInfo = mSyncAdapters.getServiceInfo(
                                SyncAdapterType.newKey(info.authority, info.account.type),
                                info.userId);
                                SyncAdapterType.newKey(
                                        authorityInfo.authority, authorityInfo.account.type),
                                authorityInfo.userId);
                        if (syncAdapterInfo == null) {
                            continue;
                        }
                        scheduleSyncOperation(
                                new SyncOperation(info.account, info.userId,
                                new SyncOperation(authorityInfo.account, authorityInfo.userId,
                                        SyncOperation.REASON_PERIODIC,
                                        SyncStorageEngine.SOURCE_PERIODIC,
                                        info.authority, extras, 0 /* delay */,
                                        authorityInfo.authority, extras, 0 /* delay */,
                                                backoff != null ? backoff.first : 0,
                                        mSyncStorageEngine.getDelayUntilTime(
                                                info.account, info.userId, info.authority),
                                                authorityInfo.account, authorityInfo.userId,
                                                authorityInfo.authority),
                                        syncAdapterInfo.type.allowParallelSyncs()));
                        status.setPeriodicSyncTime(i, nowAbsolute);
                        mSyncStorageEngine.setPeriodicSyncTime(authorityInfo.ident,
                                authorityInfo.periodicSyncs.get(i), nowAbsolute);
                    }
                    // Compute when this periodic sync should next run
                    final long nextPollTimeAbsolute = nowAbsolute + remainingMillis;

                    // remember this time if it is earlier than earliestFuturePollTime
                    // remember this time if it is earlier than
                    // earliestFuturePollTime
                    if (nextPollTimeAbsolute < earliestFuturePollTime) {
                        earliestFuturePollTime = nextPollTimeAbsolute;
                    }
+41 −19
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.util.Xml;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.server.content.SyncStorageEngine.AuthorityInfo;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -813,14 +814,6 @@ public class SyncStorageEngine extends Handler {
        }
    }

    public AuthorityInfo getOrCreateAuthority(Account account, int userId, String authority) {
        synchronized (mAuthorities) {
            return getOrCreateAuthorityLocked(account, userId, authority,
                    -1 /* assign a new identifier if creating a new authority */,
                    true /* write to storage if this results in a change */);
        }
    }

    public void removeAuthority(Account account, int userId, String authority) {
        synchronized (mAuthorities) {
            removeAuthorityLocked(account, userId, authority, true /* doWrite */);
@@ -1238,17 +1231,27 @@ public class SyncStorageEngine extends Handler {
    }

    /**
     * Return an array of the current authorities. Note
     * that the objects inside the array are the real, live objects,
     * so be careful what you do with them.
     * Return a copy of the specified authority with the corresponding sync status
     */
    public ArrayList<AuthorityInfo> getAuthorities() {
    public Pair<AuthorityInfo, SyncStatusInfo> getCopyOfAuthorityWithSyncStatus(
            Account account, int userId, String authority) {
        synchronized (mAuthorities) {
            final int N = mAuthorities.size();
            ArrayList<AuthorityInfo> infos = new ArrayList<AuthorityInfo>(N);
            for (int i=0; i<N; i++) {
                // Make deep copy because AuthorityInfo syncs are liable to change.
                infos.add(new AuthorityInfo(mAuthorities.valueAt(i)));
            AuthorityInfo authorityInfo = getOrCreateAuthorityLocked(account, userId, authority,
                    -1 /* assign a new identifier if creating a new authority */,
                    true /* write to storage if this results in a change */);
            return createCopyPairOfAuthorityWithSyncStatusLocked(authorityInfo);
        }
    }

    /**
     * Return a copy of all authorities with their corresponding sync status
     */
    public ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> getCopyOfAllAuthoritiesWithSyncStatus() {
        synchronized (mAuthorities) {
            ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> infos =
                    new ArrayList<Pair<AuthorityInfo, SyncStatusInfo>>(mAuthorities.size());
            for (int i = 0; i < mAuthorities.size(); i++) {
                infos.add(createCopyPairOfAuthorityWithSyncStatusLocked(mAuthorities.valueAt(i)));
            }
            return infos;
        }
@@ -1337,6 +1340,12 @@ public class SyncStorageEngine extends Handler {
        }
    }

    private Pair<AuthorityInfo, SyncStatusInfo> createCopyPairOfAuthorityWithSyncStatusLocked(
            AuthorityInfo authorityInfo) {
        SyncStatusInfo syncStatusInfo = getOrCreateSyncStatusLocked(authorityInfo.ident);
        return Pair.create(new AuthorityInfo(authorityInfo), new SyncStatusInfo(syncStatusInfo));
    }

    private int getCurrentDayLocked() {
        mCal.setTimeInMillis(System.currentTimeMillis());
        final int dayOfYear = mCal.get(Calendar.DAY_OF_YEAR);
@@ -1427,9 +1436,22 @@ public class SyncStorageEngine extends Handler {
        }
    }

    public SyncStatusInfo getOrCreateSyncStatus(AuthorityInfo authority) {
    /**
     * Updates (in a synchronized way) the periodic sync time of the specified
     * authority id and target periodic sync
     */
    public void setPeriodicSyncTime(
            int authorityId, Pair<Bundle, Long> targetPeriodicSync, long when) {
        synchronized (mAuthorities) {
            return getOrCreateSyncStatusLocked(authority.ident);
            final AuthorityInfo authority = mAuthorities.get(authorityId);
            for (int i = 0; i < authority.periodicSyncs.size(); i++) {
                Pair<Bundle, Long> periodicSync = authority.periodicSyncs.get(i);
                if (periodicSync.first == targetPeriodicSync.first
                        && periodicSync.second == targetPeriodicSync.second) {
                    mSyncStatus.get(authorityId).setPeriodicSyncTime(i, when);
                    break;
                }
            }
        }
    }