Sync too many retries
- When an one-shot sync with app-standby exempt fails too many times in a row, drop the "exempt from app-standby" flag. - Also obtain some constants from global settings so we can change them in CTS. Bug: 72443754 Test: Manual test (CTS WIP) Change-Id: Ibdbb348a7ff26a0be04b8f2c256e1f6ead39907d
This commit is contained in:
@@ -10504,6 +10504,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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
@@ -157,18 +157,6 @@ public class SyncManager {
|
||||
SystemProperties.getLong("sync.local_sync_delay", 30 * 1000 /* 30 seconds */);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,6 +408,10 @@ public class SyncOperation {
|
||||
extrasToStringBuilder(extras, sb);
|
||||
}
|
||||
}
|
||||
if (retries > 0) {
|
||||
sb.append(" Retries=");
|
||||
sb.append(retries);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user