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

Commit 0a17ba0e authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Fix PowerStats.Descriptor.extras comparison

Without this fix, two descriptors are seen as different
if they contain any arrays (e.g. screen and sensors)

Bug: 395954049
Test: atest PowerStatsTests; atest PowerStatsTests:BatteryUsageStatsProviderPerfTest#getBatteryUsageStats_accumulated
Flag: EXEMPT bugfix
Change-Id: Ic027a6f47538e4cb0bbd33555996b93f19218c71
parent 85ea2265
Loading
Loading
Loading
Loading
+31 −9
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ public final class PowerStats {
         * Extra parameters specific to the power component, e.g. the availability of power
         * monitors.
         */
        @NonNull
        public final PersistableBundle extras;

        private PowerStatsFormatter mDeviceStatsFormatter;
@@ -269,20 +270,41 @@ public final class PowerStats {
                    stateStatsArrayLength, uidStatsArrayLength, extras);
        }

        @SuppressWarnings("deprecation")
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof Descriptor)) return false;
            Descriptor that = (Descriptor) o;
            return powerComponentId == that.powerComponentId
                    && statsArrayLength == that.statsArrayLength
                    && stateLabels.contentEquals(that.stateLabels)
                    && stateStatsArrayLength == that.stateStatsArrayLength
                    && uidStatsArrayLength == that.uidStatsArrayLength
                    && Objects.equals(name, that.name)
                    && extras.size() == that.extras.size()        // Unparcel the Parcel if not yet
                    && Bundle.kindofEquals(extras,
                    that.extras);  // Since the Parcel is now unparceled, do a deep comparison
            if (powerComponentId != that.powerComponentId
                    || statsArrayLength != that.statsArrayLength
                    || !stateLabels.contentEquals(that.stateLabels)
                    || stateStatsArrayLength != that.stateStatsArrayLength
                    || uidStatsArrayLength != that.uidStatsArrayLength
                    || !Objects.equals(name, that.name)) {
                return false;
            }

            // Getting the size has the side-effect of unparceling the Bundle if not yet
            if (extras.size() != that.extras.size()) {
                return false;
            }

            if (Bundle.kindofEquals(extras, that.extras)) {
                return true;
            }

            // Since `kindofEquals` does not deep-compare arrays, we do that separately, albeit at
            // the expense of creating an iterator and using a deprecated API, `bundle.get`.
            // There is no performance concern, because the situation where PowerStatsDescriptors
            // are changed in an incompatible way are exceedingly rare, occurring at most
            // once per power component after a system upgrade.
            for (String key : extras.keySet()) {
                if (!Objects.deepEquals(extras.get(key), that.extras.get(key))) {
                    return false;
                }
            }
            return true;
        }

        /**
+10 −3
Original line number Diff line number Diff line
@@ -29,7 +29,8 @@ import com.android.internal.os.PowerStats;
public class ScreenPowerStatsLayout extends PowerStatsLayout {
    private static final String EXTRA_DEVICE_SCREEN_COUNT = "dsc";
    private static final String EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION = "dsd";
    private static final String EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS = "dbd";
    private static final String EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS = "dbds";
    private static final String EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS_COMPAT = "dbd";
    private static final String EXTRA_DEVICE_DOZE_DURATION_POSITION = "ddd";
    private static final String EXTRA_DEVICE_DOZE_POWER_POSITION = "ddp";
    private static final String EXTRA_UID_FOREGROUND_DURATION = "uf";
@@ -55,8 +56,14 @@ public class ScreenPowerStatsLayout extends PowerStatsLayout {
        PersistableBundle extras = descriptor.extras;
        mDisplayCount = extras.getInt(EXTRA_DEVICE_SCREEN_COUNT, 1);
        mDeviceScreenOnDurationPosition = extras.getInt(EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION);
        mDeviceBrightnessDurationPositions = extras.getIntArray(
        mDeviceBrightnessDurationPositions = getIntArray(extras,
                EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS);
        if (mDeviceBrightnessDurationPositions == null) {
            // We should never put arrays in PowerStats.Descriptor because of the performance of
            // .equals
            mDeviceBrightnessDurationPositions = extras.getIntArray(
                    EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS_COMPAT);
        }
        mDeviceScreenDozeDurationPosition = extras.getInt(EXTRA_DEVICE_DOZE_DURATION_POSITION);
        mDeviceScreenDozePowerPosition = extras.getInt(EXTRA_DEVICE_DOZE_POWER_POSITION);
        mUidTopActivityTimePosition = extras.getInt(EXTRA_UID_FOREGROUND_DURATION);
@@ -67,7 +74,7 @@ public class ScreenPowerStatsLayout extends PowerStatsLayout {
        super.toExtras(extras);
        extras.putInt(EXTRA_DEVICE_SCREEN_COUNT, mDisplayCount);
        extras.putInt(EXTRA_DEVICE_SCREEN_ON_DURATION_POSITION, mDeviceScreenOnDurationPosition);
        extras.putIntArray(EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS,
        putIntArray(extras, EXTRA_DEVICE_BRIGHTNESS_DURATION_POSITIONS,
                mDeviceBrightnessDurationPositions);
        extras.putInt(EXTRA_DEVICE_DOZE_DURATION_POSITION, mDeviceScreenDozeDurationPosition);
        extras.putInt(EXTRA_DEVICE_DOZE_POWER_POSITION, mDeviceScreenDozePowerPosition);
+13 −5
Original line number Diff line number Diff line
@@ -27,8 +27,10 @@ import java.util.Map;

public class SensorPowerStatsLayout extends PowerStatsLayout {
    private static final String TAG = "SensorPowerStatsLayout";
    private static final String EXTRA_DEVICE_SENSOR_HANDLES = "dsh";
    private static final String EXTRA_DEVICE_SENSOR_HANDLES = "dshs";
    private static final String EXTRA_DEVICE_SENSOR_HANDLES_COMPAT = "dsh";
    private static final String EXTRA_UID_SENSOR_POSITIONS = "usp";
    private static final String EXTRA_UID_SENSOR_POSITIONS_COMPAT = "usps";

    private final SparseIntArray mSensorPositions = new SparseIntArray();

@@ -47,8 +49,14 @@ public class SensorPowerStatsLayout extends PowerStatsLayout {
        super(descriptor);

        PersistableBundle extras = descriptor.extras;
        int[] handlers = extras.getIntArray(EXTRA_DEVICE_SENSOR_HANDLES);
        int[] uidDurationPositions = extras.getIntArray(EXTRA_UID_SENSOR_POSITIONS);
        int[] handlers = getIntArray(extras, EXTRA_DEVICE_SENSOR_HANDLES);
        if (handlers == null) {
            handlers = extras.getIntArray(EXTRA_DEVICE_SENSOR_HANDLES_COMPAT);
        }
        int[] uidDurationPositions = getIntArray(extras, EXTRA_UID_SENSOR_POSITIONS);
        if (uidDurationPositions == null) {
            uidDurationPositions = extras.getIntArray(EXTRA_UID_SENSOR_POSITIONS_COMPAT);
        }

        if (handlers != null && uidDurationPositions != null) {
            for (int i = 0; i < handlers.length; i++) {
@@ -69,8 +77,8 @@ public class SensorPowerStatsLayout extends PowerStatsLayout {
            uidDurationPositions[i] = mSensorPositions.valueAt(i);
        }

        extras.putIntArray(EXTRA_DEVICE_SENSOR_HANDLES, handlers);
        extras.putIntArray(EXTRA_UID_SENSOR_POSITIONS, uidDurationPositions);
        putIntArray(extras, EXTRA_DEVICE_SENSOR_HANDLES, handlers);
        putIntArray(extras, EXTRA_UID_SENSOR_POSITIONS, uidDurationPositions);
    }

    private void addUidSensorSection(int handle, String label) {