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:
@@ -17,6 +17,7 @@
|
|||||||
package com.android.server.job.controllers;
|
package com.android.server.job.controllers;
|
||||||
|
|
||||||
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
|
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.sElapsedRealtimeClock;
|
||||||
import static com.android.server.job.JobSchedulerService.sSystemClock;
|
import static com.android.server.job.JobSchedulerService.sSystemClock;
|
||||||
@@ -90,6 +91,14 @@ public class PrefetchController extends StateController {
|
|||||||
@CurrentTimeMillisLong
|
@CurrentTimeMillisLong
|
||||||
private long mLaunchTimeThresholdMs = PcConstants.DEFAULT_LAUNCH_TIME_THRESHOLD_MS;
|
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")
|
@SuppressWarnings("FieldCanBeLocal")
|
||||||
private final EstimatedLaunchTimeChangedListener mEstimatedLaunchTimeChangedListener =
|
private final EstimatedLaunchTimeChangedListener mEstimatedLaunchTimeChangedListener =
|
||||||
new EstimatedLaunchTimeChangedListener() {
|
new EstimatedLaunchTimeChangedListener() {
|
||||||
@@ -204,7 +213,8 @@ public class PrefetchController extends StateController {
|
|||||||
private long getNextEstimatedLaunchTimeLocked(int userId, @NonNull String pkgName,
|
private long getNextEstimatedLaunchTimeLocked(int userId, @NonNull String pkgName,
|
||||||
@CurrentTimeMillisLong long now) {
|
@CurrentTimeMillisLong long now) {
|
||||||
final Long nextEstimatedLaunchTime = mEstimatedLaunchTimes.get(userId, pkgName);
|
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.
|
// Don't query usage stats here because it may have to read from disk.
|
||||||
mHandler.obtainMessage(MSG_RETRIEVE_ESTIMATED_LAUNCH_TIME, userId, 0, pkgName)
|
mHandler.obtainMessage(MSG_RETRIEVE_ESTIMATED_LAUNCH_TIME, userId, 0, pkgName)
|
||||||
.sendToTarget();
|
.sendToTarget();
|
||||||
@@ -335,7 +345,9 @@ public class PrefetchController extends StateController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final long nextEstimatedLaunchTime = getNextEstimatedLaunchTimeLocked(userId, pkgName, now);
|
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.
|
// Set alarm to be notified when this crosses the threshold.
|
||||||
final long timeToCrossThresholdMs =
|
final long timeToCrossThresholdMs =
|
||||||
nextEstimatedLaunchTime - (now + mLaunchTimeThresholdMs);
|
nextEstimatedLaunchTime - (now + mLaunchTimeThresholdMs);
|
||||||
@@ -354,7 +366,7 @@ public class PrefetchController extends StateController {
|
|||||||
private boolean willBeLaunchedSoonLocked(int userId, @NonNull String pkgName,
|
private boolean willBeLaunchedSoonLocked(int userId, @NonNull String pkgName,
|
||||||
@CurrentTimeMillisLong long now) {
|
@CurrentTimeMillisLong long now) {
|
||||||
return getNextEstimatedLaunchTimeLocked(userId, pkgName, now)
|
return getNextEstimatedLaunchTimeLocked(userId, pkgName, now)
|
||||||
<= now + mLaunchTimeThresholdMs;
|
<= now + mLaunchTimeThresholdMs - mLaunchTimeAllowanceMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -494,16 +506,37 @@ public class PrefetchController extends StateController {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final String KEY_LAUNCH_TIME_THRESHOLD_MS =
|
static final String KEY_LAUNCH_TIME_THRESHOLD_MS =
|
||||||
PC_CONSTANT_PREFIX + "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_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. */
|
/** 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;
|
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")
|
@GuardedBy("mLock")
|
||||||
public void processConstantLocked(@NonNull DeviceConfig.Properties properties,
|
public void processConstantLocked(@NonNull DeviceConfig.Properties properties,
|
||||||
@NonNull String key) {
|
@NonNull String key) {
|
||||||
switch (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:
|
case KEY_LAUNCH_TIME_THRESHOLD_MS:
|
||||||
LAUNCH_TIME_THRESHOLD_MS =
|
LAUNCH_TIME_THRESHOLD_MS =
|
||||||
properties.getLong(key, DEFAULT_LAUNCH_TIME_THRESHOLD_MS);
|
properties.getLong(key, DEFAULT_LAUNCH_TIME_THRESHOLD_MS);
|
||||||
@@ -528,6 +561,7 @@ public class PrefetchController extends StateController {
|
|||||||
pw.increaseIndent();
|
pw.increaseIndent();
|
||||||
|
|
||||||
pw.print(KEY_LAUNCH_TIME_THRESHOLD_MS, LAUNCH_TIME_THRESHOLD_MS).println();
|
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();
|
pw.decreaseIndent();
|
||||||
}
|
}
|
||||||
@@ -535,6 +569,11 @@ public class PrefetchController extends StateController {
|
|||||||
|
|
||||||
//////////////////////// TESTING HELPERS /////////////////////////////
|
//////////////////////// TESTING HELPERS /////////////////////////////
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
long getLaunchTimeAllowanceMs() {
|
||||||
|
return mLaunchTimeAllowanceMs;
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
long getLaunchTimeThresholdMs() {
|
long getLaunchTimeThresholdMs() {
|
||||||
return mLaunchTimeThresholdMs;
|
return mLaunchTimeThresholdMs;
|
||||||
|
|||||||
@@ -233,27 +233,34 @@ public class PrefetchControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testConstantsUpdating_ValidValues() {
|
public void testConstantsUpdating_ValidValues() {
|
||||||
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 5 * HOUR_IN_MILLIS);
|
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 * HOUR_IN_MILLIS, mPrefetchController.getLaunchTimeThresholdMs());
|
||||||
|
assertEquals(5 * MINUTE_IN_MILLIS, mPrefetchController.getLaunchTimeAllowanceMs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConstantsUpdating_InvalidValues() {
|
public void testConstantsUpdating_InvalidValues() {
|
||||||
// Test negatives/too low.
|
// Test negatives/too low.
|
||||||
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 4 * MINUTE_IN_MILLIS);
|
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(HOUR_IN_MILLIS, mPrefetchController.getLaunchTimeThresholdMs());
|
||||||
|
assertEquals(0, mPrefetchController.getLaunchTimeAllowanceMs());
|
||||||
|
|
||||||
// Test larger than a day. Controller should cap at one day.
|
// 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_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(24 * HOUR_IN_MILLIS, mPrefetchController.getLaunchTimeThresholdMs());
|
||||||
|
assertEquals(2 * HOUR_IN_MILLIS, mPrefetchController.getLaunchTimeAllowanceMs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConstantsUpdating_ThresholdChangesAlarms() {
|
public void testConstantsUpdating_ThresholdChangesAlarms() {
|
||||||
final long launchDelayMs = 11 * HOUR_IN_MILLIS;
|
final long launchDelayMs = 11 * HOUR_IN_MILLIS;
|
||||||
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
|
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
|
||||||
|
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 0);
|
||||||
when(mUsageStatsManagerInternal
|
when(mUsageStatsManagerInternal
|
||||||
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
|
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
|
||||||
.thenReturn(sSystemClock.millis() + launchDelayMs);
|
.thenReturn(sSystemClock.millis() + launchDelayMs);
|
||||||
@@ -276,6 +283,7 @@ public class PrefetchControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConstraintNotSatisfiedWhenLaunchLate() {
|
public void testConstraintNotSatisfiedWhenLaunchLate() {
|
||||||
|
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 0);
|
||||||
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
|
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
|
||||||
|
|
||||||
final JobStatus job = createJobStatus("testConstraintNotSatisfiedWhenLaunchLate", 1);
|
final JobStatus job = createJobStatus("testConstraintNotSatisfiedWhenLaunchLate", 1);
|
||||||
@@ -290,6 +298,8 @@ public class PrefetchControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConstraintSatisfiedWhenLaunchSoon() {
|
public void testConstraintSatisfiedWhenLaunchSoon() {
|
||||||
|
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 0);
|
||||||
|
|
||||||
final JobStatus job = createJobStatus("testConstraintSatisfiedWhenLaunchSoon", 2);
|
final JobStatus job = createJobStatus("testConstraintSatisfiedWhenLaunchSoon", 2);
|
||||||
when(mUsageStatsManagerInternal
|
when(mUsageStatsManagerInternal
|
||||||
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
|
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
|
||||||
@@ -338,6 +348,8 @@ public class PrefetchControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConstraintSatisfiedWhenWidget() {
|
public void testConstraintSatisfiedWhenWidget() {
|
||||||
|
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 0);
|
||||||
|
|
||||||
final JobStatus jobNonWidget = createJobStatus("testConstraintSatisfiedWhenWidget", 1);
|
final JobStatus jobNonWidget = createJobStatus("testConstraintSatisfiedWhenWidget", 1);
|
||||||
final JobStatus jobWidget = createJobStatus("testConstraintSatisfiedWhenWidget", 2);
|
final JobStatus jobWidget = createJobStatus("testConstraintSatisfiedWhenWidget", 2);
|
||||||
|
|
||||||
@@ -365,6 +377,7 @@ public class PrefetchControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testEstimatedLaunchTimeChangedToLate() {
|
public void testEstimatedLaunchTimeChangedToLate() {
|
||||||
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
|
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
|
||||||
|
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 0);
|
||||||
when(mUsageStatsManagerInternal
|
when(mUsageStatsManagerInternal
|
||||||
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
|
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
|
||||||
.thenReturn(sSystemClock.millis() + HOUR_IN_MILLIS);
|
.thenReturn(sSystemClock.millis() + HOUR_IN_MILLIS);
|
||||||
@@ -393,6 +406,7 @@ public class PrefetchControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testEstimatedLaunchTimeChangedToSoon() {
|
public void testEstimatedLaunchTimeChangedToSoon() {
|
||||||
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
|
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
|
||||||
|
setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_ALLOWANCE_MS, 0);
|
||||||
when(mUsageStatsManagerInternal
|
when(mUsageStatsManagerInternal
|
||||||
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
|
.getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
|
||||||
.thenReturn(sSystemClock.millis() + 10 * HOUR_IN_MILLIS);
|
.thenReturn(sSystemClock.millis() + 10 * HOUR_IN_MILLIS);
|
||||||
@@ -413,4 +427,36 @@ public class PrefetchControllerTest {
|
|||||||
verify(mJobSchedulerService, timeout(DEFAULT_WAIT_MS)).onControllerStateChanged(any());
|
verify(mJobSchedulerService, timeout(DEFAULT_WAIT_MS)).onControllerStateChanged(any());
|
||||||
assertTrue(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user