Loading core/java/com/android/internal/os/BatteryStatsImpl.java +46 −36 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package com.android.internal.os; import static android.os.BatteryStatsManager.NUM_WIFI_STATES; import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES; import static com.android.internal.power.MeasuredEnergyStats.NUMBER_ENERGY_BUCKETS; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -103,7 +105,6 @@ import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeRead import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader; import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader; import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader; import com.android.internal.power.MeasuredEnergyArray; import com.android.internal.power.MeasuredEnergyStats; import com.android.internal.power.MeasuredEnergyStats.EnergyBucket; import com.android.internal.util.ArrayUtils; Loading Loading @@ -370,14 +371,6 @@ public class BatteryStatsImpl extends BatteryStats { * @param railStats */ void fillRailDataStats(RailStats railStats); /** * Function to get energy consumption data * * @return an array of measured energy (in microjoules) since boot, will be null if * measured energy data is unavailable */ @Nullable MeasuredEnergyArray getEnergyConsumptionData(); } public static abstract class UserInfoProvider { Loading Loading @@ -10704,15 +10697,13 @@ public class BatteryStatsImpl extends BatteryStats { } public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb, boolean[] supportedEnergyBuckets, UserInfoProvider userInfoProvider) { this(new SystemClocks(), systemDir, handler, cb, energyStatsCb, supportedEnergyBuckets, userInfoProvider); MeasuredEnergyRetriever energyStatsCb, UserInfoProvider userInfoProvider) { this(new SystemClocks(), systemDir, handler, cb, energyStatsCb, userInfoProvider); } private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler, PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb, boolean[] supportedEnergyBuckets, UserInfoProvider userInfoProvider) { UserInfoProvider userInfoProvider) { init(clocks); if (systemDir == null) { Loading Loading @@ -10818,10 +10809,6 @@ public class BatteryStatsImpl extends BatteryStats { // Notify statsd that the system is initially not in doze. mDeviceIdleMode = DEVICE_IDLE_MODE_OFF; FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode); mGlobalMeasuredEnergyStats = supportedEnergyBuckets == null ? null : new MeasuredEnergyStats(supportedEnergyBuckets); mScreenStateAtLastEnergyMeasurement = mScreenState; } @UnsupportedAppUsage Loading Loading @@ -12502,21 +12489,6 @@ public class BatteryStatsImpl extends BatteryStats { } } /** * Get energy consumed (in microjoules) by a set of subsystems from the {@link * MeasuredEnergyRetriever}, if available. * * @return a SparseLongArray that maps consumer id to energy consumed. Returns null if data is * unavailable. */ @Nullable public MeasuredEnergyArray getEnergyConsumptionDataLocked() { if (mMeasuredEnergyRetriever == null) { return null; } return mMeasuredEnergyRetriever.getEnergyConsumptionData(); } /** * Read and distribute kernel wake lock use across apps. */ Loading Loading @@ -14240,6 +14212,40 @@ public class BatteryStatsImpl extends BatteryStats { mConstants.startObserving(context.getContentResolver()); registerUsbStateReceiver(context); } /** * Initialize the measured energy stats data structures. * * @param supportedEnergyBuckets boolean array indicating which buckets are currently supported */ @GuardedBy("this") public void initMeasuredEnergyStatsLocked(boolean[] supportedEnergyBuckets) { boolean supportedBucketMismatch = false; mScreenStateAtLastEnergyMeasurement = mScreenState; if (supportedEnergyBuckets == null) { if (mGlobalMeasuredEnergyStats != null) { // Measured energy buckets no longer supported, wipe out the existing data. supportedBucketMismatch = true; } } else if (mGlobalMeasuredEnergyStats == null) { mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(supportedEnergyBuckets); return; } else { for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) { if (mGlobalMeasuredEnergyStats.isEnergyBucketSupported(i) != supportedEnergyBuckets[i]) { supportedBucketMismatch = true; break; } } } if (supportedBucketMismatch) { // Supported energy buckets changed since last boot. // Existing data is no longer reliable. resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime()); } } @VisibleForTesting public final class Constants extends ContentObserver { Loading Loading @@ -14919,7 +14925,11 @@ public class BatteryStatsImpl extends BatteryStats { mNextMaxDailyDeadlineMs = in.readLong(); mBatteryTimeToFullSeconds = in.readLong(); MeasuredEnergyStats.readSummaryFromParcel(mGlobalMeasuredEnergyStats, in); /** * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled * later when {@link #initMeasuredEnergyStatsLocked} is called. */ mGlobalMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(in); mStartCount++; Loading Loading @@ -15417,7 +15427,7 @@ public class BatteryStatsImpl extends BatteryStats { out.writeLong(mNextMaxDailyDeadlineMs); out.writeLong(mBatteryTimeToFullSeconds); MeasuredEnergyStats.writeSummaryToParcel(mGlobalMeasuredEnergyStats, out); MeasuredEnergyStats.writeSummaryToParcel(mGlobalMeasuredEnergyStats, out, false); mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); Loading Loading @@ -15742,7 +15752,7 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(0); } MeasuredEnergyStats.writeSummaryToParcel(u.mUidMeasuredEnergyStats, out); MeasuredEnergyStats.writeSummaryToParcel(u.mUidMeasuredEnergyStats, out, true); final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap(); int NW = wakeStats.size(); core/java/com/android/internal/power/MeasuredEnergyStats.java +23 −15 Original line number Diff line number Diff line Loading @@ -130,27 +130,32 @@ public class MeasuredEnergyStats { * Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} must be updated if summary * parceling changes. */ private void readSummaryFromParcel(Parcel in) { private void readSummaryFromParcel(Parcel in, boolean overwriteAvailability) { final int size = in.readInt(); for (int i = 0; i < size; i++) { final int bucket = in.readInt(); final long energyUJ = in.readLong(); if (overwriteAvailability) { mAccumulatedEnergiesMicroJoules[bucket] = energyUJ; } else { setValueIfSupported(bucket, energyUJ); } } } /** * Write to summary parcel. * Note: Measured subsystem availability may be different when the summary parcel is read. */ private void writeSummaryToParcel(Parcel out) { private void writeSummaryToParcel(Parcel out, boolean skipZero) { final int sizePos = out.dataPosition(); out.writeInt(0); int size = 0; // Write only the supported buckets with non-zero energy. for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) { final long energy = mAccumulatedEnergiesMicroJoules[i]; if (energy <= 0) continue; if (energy < 0) continue; if (energy == 0 && skipZero) continue; out.writeInt(i); out.writeLong(mAccumulatedEnergiesMicroJoules[i]); Loading Loading @@ -197,16 +202,19 @@ public class MeasuredEnergyStats { } /** * Populate a MeasuredEnergyStats from a parcel. If the stats is null, consume and * ignore the parcelled data. * Create a MeasuredEnergyStats object from a summary parcel. * * @return a new MeasuredEnergyStats object as described. * Returns null if the parcel indicates there is no data to populate. */ public static void readSummaryFromParcel(@Nullable MeasuredEnergyStats stats, Parcel in) { public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel(Parcel in) { // Check if any MeasuredEnergyStats exists on the parcel if (in.readInt() == 0) return; if (in.readInt() == 0) return null; // If stats is null, create a placeholder MeasuredEnergyStats to consume the parcel data final MeasuredEnergyStats mes = stats != null ? stats : new MeasuredEnergyStats(); mes.readSummaryFromParcel(in); final MeasuredEnergyStats stats = new MeasuredEnergyStats(new boolean[NUMBER_ENERGY_BUCKETS]); stats.readSummaryFromParcel(in, true); return stats; } /** Loading @@ -227,12 +235,12 @@ public class MeasuredEnergyStats { if (template == null) { // Nothing supported now. Create placeholder object just to consume the parcel data. final MeasuredEnergyStats mes = new MeasuredEnergyStats(); mes.readSummaryFromParcel(in); mes.readSummaryFromParcel(in, false); return null; } final MeasuredEnergyStats stats = createFromTemplate(template); stats.readSummaryFromParcel(in); stats.readSummaryFromParcel(in, false); if (stats.containsInterestingData()) { return stats; } else { Loading @@ -253,13 +261,13 @@ public class MeasuredEnergyStats { * Write a MeasuredEnergyStats to a parcel. If the stats is null, just write a 0. */ public static void writeSummaryToParcel(@Nullable MeasuredEnergyStats stats, Parcel dest) { Parcel dest, boolean skipZero) { if (stats == null) { dest.writeInt(0); return; } dest.writeInt(1); stats.writeSummaryToParcel(dest); stats.writeSummaryToParcel(dest, skipZero); } /** Reset accumulated energy. */ Loading core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java +60 −23 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ import androidx.test.filters.SmallTest; import org.junit.Test; import java.util.Arrays; /** * Test class for {@link MeasuredEnergyStats}. * Loading Loading @@ -114,7 +116,7 @@ public class MeasuredEnergyStatsTest { } @Test public void testReadWriteSummaryParcel() { public void testCreateAndReadSummaryFromParcel() { final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS]; supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true; supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false; Loading @@ -126,35 +128,21 @@ public class MeasuredEnergyStatsTest { stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true); final Parcel parcel = Parcel.obtain(); MeasuredEnergyStats.writeSummaryToParcel(stats, parcel); final boolean[] newSupportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS]; newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true; newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = true; // switched from false to true newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = false; // switched true to false MeasuredEnergyStats newStats = new MeasuredEnergyStats(newSupportedEnergyBuckets); MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false); parcel.setDataPosition(0); MeasuredEnergyStats.readSummaryFromParcel(newStats, parcel); MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel); for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) { if (!newSupportedEnergyBuckets[i]) { assertFalse(newStats.isEnergyBucketSupported(i)); assertEquals(ENERGY_DATA_UNAVAILABLE, newStats.getAccumulatedBucketEnergy(i)); } else if (!supportedEnergyBuckets[i]) { assertTrue(newStats.isEnergyBucketSupported(i)); assertEquals(0L, newStats.getAccumulatedBucketEnergy(i)); } else { assertTrue(newStats.isEnergyBucketSupported(i)); assertEquals(stats.isEnergyBucketSupported(i), newStats.isEnergyBucketSupported(i)); assertEquals(stats.getAccumulatedBucketEnergy(i), newStats.getAccumulatedBucketEnergy(i)); } } parcel.recycle(); } @Test public void testCreateAndReadSummaryFromParcel() { public void testCreateAndReadSummaryFromParcel_existingTemplate() { final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS]; supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true; supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false; Loading @@ -171,7 +159,7 @@ public class MeasuredEnergyStatsTest { stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 63, true); final Parcel parcel = Parcel.obtain(); MeasuredEnergyStats.writeSummaryToParcel(stats, parcel); MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false); final boolean[] newSupportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS]; newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true; Loading Loading @@ -199,6 +187,55 @@ public class MeasuredEnergyStatsTest { parcel.recycle(); } @Test public void testCreateAndReadSummaryFromParcel_skipZero() { final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS]; Arrays.fill(supportedEnergyBuckets, true); final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets); // Accumulate energy in one bucket, the rest should be zero stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 200, true); final Parcel includeZerosParcel = Parcel.obtain(); MeasuredEnergyStats.writeSummaryToParcel(stats, includeZerosParcel, false); includeZerosParcel.setDataPosition(0); MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel( includeZerosParcel); for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) { if (i == ENERGY_BUCKET_SCREEN_ON) { assertEquals(stats.isEnergyBucketSupported(i), newStats.isEnergyBucketSupported(i)); assertEquals(stats.getAccumulatedBucketEnergy(i), newStats.getAccumulatedBucketEnergy(i)); } else { assertTrue(newStats.isEnergyBucketSupported(i)); assertEquals(0L, newStats.getAccumulatedBucketEnergy(i)); } } includeZerosParcel.recycle(); final Parcel skipZerosParcel = Parcel.obtain(); MeasuredEnergyStats.writeSummaryToParcel(stats, skipZerosParcel, true); skipZerosParcel.setDataPosition(0); newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(skipZerosParcel); for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) { if (i == ENERGY_BUCKET_SCREEN_ON) { assertEquals(stats.isEnergyBucketSupported(i), newStats.isEnergyBucketSupported(i)); assertEquals(stats.getAccumulatedBucketEnergy(i), newStats.getAccumulatedBucketEnergy(i)); } else { assertFalse(newStats.isEnergyBucketSupported(i)); assertEquals(ENERGY_DATA_UNAVAILABLE, newStats.getAccumulatedBucketEnergy(i)); } } skipZerosParcel.recycle(); } @Test public void testUpdateBucket() { final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS]; Loading services/core/java/android/power/PowerStatsInternal.java 0 → 100644 +42 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.power; import android.hardware.power.stats.EnergyConsumerId; import android.hardware.power.stats.EnergyConsumerResult; import java.util.concurrent.CompletableFuture; /** * Power stats local system service interface. * * @hide Only for use within Android OS. */ public abstract class PowerStatsInternal { /** * Returns a CompletableFuture that will get an {@link EnergyConsumerResult} array for the * available requested energy consumers (power models). * * @param energyConsumerIds Array of {@link EnergyConsumerId} for which energy consumed is being * requested. * * @return A Future containing a list of {@link EnergyConsumerResult} objects containing energy * consumer results for all listed {@link EnergyConsumerId}. */ public abstract CompletableFuture<EnergyConsumerResult[]> getEnergyConsumedAsync( @EnergyConsumerId int[] energyConsumerIds); } services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +112 −27 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +46 −36 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package com.android.internal.os; import static android.os.BatteryStatsManager.NUM_WIFI_STATES; import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES; import static com.android.internal.power.MeasuredEnergyStats.NUMBER_ENERGY_BUCKETS; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -103,7 +105,6 @@ import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeRead import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader; import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader; import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader; import com.android.internal.power.MeasuredEnergyArray; import com.android.internal.power.MeasuredEnergyStats; import com.android.internal.power.MeasuredEnergyStats.EnergyBucket; import com.android.internal.util.ArrayUtils; Loading Loading @@ -370,14 +371,6 @@ public class BatteryStatsImpl extends BatteryStats { * @param railStats */ void fillRailDataStats(RailStats railStats); /** * Function to get energy consumption data * * @return an array of measured energy (in microjoules) since boot, will be null if * measured energy data is unavailable */ @Nullable MeasuredEnergyArray getEnergyConsumptionData(); } public static abstract class UserInfoProvider { Loading Loading @@ -10704,15 +10697,13 @@ public class BatteryStatsImpl extends BatteryStats { } public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb, boolean[] supportedEnergyBuckets, UserInfoProvider userInfoProvider) { this(new SystemClocks(), systemDir, handler, cb, energyStatsCb, supportedEnergyBuckets, userInfoProvider); MeasuredEnergyRetriever energyStatsCb, UserInfoProvider userInfoProvider) { this(new SystemClocks(), systemDir, handler, cb, energyStatsCb, userInfoProvider); } private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler, PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb, boolean[] supportedEnergyBuckets, UserInfoProvider userInfoProvider) { UserInfoProvider userInfoProvider) { init(clocks); if (systemDir == null) { Loading Loading @@ -10818,10 +10809,6 @@ public class BatteryStatsImpl extends BatteryStats { // Notify statsd that the system is initially not in doze. mDeviceIdleMode = DEVICE_IDLE_MODE_OFF; FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode); mGlobalMeasuredEnergyStats = supportedEnergyBuckets == null ? null : new MeasuredEnergyStats(supportedEnergyBuckets); mScreenStateAtLastEnergyMeasurement = mScreenState; } @UnsupportedAppUsage Loading Loading @@ -12502,21 +12489,6 @@ public class BatteryStatsImpl extends BatteryStats { } } /** * Get energy consumed (in microjoules) by a set of subsystems from the {@link * MeasuredEnergyRetriever}, if available. * * @return a SparseLongArray that maps consumer id to energy consumed. Returns null if data is * unavailable. */ @Nullable public MeasuredEnergyArray getEnergyConsumptionDataLocked() { if (mMeasuredEnergyRetriever == null) { return null; } return mMeasuredEnergyRetriever.getEnergyConsumptionData(); } /** * Read and distribute kernel wake lock use across apps. */ Loading Loading @@ -14240,6 +14212,40 @@ public class BatteryStatsImpl extends BatteryStats { mConstants.startObserving(context.getContentResolver()); registerUsbStateReceiver(context); } /** * Initialize the measured energy stats data structures. * * @param supportedEnergyBuckets boolean array indicating which buckets are currently supported */ @GuardedBy("this") public void initMeasuredEnergyStatsLocked(boolean[] supportedEnergyBuckets) { boolean supportedBucketMismatch = false; mScreenStateAtLastEnergyMeasurement = mScreenState; if (supportedEnergyBuckets == null) { if (mGlobalMeasuredEnergyStats != null) { // Measured energy buckets no longer supported, wipe out the existing data. supportedBucketMismatch = true; } } else if (mGlobalMeasuredEnergyStats == null) { mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(supportedEnergyBuckets); return; } else { for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) { if (mGlobalMeasuredEnergyStats.isEnergyBucketSupported(i) != supportedEnergyBuckets[i]) { supportedBucketMismatch = true; break; } } } if (supportedBucketMismatch) { // Supported energy buckets changed since last boot. // Existing data is no longer reliable. resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime()); } } @VisibleForTesting public final class Constants extends ContentObserver { Loading Loading @@ -14919,7 +14925,11 @@ public class BatteryStatsImpl extends BatteryStats { mNextMaxDailyDeadlineMs = in.readLong(); mBatteryTimeToFullSeconds = in.readLong(); MeasuredEnergyStats.readSummaryFromParcel(mGlobalMeasuredEnergyStats, in); /** * WARNING: Supported buckets may have changed across boots. Bucket mismatch is handled * later when {@link #initMeasuredEnergyStatsLocked} is called. */ mGlobalMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(in); mStartCount++; Loading Loading @@ -15417,7 +15427,7 @@ public class BatteryStatsImpl extends BatteryStats { out.writeLong(mNextMaxDailyDeadlineMs); out.writeLong(mBatteryTimeToFullSeconds); MeasuredEnergyStats.writeSummaryToParcel(mGlobalMeasuredEnergyStats, out); MeasuredEnergyStats.writeSummaryToParcel(mGlobalMeasuredEnergyStats, out, false); mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); Loading Loading @@ -15742,7 +15752,7 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(0); } MeasuredEnergyStats.writeSummaryToParcel(u.mUidMeasuredEnergyStats, out); MeasuredEnergyStats.writeSummaryToParcel(u.mUidMeasuredEnergyStats, out, true); final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap(); int NW = wakeStats.size();
core/java/com/android/internal/power/MeasuredEnergyStats.java +23 −15 Original line number Diff line number Diff line Loading @@ -130,27 +130,32 @@ public class MeasuredEnergyStats { * Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} must be updated if summary * parceling changes. */ private void readSummaryFromParcel(Parcel in) { private void readSummaryFromParcel(Parcel in, boolean overwriteAvailability) { final int size = in.readInt(); for (int i = 0; i < size; i++) { final int bucket = in.readInt(); final long energyUJ = in.readLong(); if (overwriteAvailability) { mAccumulatedEnergiesMicroJoules[bucket] = energyUJ; } else { setValueIfSupported(bucket, energyUJ); } } } /** * Write to summary parcel. * Note: Measured subsystem availability may be different when the summary parcel is read. */ private void writeSummaryToParcel(Parcel out) { private void writeSummaryToParcel(Parcel out, boolean skipZero) { final int sizePos = out.dataPosition(); out.writeInt(0); int size = 0; // Write only the supported buckets with non-zero energy. for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) { final long energy = mAccumulatedEnergiesMicroJoules[i]; if (energy <= 0) continue; if (energy < 0) continue; if (energy == 0 && skipZero) continue; out.writeInt(i); out.writeLong(mAccumulatedEnergiesMicroJoules[i]); Loading Loading @@ -197,16 +202,19 @@ public class MeasuredEnergyStats { } /** * Populate a MeasuredEnergyStats from a parcel. If the stats is null, consume and * ignore the parcelled data. * Create a MeasuredEnergyStats object from a summary parcel. * * @return a new MeasuredEnergyStats object as described. * Returns null if the parcel indicates there is no data to populate. */ public static void readSummaryFromParcel(@Nullable MeasuredEnergyStats stats, Parcel in) { public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel(Parcel in) { // Check if any MeasuredEnergyStats exists on the parcel if (in.readInt() == 0) return; if (in.readInt() == 0) return null; // If stats is null, create a placeholder MeasuredEnergyStats to consume the parcel data final MeasuredEnergyStats mes = stats != null ? stats : new MeasuredEnergyStats(); mes.readSummaryFromParcel(in); final MeasuredEnergyStats stats = new MeasuredEnergyStats(new boolean[NUMBER_ENERGY_BUCKETS]); stats.readSummaryFromParcel(in, true); return stats; } /** Loading @@ -227,12 +235,12 @@ public class MeasuredEnergyStats { if (template == null) { // Nothing supported now. Create placeholder object just to consume the parcel data. final MeasuredEnergyStats mes = new MeasuredEnergyStats(); mes.readSummaryFromParcel(in); mes.readSummaryFromParcel(in, false); return null; } final MeasuredEnergyStats stats = createFromTemplate(template); stats.readSummaryFromParcel(in); stats.readSummaryFromParcel(in, false); if (stats.containsInterestingData()) { return stats; } else { Loading @@ -253,13 +261,13 @@ public class MeasuredEnergyStats { * Write a MeasuredEnergyStats to a parcel. If the stats is null, just write a 0. */ public static void writeSummaryToParcel(@Nullable MeasuredEnergyStats stats, Parcel dest) { Parcel dest, boolean skipZero) { if (stats == null) { dest.writeInt(0); return; } dest.writeInt(1); stats.writeSummaryToParcel(dest); stats.writeSummaryToParcel(dest, skipZero); } /** Reset accumulated energy. */ Loading
core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java +60 −23 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ import androidx.test.filters.SmallTest; import org.junit.Test; import java.util.Arrays; /** * Test class for {@link MeasuredEnergyStats}. * Loading Loading @@ -114,7 +116,7 @@ public class MeasuredEnergyStatsTest { } @Test public void testReadWriteSummaryParcel() { public void testCreateAndReadSummaryFromParcel() { final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS]; supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true; supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false; Loading @@ -126,35 +128,21 @@ public class MeasuredEnergyStatsTest { stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true); final Parcel parcel = Parcel.obtain(); MeasuredEnergyStats.writeSummaryToParcel(stats, parcel); final boolean[] newSupportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS]; newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true; newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = true; // switched from false to true newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = false; // switched true to false MeasuredEnergyStats newStats = new MeasuredEnergyStats(newSupportedEnergyBuckets); MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false); parcel.setDataPosition(0); MeasuredEnergyStats.readSummaryFromParcel(newStats, parcel); MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel); for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) { if (!newSupportedEnergyBuckets[i]) { assertFalse(newStats.isEnergyBucketSupported(i)); assertEquals(ENERGY_DATA_UNAVAILABLE, newStats.getAccumulatedBucketEnergy(i)); } else if (!supportedEnergyBuckets[i]) { assertTrue(newStats.isEnergyBucketSupported(i)); assertEquals(0L, newStats.getAccumulatedBucketEnergy(i)); } else { assertTrue(newStats.isEnergyBucketSupported(i)); assertEquals(stats.isEnergyBucketSupported(i), newStats.isEnergyBucketSupported(i)); assertEquals(stats.getAccumulatedBucketEnergy(i), newStats.getAccumulatedBucketEnergy(i)); } } parcel.recycle(); } @Test public void testCreateAndReadSummaryFromParcel() { public void testCreateAndReadSummaryFromParcel_existingTemplate() { final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS]; supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true; supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false; Loading @@ -171,7 +159,7 @@ public class MeasuredEnergyStatsTest { stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 63, true); final Parcel parcel = Parcel.obtain(); MeasuredEnergyStats.writeSummaryToParcel(stats, parcel); MeasuredEnergyStats.writeSummaryToParcel(stats, parcel, false); final boolean[] newSupportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS]; newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true; Loading Loading @@ -199,6 +187,55 @@ public class MeasuredEnergyStatsTest { parcel.recycle(); } @Test public void testCreateAndReadSummaryFromParcel_skipZero() { final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS]; Arrays.fill(supportedEnergyBuckets, true); final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets); // Accumulate energy in one bucket, the rest should be zero stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 200, true); final Parcel includeZerosParcel = Parcel.obtain(); MeasuredEnergyStats.writeSummaryToParcel(stats, includeZerosParcel, false); includeZerosParcel.setDataPosition(0); MeasuredEnergyStats newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel( includeZerosParcel); for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) { if (i == ENERGY_BUCKET_SCREEN_ON) { assertEquals(stats.isEnergyBucketSupported(i), newStats.isEnergyBucketSupported(i)); assertEquals(stats.getAccumulatedBucketEnergy(i), newStats.getAccumulatedBucketEnergy(i)); } else { assertTrue(newStats.isEnergyBucketSupported(i)); assertEquals(0L, newStats.getAccumulatedBucketEnergy(i)); } } includeZerosParcel.recycle(); final Parcel skipZerosParcel = Parcel.obtain(); MeasuredEnergyStats.writeSummaryToParcel(stats, skipZerosParcel, true); skipZerosParcel.setDataPosition(0); newStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(skipZerosParcel); for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) { if (i == ENERGY_BUCKET_SCREEN_ON) { assertEquals(stats.isEnergyBucketSupported(i), newStats.isEnergyBucketSupported(i)); assertEquals(stats.getAccumulatedBucketEnergy(i), newStats.getAccumulatedBucketEnergy(i)); } else { assertFalse(newStats.isEnergyBucketSupported(i)); assertEquals(ENERGY_DATA_UNAVAILABLE, newStats.getAccumulatedBucketEnergy(i)); } } skipZerosParcel.recycle(); } @Test public void testUpdateBucket() { final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS]; Loading
services/core/java/android/power/PowerStatsInternal.java 0 → 100644 +42 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.power; import android.hardware.power.stats.EnergyConsumerId; import android.hardware.power.stats.EnergyConsumerResult; import java.util.concurrent.CompletableFuture; /** * Power stats local system service interface. * * @hide Only for use within Android OS. */ public abstract class PowerStatsInternal { /** * Returns a CompletableFuture that will get an {@link EnergyConsumerResult} array for the * available requested energy consumers (power models). * * @param energyConsumerIds Array of {@link EnergyConsumerId} for which energy consumed is being * requested. * * @return A Future containing a list of {@link EnergyConsumerResult} objects containing energy * consumer results for all listed {@link EnergyConsumerId}. */ public abstract CompletableFuture<EnergyConsumerResult[]> getEnergyConsumedAsync( @EnergyConsumerId int[] energyConsumerIds); }
services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +112 −27 File changed.Preview size limit exceeded, changes collapsed. Show changes