diff options
| author | 2019-04-15 16:43:28 -0700 | |
|---|---|---|
| committer | 2019-04-16 14:00:37 -0700 | |
| commit | 6ced0ee15adb7d40b30d60e26d65527c3640a524 (patch) | |
| tree | b655a5a85a652f90c84238ad127668876ada2def | |
| parent | 11141109f4c9f8f423245113f8588d0371015bc1 (diff) | |
Elevate standby bucket on first foreground service start
If an app is in the NEVER standby bucket, a foreground service start
will bring the app up to the ACTIVE bucket for 30 min (by default).
Foreground service starts in other circumstances will not affect the
standby bucket
Bug: 111578623
Test: atest AppStandbyControllerTests#testInitialForegroundServiceTimeout
Change-Id: Ia9d5fd7a04d2378a5525457d465da7ed463fe8fc
4 files changed, 71 insertions, 1 deletions
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java index f8dc20e9af09..7fa436084246 100644 --- a/core/java/android/app/usage/UsageStatsManager.java +++ b/core/java/android/app/usage/UsageStatsManager.java @@ -198,6 +198,8 @@ public final class UsageStatsManager { /** @hide */ public static final int REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED = 0x000E; /** @hide */ + public static final int REASON_SUB_USAGE_FOREGROUND_SERVICE_START = 0x000F; + /** @hide */ public static final int REASON_SUB_PREDICTED_RESTORED = 0x0001; @@ -997,6 +999,9 @@ public final class UsageStatsManager { case REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED: sb.append("-uss"); break; + case REASON_SUB_USAGE_FOREGROUND_SERVICE_START: + sb.append("-fss"); + break; } break; } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 0491c732db81..2c8e68cbe196 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -11811,6 +11811,7 @@ public final class Settings { * sync_adapter_duration (long) * exempted_sync_duration (long) * system_interaction_duration (long) + * initial_foreground_service_start_duration (long) * stable_charging_threshold (long) * * idle_duration (long) // This is deprecated and used to circumvent b/26355386. diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java index 6ec864c05258..f4a6231e43fb 100644 --- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java @@ -16,6 +16,7 @@ package com.android.server.usage; +import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START; import static android.app.usage.UsageEvents.Event.NOTIFICATION_SEEN; import static android.app.usage.UsageEvents.Event.SLICE_PINNED; import static android.app.usage.UsageEvents.Event.SLICE_PINNED_PRIV; @@ -821,6 +822,41 @@ public class AppStandbyControllerTests { } @Test + public void testInitialForegroundServiceTimeout() throws Exception { + setChargingState(mController, false); + + mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100; + // Make sure app is in NEVER bucket + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, + REASON_MAIN_FORCED, mInjector.mElapsedRealtime); + mController.checkIdleStates(USER_ID); + assertBucket(STANDBY_BUCKET_NEVER); + + mInjector.mElapsedRealtime += 100; + + // Trigger a FOREGROUND_SERVICE_START and verify bucket + reportEvent(mController, FOREGROUND_SERVICE_START, mInjector.mElapsedRealtime, PACKAGE_1); + mController.checkIdleStates(USER_ID); + assertBucket(STANDBY_BUCKET_ACTIVE); + + // Verify it's still in ACTIVE close to end of timeout + mInjector.mElapsedRealtime += mController.mInitialForegroundServiceStartTimeoutMillis - 100; + mController.checkIdleStates(USER_ID); + assertBucket(STANDBY_BUCKET_ACTIVE); + + // Verify bucket moves to RARE after timeout + mInjector.mElapsedRealtime += 200; + mController.checkIdleStates(USER_ID); + assertBucket(STANDBY_BUCKET_RARE); + + // Trigger a FOREGROUND_SERVICE_START again + reportEvent(mController, FOREGROUND_SERVICE_START, mInjector.mElapsedRealtime, PACKAGE_1); + mController.checkIdleStates(USER_ID); + // Bucket should not be immediately elevated on subsequent service starts + assertBucket(STANDBY_BUCKET_RARE); + } + + @Test public void testPredictionNotOverridden() throws Exception { reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); assertBucket(STANDBY_BUCKET_ACTIVE); diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java index 4b33e165bfeb..77866279a751 100644 --- a/services/usage/java/com/android/server/usage/AppStandbyController.java +++ b/services/usage/java/com/android/server/usage/AppStandbyController.java @@ -27,6 +27,7 @@ import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_ACTIVE_TIMEOU 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_FOREGROUND_SERVICE_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; import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_NOTIFICATION_SEEN; @@ -238,6 +239,11 @@ public class AppStandbyController { long mUnexemptedSyncScheduledTimeoutMillis; /** Maximum time a system interaction should keep the buckets elevated. */ long mSystemInteractionTimeoutMillis; + /** + * Maximum time a foreground service start should keep the buckets elevated if the service + * start is the first usage of the app + */ + long mInitialForegroundServiceStartTimeoutMillis; /** The length of time phone must be charging before considered stable enough to run jobs */ long mStableChargingThresholdMillis; @@ -877,7 +883,8 @@ public class AppStandbyController { || event.mEventType == UsageEvents.Event.USER_INTERACTION || event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN || event.mEventType == UsageEvents.Event.SLICE_PINNED - || event.mEventType == UsageEvents.Event.SLICE_PINNED_PRIV)) { + || event.mEventType == UsageEvents.Event.SLICE_PINNED_PRIV + || event.mEventType == UsageEvents.Event.FOREGROUND_SERVICE_START)) { final AppUsageHistory appHistory = mAppIdleHistory.getAppUsageHistory( event.mPackage, userId, elapsedRealtime); @@ -898,6 +905,13 @@ public class AppStandbyController { STANDBY_BUCKET_ACTIVE, subReason, 0, elapsedRealtime + mSystemInteractionTimeoutMillis); nextCheckTime = mSystemInteractionTimeoutMillis; + } else if (event.mEventType == UsageEvents.Event.FOREGROUND_SERVICE_START) { + // Only elevate bucket if this is the first usage of the app + if (prevBucket != STANDBY_BUCKET_NEVER) return; + mAppIdleHistory.reportUsage(appHistory, event.mPackage, + STANDBY_BUCKET_ACTIVE, subReason, + 0, elapsedRealtime + mInitialForegroundServiceStartTimeoutMillis); + nextCheckTime = mInitialForegroundServiceStartTimeoutMillis; } else { mAppIdleHistory.reportUsage(appHistory, event.mPackage, STANDBY_BUCKET_ACTIVE, subReason, @@ -930,6 +944,8 @@ public class AppStandbyController { case UsageEvents.Event.NOTIFICATION_SEEN: return REASON_SUB_USAGE_NOTIFICATION_SEEN; case UsageEvents.Event.SLICE_PINNED: return REASON_SUB_USAGE_SLICE_PINNED; case UsageEvents.Event.SLICE_PINNED_PRIV: return REASON_SUB_USAGE_SLICE_PINNED_PRIV; + case UsageEvents.Event.FOREGROUND_SERVICE_START: + return REASON_SUB_USAGE_FOREGROUND_SERVICE_START; default: return 0; } } @@ -1509,6 +1525,9 @@ public class AppStandbyController { pw.print(" mSystemInteractionTimeoutMillis="); TimeUtils.formatDuration(mSystemInteractionTimeoutMillis, pw); pw.println(); + pw.print(" mInitialForegroundServiceStartTimeoutMillis="); + TimeUtils.formatDuration(mInitialForegroundServiceStartTimeoutMillis, pw); + pw.println(); pw.print(" mPredictionTimeoutMillis="); TimeUtils.formatDuration(mPredictionTimeoutMillis, pw); @@ -1848,6 +1867,8 @@ public class AppStandbyController { "unexempted_sync_scheduled_duration"; private static final String KEY_SYSTEM_INTERACTION_HOLD_DURATION = "system_interaction_duration"; + private static final String KEY_INITIAL_FOREGROUND_SERVICE_START_HOLD_DURATION = + "initial_foreground_service_start_duration"; private static final String KEY_STABLE_CHARGING_THRESHOLD = "stable_charging_threshold"; public static final long DEFAULT_STRONG_USAGE_TIMEOUT = 1 * ONE_HOUR; public static final long DEFAULT_NOTIFICATION_TIMEOUT = 12 * ONE_HOUR; @@ -1859,6 +1880,7 @@ public class AppStandbyController { public static final long DEFAULT_EXEMPTED_SYNC_START_TIMEOUT = 10 * ONE_MINUTE; public static final long DEFAULT_UNEXEMPTED_SYNC_SCHEDULED_TIMEOUT = 10 * ONE_MINUTE; public static final long DEFAULT_STABLE_CHARGING_THRESHOLD = 10 * ONE_MINUTE; + public static final long DEFAULT_INITIAL_FOREGROUND_SERVICE_START_TIMEOUT = 30 * ONE_MINUTE; private final KeyValueListParser mParser = new KeyValueListParser(','); @@ -1964,6 +1986,12 @@ public class AppStandbyController { mSystemInteractionTimeoutMillis = mParser.getDurationMillis( KEY_SYSTEM_INTERACTION_HOLD_DURATION, COMPRESS_TIME ? ONE_MINUTE : DEFAULT_SYSTEM_INTERACTION_TIMEOUT); + + mInitialForegroundServiceStartTimeoutMillis = mParser.getDurationMillis( + KEY_INITIAL_FOREGROUND_SERVICE_START_HOLD_DURATION, + COMPRESS_TIME ? ONE_MINUTE : + DEFAULT_INITIAL_FOREGROUND_SERVICE_START_TIMEOUT); + mStableChargingThresholdMillis = mParser.getDurationMillis( KEY_STABLE_CHARGING_THRESHOLD, COMPRESS_TIME ? ONE_MINUTE : DEFAULT_STABLE_CHARGING_THRESHOLD); |