Merge "Allow standby timeouts to occur after usage"
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index dbaace2..29e7439 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -118,7 +118,15 @@
AppIdleStateChangeListener listener);
public static abstract class AppIdleStateChangeListener {
- public abstract void onAppIdleStateChanged(String packageName, int userId, boolean idle);
+
+ /** Callback to inform listeners that the idle state has changed to a new bucket. */
+ public abstract void onAppIdleStateChanged(String packageName, int userId, boolean idle,
+ int bucket);
+
+ /**
+ * Callback to inform listeners that the parole state has changed. This means apps are
+ * allowed to do work even if they're idle or in a low bucket.
+ */
public abstract void onParoleStateChanged(boolean isParoleOn);
}
diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java
index 39f2a96..caa8522 100644
--- a/services/core/java/com/android/server/job/controllers/AppIdleController.java
+++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java
@@ -174,7 +174,7 @@
private final class AppIdleStateChangeListener
extends UsageStatsManagerInternal.AppIdleStateChangeListener {
@Override
- public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
+ public void onAppIdleStateChanged(String packageName, int userId, boolean idle, int bucket) {
boolean changed = false;
synchronized (mLock) {
if (mAppIdleParoleOn) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 551cb10..3fa3cd4 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -3746,7 +3746,7 @@
extends UsageStatsManagerInternal.AppIdleStateChangeListener {
@Override
- public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
+ public void onAppIdleStateChanged(String packageName, int userId, boolean idle, int bucket) {
try {
final int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
index 67ffe58..39d256a 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
@@ -16,16 +16,14 @@
package com.android.server.usage;
-import static android.app.usage.AppStandby.REASON_TIMEOUT;
-import static android.app.usage.AppStandby.STANDBY_BUCKET_ACTIVE;
-import static android.app.usage.AppStandby.STANDBY_BUCKET_RARE;
-
import android.app.usage.AppStandby;
import android.os.FileUtils;
import android.test.AndroidTestCase;
import java.io.File;
+import static android.app.usage.AppStandby.*;
+
public class AppIdleHistoryTests extends AndroidTestCase {
File mStorageDir;
@@ -111,5 +109,9 @@
assertEquals(aih.getAppStandbyBucket(PACKAGE_1, USER_ID, 5000), STANDBY_BUCKET_RARE);
assertEquals(aih.getAppStandbyBucket(PACKAGE_2, USER_ID, 5000), STANDBY_BUCKET_ACTIVE);
assertEquals(aih.getAppStandbyReason(PACKAGE_1, USER_ID, 5000), REASON_TIMEOUT);
+
+ assertTrue(aih.shouldInformListeners(PACKAGE_1, USER_ID, 5000, STANDBY_BUCKET_RARE));
+ assertFalse(aih.shouldInformListeners(PACKAGE_1, USER_ID, 5000, STANDBY_BUCKET_RARE));
+ assertTrue(aih.shouldInformListeners(PACKAGE_1, USER_ID, 5000, STANDBY_BUCKET_FREQUENT));
}
}
\ No newline at end of file
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 9846d6f..8531baf5 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -16,11 +16,7 @@
package com.android.server.usage;
-import static android.app.usage.AppStandby.STANDBY_BUCKET_ACTIVE;
-import static android.app.usage.AppStandby.STANDBY_BUCKET_FREQUENT;
-import static android.app.usage.AppStandby.STANDBY_BUCKET_RARE;
-import static android.app.usage.AppStandby.STANDBY_BUCKET_WORKING_SET;
-
+import static android.app.usage.AppStandby.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -251,10 +247,22 @@
false));
}
+ private void reportEvent(AppStandbyController controller, long elapsedTime) {
+ // Back to ACTIVE on event
+ UsageEvents.Event ev = new UsageEvents.Event();
+ ev.mPackage = PACKAGE_1;
+ ev.mEventType = UsageEvents.Event.USER_INTERACTION;
+ controller.reportEvent(ev, elapsedTime, USER_ID);
+ }
+
@Test
public void testBuckets() throws Exception {
AppStandbyController controller = setupController();
+ assertTimeout(controller, 0, STANDBY_BUCKET_NEVER);
+
+ reportEvent(controller, 0);
+
// ACTIVE bucket
assertTimeout(controller, 11 * HOUR_MS, STANDBY_BUCKET_ACTIVE);
@@ -270,11 +278,7 @@
// RARE bucket
assertTimeout(controller, 9 * DAY_MS, STANDBY_BUCKET_RARE);
- // Back to ACTIVE on event
- UsageEvents.Event ev = new UsageEvents.Event();
- ev.mPackage = PACKAGE_1;
- ev.mEventType = UsageEvents.Event.USER_INTERACTION;
- controller.reportEvent(ev, mInjector.mElapsedRealtime, USER_ID);
+ reportEvent(controller, 9 * DAY_MS);
assertTimeout(controller, 9 * DAY_MS, STANDBY_BUCKET_ACTIVE);
@@ -287,6 +291,10 @@
AppStandbyController controller = setupController();
mInjector.setDisplayOn(false);
+ assertTimeout(controller, 0, STANDBY_BUCKET_NEVER);
+
+ reportEvent(controller, 0);
+
// ACTIVE bucket
assertTimeout(controller, 11 * HOUR_MS, STANDBY_BUCKET_ACTIVE);
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index e5d3915..c5ca330 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -103,7 +103,7 @@
long lastUsedScreenTime;
@StandbyBuckets int currentBucket;
String bucketingReason;
- int lastInformedState;
+ int lastInformedBucket;
}
AppIdleHistory(File storageDir, long elapsedRealtime) {
@@ -333,13 +333,12 @@
}
boolean shouldInformListeners(String packageName, int userId,
- long elapsedRealtime, boolean isIdle) {
+ long elapsedRealtime, int bucket) {
ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
elapsedRealtime, true);
- int targetState = isIdle? STATE_IDLE : STATE_ACTIVE;
- if (appUsageHistory.lastInformedState != (isIdle ? STATE_IDLE : STATE_ACTIVE)) {
- appUsageHistory.lastInformedState = targetState;
+ if (appUsageHistory.lastInformedBucket != bucket) {
+ appUsageHistory.lastInformedBucket = bucket;
return true;
}
return false;
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 17fde57..5623a68 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -160,7 +160,6 @@
private final Context mContext;
// TODO: Provide a mechanism to set an external bucketing service
- private boolean mUseInternalBucketingHeuristics = true;
private AppWidgetManager mAppWidgetManager;
private PowerManager mPowerManager;
@@ -367,29 +366,33 @@
Slog.d(TAG, " Checking idle state for " + packageName);
}
if (isSpecial) {
- maybeInformListeners(packageName, userId, elapsedRealtime, false);
- } else if (mUseInternalBucketingHeuristics) {
+ maybeInformListeners(packageName, userId, elapsedRealtime,
+ AppStandby.STANDBY_BUCKET_ACTIVE);
+ } else {
synchronized (mAppIdleLock) {
- int oldBucket = mAppIdleHistory.getAppStandbyBucket(packageName, userId,
- elapsedRealtime);
String bucketingReason = mAppIdleHistory.getAppStandbyReason(packageName,
userId, elapsedRealtime);
- if (bucketingReason != null
- && (bucketingReason.equals(AppStandby.REASON_FORCED)
- || bucketingReason.startsWith(AppStandby.REASON_PREDICTED))) {
+ // If the bucket was forced by the developer, leave it alone
+ if (AppStandby.REASON_FORCED.equals(bucketingReason)) {
continue;
}
- int newBucket = getBucketForLocked(packageName, userId,
- elapsedRealtime);
- if (DEBUG) {
- Slog.d(TAG, " Old bucket=" + oldBucket
- + ", newBucket=" + newBucket);
- }
- if (oldBucket != newBucket) {
- mAppIdleHistory.setAppStandbyBucket(packageName, userId,
- elapsedRealtime, newBucket, AppStandby.REASON_TIMEOUT);
- maybeInformListeners(packageName, userId, elapsedRealtime,
- newBucket >= AppStandby.STANDBY_BUCKET_RARE);
+ // If the bucket was moved up due to usage, let the timeouts apply.
+ if (AppStandby.REASON_USAGE.equals(bucketingReason)
+ || AppStandby.REASON_TIMEOUT.equals(bucketingReason)) {
+ int oldBucket = mAppIdleHistory.getAppStandbyBucket(packageName, userId,
+ elapsedRealtime);
+ int newBucket = getBucketForLocked(packageName, userId,
+ elapsedRealtime);
+ if (DEBUG) {
+ Slog.d(TAG, " Old bucket=" + oldBucket
+ + ", newBucket=" + newBucket);
+ }
+ if (oldBucket < newBucket) {
+ mAppIdleHistory.setAppStandbyBucket(packageName, userId,
+ elapsedRealtime, newBucket, AppStandby.REASON_TIMEOUT);
+ maybeInformListeners(packageName, userId, elapsedRealtime,
+ newBucket);
+ }
}
}
}
@@ -403,12 +406,12 @@
}
private void maybeInformListeners(String packageName, int userId,
- long elapsedRealtime, boolean isIdle) {
+ long elapsedRealtime, int bucket) {
synchronized (mAppIdleLock) {
if (mAppIdleHistory.shouldInformListeners(packageName, userId,
- elapsedRealtime, isIdle)) {
+ elapsedRealtime, bucket)) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
- userId, isIdle ? 1 : 0, packageName));
+ userId, bucket, packageName));
}
}
}
@@ -461,11 +464,13 @@
if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle);
boolean paroled = false;
synchronized (mAppIdleLock) {
- final long timeSinceLastParole = mInjector.currentTimeMillis() - mLastAppIdleParoledTime;
+ final long timeSinceLastParole =
+ mInjector.currentTimeMillis() - mLastAppIdleParoledTime;
if (!deviceIdle
&& timeSinceLastParole >= mAppIdleParoleIntervalMillis) {
if (DEBUG) {
- Slog.i(TAG, "Bringing idle apps out of inactive state due to deviceIdleMode=false");
+ Slog.i(TAG,
+ "Bringing idle apps out of inactive state due to deviceIdleMode=false");
}
paroled = true;
} else if (deviceIdle) {
@@ -491,7 +496,8 @@
|| event.mEventType == UsageEvents.Event.USER_INTERACTION)) {
mAppIdleHistory.reportUsage(event.mPackage, userId, elapsedRealtime);
if (previouslyIdle) {
- maybeInformListeners(event.mPackage, userId, elapsedRealtime, false);
+ maybeInformListeners(event.mPackage, userId, elapsedRealtime,
+ AppStandby.STANDBY_BUCKET_ACTIVE);
notifyBatteryStats(event.mPackage, userId, false);
}
}
@@ -729,7 +735,8 @@
void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
String reason, long elapsedRealtime) {
- mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket, reason);
+ mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket,
+ reason);
}
private boolean isActiveDeviceAdmin(String packageName, int userId) {
@@ -786,9 +793,10 @@
return packageName != null && packageName.equals(activeScorer);
}
- void informListeners(String packageName, int userId, boolean isIdle) {
+ void informListeners(String packageName, int userId, int bucket) {
+ final boolean idle = bucket >= AppStandby.STANDBY_BUCKET_RARE;
for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
- listener.onAppIdleStateChanged(packageName, userId, isIdle);
+ listener.onAppIdleStateChanged(packageName, userId, idle, bucket);
}
}
@@ -1037,7 +1045,7 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_INFORM_LISTENERS:
- informListeners((String) msg.obj, msg.arg1, msg.arg2 == 1);
+ informListeners((String) msg.obj, msg.arg1, msg.arg2);
break;
case MSG_FORCE_IDLE_STATE:
@@ -1187,7 +1195,8 @@
mAppStandbyScreenThresholds = parseLongArray(screenThresholdsValue,
SCREEN_TIME_THRESHOLDS);
- String elapsedThresholdsValue = mParser.getString(KEY_ELAPSED_TIME_THRESHOLDS, null);
+ String elapsedThresholdsValue = mParser.getString(KEY_ELAPSED_TIME_THRESHOLDS,
+ null);
mAppStandbyElapsedThresholds = parseLongArray(elapsedThresholdsValue,
ELAPSED_TIME_THRESHOLDS);
}