Merge "Add grace period to estimated launch times." into tm-dev am: d9bb349561

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18354131

Change-Id: I28fd168fdb9dcfd550d24a361f651b04247b04c5
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
TreeHugger Robot
2022-05-13 22:32:29 +00:00
committed by Automerger Merge Worker
2 changed files with 88 additions and 3 deletions

View File

@@ -17,6 +17,7 @@
package com.android.server.job.controllers;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import static com.android.server.job.JobSchedulerService.sSystemClock;
@@ -90,6 +91,14 @@ public class PrefetchController extends StateController {
@CurrentTimeMillisLong
private long mLaunchTimeThresholdMs = PcConstants.DEFAULT_LAUNCH_TIME_THRESHOLD_MS;
/**
* The additional time we'll add to a launch time estimate before considering it obsolete and
* try to get a new estimate. This will help make prefetch jobs more viable in case an estimate
* is a few minutes early.
*/
@GuardedBy("mLock")
private long mLaunchTimeAllowanceMs = PcConstants.DEFAULT_LAUNCH_TIME_ALLOWANCE_MS;
@SuppressWarnings("FieldCanBeLocal")
private final EstimatedLaunchTimeChangedListener mEstimatedLaunchTimeChangedListener =
new EstimatedLaunchTimeChangedListener() {
@@ -204,7 +213,8 @@ public class PrefetchController extends StateController {
private long getNextEstimatedLaunchTimeLocked(int userId, @NonNull String pkgName,
@CurrentTimeMillisLong long now) {
final Long nextEstimatedLaunchTime = mEstimatedLaunchTimes.get(userId, pkgName);
if (nextEstimatedLaunchTime == null || nextEstimatedLaunchTime < now) {
if (nextEstimatedLaunchTime == null
|| nextEstimatedLaunchTime < now - mLaunchTimeAllowanceMs) {
// Don't query usage stats here because it may have to read from disk.
mHandler.obtainMessage(MSG_RETRIEVE_ESTIMATED_LAUNCH_TIME, userId, 0, pkgName)
.sendToTarget();
@@ -335,7 +345,9 @@ public class PrefetchController extends StateController {
}
final long nextEstimatedLaunchTime = getNextEstimatedLaunchTimeLocked(userId, pkgName, now);
if (nextEstimatedLaunchTime - now > mLaunchTimeThresholdMs) {
// Avoid setting an alarm for the end of time.
if (nextEstimatedLaunchTime != Long.MAX_VALUE
&& nextEstimatedLaunchTime - now > mLaunchTimeThresholdMs) {
// Set alarm to be notified when this crosses the threshold.
final long timeToCrossThresholdMs =
nextEstimatedLaunchTime - (now + mLaunchTimeThresholdMs);
@@ -354,7 +366,7 @@ public class PrefetchController extends StateController {
private boolean willBeLaunchedSoonLocked(int userId, @NonNull String pkgName,
@CurrentTimeMillisLong long now) {
return getNextEstimatedLaunchTimeLocked(userId, pkgName, now)
<= now + mLaunchTimeThresholdMs;
<= now + mLaunchTimeThresholdMs - mLaunchTimeAllowanceMs;
}
@Override
@@ -494,16 +506,37 @@ public class PrefetchController extends StateController {
@VisibleForTesting
static final String KEY_LAUNCH_TIME_THRESHOLD_MS =
PC_CONSTANT_PREFIX + "launch_time_threshold_ms";
@VisibleForTesting
static final String KEY_LAUNCH_TIME_ALLOWANCE_MS =
PC_CONSTANT_PREFIX + "launch_time_allowance_ms";
private static final long DEFAULT_LAUNCH_TIME_THRESHOLD_MS = 7 * HOUR_IN_MILLIS;
private static final long DEFAULT_LAUNCH_TIME_ALLOWANCE_MS = 20 * MINUTE_IN_MILLIS;
/** How much time each app will have to run jobs within their standby bucket window. */
public long LAUNCH_TIME_THRESHOLD_MS = DEFAULT_LAUNCH_TIME_THRESHOLD_MS;
/**
* How much additional time to add to an estimated launch time before considering it
* unusable.
*/
public long LAUNCH_TIME_ALLOWANCE_MS = DEFAULT_LAUNCH_TIME_ALLOWANCE_MS;
@GuardedBy("mLock")
public void processConstantLocked(@NonNull DeviceConfig.Properties properties,
@NonNull String key) {
switch (key) {
case KEY_LAUNCH_TIME_ALLOWANCE_MS:
LAUNCH_TIME_ALLOWANCE_MS =
properties.getLong(key, DEFAULT_LAUNCH_TIME_ALLOWANCE_MS);
// Limit the allowance to the range [0 minutes, 2 hours].
long newLaunchTimeAllowanceMs = Math.min(2 * HOUR_IN_MILLIS,
Math.max(0, LAUNCH_TIME_ALLOWANCE_MS));
if (mLaunchTimeAllowanceMs != newLaunchTimeAllowanceMs) {
mLaunchTimeAllowanceMs = newLaunchTimeAllowanceMs;
mShouldReevaluateConstraints = true;
}
break;
case KEY_LAUNCH_TIME_THRESHOLD_MS:
LAUNCH_TIME_THRESHOLD_MS =
properties.getLong(key, DEFAULT_LAUNCH_TIME_THRESHOLD_MS);
@@ -528,6 +561,7 @@ public class PrefetchController extends StateController {
pw.increaseIndent();
pw.print(KEY_LAUNCH_TIME_THRESHOLD_MS, LAUNCH_TIME_THRESHOLD_MS).println();
pw.print(KEY_LAUNCH_TIME_ALLOWANCE_MS, LAUNCH_TIME_ALLOWANCE_MS).println();
pw.decreaseIndent();
}
@@ -535,6 +569,11 @@ public class PrefetchController extends StateController {
//////////////////////// TESTING HELPERS /////////////////////////////
@VisibleForTesting
long getLaunchTimeAllowanceMs() {
return mLaunchTimeAllowanceMs;
}
@VisibleForTesting
long getLaunchTimeThresholdMs() {
return mLaunchTimeThresholdMs;

View File

@@ -233,27 +233,34 @@ public class PrefetchControllerTest {
@Test
public void testConstantsUpdating_ValidValues() {
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 5 * HOUR_IN_MILLIS);
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 5 * MINUTE_IN_MILLIS);
assertEquals(5 * HOUR_IN_MILLIS, mPrefetchController.getLaunchTimeThresholdMs());
assertEquals(5 * MINUTE_IN_MILLIS, mPrefetchController.getLaunchTimeAllowanceMs());
}
@Test
public void testConstantsUpdating_InvalidValues() {
// Test negatives/too low.
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 4 * MINUTE_IN_MILLIS);
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, -MINUTE_IN_MILLIS);
assertEquals(HOUR_IN_MILLIS, mPrefetchController.getLaunchTimeThresholdMs());
assertEquals(0, mPrefetchController.getLaunchTimeAllowanceMs());
// Test larger than a day. Controller should cap at one day.
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 25 * HOUR_IN_MILLIS);
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 5 * HOUR_IN_MILLIS);
assertEquals(24 * HOUR_IN_MILLIS, mPrefetchController.getLaunchTimeThresholdMs());
assertEquals(2 * HOUR_IN_MILLIS, mPrefetchController.getLaunchTimeAllowanceMs());
}
@Test
public void testConstantsUpdating_ThresholdChangesAlarms() {
final long launchDelayMs = 11 * HOUR_IN_MILLIS;
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 0);
when(mUsageStatsManagerInternal
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
.thenReturn(sSystemClock.millis() + launchDelayMs);
@@ -276,6 +283,7 @@ public class PrefetchControllerTest {
@Test
public void testConstraintNotSatisfiedWhenLaunchLate() {
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 0);
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
final JobStatus job = createJobStatus("testConstraintNotSatisfiedWhenLaunchLate", 1);
@@ -290,6 +298,8 @@ public class PrefetchControllerTest {
@Test
public void testConstraintSatisfiedWhenLaunchSoon() {
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 0);
final JobStatus job = createJobStatus("testConstraintSatisfiedWhenLaunchSoon", 2);
when(mUsageStatsManagerInternal
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
@@ -338,6 +348,8 @@ public class PrefetchControllerTest {
@Test
public void testConstraintSatisfiedWhenWidget() {
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 0);
final JobStatus jobNonWidget = createJobStatus("testConstraintSatisfiedWhenWidget", 1);
final JobStatus jobWidget = createJobStatus("testConstraintSatisfiedWhenWidget", 2);
@@ -365,6 +377,7 @@ public class PrefetchControllerTest {
@Test
public void testEstimatedLaunchTimeChangedToLate() {
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 0);
when(mUsageStatsManagerInternal
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
.thenReturn(sSystemClock.millis() + HOUR_IN_MILLIS);
@@ -393,6 +406,7 @@ public class PrefetchControllerTest {
@Test
public void testEstimatedLaunchTimeChangedToSoon() {
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 0);
when(mUsageStatsManagerInternal
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
.thenReturn(sSystemClock.millis() + 10 * HOUR_IN_MILLIS);
@@ -413,4 +427,36 @@ public class PrefetchControllerTest {
verify(mJobSchedulerService, timeout(DEFAULT_WAIT_MS)).onControllerStateChanged(any());
assertTrue(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
}
@Test
public void testEstimatedLaunchTimeAllowance() {
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 15 * MINUTE_IN_MILLIS);
when(mUsageStatsManagerInternal
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
.thenReturn(sSystemClock.millis() + 10 * HOUR_IN_MILLIS);
InOrder inOrder = inOrder(mUsageStatsManagerInternal);
JobStatus jobStatus = createJobStatus("testEstimatedLaunchTimeAllowance", 1);
trackJobs(jobStatus);
inOrder.verify(mUsageStatsManagerInternal, timeout(DEFAULT_WAIT_MS))
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID);
// The allowance shouldn't shift the alarm
verify(mAlarmManager, timeout(DEFAULT_WAIT_MS).times(1))
.setWindow(
anyInt(), eq(sElapsedRealtimeClock.millis() + 3 * HOUR_IN_MILLIS),
anyLong(), eq(TAG_PREFETCH), any(), any());
assertFalse(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
mEstimatedLaunchTimeChangedListener.onEstimatedLaunchTimeChanged(SOURCE_USER_ID,
SOURCE_PACKAGE, sSystemClock.millis() + HOUR_IN_MILLIS);
inOrder.verify(mUsageStatsManagerInternal, timeout(DEFAULT_WAIT_MS).times(0))
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID);
verify(mJobSchedulerService, timeout(DEFAULT_WAIT_MS)).onControllerStateChanged(any());
assertTrue(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
sSystemClock = getShiftedClock(sSystemClock, HOUR_IN_MILLIS + MINUTE_IN_MILLIS);
}
}