Loading core/java/android/os/BatteryConsumer.java +10 −2 Original line number Diff line number Diff line Loading @@ -45,6 +45,8 @@ public abstract class BatteryConsumer { POWER_COMPONENT_FLASHLIGHT, POWER_COMPONENT_MOBILE_RADIO, POWER_COMPONENT_SYSTEM_SERVICES, POWER_COMPONENT_SENSORS, POWER_COMPONENT_GNSS, }) @Retention(RetentionPolicy.SOURCE) public static @interface PowerComponent { Loading @@ -59,8 +61,10 @@ public abstract class BatteryConsumer { public static final int POWER_COMPONENT_FLASHLIGHT = 6; public static final int POWER_COMPONENT_SYSTEM_SERVICES = 7; public static final int POWER_COMPONENT_MOBILE_RADIO = 8; public static final int POWER_COMPONENT_SENSORS = 9; public static final int POWER_COMPONENT_GNSS = 10; public static final int POWER_COMPONENT_COUNT = 9; public static final int POWER_COMPONENT_COUNT = 11; public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000; public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999; Loading Loading @@ -90,6 +94,8 @@ public abstract class BatteryConsumer { TIME_COMPONENT_CAMERA, TIME_COMPONENT_FLASHLIGHT, TIME_COMPONENT_MOBILE_RADIO, TIME_COMPONENT_SENSORS, TIME_COMPONENT_GNSS, }) @Retention(RetentionPolicy.SOURCE) public static @interface TimeComponent { Loading @@ -104,8 +110,10 @@ public abstract class BatteryConsumer { public static final int TIME_COMPONENT_VIDEO = 6; public static final int TIME_COMPONENT_FLASHLIGHT = 7; public static final int TIME_COMPONENT_MOBILE_RADIO = 8; public static final int TIME_COMPONENT_SENSORS = 9; public static final int TIME_COMPONENT_GNSS = 10; public static final int TIME_COMPONENT_COUNT = 9; public static final int TIME_COMPONENT_COUNT = 11; public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000; public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999; Loading core/java/com/android/internal/os/BatteryStatsHelper.java +2 −1 Original line number Diff line number Diff line Loading @@ -339,8 +339,9 @@ public class BatteryStatsHelper { } mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile)); mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile)); mPowerCalculators.add(new SensorPowerCalculator(mPowerProfile, mPowerCalculators.add(new SensorPowerCalculator( mContext.getSystemService(SensorManager.class))); mPowerCalculators.add(new GnssPowerCalculator(mPowerProfile)); mPowerCalculators.add(new CameraPowerCalculator(mPowerProfile)); mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile)); mPowerCalculators.add(new MediaPowerCalculator(mPowerProfile)); Loading core/java/com/android/internal/os/BatteryUsageStatsProvider.java +2 −1 Original line number Diff line number Diff line Loading @@ -62,8 +62,9 @@ public class BatteryUsageStatsProvider { } mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile)); mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile)); mPowerCalculators.add(new SensorPowerCalculator(mPowerProfile, mPowerCalculators.add(new SensorPowerCalculator( mContext.getSystemService(SensorManager.class))); mPowerCalculators.add(new GnssPowerCalculator(mPowerProfile)); mPowerCalculators.add(new CameraPowerCalculator(mPowerProfile)); mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile)); mPowerCalculators.add(new AudioPowerCalculator(mPowerProfile)); Loading core/java/com/android/internal/os/GnssPowerCalculator.java 0 → 100644 +124 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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 com.android.internal.os; import android.location.GnssSignalQuality; import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; import android.os.UidBatteryConsumer; import android.os.UserHandle; import android.util.SparseArray; import java.util.List; /** * Estimates the amount of power consumed by the GNSS (e.g. GPS). */ public class GnssPowerCalculator extends PowerCalculator { private final double mAveragePowerGnssOn; private final double[] mAveragePowerPerSignalQuality; public GnssPowerCalculator(PowerProfile profile) { mAveragePowerGnssOn = profile.getAveragePowerOrDefault(PowerProfile.POWER_GPS_ON, -1); mAveragePowerPerSignalQuality = new double[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS]; for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) { mAveragePowerPerSignalQuality[i] = profile.getAveragePower( PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i); } } @Override public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats, long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query, SparseArray<UserHandle> asUsers) { final double averageGnssPowerMa = getAverageGnssPower(batteryStats, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED); final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders = builder.getUidBatteryConsumerBuilders(); for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i); calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs, rawUptimeUs, query, averageGnssPowerMa); } } private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query, double averageGnssPowerMa) { final long durationMs = computeDuration(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED); double powerMah = computePower(durationMs, averageGnssPowerMa); app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_GNSS, durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_GNSS, powerMah); } @Override public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats, long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) { double averageGnssPowerMa = getAverageGnssPower(batteryStats, rawRealtimeUs, statsType); for (int i = sippers.size() - 1; i >= 0; i--) { final BatterySipper app = sippers.get(i); if (app.drainType == BatterySipper.DrainType.APP) { calculateApp(app, app.uidObj, rawRealtimeUs, statsType, averageGnssPowerMa); } } } protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, int statsType, double averageGnssPowerMa) { final long durationMs = computeDuration(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED); double powerMah = computePower(durationMs, averageGnssPowerMa); app.gpsTimeMs = durationMs; app.gpsPowerMah = powerMah; } private long computeDuration(BatteryStats.Uid u, long rawRealtimeUs, int statsType) { final SparseArray<? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats(); final BatteryStats.Uid.Sensor sensor = sensorStats.get(BatteryStats.Uid.Sensor.GPS); if (sensor == null) { return 0; } final BatteryStats.Timer timer = sensor.getSensorTime(); return timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000; } private double computePower(long sensorTime, double averageGnssPowerMa) { return (sensorTime * averageGnssPowerMa) / (1000 * 60 * 60); } private double getAverageGnssPower(BatteryStats stats, long rawRealtimeUs, int statsType) { double averagePower = mAveragePowerGnssOn; if (averagePower != -1) { return averagePower; } averagePower = 0; long totalTime = 0; double totalPower = 0; for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) { long timePerLevel = stats.getGpsSignalQualityTime(i, rawRealtimeUs, statsType); totalTime += timePerLevel; totalPower += mAveragePowerPerSignalQuality[i] * timePerLevel; } if (totalTime != 0) { averagePower = totalPower / totalTime; } return averagePower; } } core/java/com/android/internal/os/SensorPowerCalculator.java +50 −52 Original line number Diff line number Diff line Loading @@ -17,81 +17,79 @@ package com.android.internal.os; import android.hardware.Sensor; import android.hardware.SensorManager; import android.location.GnssSignalQuality; import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.UserHandle; import android.os.BatteryUsageStatsQuery; import android.os.UidBatteryConsumer; import android.util.SparseArray; import java.util.List; public class SensorPowerCalculator extends PowerCalculator { private final PowerProfile mPowerProfile; private final List<Sensor> mSensors; private double mGpsPower; private final SparseArray<Sensor> mSensors; public SensorPowerCalculator(PowerProfile profile, SensorManager sensorManager) { mPowerProfile = profile; mSensors = sensorManager.getSensorList(Sensor.TYPE_ALL); public SensorPowerCalculator(SensorManager sensorManager) { List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL); mSensors = new SparseArray<>(sensors.size()); for (int i = 0; i < sensors.size(); i++) { Sensor sensor = sensors.get(i); mSensors.put(sensor.getHandle(), sensor); } } @Override public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats, long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) { mGpsPower = getAverageGpsPower(batteryStats, rawRealtimeUs, statsType); super.calculate(sippers, batteryStats, rawRealtimeUs, rawUptimeUs, statsType, asUsers); protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_SENSORS, calculateDuration(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED)) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SENSORS, calculatePowerMah(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED)); } @Override protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, long rawUptimeUs, int statsType) { // Process Sensor usage app.sensorPowerMah = calculatePowerMah(u, rawRealtimeUs, statsType); } private long calculateDuration(BatteryStats.Uid u, long rawRealtimeUs, int statsType) { long durationMs = 0; final SparseArray<? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats(); final int NSE = sensorStats.size(); for (int ise = 0; ise < NSE; ise++) { final BatteryStats.Uid.Sensor sensor = sensorStats.valueAt(ise); final int sensorHandle = sensorStats.keyAt(ise); final BatteryStats.Timer timer = sensor.getSensorTime(); final long sensorTime = timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000; switch (sensorHandle) { case BatteryStats.Uid.Sensor.GPS: app.gpsTimeMs = sensorTime; app.gpsPowerMah = (app.gpsTimeMs * mGpsPower) / (1000 * 60 * 60); break; default: final int sensorsCount = mSensors.size(); for (int i = 0; i < sensorsCount; i++) { final Sensor s = mSensors.get(i); if (s.getHandle() == sensorHandle) { app.sensorPowerMah += (sensorTime * s.getPower()) / (1000 * 60 * 60); break; if (sensorHandle == BatteryStats.Uid.Sensor.GPS) { continue; } final BatteryStats.Uid.Sensor sensor = sensorStats.valueAt(ise); final BatteryStats.Timer timer = sensor.getSensorTime(); durationMs += timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000; } break; } return durationMs; } private double calculatePowerMah(BatteryStats.Uid u, long rawRealtimeUs, int statsType) { double powerMah = 0; final SparseArray<? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats(); final int count = sensorStats.size(); for (int ise = 0; ise < count; ise++) { final int sensorHandle = sensorStats.keyAt(ise); // TODO(b/178127364): remove BatteryStats.Uid.Sensor.GPS and references to it. if (sensorHandle == BatteryStats.Uid.Sensor.GPS) { continue; } private double getAverageGpsPower(BatteryStats stats, long rawRealtimeUs, int statsType) { double averagePower = mPowerProfile.getAveragePowerOrDefault(PowerProfile.POWER_GPS_ON, -1); if (averagePower != -1) { return averagePower; final BatteryStats.Uid.Sensor sensor = sensorStats.valueAt(ise); final BatteryStats.Timer timer = sensor.getSensorTime(); final long sensorTime = timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000; if (sensorTime != 0) { Sensor s = mSensors.get(sensorHandle); if (s != null) { powerMah += (sensorTime * s.getPower()) / (1000 * 60 * 60); } averagePower = 0; long totalTime = 0; double totalPower = 0; for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) { long timePerLevel = stats.getGpsSignalQualityTime(i, rawRealtimeUs, statsType); totalTime += timePerLevel; totalPower += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i) * timePerLevel; } if (totalTime != 0) { averagePower = totalPower / totalTime; } return averagePower; return powerMah; } } Loading
core/java/android/os/BatteryConsumer.java +10 −2 Original line number Diff line number Diff line Loading @@ -45,6 +45,8 @@ public abstract class BatteryConsumer { POWER_COMPONENT_FLASHLIGHT, POWER_COMPONENT_MOBILE_RADIO, POWER_COMPONENT_SYSTEM_SERVICES, POWER_COMPONENT_SENSORS, POWER_COMPONENT_GNSS, }) @Retention(RetentionPolicy.SOURCE) public static @interface PowerComponent { Loading @@ -59,8 +61,10 @@ public abstract class BatteryConsumer { public static final int POWER_COMPONENT_FLASHLIGHT = 6; public static final int POWER_COMPONENT_SYSTEM_SERVICES = 7; public static final int POWER_COMPONENT_MOBILE_RADIO = 8; public static final int POWER_COMPONENT_SENSORS = 9; public static final int POWER_COMPONENT_GNSS = 10; public static final int POWER_COMPONENT_COUNT = 9; public static final int POWER_COMPONENT_COUNT = 11; public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000; public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999; Loading Loading @@ -90,6 +94,8 @@ public abstract class BatteryConsumer { TIME_COMPONENT_CAMERA, TIME_COMPONENT_FLASHLIGHT, TIME_COMPONENT_MOBILE_RADIO, TIME_COMPONENT_SENSORS, TIME_COMPONENT_GNSS, }) @Retention(RetentionPolicy.SOURCE) public static @interface TimeComponent { Loading @@ -104,8 +110,10 @@ public abstract class BatteryConsumer { public static final int TIME_COMPONENT_VIDEO = 6; public static final int TIME_COMPONENT_FLASHLIGHT = 7; public static final int TIME_COMPONENT_MOBILE_RADIO = 8; public static final int TIME_COMPONENT_SENSORS = 9; public static final int TIME_COMPONENT_GNSS = 10; public static final int TIME_COMPONENT_COUNT = 9; public static final int TIME_COMPONENT_COUNT = 11; public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000; public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999; Loading
core/java/com/android/internal/os/BatteryStatsHelper.java +2 −1 Original line number Diff line number Diff line Loading @@ -339,8 +339,9 @@ public class BatteryStatsHelper { } mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile)); mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile)); mPowerCalculators.add(new SensorPowerCalculator(mPowerProfile, mPowerCalculators.add(new SensorPowerCalculator( mContext.getSystemService(SensorManager.class))); mPowerCalculators.add(new GnssPowerCalculator(mPowerProfile)); mPowerCalculators.add(new CameraPowerCalculator(mPowerProfile)); mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile)); mPowerCalculators.add(new MediaPowerCalculator(mPowerProfile)); Loading
core/java/com/android/internal/os/BatteryUsageStatsProvider.java +2 −1 Original line number Diff line number Diff line Loading @@ -62,8 +62,9 @@ public class BatteryUsageStatsProvider { } mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile)); mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile)); mPowerCalculators.add(new SensorPowerCalculator(mPowerProfile, mPowerCalculators.add(new SensorPowerCalculator( mContext.getSystemService(SensorManager.class))); mPowerCalculators.add(new GnssPowerCalculator(mPowerProfile)); mPowerCalculators.add(new CameraPowerCalculator(mPowerProfile)); mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile)); mPowerCalculators.add(new AudioPowerCalculator(mPowerProfile)); Loading
core/java/com/android/internal/os/GnssPowerCalculator.java 0 → 100644 +124 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 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 com.android.internal.os; import android.location.GnssSignalQuality; import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; import android.os.UidBatteryConsumer; import android.os.UserHandle; import android.util.SparseArray; import java.util.List; /** * Estimates the amount of power consumed by the GNSS (e.g. GPS). */ public class GnssPowerCalculator extends PowerCalculator { private final double mAveragePowerGnssOn; private final double[] mAveragePowerPerSignalQuality; public GnssPowerCalculator(PowerProfile profile) { mAveragePowerGnssOn = profile.getAveragePowerOrDefault(PowerProfile.POWER_GPS_ON, -1); mAveragePowerPerSignalQuality = new double[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS]; for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) { mAveragePowerPerSignalQuality[i] = profile.getAveragePower( PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i); } } @Override public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats, long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query, SparseArray<UserHandle> asUsers) { final double averageGnssPowerMa = getAverageGnssPower(batteryStats, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED); final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders = builder.getUidBatteryConsumerBuilders(); for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i); calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs, rawUptimeUs, query, averageGnssPowerMa); } } private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query, double averageGnssPowerMa) { final long durationMs = computeDuration(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED); double powerMah = computePower(durationMs, averageGnssPowerMa); app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_GNSS, durationMs) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_GNSS, powerMah); } @Override public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats, long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) { double averageGnssPowerMa = getAverageGnssPower(batteryStats, rawRealtimeUs, statsType); for (int i = sippers.size() - 1; i >= 0; i--) { final BatterySipper app = sippers.get(i); if (app.drainType == BatterySipper.DrainType.APP) { calculateApp(app, app.uidObj, rawRealtimeUs, statsType, averageGnssPowerMa); } } } protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, int statsType, double averageGnssPowerMa) { final long durationMs = computeDuration(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED); double powerMah = computePower(durationMs, averageGnssPowerMa); app.gpsTimeMs = durationMs; app.gpsPowerMah = powerMah; } private long computeDuration(BatteryStats.Uid u, long rawRealtimeUs, int statsType) { final SparseArray<? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats(); final BatteryStats.Uid.Sensor sensor = sensorStats.get(BatteryStats.Uid.Sensor.GPS); if (sensor == null) { return 0; } final BatteryStats.Timer timer = sensor.getSensorTime(); return timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000; } private double computePower(long sensorTime, double averageGnssPowerMa) { return (sensorTime * averageGnssPowerMa) / (1000 * 60 * 60); } private double getAverageGnssPower(BatteryStats stats, long rawRealtimeUs, int statsType) { double averagePower = mAveragePowerGnssOn; if (averagePower != -1) { return averagePower; } averagePower = 0; long totalTime = 0; double totalPower = 0; for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) { long timePerLevel = stats.getGpsSignalQualityTime(i, rawRealtimeUs, statsType); totalTime += timePerLevel; totalPower += mAveragePowerPerSignalQuality[i] * timePerLevel; } if (totalTime != 0) { averagePower = totalPower / totalTime; } return averagePower; } }
core/java/com/android/internal/os/SensorPowerCalculator.java +50 −52 Original line number Diff line number Diff line Loading @@ -17,81 +17,79 @@ package com.android.internal.os; import android.hardware.Sensor; import android.hardware.SensorManager; import android.location.GnssSignalQuality; import android.os.BatteryConsumer; import android.os.BatteryStats; import android.os.UserHandle; import android.os.BatteryUsageStatsQuery; import android.os.UidBatteryConsumer; import android.util.SparseArray; import java.util.List; public class SensorPowerCalculator extends PowerCalculator { private final PowerProfile mPowerProfile; private final List<Sensor> mSensors; private double mGpsPower; private final SparseArray<Sensor> mSensors; public SensorPowerCalculator(PowerProfile profile, SensorManager sensorManager) { mPowerProfile = profile; mSensors = sensorManager.getSensorList(Sensor.TYPE_ALL); public SensorPowerCalculator(SensorManager sensorManager) { List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL); mSensors = new SparseArray<>(sensors.size()); for (int i = 0; i < sensors.size(); i++) { Sensor sensor = sensors.get(i); mSensors.put(sensor.getHandle(), sensor); } } @Override public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats, long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) { mGpsPower = getAverageGpsPower(batteryStats, rawRealtimeUs, statsType); super.calculate(sippers, batteryStats, rawRealtimeUs, rawUptimeUs, statsType, asUsers); protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_SENSORS, calculateDuration(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED)) .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SENSORS, calculatePowerMah(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED)); } @Override protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, long rawUptimeUs, int statsType) { // Process Sensor usage app.sensorPowerMah = calculatePowerMah(u, rawRealtimeUs, statsType); } private long calculateDuration(BatteryStats.Uid u, long rawRealtimeUs, int statsType) { long durationMs = 0; final SparseArray<? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats(); final int NSE = sensorStats.size(); for (int ise = 0; ise < NSE; ise++) { final BatteryStats.Uid.Sensor sensor = sensorStats.valueAt(ise); final int sensorHandle = sensorStats.keyAt(ise); final BatteryStats.Timer timer = sensor.getSensorTime(); final long sensorTime = timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000; switch (sensorHandle) { case BatteryStats.Uid.Sensor.GPS: app.gpsTimeMs = sensorTime; app.gpsPowerMah = (app.gpsTimeMs * mGpsPower) / (1000 * 60 * 60); break; default: final int sensorsCount = mSensors.size(); for (int i = 0; i < sensorsCount; i++) { final Sensor s = mSensors.get(i); if (s.getHandle() == sensorHandle) { app.sensorPowerMah += (sensorTime * s.getPower()) / (1000 * 60 * 60); break; if (sensorHandle == BatteryStats.Uid.Sensor.GPS) { continue; } final BatteryStats.Uid.Sensor sensor = sensorStats.valueAt(ise); final BatteryStats.Timer timer = sensor.getSensorTime(); durationMs += timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000; } break; } return durationMs; } private double calculatePowerMah(BatteryStats.Uid u, long rawRealtimeUs, int statsType) { double powerMah = 0; final SparseArray<? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats(); final int count = sensorStats.size(); for (int ise = 0; ise < count; ise++) { final int sensorHandle = sensorStats.keyAt(ise); // TODO(b/178127364): remove BatteryStats.Uid.Sensor.GPS and references to it. if (sensorHandle == BatteryStats.Uid.Sensor.GPS) { continue; } private double getAverageGpsPower(BatteryStats stats, long rawRealtimeUs, int statsType) { double averagePower = mPowerProfile.getAveragePowerOrDefault(PowerProfile.POWER_GPS_ON, -1); if (averagePower != -1) { return averagePower; final BatteryStats.Uid.Sensor sensor = sensorStats.valueAt(ise); final BatteryStats.Timer timer = sensor.getSensorTime(); final long sensorTime = timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000; if (sensorTime != 0) { Sensor s = mSensors.get(sensorHandle); if (s != null) { powerMah += (sensorTime * s.getPower()) / (1000 * 60 * 60); } averagePower = 0; long totalTime = 0; double totalPower = 0; for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) { long timePerLevel = stats.getGpsSignalQualityTime(i, rawRealtimeUs, statsType); totalTime += timePerLevel; totalPower += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i) * timePerLevel; } if (totalTime != 0) { averagePower = totalPower / totalTime; } return averagePower; return powerMah; } }