diff --git a/services/core/java/com/android/server/am/AppBatteryTracker.java b/services/core/java/com/android/server/am/AppBatteryTracker.java index 8c42d4d1bd5ac..6fa13eb0058b1 100644 --- a/services/core/java/com/android/server/am/AppBatteryTracker.java +++ b/services/core/java/com/android/server/am/AppBatteryTracker.java @@ -269,10 +269,10 @@ final class AppBatteryTracker extends BaseAppStateTracker AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN, // RestrictionLevel AppBackgroundRestrictionsInfo.THRESHOLD_UNKNOWN, AppBackgroundRestrictionsInfo.UNKNOWN_TRACKER, - null /*byte[] fgs_tracker_info*/, - getBatteryTrackerInfoProtoLocked(uid) /*byte[] battery_tracker_info*/, - null /*byte[] broadcast_events_tracker_info*/, - null /*byte[] bind_service_events_tracker_info*/, + null, // FgsTrackerInfo + getTrackerInfoForStatsd(uid), + null, // BroadcastEventsTrackerInfo + null, // BindServiceEventsTrackerInfo AppBackgroundRestrictionsInfo.REASON_UNKNOWN, // ExemptionReason AppBackgroundRestrictionsInfo.UNKNOWN, // OptimizationLevel AppBackgroundRestrictionsInfo.SDK_UNKNOWN, // TargetSdk @@ -282,14 +282,14 @@ final class AppBatteryTracker extends BaseAppStateTracker } /** - * Get the BatteryTrackerInfo proto of a UID. - * @param uid - * @return byte array of the proto. + * Get the BatteryTrackerInfo object of the given uid. + * @return byte array of the proto object. */ - @NonNull byte[] getBatteryTrackerInfoProtoLocked(int uid) { + @Override + byte[] getTrackerInfoForStatsd(int uid) { final ImmutableBatteryUsage temp = mUidBatteryUsageInWindow.get(uid); if (temp == null) { - return new byte[0]; + return null; } final BatteryUsage bgUsage = temp.calcPercentage(uid, mInjector.getPolicy()); final double allUsage = bgUsage.mPercentage[BatteryUsage.BATTERY_USAGE_INDEX_UNSPECIFIED] @@ -301,10 +301,12 @@ final class AppBatteryTracker extends BaseAppStateTracker bgUsage.mPercentage[BatteryUsage.BATTERY_USAGE_INDEX_BACKGROUND]; final double usageFgs = bgUsage.mPercentage[BatteryUsage.BATTERY_USAGE_INDEX_FOREGROUND_SERVICE]; - Slog.d(TAG, "getBatteryTrackerInfoProtoLocked uid:" + uid - + " allUsage:" + String.format("%4.2f%%", allUsage) - + " usageBackground:" + String.format("%4.2f%%", usageBackground) - + " usageFgs:" + String.format("%4.2f%%", usageFgs)); + if (DEBUG_BACKGROUND_BATTERY_TRACKER_VERBOSE) { + Slog.d(TAG, "getBatteryTrackerInfoProtoLocked uid:" + uid + + " allUsage:" + String.format("%4.2f%%", allUsage) + + " usageBackground:" + String.format("%4.2f%%", usageBackground) + + " usageFgs:" + String.format("%4.2f%%", usageFgs)); + } final ProtoOutputStream proto = new ProtoOutputStream(); proto.write(AppBackgroundRestrictionsInfo.BatteryTrackerInfo.BATTERY_24H, allUsage * 10000); diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java index d70404fb6a65d..519f7dd0d2534 100644 --- a/services/core/java/com/android/server/am/AppRestrictionController.java +++ b/services/core/java/com/android/server/am/AppRestrictionController.java @@ -328,6 +328,8 @@ public final class AppRestrictionController { }) @interface TrackerType {} + private final TrackerInfo mEmptyTrackerInfo = new TrackerInfo(); + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -914,7 +916,7 @@ public final class AppRestrictionController { final int curBucket = mInjector.getAppStandbyInternal().getAppStandbyBucket( packageName, UserHandle.getUserId(uid), now, false); if (applyLevel) { - applyRestrictionLevel(packageName, uid, curLevel, TRACKER_TYPE_UNKNOWN, + applyRestrictionLevel(packageName, uid, curLevel, mEmptyTrackerInfo, curBucket, true, reason & REASON_MAIN_MASK, reason & REASON_SUB_MASK); } else { pkgSettings.update(curLevel, @@ -1331,6 +1333,25 @@ public final class AppRestrictionController { } } + /** + * A helper object which holds an app state tracker's type and its relevant info used for + * logging atoms to statsd. + */ + private class TrackerInfo { + final int mType; // tracker type + final byte[] mInfo; // tracker info proto object for statsd + + TrackerInfo() { + mType = TRACKER_TYPE_UNKNOWN; + mInfo = null; + } + + TrackerInfo(int type, byte[] info) { + mType = type; + mInfo = info; + } + } + private final ConstantsObserver mConstantsObserver; private final AppStateTracker.BackgroundRestrictedAppListener mBackgroundRestrictionListener = @@ -1578,7 +1599,7 @@ public final class AppRestrictionController { Slog.e(TAG, "Unable to find " + info.mPackageName + "/u" + userId); continue; } - final Pair levelTypePair = calcAppRestrictionLevel( + final Pair levelTypePair = calcAppRestrictionLevel( userId, uid, info.mPackageName, info.mStandbyBucket, false, false); if (DEBUG_BG_RESTRICTION_CONTROLLER) { Slog.i(TAG, "Proposed restriction level of " + info.mPackageName + "/" @@ -1602,8 +1623,8 @@ public final class AppRestrictionController { final long now = SystemClock.elapsedRealtime(); for (String pkg: packages) { final int curBucket = appStandbyInternal.getAppStandbyBucket(pkg, userId, now, false); - final Pair levelTypePair = calcAppRestrictionLevel(userId, uid, pkg, - curBucket, allowRequestBgRestricted, true); + final Pair levelTypePair = calcAppRestrictionLevel(userId, uid, + pkg, curBucket, allowRequestBgRestricted, true); if (DEBUG_BG_RESTRICTION_CONTROLLER) { Slog.i(TAG, "Proposed restriction level of " + pkg + "/" + UserHandle.formatUid(uid) + ": " @@ -1614,14 +1635,14 @@ public final class AppRestrictionController { } } - private Pair calcAppRestrictionLevel(@UserIdInt int userId, int uid, + private Pair calcAppRestrictionLevel(@UserIdInt int userId, int uid, String packageName, @UsageStatsManager.StandbyBuckets int standbyBucket, boolean allowRequestBgRestricted, boolean calcTrackers) { if (mInjector.getAppHibernationInternal().isHibernatingForUser(packageName, userId)) { - return new Pair<>(RESTRICTION_LEVEL_HIBERNATION, TRACKER_TYPE_UNKNOWN); + return new Pair<>(RESTRICTION_LEVEL_HIBERNATION, mEmptyTrackerInfo); } @RestrictionLevel int level; - @TrackerType int trackerType = TRACKER_TYPE_UNKNOWN; + TrackerInfo trackerInfo = null; switch (standbyBucket) { case STANDBY_BUCKET_EXEMPTED: level = RESTRICTION_LEVEL_EXEMPTED; @@ -1637,22 +1658,22 @@ public final class AppRestrictionController { default: if (mInjector.getAppStateTracker() .isAppBackgroundRestricted(uid, packageName)) { - return new Pair<>(RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, trackerType); + return new Pair<>(RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, mEmptyTrackerInfo); } level = mConstantsObserver.mRestrictedBucketEnabled && standbyBucket == STANDBY_BUCKET_RESTRICTED ? RESTRICTION_LEVEL_RESTRICTED_BUCKET : RESTRICTION_LEVEL_ADAPTIVE_BUCKET; if (calcTrackers) { - Pair levelTypePair = calcAppRestrictionLevelFromTackers( + Pair levelTypePair = calcAppRestrictionLevelFromTackers( uid, packageName, RESTRICTION_LEVEL_MAX); @RestrictionLevel int l = levelTypePair.first; if (l == RESTRICTION_LEVEL_EXEMPTED) { return new Pair<>(RESTRICTION_LEVEL_EXEMPTED, levelTypePair.second); } - level = Math.max(l, level); - if (l == level) { - trackerType = levelTypePair.second; + if (l > level) { + level = l; + trackerInfo = levelTypePair.second; } if (level == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) { // This level can't be entered without user consent @@ -1664,29 +1685,29 @@ public final class AppRestrictionController { levelTypePair = calcAppRestrictionLevelFromTackers(uid, packageName, RESTRICTION_LEVEL_BACKGROUND_RESTRICTED); level = levelTypePair.first; - trackerType = levelTypePair.second; + trackerInfo = levelTypePair.second; } } break; } - return new Pair<>(level, trackerType); + return new Pair<>(level, trackerInfo); } /** * Ask each of the trackers for their proposed restriction levels for the given uid/package, - * and return the most restrictive level along with the type of tracker which applied this - * restriction level as a {@code Pair<@RestrictionLevel, @TrackerType>}. + * and return the most restrictive level along with the type of tracker and its relevant info + * which applied this restriction level as a {@code Pair<@RestrictionLevel, TrackerInfo>}. * *

