Merge "Tweak exemption for sync requests made by FG apps" into pi-dev

am: 621fd20f55

Change-Id: I31ae3e9e11b9defb7e6352830439484d7ec7ac01
This commit is contained in:
Makoto Onuki
2018-05-24 17:54:37 -07:00
committed by android-build-merger
11 changed files with 185 additions and 31 deletions

View File

@@ -211,10 +211,10 @@ public class RequestSync {
mExtras.putBoolean(key, Boolean.valueOf(value));
} else if (opt.equals("-f") || opt.equals("--foreground")) {
mExemptionFlag = ContentResolver.SYNC_EXEMPTION_ACTIVE;
mExemptionFlag = ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET;
} else if (opt.equals("-F") || opt.equals("--top")) {
mExemptionFlag = ContentResolver.SYNC_EXEMPTION_ACTIVE_WITH_TEMP;
mExemptionFlag = ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP;
} else {
System.err.println("Error: Unknown option: " + opt);

View File

@@ -184,7 +184,11 @@ public final class UsageStatsManager {
/** @hide */
public static final int REASON_SUB_USAGE_SLICE_PINNED_PRIV = 0x000A;
/** @hide */
public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000B;
public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE = 0x000B;
/** @hide */
public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE = 0x000C;
/** @hide */
public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000D;
/** @hide */
public static final int REASON_SUB_PREDICTED_RESTORED = 0x0001;
@@ -669,13 +673,19 @@ public final class UsageStatsManager {
sb.append("-sa");
break;
case REASON_SUB_USAGE_SLICE_PINNED:
sb.append("slp");
sb.append("-lp");
break;
case REASON_SUB_USAGE_SLICE_PINNED_PRIV:
sb.append("slpp");
sb.append("-lv");
break;
case REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE:
sb.append("-en");
break;
case REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE:
sb.append("-ed");
break;
case REASON_SUB_USAGE_EXEMPTED_SYNC_START:
sb.append("es");
sb.append("-es");
break;
}
break;

View File

@@ -245,7 +245,15 @@ public abstract class UsageStatsManagerInternal {
int numDeferredJobs, long timeSinceLastJobRun);
/**
* Report a sync that was scheduled by an active app is about to be executed.
* Report a sync is scheduled by a foreground app.
*
* @param packageName name of the package that owns the sync adapter.
* @param userId which user the app is associated with
*/
public abstract void reportExemptedSyncScheduled(String packageName, @UserIdInt int userId);
/**
* Report a sync that was scheduled by a foreground app is about to be executed.
*
* @param packageName name of the package that owns the sync adapter.
* @param userId which user the app is associated with

View File

@@ -520,27 +520,36 @@ public abstract class ContentResolver {
public static final int SYNC_EXEMPTION_NONE = 0;
/**
* When executing a sync with this exemption, we'll put the target app in the ACTIVE bucket
* for 10 minutes. This will allow the sync adapter to schedule/run further syncs and jobs.
* Exemption given to a sync request made by a foreground app (including
* PROCESS_STATE_IMPORTANT_FOREGROUND).
*
* At the schedule time, we promote the sync adapter app for a higher bucket:
* - If the device is not dozing (so the sync will start right away)
* promote to ACTIVE for 1 hour.
* - If the device is dozing (so the sync *won't* start right away),
* promote to WORKING_SET for 4 hours, so it'll get a higher chance to be started once the
* device comes out of doze.
* - When the sync actually starts, we promote the sync adapter app to ACTIVE for 10 minutes,
* so it can schedule and start more syncs without getting throttled, even when the first
* operation was canceled and now we're retrying.
*
*
* Note this will still *not* let RARE apps to run syncs, because they still won't get network
* connection.
* @hide
*/
public static final int SYNC_EXEMPTION_ACTIVE = 1;
public static final int SYNC_EXEMPTION_PROMOTE_BUCKET = 1;
/**
* In addition to {@link #SYNC_EXEMPTION_ACTIVE}, we put the sync adapter app in the
* In addition to {@link #SYNC_EXEMPTION_PROMOTE_BUCKET}, we put the sync adapter app in the
* temp whitelist for 10 minutes, so that even RARE apps can run syncs right away.
* @hide
*/
public static final int SYNC_EXEMPTION_ACTIVE_WITH_TEMP = 2;
public static final int SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP = 2;
/** @hide */
@IntDef(flag = false, prefix = { "SYNC_EXEMPTION_" }, value = {
SYNC_EXEMPTION_NONE,
SYNC_EXEMPTION_ACTIVE,
SYNC_EXEMPTION_ACTIVE_WITH_TEMP,
SYNC_EXEMPTION_PROMOTE_BUCKET,
SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SyncExemption {}

View File

@@ -1310,10 +1310,10 @@ public final class ContentService extends IContentService.Stub {
: ActivityManager.PROCESS_STATE_NONEXISTENT;
if (procState <= ActivityManager.PROCESS_STATE_TOP) {
return ContentResolver.SYNC_EXEMPTION_ACTIVE_WITH_TEMP;
return ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP;
}
if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
return ContentResolver.SYNC_EXEMPTION_ACTIVE;
return ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET;
}
return ContentResolver.SYNC_EXEMPTION_NONE;
}

View File

@@ -1656,7 +1656,7 @@ public class SyncManager {
}
if (syncOperation.syncExemptionFlag
== ContentResolver.SYNC_EXEMPTION_ACTIVE_WITH_TEMP) {
== ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP) {
DeviceIdleController.LocalService dic =
LocalServices.getService(DeviceIdleController.LocalService.class);
if (dic != null) {
@@ -1668,6 +1668,15 @@ public class SyncManager {
}
}
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());
}

View File

@@ -390,10 +390,10 @@ public class SyncOperation {
switch (syncExemptionFlag) {
case ContentResolver.SYNC_EXEMPTION_NONE:
break;
case ContentResolver.SYNC_EXEMPTION_ACTIVE:
case ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET:
sb.append(" STANDBY-EXEMPTED");
break;
case ContentResolver.SYNC_EXEMPTION_ACTIVE_WITH_TEMP:
case ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP:
sb.append(" STANDBY-EXEMPTED(TOP)");
break;
default:

View File

@@ -341,6 +341,7 @@ public class SyncStorageEngine {
boolean initialization;
Bundle extras;
int reason;
int syncExemptionFlag;
}
public static class DayStats {
@@ -1142,6 +1143,7 @@ public class SyncStorageEngine {
item.reason = op.reason;
item.extras = op.extras;
item.event = EVENT_START;
item.syncExemptionFlag = op.syncExemptionFlag;
mSyncHistory.add(0, item);
while (mSyncHistory.size() > MAX_HISTORY) {
mSyncHistory.remove(mSyncHistory.size()-1);
@@ -1262,6 +1264,20 @@ public class SyncStorageEngine {
SyncManager.formatDurationHMS(event, elapsedTime);
event.append(" Reason=");
event.append(SyncOperation.reasonToString(null, item.reason));
if (item.syncExemptionFlag != ContentResolver.SYNC_EXEMPTION_NONE) {
event.append(" Exemption=");
switch (item.syncExemptionFlag) {
case ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET:
event.append("fg");
break;
case ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP:
event.append("top");
break;
default:
event.append(item.syncExemptionFlag);
break;
}
}
event.append(" Extras=");
SyncOperation.extrasToStringBuilder(item.extras, event);

View File

@@ -218,6 +218,11 @@ public class AppStandbyControllerTests {
+ "stable_charging_threshold=" + STABLE_CHARGING_THRESHOLD;
}
@Override
public boolean isDeviceIdleMode() {
return false;
}
// Internal methods
void setDisplayOn(boolean on) {

View File

@@ -24,6 +24,8 @@ import static android.app.usage.UsageStatsManager.REASON_MAIN_TIMEOUT;
import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
import static android.app.usage.UsageStatsManager.REASON_SUB_PREDICTED_RESTORED;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_ACTIVE_TIMEOUT;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_START;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_BACKGROUND;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
@@ -194,8 +196,9 @@ public class AppStandbyController {
static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10;
/** Check the state of one app: arg1 = userId, arg2 = uid, obj = (String) packageName */
static final int MSG_CHECK_PACKAGE_IDLE_STATE = 11;
static final int MSG_REPORT_EXEMPTED_SYNC_START = 12;
static final int MSG_UPDATE_STABLE_CHARGING= 13;
static final int MSG_REPORT_EXEMPTED_SYNC_SCHEDULED = 12;
static final int MSG_REPORT_EXEMPTED_SYNC_START = 13;
static final int MSG_UPDATE_STABLE_CHARGING= 14;
long mCheckIdleIntervalMillis;
long mAppIdleParoleIntervalMillis;
@@ -213,8 +216,20 @@ public class AppStandbyController {
long mPredictionTimeoutMillis;
/** Maximum time a sync adapter associated with a CP should keep the buckets elevated. */
long mSyncAdapterTimeoutMillis;
/** Maximum time an exempted sync should keep the buckets elevated. */
long mExemptedSyncAdapterTimeoutMillis;
/**
* Maximum time an exempted sync should keep the buckets elevated, when sync is scheduled in
* non-doze
*/
long mExemptedSyncScheduledNonDozeTimeoutMillis;
/**
* Maximum time an exempted sync should keep the buckets elevated, when sync is scheduled in
* doze
*/
long mExemptedSyncScheduledDozeTimeoutMillis;
/**
* Maximum time an exempted sync should keep the buckets elevated, when sync is started.
*/
long mExemptedSyncStartTimeoutMillis;
/** Maximum time a system interaction should keep the buckets elevated. */
long mSystemInteractionTimeoutMillis;
/** The length of time phone must be charging before considered stable enough to run jobs */
@@ -393,6 +408,37 @@ public class AppStandbyController {
}
}
void reportExemptedSyncScheduled(String packageName, int userId) {
if (!mAppIdleEnabled) return;
final int bucketToPromote;
final int usageReason;
final long durationMillis;
if (!mInjector.isDeviceIdleMode()) {
// Not dozing.
bucketToPromote = STANDBY_BUCKET_ACTIVE;
usageReason = REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE;
durationMillis = mExemptedSyncScheduledNonDozeTimeoutMillis;
} else {
// Dozing.
bucketToPromote = STANDBY_BUCKET_WORKING_SET;
usageReason = REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE;
durationMillis = mExemptedSyncScheduledDozeTimeoutMillis;
}
final long elapsedRealtime = mInjector.elapsedRealtime();
synchronized (mAppIdleLock) {
AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId,
bucketToPromote, usageReason,
0,
elapsedRealtime + durationMillis);
maybeInformListeners(packageName, userId, elapsedRealtime,
appUsage.currentBucket, appUsage.bucketingReason, false);
}
}
void reportExemptedSyncStart(String packageName, int userId) {
if (!mAppIdleEnabled) return;
@@ -402,7 +448,7 @@ public class AppStandbyController {
AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId,
STANDBY_BUCKET_ACTIVE, REASON_SUB_USAGE_EXEMPTED_SYNC_START,
0,
elapsedRealtime + mExemptedSyncAdapterTimeoutMillis);
elapsedRealtime + mExemptedSyncStartTimeoutMillis);
maybeInformListeners(packageName, userId, elapsedRealtime,
appUsage.currentBucket, appUsage.bucketingReason, false);
}
@@ -1365,6 +1411,11 @@ public class AppStandbyController {
.sendToTarget();
}
void postReportExemptedSyncScheduled(String packageName, int userId) {
mHandler.obtainMessage(MSG_REPORT_EXEMPTED_SYNC_SCHEDULED, userId, 0, packageName)
.sendToTarget();
}
void postReportExemptedSyncStart(String packageName, int userId) {
mHandler.obtainMessage(MSG_REPORT_EXEMPTED_SYNC_START, userId, 0, packageName)
.sendToTarget();
@@ -1401,6 +1452,16 @@ public class AppStandbyController {
TimeUtils.formatDuration(mAppIdleParoleDurationMillis, pw);
pw.println();
pw.print(" mExemptedSyncScheduledNonDozeTimeoutMillis=");
TimeUtils.formatDuration(mExemptedSyncScheduledNonDozeTimeoutMillis, pw);
pw.println();
pw.print(" mExemptedSyncScheduledDozeTimeoutMillis=");
TimeUtils.formatDuration(mExemptedSyncScheduledDozeTimeoutMillis, pw);
pw.println();
pw.print(" mExemptedSyncStartTimeoutMillis=");
TimeUtils.formatDuration(mExemptedSyncStartTimeoutMillis, pw);
pw.println();
pw.println();
pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
pw.print(" mAppIdleTempParoled="); pw.print(mAppIdleTempParoled);
@@ -1429,6 +1490,7 @@ public class AppStandbyController {
private IBatteryStats mBatteryStats;
private PackageManagerInternal mPackageManagerInternal;
private DisplayManager mDisplayManager;
private PowerManager mPowerManager;
int mBootPhase;
Injector(Context context, Looper looper) {
@@ -1453,6 +1515,7 @@ public class AppStandbyController {
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mDisplayManager = (DisplayManager) mContext.getSystemService(
Context.DISPLAY_SERVICE);
mPowerManager = mContext.getSystemService(PowerManager.class);
}
mBootPhase = phase;
}
@@ -1532,6 +1595,11 @@ public class AppStandbyController {
return Global.getString(mContext.getContentResolver(),
Global.APP_IDLE_CONSTANTS);
}
/** Whether the device is in doze or not. */
public boolean isDeviceIdleMode() {
return mPowerManager.isDeviceIdleMode();
}
}
class AppStandbyHandler extends Handler {
@@ -1595,6 +1663,10 @@ public class AppStandbyController {
mInjector.elapsedRealtime());
break;
case MSG_REPORT_EXEMPTED_SYNC_SCHEDULED:
reportExemptedSyncScheduled((String) msg.obj, msg.arg1);
break;
case MSG_REPORT_EXEMPTED_SYNC_START:
reportExemptedSyncStart((String) msg.obj, msg.arg1);
break;
@@ -1684,7 +1756,12 @@ public class AppStandbyController {
"system_update_usage_duration";
private static final String KEY_PREDICTION_TIMEOUT = "prediction_timeout";
private static final String KEY_SYNC_ADAPTER_HOLD_DURATION = "sync_adapter_duration";
private static final String KEY_EXEMPTED_SYNC_HOLD_DURATION = "exempted_sync_duration";
private static final String KEY_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_HOLD_DURATION
= "exempted_sync_scheduled_nd_duration";
private static final String KEY_EXEMPTED_SYNC_SCHEDULED_DOZE_HOLD_DURATION
= "exempted_sync_scheduled_d_duration";
private static final String KEY_EXEMPTED_SYNC_START_HOLD_DURATION
= "exempted_sync_start_duration";
private static final String KEY_SYSTEM_INTERACTION_HOLD_DURATION =
"system_interaction_duration";
private static final String KEY_STABLE_CHARGING_THRESHOLD = "stable_charging_threshold";
@@ -1693,7 +1770,9 @@ public class AppStandbyController {
public static final long DEFAULT_SYSTEM_UPDATE_TIMEOUT = 2 * ONE_HOUR;
public static final long DEFAULT_SYSTEM_INTERACTION_TIMEOUT = 10 * ONE_MINUTE;
public static final long DEFAULT_SYNC_ADAPTER_TIMEOUT = 10 * ONE_MINUTE;
public static final long DEFAULT_EXEMPTED_SYNC_TIMEOUT = 10 * ONE_MINUTE;
public static final long DEFAULT_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_TIMEOUT = 10 * ONE_MINUTE;
public static final long DEFAULT_EXEMPTED_SYNC_SCHEDULED_DOZE_TIMEOUT = 4 * ONE_HOUR;
public static final long DEFAULT_EXEMPTED_SYNC_START_TIMEOUT = 10 * ONE_MINUTE;
public static final long DEFAULT_STABLE_CHARGING_THRESHOLD = 10 * ONE_MINUTE;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -1778,9 +1857,22 @@ public class AppStandbyController {
mSyncAdapterTimeoutMillis = mParser.getDurationMillis
(KEY_SYNC_ADAPTER_HOLD_DURATION,
COMPRESS_TIME ? ONE_MINUTE : DEFAULT_SYNC_ADAPTER_TIMEOUT);
mExemptedSyncAdapterTimeoutMillis = mParser.getDurationMillis
(KEY_EXEMPTED_SYNC_HOLD_DURATION,
COMPRESS_TIME ? ONE_MINUTE : DEFAULT_EXEMPTED_SYNC_TIMEOUT);
mExemptedSyncScheduledNonDozeTimeoutMillis = mParser.getDurationMillis
(KEY_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_HOLD_DURATION,
COMPRESS_TIME ? (ONE_MINUTE / 2)
: DEFAULT_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_TIMEOUT);
mExemptedSyncScheduledDozeTimeoutMillis = mParser.getDurationMillis
(KEY_EXEMPTED_SYNC_SCHEDULED_DOZE_HOLD_DURATION,
COMPRESS_TIME ? ONE_MINUTE
: DEFAULT_EXEMPTED_SYNC_SCHEDULED_DOZE_TIMEOUT);
mExemptedSyncStartTimeoutMillis = mParser.getDurationMillis
(KEY_EXEMPTED_SYNC_START_HOLD_DURATION,
COMPRESS_TIME ? ONE_MINUTE
: DEFAULT_EXEMPTED_SYNC_START_TIMEOUT);
mSystemInteractionTimeoutMillis = mParser.getDurationMillis
(KEY_SYSTEM_INTERACTION_HOLD_DURATION,
COMPRESS_TIME ? ONE_MINUTE : DEFAULT_SYSTEM_INTERACTION_TIMEOUT);

View File

@@ -1370,6 +1370,11 @@ public class UsageStatsService extends SystemService implements
mAppStandby.onAdminDataAvailable();
}
@Override
public void reportExemptedSyncScheduled(String packageName, int userId) {
mAppStandby.postReportExemptedSyncScheduled(packageName, userId);
}
@Override
public void reportExemptedSyncStart(String packageName, int userId) {
mAppStandby.postReportExemptedSyncStart(packageName, userId);