Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ea31633 authored by Ruchir Rastogi's avatar Ruchir Rastogi
Browse files

Migrate DeviceCalculcatedPower pullers to new API

As part of migrating the pullers to the new API, we modify
permission checks within BatteryStatsService. Previously, a Binder
thread within StatsCompanionService (with statsd's calling identity)
called BatteryStatsService functions, which was why statsd was assigned
the BATTERY_STATS permission. Now, that call is being made from the
system process Background thread. Because enforceCallingPermission
outside of Binder threads, we switched to enforceCallingOrSelfPermission.

Test: m -j
Test: adb shell cmd stats pull-source 10039
Test: adb shell cmd stats pull-source 10040
Test: adb shell cmd stats pull-source 10041
Test: atest CtsStatsdHostTestCases:UidAtomTests#testDeviceCalculatedPowerUse
Test: atest
CtsStatsdHostTestCases:UidAtomTests#testDeviceCalculatedPowerBlameUid
Test: atest CtsStatsdHostTestCases:BatteryStatsValidationTests#testPowerUse
Bug: 145565211
Change-Id: Ie009e6eead3e48ecee6b40d9a38c9d571d4d4117
parent 69ab6eed
Loading
Loading
Loading
Loading
+0 −87
Original line number Diff line number Diff line
@@ -1404,78 +1404,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
        }
    }

    private BatteryStatsHelper getBatteryStatsHelper() {
        if (mBatteryStatsHelper == null) {
            final long callingToken = Binder.clearCallingIdentity();
            try {
                // clearCallingIdentity required for BatteryStatsHelper.checkWifiOnly().
                mBatteryStatsHelper = new BatteryStatsHelper(mContext, false);
            } finally {
                Binder.restoreCallingIdentity(callingToken);
            }
            mBatteryStatsHelper.create((Bundle) null);
        }
        long currentTime = SystemClock.elapsedRealtime();
        if (currentTime - mBatteryStatsHelperTimestampMs >= MAX_BATTERY_STATS_HELPER_FREQUENCY_MS) {
            // Load BatteryStats and do all the calculations.
            mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.USER_ALL);
            // Calculations are done so we don't need to save the raw BatteryStats data in RAM.
            mBatteryStatsHelper.clearStats();
            mBatteryStatsHelperTimestampMs = currentTime;
        }
        return mBatteryStatsHelper;
    }

    private long milliAmpHrsToNanoAmpSecs(double mAh) {
        final long MILLI_AMP_HR_TO_NANO_AMP_SECS = 1_000_000L * 3600L;
        return (long) (mAh * MILLI_AMP_HR_TO_NANO_AMP_SECS + 0.5);
    }

    private void pullDeviceCalculatedPowerUse(int tagId,
            long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
        BatteryStatsHelper bsHelper = getBatteryStatsHelper();
        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
        e.writeLong(milliAmpHrsToNanoAmpSecs(bsHelper.getComputedPower()));
        pulledData.add(e);
    }

    private void pullDeviceCalculatedPowerBlameUid(int tagId,
            long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
        final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
        if (sippers == null) {
            return;
        }
        for (BatterySipper bs : sippers) {
            if (bs.drainType != bs.drainType.APP) {
                continue;
            }
            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
            e.writeInt(bs.uidObj.getUid());
            e.writeLong(milliAmpHrsToNanoAmpSecs(bs.totalPowerMah));
            pulledData.add(e);
        }
    }

    private void pullDeviceCalculatedPowerBlameOther(int tagId,
            long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
        final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
        if (sippers == null) {
            return;
        }
        for (BatterySipper bs : sippers) {
            if (bs.drainType == bs.drainType.APP) {
                continue; // This is a separate atom; see pullDeviceCalculatedPowerBlameUid().
            }
            if (bs.drainType == bs.drainType.USER) {
                continue; // This is not supported. We purposefully calculate over USER_ALL.
            }
            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
            e.writeInt(bs.drainType.ordinal());
            e.writeLong(milliAmpHrsToNanoAmpSecs(bs.totalPowerMah));
            pulledData.add(e);
        }
    }

    private void pullDiskIo(int tagId, long elapsedNanos, final long wallClockNanos,
            List<StatsLogEventWrapper> pulledData) {
        mStoragedUidIoStatsReader.readAbsolute((uid, fgCharsRead, fgCharsWrite, fgBytesRead,
@@ -2107,21 +2035,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
                break;
            }

            case StatsLog.DEVICE_CALCULATED_POWER_USE: {
                pullDeviceCalculatedPowerUse(tagId, elapsedNanos, wallClockNanos, ret);
                break;
            }

            case StatsLog.DEVICE_CALCULATED_POWER_BLAME_UID: {
                pullDeviceCalculatedPowerBlameUid(tagId, elapsedNanos, wallClockNanos, ret);
                break;
            }

            case StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER: {
                pullDeviceCalculatedPowerBlameOther(tagId, elapsedNanos, wallClockNanos, ret);
                break;
            }

            case StatsLog.TEMPERATURE: {
                pullTemperature(tagId, elapsedNanos, wallClockNanos, ret);
                break;
+0 −14
Original line number Diff line number Diff line
@@ -193,20 +193,6 @@ std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
         {.additiveFields = {7, 9, 11, 13, 15, 17, 19, 21},
          .puller = new StatsCompanionServicePuller(android::util::CPU_TIME_PER_THREAD_FREQ)}},

        // DeviceCalculatedPowerUse.
        {{.atomTag = android::util::DEVICE_CALCULATED_POWER_USE},
         {.puller = new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_USE)}},

        // DeviceCalculatedPowerBlameUid.
        {{.atomTag = android::util::DEVICE_CALCULATED_POWER_BLAME_UID},
         {.puller = new StatsCompanionServicePuller(
                  android::util::DEVICE_CALCULATED_POWER_BLAME_UID)}},

        // DeviceCalculatedPowerBlameOther.
        {{.atomTag = android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER},
         {.puller = new StatsCompanionServicePuller(
                  android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER)}},

        // DebugElapsedClock.
        {{.atomTag = android::util::DEBUG_ELAPSED_CLOCK},
         {.additiveFields = {1, 2, 3, 4},
+0 −1
Original line number Diff line number Diff line
@@ -180,7 +180,6 @@
    <assign-permission name="android.permission.ACCESS_LOWPAN_STATE" uid="lowpan" />
    <assign-permission name="android.permission.MANAGE_LOWPAN_INTERFACES" uid="lowpan" />

    <assign-permission name="android.permission.BATTERY_STATS" uid="statsd" />
    <assign-permission name="android.permission.DUMP" uid="statsd" />
    <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="statsd" />
    <assign-permission name="android.permission.STATSCOMPANION" uid="statsd" />
+1 −1
Original line number Diff line number Diff line
@@ -402,7 +402,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
    }

    public ParcelFileDescriptor getStatisticsStream() {
        mContext.enforceCallingPermission(
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.BATTERY_STATS, null);
        //Slog.i("foo", "SENDING BATTERY INFO:");
        //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
+100 −9
Original line number Diff line number Diff line
@@ -1113,28 +1113,119 @@ public class StatsPullAtomService extends SystemService {
        // No op.
    }

    // TODO: move to top of file when all migrations are complete
    private BatteryStatsHelper mBatteryStatsHelper = null;
    private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000;
    private long mBatteryStatsHelperTimestampMs = -MAX_BATTERY_STATS_HELPER_FREQUENCY_MS;
    private static final long MILLI_AMP_HR_TO_NANO_AMP_SECS = 1_000_000L * 3600L;

    private BatteryStatsHelper getBatteryStatsHelper() {
        if (mBatteryStatsHelper == null) {
            final long callingToken = Binder.clearCallingIdentity();
            try {
                // clearCallingIdentity required for BatteryStatsHelper.checkWifiOnly().
                mBatteryStatsHelper = new BatteryStatsHelper(mContext, false);
            } finally {
                Binder.restoreCallingIdentity(callingToken);
            }
            mBatteryStatsHelper.create((Bundle) null);
        }
        long currentTime = SystemClock.elapsedRealtime();
        if (currentTime - mBatteryStatsHelperTimestampMs >= MAX_BATTERY_STATS_HELPER_FREQUENCY_MS) {
            // Load BatteryStats and do all the calculations.
            mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.USER_ALL);
            // Calculations are done so we don't need to save the raw BatteryStats data in RAM.
            mBatteryStatsHelper.clearStats();
            mBatteryStatsHelperTimestampMs = currentTime;
        }
        return mBatteryStatsHelper;
    }

    private long milliAmpHrsToNanoAmpSecs(double mAh) {
        return (long) (mAh * MILLI_AMP_HR_TO_NANO_AMP_SECS + 0.5);
    }

    private void registerDeviceCalculatedPowerUse() {
        // No op.
        int tagId = StatsLog.DEVICE_CALCULATED_POWER_USE;
        mStatsManager.registerPullAtomCallback(
                tagId,
                null, // use default PullAtomMetadata values
                (atomTag, data) -> pullDeviceCalculatedPowerUse(atomTag, data),
                BackgroundThread.getExecutor()
        );
    }

    private void pullDeviceCalculatedPowerUse() {
        // No op.
    private int pullDeviceCalculatedPowerUse(int atomTag, List<StatsEvent> pulledData) {
        BatteryStatsHelper bsHelper = getBatteryStatsHelper();
        StatsEvent e = StatsEvent.newBuilder()
                .setAtomId(atomTag)
                .writeLong(milliAmpHrsToNanoAmpSecs(bsHelper.getComputedPower()))
                .build();
        pulledData.add(e);
        return StatsManager.PULL_SUCCESS;
    }

    private void registerDeviceCalculatedPowerBlameUid() {
        // No op.
        int tagId = StatsLog.DEVICE_CALCULATED_POWER_BLAME_UID;
        mStatsManager.registerPullAtomCallback(
                tagId,
                null, // use default PullAtomMetadata values
                (atomTag, data) -> pullDeviceCalculatedPowerBlameUid(atomTag, data),
                BackgroundThread.getExecutor()
        );
    }

    private void pullDeviceCalculatedPowerBlameUid() {
        // No op.
    private int pullDeviceCalculatedPowerBlameUid(int atomTag, List<StatsEvent> pulledData) {
        final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
        if (sippers == null) {
            return StatsManager.PULL_SKIP;
        }

        for (BatterySipper bs : sippers) {
            if (bs.drainType != bs.drainType.APP) {
                continue;
            }
            StatsEvent e = StatsEvent.newBuilder()
                    .setAtomId(atomTag)
                    .writeInt(bs.uidObj.getUid())
                    .writeLong(milliAmpHrsToNanoAmpSecs(bs.totalPowerMah))
                    .build();
            pulledData.add(e);
        }
        return StatsManager.PULL_SUCCESS;
    }

    private void registerDeviceCalculatedPowerBlameOther() {
        // No op.
        int tagId = StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER;
        mStatsManager.registerPullAtomCallback(
                tagId,
                null, // use default PullAtomMetadata values
                (atomTag, data) -> pullDeviceCalculatedPowerBlameOther(atomTag, data),
                BackgroundThread.getExecutor()
        );
    }

    private void pullDeviceCalculatedPowerBlameOther() {
        // No op.
    private int pullDeviceCalculatedPowerBlameOther(int atomTag, List<StatsEvent> pulledData) {
        final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
        if (sippers == null) {
            return StatsManager.PULL_SKIP;
        }

        for (BatterySipper bs : sippers) {
            if (bs.drainType == bs.drainType.APP) {
                continue; // This is a separate atom; see pullDeviceCalculatedPowerBlameUid().
            }
            if (bs.drainType == bs.drainType.USER) {
                continue; // This is not supported. We purposefully calculate over USER_ALL.
            }
            StatsEvent e = StatsEvent.newBuilder()
                    .setAtomId(atomTag)
                    .writeInt(bs.drainType.ordinal())
                    .writeLong(milliAmpHrsToNanoAmpSecs(bs.totalPowerMah))
                    .build();
            pulledData.add(e);
        }
        return StatsManager.PULL_SUCCESS;
    }

    private void registerDebugElapsedClock() {