Link BatteryTrackerInfo to the metrics logging.

Add a new interface method for state trackers to implement
when AppRestrictionController asks for relevant tracker info
for logging.

This CL specifically links the info from AppBatteryTracker.

Bug: 217744262
Test: statsd_testdrive 441
Change-Id: Ie97653e804a00a240bcff80556b6e5532e4becf4
This commit is contained in:
Varun Shah
2022-04-19 13:23:00 -07:00
parent 3afb3e1922
commit dd74697750
3 changed files with 80 additions and 43 deletions

View File

@@ -269,10 +269,10 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
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<AppBatteryPolicy>
}
/**
* 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<AppBatteryPolicy>
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);

View File

@@ -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<Integer, Integer> levelTypePair = calcAppRestrictionLevel(
final Pair<Integer, TrackerInfo> 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<Integer, Integer> levelTypePair = calcAppRestrictionLevel(userId, uid, pkg,
curBucket, allowRequestBgRestricted, true);
final Pair<Integer, TrackerInfo> 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<Integer, Integer> calcAppRestrictionLevel(@UserIdInt int userId, int uid,
private Pair<Integer, TrackerInfo> 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<Integer, Integer> levelTypePair = calcAppRestrictionLevelFromTackers(
Pair<Integer, TrackerInfo> 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>}.
*
* <p>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. </p>
*/
private Pair<Integer, Integer> calcAppRestrictionLevelFromTackers(int uid, String packageName,
@RestrictionLevel int maxLevel) {
private Pair<Integer, TrackerInfo> 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<Integer, Integer> levelTypePair = calcAppRestrictionLevel(
final Pair<Integer, TrackerInfo> 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<Integer, Integer> levelTypePair = calcAppRestrictionLevel(
final Pair<Integer, TrackerInfo> levelTypePair = calcAppRestrictionLevel(
userId, uid, packageName, bucket, false, false);
applyRestrictionLevel(packageName, uid, levelTypePair.first, levelTypePair.second,
bucket, false, REASON_MAIN_DEFAULT, REASON_SUB_DEFAULT_UNDEFINED);

View File

@@ -168,6 +168,13 @@ public abstract class BaseAppStateTracker<T extends BaseAppStatePolicy> {
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.
*/