Note, it's different from the {@link #getRestrictionLevel} where it returns the least * restrictive level. We're returning the most restrictive level here because each tracker * monitors certain dimensions of the app, the abusive behaviors could be detected in one or * more of these dimensions, but not necessarily all of them.

*/ - private Pair calcAppRestrictionLevelFromTackers(int uid, String packageName, - @RestrictionLevel int maxLevel) { + private Pair calcAppRestrictionLevelFromTackers(int uid, + String packageName, @RestrictionLevel int maxLevel) { @RestrictionLevel int level = RESTRICTION_LEVEL_UNKNOWN; @RestrictionLevel int prevLevel = level; - @TrackerType int trackerType = TRACKER_TYPE_UNKNOWN; + BaseAppStateTracker resultTracker = null; final boolean isRestrictedBucketEnabled = mConstantsObserver.mRestrictedBucketEnabled; for (int i = mAppStateTrackers.size() - 1; i >= 0; i--) { @RestrictionLevel int l = mAppStateTrackers.get(i).getPolicy() @@ -1696,11 +1717,15 @@ public final class AppRestrictionController { } level = Math.max(level, l); if (level != prevLevel) { - trackerType = mAppStateTrackers.get(i).getType(); + resultTracker = mAppStateTrackers.get(i); prevLevel = level; } } - return new Pair<>(level, trackerType); + final TrackerInfo trackerInfo = resultTracker == null + ? mEmptyTrackerInfo + : new TrackerInfo(resultTracker.getType(), + resultTracker.getTrackerInfoForStatsd(uid)); + return new Pair<>(level, trackerInfo); } private static @RestrictionLevel int standbyBucketToRestrictionLevel( @@ -2017,7 +2042,7 @@ public final class AppRestrictionController { } private void applyRestrictionLevel(String pkgName, int uid, - @RestrictionLevel int level, @TrackerType int trackerType, + @RestrictionLevel int level, TrackerInfo trackerInfo, int curBucket, boolean allowUpdateBucket, int reason, int subReason) { int curLevel; int prevReason; @@ -2098,14 +2123,17 @@ public final class AppRestrictionController { reason, subReason); } + if (trackerInfo == null) { + trackerInfo = mEmptyTrackerInfo; + } FrameworkStatsLog.write(FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO, uid, getRestrictionLevelStatsd(level), getThresholdStatsd(reason), - getTrackerTypeStatsd(trackerType), - null, // FgsTrackerInfo - null, // BatteryTrackerInfo - null, // BroadcastEventsTrackerInfo - null, // BindServiceEventsTrackerInfo + getTrackerTypeStatsd(trackerInfo.mType), + trackerInfo.mType == TRACKER_TYPE_FGS ? trackerInfo.mInfo : null, + trackerInfo.mType == TRACKER_TYPE_BATTERY ? trackerInfo.mInfo : null, + trackerInfo.mType == TRACKER_TYPE_BROADCAST_EVENTS ? trackerInfo.mInfo : null, + trackerInfo.mType == TRACKER_TYPE_BIND_SERVICE_EVENTS ? trackerInfo.mInfo : null, getExemptionReasonStatsd(uid, level), getOptimizationLevelStatsd(level), getTargetSdkStatsd(pkgName), @@ -2127,7 +2155,7 @@ public final class AppRestrictionController { // The app could fall into the background restricted with user consent only, // so set the reason to it. applyRestrictionLevel(pkgName, uid, RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, - TRACKER_TYPE_UNKNOWN, curBucket, true, REASON_MAIN_FORCED_BY_USER, + mEmptyTrackerInfo, curBucket, true, REASON_MAIN_FORCED_BY_USER, REASON_SUB_FORCED_USER_FLAG_INTERACTION); mBgHandler.obtainMessage(BgHandler.MSG_CANCEL_REQUEST_BG_RESTRICTED, uid, 0, pkgName) .sendToTarget(); @@ -2140,7 +2168,7 @@ public final class AppRestrictionController { ? STANDBY_BUCKET_EXEMPTED : (lastLevel == RESTRICTION_LEVEL_RESTRICTED_BUCKET ? STANDBY_BUCKET_RESTRICTED : STANDBY_BUCKET_RARE); - final Pair levelTypePair = calcAppRestrictionLevel( + final Pair levelTypePair = calcAppRestrictionLevel( UserHandle.getUserId(uid), uid, pkgName, tentativeBucket, false, true); applyRestrictionLevel(pkgName, uid, levelTypePair.first, levelTypePair.second, @@ -2184,7 +2212,7 @@ public final class AppRestrictionController { @UserIdInt int userId) { final int uid = mInjector.getPackageManagerInternal().getPackageUid( packageName, STOCK_PM_FLAGS, userId); - final Pair levelTypePair = calcAppRestrictionLevel( + final Pair levelTypePair = calcAppRestrictionLevel( userId, uid, packageName, bucket, false, false); applyRestrictionLevel(packageName, uid, levelTypePair.first, levelTypePair.second, bucket, false, REASON_MAIN_DEFAULT, REASON_SUB_DEFAULT_UNDEFINED); diff --git a/services/core/java/com/android/server/am/BaseAppStateTracker.java b/services/core/java/com/android/server/am/BaseAppStateTracker.java index 5afcecaa069eb..8d609104656da 100644 --- a/services/core/java/com/android/server/am/BaseAppStateTracker.java +++ b/services/core/java/com/android/server/am/BaseAppStateTracker.java @@ -168,6 +168,13 @@ public abstract class BaseAppStateTracker { return AppRestrictionController.TRACKER_TYPE_UNKNOWN; } + /** + * Return the relevant info object for the tracker for the given uid, used for statsd. + */ + byte[] getTrackerInfoForStatsd(int uid) { + return null; + } + /** * Return the policy holder of this tracker. */