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
diff --git a/services/core/java/com/android/server/am/AppBatteryTracker.java b/services/core/java/com/android/server/am/AppBatteryTracker.java
index 8c42d4d..6fa13eb 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 @@
                         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 @@
     }
 
     /**
-     * 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 @@
                 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 d70404f..519f7dd 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 @@
     })
     @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 @@
                 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 @@
         }
     }
 
+    /**
+     * 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 @@
                 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 @@
         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 @@
         }
     }
 
-    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 @@
             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 @@
                         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 @@
             }
             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 @@
     }
 
     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 @@
                     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 @@
             // 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 @@
                     ? 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 @@
             @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);
diff --git a/services/core/java/com/android/server/am/BaseAppStateTracker.java b/services/core/java/com/android/server/am/BaseAppStateTracker.java
index 5afceca..8d60910 100644
--- a/services/core/java/com/android/server/am/BaseAppStateTracker.java
+++ b/services/core/java/com/android/server/am/BaseAppStateTracker.java
@@ -169,6 +169,13 @@
     }
 
     /**
+     * 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.
      */
     T getPolicy() {