diff options
6 files changed, 200 insertions, 26 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 021c22c763af..fef6495e5c88 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10505,6 +10505,16 @@ public final class Settings { public static final String BATTERY_STATS_CONSTANTS = "battery_stats_constants"; /** + * SyncManager specific settings. + * + * <p> + * Type: string + * @hide + * @see com.android.server.content.SyncManagerConstants + */ + public static final String SYNC_MANAGER_CONSTANTS = "sync_manager_constants"; + + /** * Whether or not App Standby feature is enabled. This controls throttling of apps * based on usage patterns and predictions. * Type: int (0 for false, 1 for true) diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 5bb9abefb535..a0b6297db235 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -366,6 +366,7 @@ public class SettingsBackupTest { Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, Settings.Global.STORAGE_BENCHMARK_INTERVAL, Settings.Global.STORAGE_SETTINGS_CLOBBER_THRESHOLD, + Settings.Global.SYNC_MANAGER_CONSTANTS, Settings.Global.SYNC_MAX_RETRY_DELAY_IN_SECONDS, Settings.Global.SYS_FREE_STORAGE_LOG_INTERVAL, Settings.Global.SYS_STORAGE_CACHE_MAX_BYTES, diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index c3f020ade635..95a024698864 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -97,9 +97,7 @@ public final class ContentService extends IContentService.Stub { @Override public void onBootPhase(int phase) { - if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { - mService.systemReady(); - } + mService.onBootPhase(phase); } @@ -300,8 +298,15 @@ public final class ContentService extends IContentService.Stub { localeFilter, null, null); } - void systemReady() { - getSyncManager(); + void onBootPhase(int phase) { + switch (phase) { + case SystemService.PHASE_SYSTEM_SERVICES_READY: + getSyncManager(); + break; + } + if (mSyncManager != null) { + mSyncManager.onBootPhase(phase); + } } /** diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index de17ec782be4..d87a1bb9f96f 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -89,6 +89,7 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.util.ArrayUtils; import com.android.server.LocalServices; +import com.android.server.SystemService; import com.android.server.job.JobSchedulerInternal; import com.google.android.collect.Lists; import com.google.android.collect.Maps; @@ -102,7 +103,6 @@ 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.JobStorePersistStats; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -158,18 +158,6 @@ public class SyncManager { } /** - * When retrying a sync for the first time use this delay. After that - * the retry time will double until it reached MAX_SYNC_RETRY_TIME. - * In milliseconds. - */ - private static final long INITIAL_SYNC_RETRY_TIME_IN_MS = 30 * 1000; // 30 seconds - - /** - * Default the max sync retry time to this value. - */ - private static final long DEFAULT_MAX_SYNC_RETRY_TIME_IN_SECONDS = 60 * 60; // one hour - - /** * 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; @@ -449,6 +437,7 @@ public class SyncManager { }; private final SyncHandler mSyncHandler; + private final SyncManagerConstants mConstants; private volatile boolean mBootCompleted = false; private volatile boolean mJobServiceReady = false; @@ -616,6 +605,7 @@ public class SyncManager { }, mSyncHandler); mRand = new Random(System.currentTimeMillis()); + mConstants = new SyncManagerConstants(context); IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); context.registerReceiver(mConnectivityIntentReceiver, intentFilter); @@ -756,6 +746,14 @@ public class SyncManager { mSyncHandler.post(() -> mLogger.log("onStopUser: user=", userHandle)); } + public void onBootPhase(int phase) { + // Note SyncManager only receives PHASE_SYSTEM_SERVICES_READY and after. + switch (phase) { + case SystemService.PHASE_SYSTEM_SERVICES_READY: + mConstants.start(); + break; + } + } private void whiteListExistingSyncAdaptersIfNeeded() { if (!mSyncStorageEngine.shouldGrantSyncAdaptersAccountAccess()) { @@ -903,7 +901,10 @@ public class SyncManager { } if (isLoggable) { Log.d(TAG, "one-time sync for: " + requestedAccount + " " + extras.toString() + " " - + requestedAuthority); + + requestedAuthority + + " reason=" + reason + + " checkIfAccountReady=" + checkIfAccountReady + + " isAppStandbyExempted=" + isAppStandbyExempted); } AccountAndUser[] accounts = null; @@ -1368,18 +1369,18 @@ public class SyncManager { return; } // Subsequent delays are the double of the previous delay. - newDelayInMs = previousSettings.second * 2; + newDelayInMs = + (long) (previousSettings.second * mConstants.getRetryTimeIncreaseFactor()); } if (newDelayInMs <= 0) { // The initial delay is the jitterized INITIAL_SYNC_RETRY_TIME_IN_MS. - newDelayInMs = jitterize(INITIAL_SYNC_RETRY_TIME_IN_MS, - (long)(INITIAL_SYNC_RETRY_TIME_IN_MS * 1.1)); + final long initialRetryMs = mConstants.getInitialSyncRetryTimeInSeconds() * 1000; + newDelayInMs = jitterize(initialRetryMs, (long)(initialRetryMs * 1.1)); } // Cap the delay. - long maxSyncRetryTimeInSeconds = Settings.Global.getLong(mContext.getContentResolver(), - Settings.Global.SYNC_MAX_RETRY_DELAY_IN_SECONDS, - DEFAULT_MAX_SYNC_RETRY_TIME_IN_SECONDS); + final long maxSyncRetryTimeInSeconds = mConstants.getMaxSyncRetryTimeInSeconds(); + if (newDelayInMs > maxSyncRetryTimeInSeconds * 1000) { newDelayInMs = maxSyncRetryTimeInSeconds * 1000; } @@ -1930,6 +1931,7 @@ public class SyncManager { protected void dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll) { final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); dumpSyncState(ipw); + mConstants.dump(pw, ""); dumpSyncAdapters(ipw); if (dumpAll) { @@ -3573,7 +3575,13 @@ public class SyncManager { reschedulePeriodicSyncH(syncOperation); } } else { - Log.d(TAG, "failed sync operation " + syncOperation + ", " + syncResult); + Log.w(TAG, "failed sync operation " + syncOperation + ", " + syncResult); + + syncOperation.retries++; + if (syncOperation.retries > mConstants.getMaxRetriesWithAppStandbyExemption()) { + syncOperation.isAppStandbyExempted = false; + } + // the operation failed so increase the backoff time increaseBackoffSetting(syncOperation.target); if (!syncOperation.isPeriodic) { diff --git a/services/core/java/com/android/server/content/SyncManagerConstants.java b/services/core/java/com/android/server/content/SyncManagerConstants.java new file mode 100644 index 000000000000..2f35687fa44f --- /dev/null +++ b/services/core/java/com/android/server/content/SyncManagerConstants.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2018 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.content.Context; +import android.database.ContentObserver; +import android.provider.Settings; +import android.provider.Settings.Global; +import android.util.KeyValueListParser; +import android.util.Slog; + +import java.io.PrintWriter; + +public class SyncManagerConstants extends ContentObserver { + private static final String TAG = "SyncManagerConfig"; + + private final Object mLock = new Object(); + private final Context mContext; + + private static final String KEY_INITIAL_SYNC_RETRY_TIME_IN_SECONDS = + "initial_sync_retry_time_in_seconds"; + private static final int DEF_INITIAL_SYNC_RETRY_TIME_IN_SECONDS = 30; + private int mInitialSyncRetryTimeInSeconds = DEF_INITIAL_SYNC_RETRY_TIME_IN_SECONDS; + + private static final String KEY_RETRY_TIME_INCREASE_FACTOR = + "retry_time_increase_factor"; + private static final float DEF_RETRY_TIME_INCREASE_FACTOR = 2.0f; + private float mRetryTimeIncreaseFactor = DEF_RETRY_TIME_INCREASE_FACTOR; + + private static final String KEY_MAX_SYNC_RETRY_TIME_IN_SECONDS = + "max_sync_retry_time_in_seconds"; + private static final int DEF_MAX_SYNC_RETRY_TIME_IN_SECONDS = 60 * 60; + private int mMaxSyncRetryTimeInSeconds = DEF_MAX_SYNC_RETRY_TIME_IN_SECONDS; + + private static final String KEY_MAX_RETRIES_WITH_APP_STANDBY_EXEMPTION = + "max_retries_with_app_standby_exemption"; + private static final int DEF_MAX_RETRIES_WITH_APP_STANDBY_EXEMPTION = 5; + private int mMaxRetriesWithAppStandbyExemption = DEF_MAX_RETRIES_WITH_APP_STANDBY_EXEMPTION; + + protected SyncManagerConstants(Context context) { + super(null); + mContext = context; + refresh(); + } + + public void start() { + mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor( + Settings.Global.SYNC_MANAGER_CONSTANTS), false, this); + refresh(); + } + + @Override + public void onChange(boolean selfChange) { + refresh(); + } + + private void refresh() { + synchronized (mLock) { + + String newValue = Settings.Global.getString(mContext.getContentResolver(), + Global.SYNC_MANAGER_CONSTANTS); + final KeyValueListParser parser = new KeyValueListParser(','); + try { + parser.setString(newValue); + } catch (IllegalArgumentException e) { + Slog.wtf(TAG, "Bad constants: " + newValue); + } + + mInitialSyncRetryTimeInSeconds = parser.getInt( + KEY_INITIAL_SYNC_RETRY_TIME_IN_SECONDS, + DEF_INITIAL_SYNC_RETRY_TIME_IN_SECONDS); + + mMaxSyncRetryTimeInSeconds = parser.getInt( + KEY_MAX_SYNC_RETRY_TIME_IN_SECONDS, + DEF_MAX_SYNC_RETRY_TIME_IN_SECONDS); + + mRetryTimeIncreaseFactor = parser.getFloat( + KEY_RETRY_TIME_INCREASE_FACTOR, + DEF_RETRY_TIME_INCREASE_FACTOR); + + mMaxRetriesWithAppStandbyExemption = parser.getInt( + KEY_MAX_RETRIES_WITH_APP_STANDBY_EXEMPTION, + DEF_MAX_RETRIES_WITH_APP_STANDBY_EXEMPTION); + } + } + + public int getInitialSyncRetryTimeInSeconds() { + synchronized (mLock) { + return mInitialSyncRetryTimeInSeconds; + } + } + + public float getRetryTimeIncreaseFactor() { + synchronized (mLock) { + return mRetryTimeIncreaseFactor; + } + } + + public int getMaxSyncRetryTimeInSeconds() { + synchronized (mLock) { + return mMaxSyncRetryTimeInSeconds; + } + } + + public int getMaxRetriesWithAppStandbyExemption() { + synchronized (mLock) { + return mMaxRetriesWithAppStandbyExemption; + } + } + + public void dump(PrintWriter pw, String prefix) { + synchronized (mLock) { + pw.print(prefix); + pw.println("SyncManager Config:"); + + pw.print(prefix); + pw.print(" mInitialSyncRetryTimeInSeconds="); + pw.println(mInitialSyncRetryTimeInSeconds); + + pw.print(prefix); + pw.print(" mRetryTimeIncreaseFactor="); + pw.println(mRetryTimeIncreaseFactor); + + pw.print(prefix); + pw.print(" mMaxSyncRetryTimeInSeconds="); + pw.println(mMaxSyncRetryTimeInSeconds); + + pw.print(prefix); + pw.print(" mMaxRetriesWithAppStandbyExemption="); + pw.println(mMaxRetriesWithAppStandbyExemption); + } + } +} diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java index f6b481920faf..96bdaeabf17c 100644 --- a/services/core/java/com/android/server/content/SyncOperation.java +++ b/services/core/java/com/android/server/content/SyncOperation.java @@ -408,6 +408,10 @@ public class SyncOperation { extrasToStringBuilder(extras, sb); } } + if (retries > 0) { + sb.append(" Retries="); + sb.append(retries); + } return sb.toString(); } |