Loading core/java/android/os/BatteryStats.java +1 −13 Original line number Diff line number Diff line Loading @@ -1556,8 +1556,7 @@ public abstract class BatteryStats implements Parcelable { public int statSoftIrqTime; public int statIdlTime; // Platform-level low power state stats public String statPlatformIdleState; // Low power state stats public String statSubsystemPowerState; public HistoryStepDetails() { Loading Loading @@ -1589,7 +1588,6 @@ public abstract class BatteryStats implements Parcelable { out.writeInt(statIrqTime); out.writeInt(statSoftIrqTime); out.writeInt(statIdlTime); out.writeString(statPlatformIdleState); out.writeString(statSubsystemPowerState); } Loading @@ -1611,7 +1609,6 @@ public abstract class BatteryStats implements Parcelable { statIrqTime = in.readInt(); statSoftIrqTime = in.readInt(); statIdlTime = in.readInt(); statPlatformIdleState = in.readString(); statSubsystemPowerState = in.readString(); } } Loading Loading @@ -6600,9 +6597,6 @@ public abstract class BatteryStats implements Parcelable { item.append(sb); item.append(")"); } item.append(", PlatformIdleStat "); item.append(rec.stepDetails.statPlatformIdleState); item.append("\n"); item.append(", SubsystemPowerState "); item.append(rec.stepDetails.statSubsystemPowerState); Loading Loading @@ -6640,12 +6634,6 @@ public abstract class BatteryStats implements Parcelable { item.append(','); item.append(rec.stepDetails.statIdlTime); item.append(','); if (rec.stepDetails.statPlatformIdleState != null) { item.append(rec.stepDetails.statPlatformIdleState); if (rec.stepDetails.statSubsystemPowerState != null) { item.append(','); } } if (rec.stepDetails.statSubsystemPowerState != null) { item.append(rec.stepDetails.statSubsystemPowerState); Loading core/java/com/android/internal/os/BatteryStatsImpl.java +1 −7 Original line number Diff line number Diff line Loading @@ -173,7 +173,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version static final int VERSION = 191 + (USE_OLD_HISTORY ? 1000 : 0); static final int VERSION = 192 + (USE_OLD_HISTORY ? 1000 : 0); // The maximum number of names wakelocks we will keep track of // per uid; once the limit is reached, we batch the remaining wakelocks Loading Loading @@ -362,7 +362,6 @@ public class BatteryStatsImpl extends BatteryStats { public interface PlatformIdleStateCallback { public void fillLowPowerStats(RpmStats rpmStats); public String getPlatformLowPowerStats(); public String getSubsystemLowPowerStats(); } Loading Loading @@ -3482,11 +3481,6 @@ public class BatteryStatsImpl extends BatteryStats { } if (computeStepDetails) { if (mPlatformIdleStateCallback != null) { mCurHistoryStepDetails.statPlatformIdleState = mPlatformIdleStateCallback.getPlatformLowPowerStats(); if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" + mCurHistoryStepDetails.statPlatformIdleState); mCurHistoryStepDetails.statSubsystemPowerState = mPlatformIdleStateCallback.getSubsystemLowPowerStats(); if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" + Loading services/core/java/android/power/PowerStatsInternal.java +45 −0 Original line number Diff line number Diff line Loading @@ -18,8 +18,12 @@ package android.power; import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.power.stats.Channel; import android.hardware.power.stats.EnergyConsumer; import android.hardware.power.stats.EnergyConsumerResult; import android.hardware.power.stats.EnergyMeasurement; import android.hardware.power.stats.PowerEntity; import android.hardware.power.stats.StateResidencyResult; import java.util.concurrent.CompletableFuture; Loading Loading @@ -51,4 +55,45 @@ public abstract class PowerStatsInternal { @NonNull public abstract CompletableFuture<EnergyConsumerResult[]> getEnergyConsumedAsync( int[] energyConsumerIds); /** * Returns the power entity info for all available {@link PowerEntity} * * @return List of available {@link PowerEntity} */ public abstract PowerEntity[] getPowerEntityInfo(); /** * Returns a CompletableFuture that will get a {@link StateResidencyResult} array for the * available requested power entities. * * @param powerEntityIds Array of {@link PowerEntity.id} for which state residency is being * requested. * * @return A Future containing a list of {@link StateResidencyResult} objects containing state * residency results for all listed {@link PowerEntity.id}. */ @NonNull public abstract CompletableFuture<StateResidencyResult[]> getStateResidencyAsync( int[] powerEntityIds); /** * Returns the channel info for all available {@link Channel} * * @return List of available {@link Channel} */ public abstract Channel[] getEnergyMeterInfo(); /** * Returns a CompletableFuture that will get a {@link EnergyMeasurement} array for the * available requested channels. * * @param channelIds Array of {@link Channel.id} for accumulated energy is being requested. * * @return A Future containing a list of {@link EnergyMeasurement} objects containing * accumulated energy measurements for all listed {@link Channel.id}. */ @NonNull public abstract CompletableFuture<EnergyMeasurement[]> readEnergyMeterAsync( int[] channelIds); } services/core/java/com/android/server/am/BatteryStatsService.java +98 −45 Original line number Diff line number Diff line Loading @@ -21,6 +21,10 @@ import android.content.ContentResolver; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.hardware.power.stats.PowerEntity; import android.hardware.power.stats.State; import android.hardware.power.stats.StateResidency; import android.hardware.power.stats.StateResidencyResult; import android.net.INetworkManagementEventObserver; import android.net.NetworkCapabilities; import android.os.BatteryStats; Loading Loading @@ -51,6 +55,7 @@ import android.os.connectivity.WifiBatteryStats; import android.os.health.HealthStatsParceler; import android.os.health.HealthStatsWriter; import android.os.health.UidHealthStats; import android.power.PowerStatsInternal; import android.provider.Settings; import android.telephony.DataConnectionRealTimeInfo; import android.telephony.ModemActivityInfo; Loading Loading @@ -87,10 +92,13 @@ import java.nio.charset.CodingErrorAction; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; /** * All information we are collecting about things that can happen that impact Loading @@ -112,23 +120,23 @@ public final class BatteryStatsService extends IBatteryStats.Stub private final BatteryExternalStatsWorker mWorker; private final BatteryUsageStatsProvider mBatteryUsageStatsProvider; private native void getLowPowerStats(RpmStats rpmStats); private native int getPlatformLowPowerStats(ByteBuffer outBuffer); private native int getSubsystemLowPowerStats(ByteBuffer outBuffer); private native void getRailEnergyPowerStats(RailStats railStats); private CharsetDecoder mDecoderStat = StandardCharsets.UTF_8 .newDecoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .replaceWith("?"); private ByteBuffer mUtf8BufferStat = ByteBuffer.allocateDirect(MAX_LOW_POWER_STATS_SIZE); private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE); private static final int MAX_LOW_POWER_STATS_SIZE = 4096; private static final int POWER_STATS_QUERY_TIMEOUT_MILLIS = 2000; private final HandlerThread mHandlerThread; private final Handler mHandler; private final Object mLock = new Object(); private PowerStatsInternal mPowerStatsInternal = null; private Map<Integer, String> mEntityNames = new HashMap(); private Map<Integer, Map<Integer, String>> mStateNames = new HashMap(); @GuardedBy("mStats") private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; @GuardedBy("mStats") Loading Loading @@ -163,16 +171,57 @@ public final class BatteryStatsService extends IBatteryStats.Stub } }; private void populatePowerEntityMaps() { if (mPowerStatsInternal == null) { // PowerStatsInternal unavailable, don't bother populating maps. mEntityNames = null; mStateNames = null; return; } PowerEntity[] entities = mPowerStatsInternal.getPowerEntityInfo(); if (entities == null) { return; } for (int i = 0; i < entities.length; i++) { final PowerEntity entity = entities[i]; Map<Integer, String> states = new HashMap(); for (int j = 0; j < entity.states.length; j++) { final State state = entity.states[j]; states.put(state.id, state.name); } mEntityNames.put(entity.id, entity.name); mStateNames.put(entity.id, states); } } /** * Replaces the information in the given rpmStats with up-to-date information. */ @Override public void fillLowPowerStats(RpmStats rpmStats) { if (DBG) Slog.d(TAG, "begin getLowPowerStats"); final StateResidencyResult[] results; try { getLowPowerStats(rpmStats); } finally { if (DBG) Slog.d(TAG, "end getLowPowerStats"); results = mPowerStatsInternal.getStateResidencyAsync(new int[0]) .get(POWER_STATS_QUERY_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); } catch (Exception e) { Slog.e(TAG, "Failed to getStateResidencyAsync", e); return; } for (int i = 0; i < results.length; i++) { final StateResidencyResult result = results[i]; RpmStats.PowerStateSubsystem subsystem = rpmStats.getSubsystem(mEntityNames.get(result.id)); for (int j = 0; j < result.stateResidencyData.length; j++) { final StateResidency stateResidency = result.stateResidencyData[j]; subsystem.putState(mStateNames.get(result.id).get(stateResidency.id), stateResidency.totalTimeInStateMs, (int) stateResidency.totalStateEntryCount); } } } Loading @@ -187,47 +236,46 @@ public final class BatteryStatsService extends IBatteryStats.Stub } @Override public String getPlatformLowPowerStats() { if (DBG) Slog.d(TAG, "begin getPlatformLowPowerStats"); public String getSubsystemLowPowerStats() { final StateResidencyResult[] results; try { mUtf8BufferStat.clear(); mUtf16BufferStat.clear(); mDecoderStat.reset(); int bytesWritten = getPlatformLowPowerStats(mUtf8BufferStat); if (bytesWritten < 0) { return null; } else if (bytesWritten == 0) { results = mPowerStatsInternal.getStateResidencyAsync(new int[0]) .get(POWER_STATS_QUERY_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); } catch (Exception e) { Slog.e(TAG, "Failed to getStateResidencyAsync", e); return "Empty"; } mUtf8BufferStat.limit(bytesWritten); mDecoderStat.decode(mUtf8BufferStat, mUtf16BufferStat, true); mUtf16BufferStat.flip(); return mUtf16BufferStat.toString(); } finally { if (DBG) Slog.d(TAG, "end getPlatformLowPowerStats"); } if (results.length == 0) return "Empty"; int charsLeft = MAX_LOW_POWER_STATS_SIZE; StringBuilder builder = new StringBuilder("SubsystemPowerState"); for (int i = 0; i < results.length; i++) { final StateResidencyResult result = results[i]; StringBuilder subsystemBuilder = new StringBuilder(); subsystemBuilder.append(" subsystem_" + i); subsystemBuilder.append(" name=" + mEntityNames.get(result.id)); for (int j = 0; j < result.stateResidencyData.length; j++) { final StateResidency stateResidency = result.stateResidencyData[j]; subsystemBuilder.append(" state_" + j); subsystemBuilder.append(" name=" + mStateNames.get(result.id).get( stateResidency.id)); subsystemBuilder.append(" time=" + stateResidency.totalTimeInStateMs); subsystemBuilder.append(" count=" + stateResidency.totalStateEntryCount); subsystemBuilder.append(" last entry=" + stateResidency.lastEntryTimestampMs); } @Override public String getSubsystemLowPowerStats() { if (DBG) Slog.d(TAG, "begin getSubsystemLowPowerStats"); try { mUtf8BufferStat.clear(); mUtf16BufferStat.clear(); mDecoderStat.reset(); int bytesWritten = getSubsystemLowPowerStats(mUtf8BufferStat); if (bytesWritten < 0) { return null; } else if (bytesWritten == 0) { return "Empty"; if (subsystemBuilder.length() <= charsLeft) { charsLeft -= subsystemBuilder.length(); builder.append(subsystemBuilder); } else { Slog.e(TAG, "getSubsystemLowPowerStats: buffer not enough"); break; } mUtf8BufferStat.limit(bytesWritten); mDecoderStat.decode(mUtf8BufferStat, mUtf16BufferStat, true); mUtf16BufferStat.flip(); return mUtf16BufferStat.toString(); } finally { if (DBG) Slog.d(TAG, "end getSubsystemLowPowerStats"); } return builder.toString(); } BatteryStatsService(Context context, File systemDir, Handler handler) { Loading Loading @@ -274,6 +322,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub } catch (RemoteException e) { Slog.e(TAG, "Could not register INetworkManagement event observer " + e); } mPowerStatsInternal = LocalServices.getService(PowerStatsInternal.class); if (mPowerStatsInternal != null) { populatePowerEntityMaps(); } Watchdog.getInstance().addMonitor(this); } Loading services/core/java/com/android/server/powerstats/PowerStatsService.java +42 −0 Original line number Diff line number Diff line Loading @@ -21,7 +21,9 @@ import android.content.Context; import android.hardware.power.stats.Channel; import android.hardware.power.stats.EnergyConsumer; import android.hardware.power.stats.EnergyConsumerResult; import android.hardware.power.stats.EnergyMeasurement; import android.hardware.power.stats.PowerEntity; import android.hardware.power.stats.StateResidencyResult; import android.os.Binder; import android.os.Environment; import android.os.Handler; Loading Loading @@ -245,10 +247,50 @@ public class PowerStatsService extends SystemService { future, energyConsumerIds)); return future; } @Override public PowerEntity[] getPowerEntityInfo() { return getPowerStatsHal().getPowerEntityInfo(); } @Override public CompletableFuture<StateResidencyResult[]> getStateResidencyAsync( int[] powerEntityIds) { final CompletableFuture<StateResidencyResult[]> future = new CompletableFuture<>(); mHandler.sendMessage( PooledLambda.obtainMessage(PowerStatsService.this::getStateResidencyAsync, future, powerEntityIds)); return future; } @Override public Channel[] getEnergyMeterInfo() { return getPowerStatsHal().getEnergyMeterInfo(); } @Override public CompletableFuture<EnergyMeasurement[]> readEnergyMeterAsync( int[] channelIds) { final CompletableFuture<EnergyMeasurement[]> future = new CompletableFuture<>(); mHandler.sendMessage( PooledLambda.obtainMessage(PowerStatsService.this::readEnergyMeterAsync, future, channelIds)); return future; } } private void getEnergyConsumedAsync(CompletableFuture<EnergyConsumerResult[]> future, int[] energyConsumerIds) { future.complete(getPowerStatsHal().getEnergyConsumed(energyConsumerIds)); } private void getStateResidencyAsync(CompletableFuture<StateResidencyResult[]> future, int[] powerEntityIds) { future.complete(getPowerStatsHal().getStateResidency(powerEntityIds)); } private void readEnergyMeterAsync(CompletableFuture<EnergyMeasurement[]> future, int[] channelIds) { future.complete(getPowerStatsHal().readEnergyMeters(channelIds)); } } Loading
core/java/android/os/BatteryStats.java +1 −13 Original line number Diff line number Diff line Loading @@ -1556,8 +1556,7 @@ public abstract class BatteryStats implements Parcelable { public int statSoftIrqTime; public int statIdlTime; // Platform-level low power state stats public String statPlatformIdleState; // Low power state stats public String statSubsystemPowerState; public HistoryStepDetails() { Loading Loading @@ -1589,7 +1588,6 @@ public abstract class BatteryStats implements Parcelable { out.writeInt(statIrqTime); out.writeInt(statSoftIrqTime); out.writeInt(statIdlTime); out.writeString(statPlatformIdleState); out.writeString(statSubsystemPowerState); } Loading @@ -1611,7 +1609,6 @@ public abstract class BatteryStats implements Parcelable { statIrqTime = in.readInt(); statSoftIrqTime = in.readInt(); statIdlTime = in.readInt(); statPlatformIdleState = in.readString(); statSubsystemPowerState = in.readString(); } } Loading Loading @@ -6600,9 +6597,6 @@ public abstract class BatteryStats implements Parcelable { item.append(sb); item.append(")"); } item.append(", PlatformIdleStat "); item.append(rec.stepDetails.statPlatformIdleState); item.append("\n"); item.append(", SubsystemPowerState "); item.append(rec.stepDetails.statSubsystemPowerState); Loading Loading @@ -6640,12 +6634,6 @@ public abstract class BatteryStats implements Parcelable { item.append(','); item.append(rec.stepDetails.statIdlTime); item.append(','); if (rec.stepDetails.statPlatformIdleState != null) { item.append(rec.stepDetails.statPlatformIdleState); if (rec.stepDetails.statSubsystemPowerState != null) { item.append(','); } } if (rec.stepDetails.statSubsystemPowerState != null) { item.append(rec.stepDetails.statSubsystemPowerState); Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +1 −7 Original line number Diff line number Diff line Loading @@ -173,7 +173,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version static final int VERSION = 191 + (USE_OLD_HISTORY ? 1000 : 0); static final int VERSION = 192 + (USE_OLD_HISTORY ? 1000 : 0); // The maximum number of names wakelocks we will keep track of // per uid; once the limit is reached, we batch the remaining wakelocks Loading Loading @@ -362,7 +362,6 @@ public class BatteryStatsImpl extends BatteryStats { public interface PlatformIdleStateCallback { public void fillLowPowerStats(RpmStats rpmStats); public String getPlatformLowPowerStats(); public String getSubsystemLowPowerStats(); } Loading Loading @@ -3482,11 +3481,6 @@ public class BatteryStatsImpl extends BatteryStats { } if (computeStepDetails) { if (mPlatformIdleStateCallback != null) { mCurHistoryStepDetails.statPlatformIdleState = mPlatformIdleStateCallback.getPlatformLowPowerStats(); if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" + mCurHistoryStepDetails.statPlatformIdleState); mCurHistoryStepDetails.statSubsystemPowerState = mPlatformIdleStateCallback.getSubsystemLowPowerStats(); if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" + Loading
services/core/java/android/power/PowerStatsInternal.java +45 −0 Original line number Diff line number Diff line Loading @@ -18,8 +18,12 @@ package android.power; import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.power.stats.Channel; import android.hardware.power.stats.EnergyConsumer; import android.hardware.power.stats.EnergyConsumerResult; import android.hardware.power.stats.EnergyMeasurement; import android.hardware.power.stats.PowerEntity; import android.hardware.power.stats.StateResidencyResult; import java.util.concurrent.CompletableFuture; Loading Loading @@ -51,4 +55,45 @@ public abstract class PowerStatsInternal { @NonNull public abstract CompletableFuture<EnergyConsumerResult[]> getEnergyConsumedAsync( int[] energyConsumerIds); /** * Returns the power entity info for all available {@link PowerEntity} * * @return List of available {@link PowerEntity} */ public abstract PowerEntity[] getPowerEntityInfo(); /** * Returns a CompletableFuture that will get a {@link StateResidencyResult} array for the * available requested power entities. * * @param powerEntityIds Array of {@link PowerEntity.id} for which state residency is being * requested. * * @return A Future containing a list of {@link StateResidencyResult} objects containing state * residency results for all listed {@link PowerEntity.id}. */ @NonNull public abstract CompletableFuture<StateResidencyResult[]> getStateResidencyAsync( int[] powerEntityIds); /** * Returns the channel info for all available {@link Channel} * * @return List of available {@link Channel} */ public abstract Channel[] getEnergyMeterInfo(); /** * Returns a CompletableFuture that will get a {@link EnergyMeasurement} array for the * available requested channels. * * @param channelIds Array of {@link Channel.id} for accumulated energy is being requested. * * @return A Future containing a list of {@link EnergyMeasurement} objects containing * accumulated energy measurements for all listed {@link Channel.id}. */ @NonNull public abstract CompletableFuture<EnergyMeasurement[]> readEnergyMeterAsync( int[] channelIds); }
services/core/java/com/android/server/am/BatteryStatsService.java +98 −45 Original line number Diff line number Diff line Loading @@ -21,6 +21,10 @@ import android.content.ContentResolver; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.hardware.power.stats.PowerEntity; import android.hardware.power.stats.State; import android.hardware.power.stats.StateResidency; import android.hardware.power.stats.StateResidencyResult; import android.net.INetworkManagementEventObserver; import android.net.NetworkCapabilities; import android.os.BatteryStats; Loading Loading @@ -51,6 +55,7 @@ import android.os.connectivity.WifiBatteryStats; import android.os.health.HealthStatsParceler; import android.os.health.HealthStatsWriter; import android.os.health.UidHealthStats; import android.power.PowerStatsInternal; import android.provider.Settings; import android.telephony.DataConnectionRealTimeInfo; import android.telephony.ModemActivityInfo; Loading Loading @@ -87,10 +92,13 @@ import java.nio.charset.CodingErrorAction; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; /** * All information we are collecting about things that can happen that impact Loading @@ -112,23 +120,23 @@ public final class BatteryStatsService extends IBatteryStats.Stub private final BatteryExternalStatsWorker mWorker; private final BatteryUsageStatsProvider mBatteryUsageStatsProvider; private native void getLowPowerStats(RpmStats rpmStats); private native int getPlatformLowPowerStats(ByteBuffer outBuffer); private native int getSubsystemLowPowerStats(ByteBuffer outBuffer); private native void getRailEnergyPowerStats(RailStats railStats); private CharsetDecoder mDecoderStat = StandardCharsets.UTF_8 .newDecoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .replaceWith("?"); private ByteBuffer mUtf8BufferStat = ByteBuffer.allocateDirect(MAX_LOW_POWER_STATS_SIZE); private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE); private static final int MAX_LOW_POWER_STATS_SIZE = 4096; private static final int POWER_STATS_QUERY_TIMEOUT_MILLIS = 2000; private final HandlerThread mHandlerThread; private final Handler mHandler; private final Object mLock = new Object(); private PowerStatsInternal mPowerStatsInternal = null; private Map<Integer, String> mEntityNames = new HashMap(); private Map<Integer, Map<Integer, String>> mStateNames = new HashMap(); @GuardedBy("mStats") private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; @GuardedBy("mStats") Loading Loading @@ -163,16 +171,57 @@ public final class BatteryStatsService extends IBatteryStats.Stub } }; private void populatePowerEntityMaps() { if (mPowerStatsInternal == null) { // PowerStatsInternal unavailable, don't bother populating maps. mEntityNames = null; mStateNames = null; return; } PowerEntity[] entities = mPowerStatsInternal.getPowerEntityInfo(); if (entities == null) { return; } for (int i = 0; i < entities.length; i++) { final PowerEntity entity = entities[i]; Map<Integer, String> states = new HashMap(); for (int j = 0; j < entity.states.length; j++) { final State state = entity.states[j]; states.put(state.id, state.name); } mEntityNames.put(entity.id, entity.name); mStateNames.put(entity.id, states); } } /** * Replaces the information in the given rpmStats with up-to-date information. */ @Override public void fillLowPowerStats(RpmStats rpmStats) { if (DBG) Slog.d(TAG, "begin getLowPowerStats"); final StateResidencyResult[] results; try { getLowPowerStats(rpmStats); } finally { if (DBG) Slog.d(TAG, "end getLowPowerStats"); results = mPowerStatsInternal.getStateResidencyAsync(new int[0]) .get(POWER_STATS_QUERY_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); } catch (Exception e) { Slog.e(TAG, "Failed to getStateResidencyAsync", e); return; } for (int i = 0; i < results.length; i++) { final StateResidencyResult result = results[i]; RpmStats.PowerStateSubsystem subsystem = rpmStats.getSubsystem(mEntityNames.get(result.id)); for (int j = 0; j < result.stateResidencyData.length; j++) { final StateResidency stateResidency = result.stateResidencyData[j]; subsystem.putState(mStateNames.get(result.id).get(stateResidency.id), stateResidency.totalTimeInStateMs, (int) stateResidency.totalStateEntryCount); } } } Loading @@ -187,47 +236,46 @@ public final class BatteryStatsService extends IBatteryStats.Stub } @Override public String getPlatformLowPowerStats() { if (DBG) Slog.d(TAG, "begin getPlatformLowPowerStats"); public String getSubsystemLowPowerStats() { final StateResidencyResult[] results; try { mUtf8BufferStat.clear(); mUtf16BufferStat.clear(); mDecoderStat.reset(); int bytesWritten = getPlatformLowPowerStats(mUtf8BufferStat); if (bytesWritten < 0) { return null; } else if (bytesWritten == 0) { results = mPowerStatsInternal.getStateResidencyAsync(new int[0]) .get(POWER_STATS_QUERY_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); } catch (Exception e) { Slog.e(TAG, "Failed to getStateResidencyAsync", e); return "Empty"; } mUtf8BufferStat.limit(bytesWritten); mDecoderStat.decode(mUtf8BufferStat, mUtf16BufferStat, true); mUtf16BufferStat.flip(); return mUtf16BufferStat.toString(); } finally { if (DBG) Slog.d(TAG, "end getPlatformLowPowerStats"); } if (results.length == 0) return "Empty"; int charsLeft = MAX_LOW_POWER_STATS_SIZE; StringBuilder builder = new StringBuilder("SubsystemPowerState"); for (int i = 0; i < results.length; i++) { final StateResidencyResult result = results[i]; StringBuilder subsystemBuilder = new StringBuilder(); subsystemBuilder.append(" subsystem_" + i); subsystemBuilder.append(" name=" + mEntityNames.get(result.id)); for (int j = 0; j < result.stateResidencyData.length; j++) { final StateResidency stateResidency = result.stateResidencyData[j]; subsystemBuilder.append(" state_" + j); subsystemBuilder.append(" name=" + mStateNames.get(result.id).get( stateResidency.id)); subsystemBuilder.append(" time=" + stateResidency.totalTimeInStateMs); subsystemBuilder.append(" count=" + stateResidency.totalStateEntryCount); subsystemBuilder.append(" last entry=" + stateResidency.lastEntryTimestampMs); } @Override public String getSubsystemLowPowerStats() { if (DBG) Slog.d(TAG, "begin getSubsystemLowPowerStats"); try { mUtf8BufferStat.clear(); mUtf16BufferStat.clear(); mDecoderStat.reset(); int bytesWritten = getSubsystemLowPowerStats(mUtf8BufferStat); if (bytesWritten < 0) { return null; } else if (bytesWritten == 0) { return "Empty"; if (subsystemBuilder.length() <= charsLeft) { charsLeft -= subsystemBuilder.length(); builder.append(subsystemBuilder); } else { Slog.e(TAG, "getSubsystemLowPowerStats: buffer not enough"); break; } mUtf8BufferStat.limit(bytesWritten); mDecoderStat.decode(mUtf8BufferStat, mUtf16BufferStat, true); mUtf16BufferStat.flip(); return mUtf16BufferStat.toString(); } finally { if (DBG) Slog.d(TAG, "end getSubsystemLowPowerStats"); } return builder.toString(); } BatteryStatsService(Context context, File systemDir, Handler handler) { Loading Loading @@ -274,6 +322,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub } catch (RemoteException e) { Slog.e(TAG, "Could not register INetworkManagement event observer " + e); } mPowerStatsInternal = LocalServices.getService(PowerStatsInternal.class); if (mPowerStatsInternal != null) { populatePowerEntityMaps(); } Watchdog.getInstance().addMonitor(this); } Loading
services/core/java/com/android/server/powerstats/PowerStatsService.java +42 −0 Original line number Diff line number Diff line Loading @@ -21,7 +21,9 @@ import android.content.Context; import android.hardware.power.stats.Channel; import android.hardware.power.stats.EnergyConsumer; import android.hardware.power.stats.EnergyConsumerResult; import android.hardware.power.stats.EnergyMeasurement; import android.hardware.power.stats.PowerEntity; import android.hardware.power.stats.StateResidencyResult; import android.os.Binder; import android.os.Environment; import android.os.Handler; Loading Loading @@ -245,10 +247,50 @@ public class PowerStatsService extends SystemService { future, energyConsumerIds)); return future; } @Override public PowerEntity[] getPowerEntityInfo() { return getPowerStatsHal().getPowerEntityInfo(); } @Override public CompletableFuture<StateResidencyResult[]> getStateResidencyAsync( int[] powerEntityIds) { final CompletableFuture<StateResidencyResult[]> future = new CompletableFuture<>(); mHandler.sendMessage( PooledLambda.obtainMessage(PowerStatsService.this::getStateResidencyAsync, future, powerEntityIds)); return future; } @Override public Channel[] getEnergyMeterInfo() { return getPowerStatsHal().getEnergyMeterInfo(); } @Override public CompletableFuture<EnergyMeasurement[]> readEnergyMeterAsync( int[] channelIds) { final CompletableFuture<EnergyMeasurement[]> future = new CompletableFuture<>(); mHandler.sendMessage( PooledLambda.obtainMessage(PowerStatsService.this::readEnergyMeterAsync, future, channelIds)); return future; } } private void getEnergyConsumedAsync(CompletableFuture<EnergyConsumerResult[]> future, int[] energyConsumerIds) { future.complete(getPowerStatsHal().getEnergyConsumed(energyConsumerIds)); } private void getStateResidencyAsync(CompletableFuture<StateResidencyResult[]> future, int[] powerEntityIds) { future.complete(getPowerStatsHal().getStateResidency(powerEntityIds)); } private void readEnergyMeterAsync(CompletableFuture<EnergyMeasurement[]> future, int[] channelIds) { future.complete(getPowerStatsHal().readEnergyMeters(channelIds)); } }