Loading apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java +34 −20 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_USER; import static android.app.usage.UsageStatsManager.REASON_MAIN_MASK; import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED; import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE; import static android.app.usage.UsageStatsManager.REASON_SUB_MASK; import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACTION; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER; Loading @@ -43,6 +44,7 @@ import android.util.Xml; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.CollectionUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.IndentingPrintWriter; import libcore.io.IoUtils; Loading Loading @@ -244,9 +246,9 @@ public class AppIdleHistory { * @param elapsedRealtime mark as used time if non-zero * @param timeout set the timeout of the specified bucket, if non-zero. Can only be used * with bucket values of ACTIVE and WORKING_SET. * @return * @return {@code appUsageHistory} */ public AppUsageHistory reportUsage(AppUsageHistory appUsageHistory, String packageName, AppUsageHistory reportUsage(AppUsageHistory appUsageHistory, String packageName, int userId, int newBucket, int usageReason, long elapsedRealtime, long timeout) { int bucketingReason = REASON_MAIN_USAGE | usageReason; final boolean isUserUsage = isUserUsage(bucketingReason); Loading Loading @@ -284,11 +286,7 @@ public class AppIdleHistory { if (appUsageHistory.currentBucket > newBucket) { appUsageHistory.currentBucket = newBucket; if (DEBUG) { Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory .currentBucket + ", reason=0x0" + Integer.toHexString(appUsageHistory.bucketingReason)); } logAppStandbyBucketChanged(packageName, userId, newBucket, bucketingReason); } appUsageHistory.bucketingReason = bucketingReason; Loading @@ -313,7 +311,8 @@ public class AppIdleHistory { int usageReason, long nowElapsed, long timeout) { ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId); AppUsageHistory history = getPackageHistory(userHistory, packageName, nowElapsed, true); return reportUsage(history, packageName, newBucket, usageReason, nowElapsed, timeout); return reportUsage(history, packageName, userId, newBucket, usageReason, nowElapsed, timeout); } private ArrayMap<String, AppUsageHistory> getUserHistory(int userId) { Loading Loading @@ -372,6 +371,7 @@ public class AppIdleHistory { ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId); AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName, elapsedRealtime, true); final boolean changed = appUsageHistory.currentBucket != bucket; appUsageHistory.currentBucket = bucket; appUsageHistory.bucketingReason = reason; Loading @@ -385,9 +385,8 @@ public class AppIdleHistory { appUsageHistory.bucketActiveTimeoutTime = elapsed; appUsageHistory.bucketWorkingSetTimeoutTime = elapsed; } if (DEBUG) { Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket + ", reason=0x0" + Integer.toHexString(appUsageHistory.bucketingReason)); if (changed) { logAppStandbyBucketChanged(packageName, userId, bucket, reason); } } Loading Loading @@ -485,18 +484,19 @@ public class AppIdleHistory { /* Returns the new standby bucket the app is assigned to */ public int setIdle(String packageName, int userId, boolean idle, long elapsedRealtime) { ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId); AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName, elapsedRealtime, true); final int newBucket; final int reason; if (idle) { appUsageHistory.currentBucket = STANDBY_BUCKET_RARE; appUsageHistory.bucketingReason = REASON_MAIN_FORCED_BY_USER; newBucket = STANDBY_BUCKET_RARE; reason = REASON_MAIN_FORCED_BY_USER; } else { appUsageHistory.currentBucket = STANDBY_BUCKET_ACTIVE; newBucket = STANDBY_BUCKET_ACTIVE; // This is to pretend that the app was just used, don't freeze the state anymore. appUsageHistory.bucketingReason = REASON_MAIN_USAGE | REASON_SUB_USAGE_USER_INTERACTION; reason = REASON_MAIN_USAGE | REASON_SUB_USAGE_USER_INTERACTION; } return appUsageHistory.currentBucket; setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket, reason, false); return newBucket; } public void clearUsage(String packageName, int userId) { Loading Loading @@ -551,13 +551,27 @@ public class AppIdleHistory { return 0; } /** * Log a standby bucket change to statsd, and also logcat if debug logging is enabled. */ private void logAppStandbyBucketChanged(String packageName, int userId, int bucket, int reason) { FrameworkStatsLog.write( FrameworkStatsLog.APP_STANDBY_BUCKET_CHANGED, packageName, userId, bucket, (reason & REASON_MAIN_MASK), (reason & REASON_SUB_MASK)); if (DEBUG) { Slog.d(TAG, "Moved " + packageName + " to bucket=" + bucket + ", reason=0x0" + Integer.toHexString(reason)); } } @VisibleForTesting File getUserFile(int userId) { return new File(new File(new File(mStorageDir, "users"), Integer.toString(userId)), APP_IDLE_FILENAME); } /** * Check if App Idle File exists on disk * @param userId Loading apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +4 −4 Original line number Diff line number Diff line Loading @@ -831,24 +831,24 @@ public class AppStandbyController implements AppStandbyInternal { if (eventType == UsageEvents.Event.NOTIFICATION_SEEN || eventType == UsageEvents.Event.SLICE_PINNED) { // Mild usage elevates to WORKING_SET but doesn't change usage time. mAppIdleHistory.reportUsage(appHistory, pkg, mAppIdleHistory.reportUsage(appHistory, pkg, userId, STANDBY_BUCKET_WORKING_SET, subReason, 0, elapsedRealtime + mNotificationSeenTimeoutMillis); nextCheckDelay = mNotificationSeenTimeoutMillis; } else if (eventType == UsageEvents.Event.SYSTEM_INTERACTION) { mAppIdleHistory.reportUsage(appHistory, pkg, mAppIdleHistory.reportUsage(appHistory, pkg, userId, STANDBY_BUCKET_ACTIVE, subReason, 0, elapsedRealtime + mSystemInteractionTimeoutMillis); nextCheckDelay = mSystemInteractionTimeoutMillis; } else if (eventType == 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, pkg, mAppIdleHistory.reportUsage(appHistory, pkg, userId, STANDBY_BUCKET_ACTIVE, subReason, 0, elapsedRealtime + mInitialForegroundServiceStartTimeoutMillis); nextCheckDelay = mInitialForegroundServiceStartTimeoutMillis; } else { mAppIdleHistory.reportUsage(appHistory, pkg, mAppIdleHistory.reportUsage(appHistory, pkg, userId, STANDBY_BUCKET_ACTIVE, subReason, elapsedRealtime, elapsedRealtime + mStrongUsageTimeoutMillis); nextCheckDelay = mStrongUsageTimeoutMillis; Loading cmds/statsd/src/atoms.proto +44 −11 Original line number Diff line number Diff line Loading @@ -396,6 +396,7 @@ message Atom { ForegroundServiceAppOpSessionEnded foreground_service_app_op_session_ended = 256 [(module) = "framework"]; DisplayJankReported display_jank_reported = 257; AppStandbyBucketChanged app_standby_bucket_changed = 258 [(module) = "framework"]; SdkExtensionStatus sdk_extension_status = 354; } Loading Loading @@ -1227,18 +1228,8 @@ message WakeupAlarmOccurred { // Name of source package (for historical reasons, since BatteryStats tracked it). optional string package_name = 3; // These enum values match the STANDBY_BUCKET_XXX constants defined in UsageStatsManager.java. enum Bucket { UNKNOWN = 0; EXEMPTED = 5; ACTIVE = 10; WORKING_SET = 20; FREQUENT = 30; RARE = 40; NEVER = 50; } // The App Standby bucket of the app that scheduled the alarm at the time the alarm fired. optional Bucket app_standby_bucket = 4; optional AppStandbyBucketChanged.Bucket app_standby_bucket = 4; } /** Loading Loading @@ -8724,3 +8715,45 @@ message GnssStats { // Total number of L5 sv status messages reports, where sv is used in fix since boot optional int64 l5_sv_status_reports_used_in_fix = 14; } /** * Logs when an app is moved to a different standby bucket. * * Logged from: * frameworks/base/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java */ message AppStandbyBucketChanged { optional string package_name = 1; // Should be 0, 10, 11, 12, etc. where 0 is the owner. See UserHandle for more documentation. optional int32 user_id = 2; // These enum values match the constants defined in UsageStatsManager.java. enum Bucket { BUCKET_UNKNOWN = 0; BUCKET_EXEMPTED = 5; BUCKET_ACTIVE = 10; BUCKET_WORKING_SET = 20; BUCKET_FREQUENT = 30; BUCKET_RARE = 40; BUCKET_RESTRICTED = 45; BUCKET_NEVER = 50; } optional Bucket bucket = 3; enum MainReason { MAIN_UNKNOWN = 0; MAIN_DEFAULT = 0x0100; MAIN_TIMEOUT = 0x0200; MAIN_USAGE = 0x0300; MAIN_FORCED_BY_USER = 0x0400; MAIN_PREDICTED = 0x0500; MAIN_FORCED_BY_SYSTEM = 0x0600; } optional MainReason main_reason = 4; // A more detailed reason for the standby bucket change. The sub reason name is dependent on // the main reason. Values are one of the REASON_SUB_XXX constants defined in // UsageStatsManager.java. optional int32 sub_reason = 5; } Loading
apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java +34 −20 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_USER; import static android.app.usage.UsageStatsManager.REASON_MAIN_MASK; import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED; import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE; import static android.app.usage.UsageStatsManager.REASON_SUB_MASK; import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACTION; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER; Loading @@ -43,6 +44,7 @@ import android.util.Xml; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.CollectionUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.IndentingPrintWriter; import libcore.io.IoUtils; Loading Loading @@ -244,9 +246,9 @@ public class AppIdleHistory { * @param elapsedRealtime mark as used time if non-zero * @param timeout set the timeout of the specified bucket, if non-zero. Can only be used * with bucket values of ACTIVE and WORKING_SET. * @return * @return {@code appUsageHistory} */ public AppUsageHistory reportUsage(AppUsageHistory appUsageHistory, String packageName, AppUsageHistory reportUsage(AppUsageHistory appUsageHistory, String packageName, int userId, int newBucket, int usageReason, long elapsedRealtime, long timeout) { int bucketingReason = REASON_MAIN_USAGE | usageReason; final boolean isUserUsage = isUserUsage(bucketingReason); Loading Loading @@ -284,11 +286,7 @@ public class AppIdleHistory { if (appUsageHistory.currentBucket > newBucket) { appUsageHistory.currentBucket = newBucket; if (DEBUG) { Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory .currentBucket + ", reason=0x0" + Integer.toHexString(appUsageHistory.bucketingReason)); } logAppStandbyBucketChanged(packageName, userId, newBucket, bucketingReason); } appUsageHistory.bucketingReason = bucketingReason; Loading @@ -313,7 +311,8 @@ public class AppIdleHistory { int usageReason, long nowElapsed, long timeout) { ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId); AppUsageHistory history = getPackageHistory(userHistory, packageName, nowElapsed, true); return reportUsage(history, packageName, newBucket, usageReason, nowElapsed, timeout); return reportUsage(history, packageName, userId, newBucket, usageReason, nowElapsed, timeout); } private ArrayMap<String, AppUsageHistory> getUserHistory(int userId) { Loading Loading @@ -372,6 +371,7 @@ public class AppIdleHistory { ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId); AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName, elapsedRealtime, true); final boolean changed = appUsageHistory.currentBucket != bucket; appUsageHistory.currentBucket = bucket; appUsageHistory.bucketingReason = reason; Loading @@ -385,9 +385,8 @@ public class AppIdleHistory { appUsageHistory.bucketActiveTimeoutTime = elapsed; appUsageHistory.bucketWorkingSetTimeoutTime = elapsed; } if (DEBUG) { Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket + ", reason=0x0" + Integer.toHexString(appUsageHistory.bucketingReason)); if (changed) { logAppStandbyBucketChanged(packageName, userId, bucket, reason); } } Loading Loading @@ -485,18 +484,19 @@ public class AppIdleHistory { /* Returns the new standby bucket the app is assigned to */ public int setIdle(String packageName, int userId, boolean idle, long elapsedRealtime) { ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId); AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName, elapsedRealtime, true); final int newBucket; final int reason; if (idle) { appUsageHistory.currentBucket = STANDBY_BUCKET_RARE; appUsageHistory.bucketingReason = REASON_MAIN_FORCED_BY_USER; newBucket = STANDBY_BUCKET_RARE; reason = REASON_MAIN_FORCED_BY_USER; } else { appUsageHistory.currentBucket = STANDBY_BUCKET_ACTIVE; newBucket = STANDBY_BUCKET_ACTIVE; // This is to pretend that the app was just used, don't freeze the state anymore. appUsageHistory.bucketingReason = REASON_MAIN_USAGE | REASON_SUB_USAGE_USER_INTERACTION; reason = REASON_MAIN_USAGE | REASON_SUB_USAGE_USER_INTERACTION; } return appUsageHistory.currentBucket; setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket, reason, false); return newBucket; } public void clearUsage(String packageName, int userId) { Loading Loading @@ -551,13 +551,27 @@ public class AppIdleHistory { return 0; } /** * Log a standby bucket change to statsd, and also logcat if debug logging is enabled. */ private void logAppStandbyBucketChanged(String packageName, int userId, int bucket, int reason) { FrameworkStatsLog.write( FrameworkStatsLog.APP_STANDBY_BUCKET_CHANGED, packageName, userId, bucket, (reason & REASON_MAIN_MASK), (reason & REASON_SUB_MASK)); if (DEBUG) { Slog.d(TAG, "Moved " + packageName + " to bucket=" + bucket + ", reason=0x0" + Integer.toHexString(reason)); } } @VisibleForTesting File getUserFile(int userId) { return new File(new File(new File(mStorageDir, "users"), Integer.toString(userId)), APP_IDLE_FILENAME); } /** * Check if App Idle File exists on disk * @param userId Loading
apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +4 −4 Original line number Diff line number Diff line Loading @@ -831,24 +831,24 @@ public class AppStandbyController implements AppStandbyInternal { if (eventType == UsageEvents.Event.NOTIFICATION_SEEN || eventType == UsageEvents.Event.SLICE_PINNED) { // Mild usage elevates to WORKING_SET but doesn't change usage time. mAppIdleHistory.reportUsage(appHistory, pkg, mAppIdleHistory.reportUsage(appHistory, pkg, userId, STANDBY_BUCKET_WORKING_SET, subReason, 0, elapsedRealtime + mNotificationSeenTimeoutMillis); nextCheckDelay = mNotificationSeenTimeoutMillis; } else if (eventType == UsageEvents.Event.SYSTEM_INTERACTION) { mAppIdleHistory.reportUsage(appHistory, pkg, mAppIdleHistory.reportUsage(appHistory, pkg, userId, STANDBY_BUCKET_ACTIVE, subReason, 0, elapsedRealtime + mSystemInteractionTimeoutMillis); nextCheckDelay = mSystemInteractionTimeoutMillis; } else if (eventType == 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, pkg, mAppIdleHistory.reportUsage(appHistory, pkg, userId, STANDBY_BUCKET_ACTIVE, subReason, 0, elapsedRealtime + mInitialForegroundServiceStartTimeoutMillis); nextCheckDelay = mInitialForegroundServiceStartTimeoutMillis; } else { mAppIdleHistory.reportUsage(appHistory, pkg, mAppIdleHistory.reportUsage(appHistory, pkg, userId, STANDBY_BUCKET_ACTIVE, subReason, elapsedRealtime, elapsedRealtime + mStrongUsageTimeoutMillis); nextCheckDelay = mStrongUsageTimeoutMillis; Loading
cmds/statsd/src/atoms.proto +44 −11 Original line number Diff line number Diff line Loading @@ -396,6 +396,7 @@ message Atom { ForegroundServiceAppOpSessionEnded foreground_service_app_op_session_ended = 256 [(module) = "framework"]; DisplayJankReported display_jank_reported = 257; AppStandbyBucketChanged app_standby_bucket_changed = 258 [(module) = "framework"]; SdkExtensionStatus sdk_extension_status = 354; } Loading Loading @@ -1227,18 +1228,8 @@ message WakeupAlarmOccurred { // Name of source package (for historical reasons, since BatteryStats tracked it). optional string package_name = 3; // These enum values match the STANDBY_BUCKET_XXX constants defined in UsageStatsManager.java. enum Bucket { UNKNOWN = 0; EXEMPTED = 5; ACTIVE = 10; WORKING_SET = 20; FREQUENT = 30; RARE = 40; NEVER = 50; } // The App Standby bucket of the app that scheduled the alarm at the time the alarm fired. optional Bucket app_standby_bucket = 4; optional AppStandbyBucketChanged.Bucket app_standby_bucket = 4; } /** Loading Loading @@ -8724,3 +8715,45 @@ message GnssStats { // Total number of L5 sv status messages reports, where sv is used in fix since boot optional int64 l5_sv_status_reports_used_in_fix = 14; } /** * Logs when an app is moved to a different standby bucket. * * Logged from: * frameworks/base/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java */ message AppStandbyBucketChanged { optional string package_name = 1; // Should be 0, 10, 11, 12, etc. where 0 is the owner. See UserHandle for more documentation. optional int32 user_id = 2; // These enum values match the constants defined in UsageStatsManager.java. enum Bucket { BUCKET_UNKNOWN = 0; BUCKET_EXEMPTED = 5; BUCKET_ACTIVE = 10; BUCKET_WORKING_SET = 20; BUCKET_FREQUENT = 30; BUCKET_RARE = 40; BUCKET_RESTRICTED = 45; BUCKET_NEVER = 50; } optional Bucket bucket = 3; enum MainReason { MAIN_UNKNOWN = 0; MAIN_DEFAULT = 0x0100; MAIN_TIMEOUT = 0x0200; MAIN_USAGE = 0x0300; MAIN_FORCED_BY_USER = 0x0400; MAIN_PREDICTED = 0x0500; MAIN_FORCED_BY_SYSTEM = 0x0600; } optional MainReason main_reason = 4; // A more detailed reason for the standby bucket change. The sub reason name is dependent on // the main reason. Values are one of the REASON_SUB_XXX constants defined in // UsageStatsManager.java. optional int32 sub_reason = 5; }