diff options
11 files changed, 377 insertions, 430 deletions
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/res/drawable/gm_amp_24.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/drawable/gm_amp_24.xml new file mode 100644 index 000000000000..1f5731821c94 --- /dev/null +++ b/core/tests/batterystatstests/BatteryStatsViewer/res/drawable/gm_amp_24.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="#d14d2c"> + <path + android:fillColor="@android:color/white" + android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM11.17,19.5h-0.83l0.82,-5.83 -4.18,0.01 5.85,-9.17h0.83l-0.84,5.84h4.17l-5.82,9.15z"/> +</vector> diff --git a/core/tests/batterystatstests/BatteryStatsViewer/res/drawable/gm_calculate_24.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/drawable/gm_calculate_24.xml new file mode 100644 index 000000000000..70aac32227c4 --- /dev/null +++ b/core/tests/batterystatstests/BatteryStatsViewer/res/drawable/gm_calculate_24.xml @@ -0,0 +1,25 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="#269e5c"> + <path + android:fillColor="@android:color/white" + android:pathData="M19,3H5C3.9,3 3,3.9 3,5v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5C21,3.9 20.1,3 19,3zM19,19H5V5h14V19z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M6.25,7.72h5v1.5h-5z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M13,15.75h5v1.5h-5z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M13,13.25h5v1.5h-5z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M8,18l1.5,0l0,-2l2,0l0,-1.5l-2,0l0,-2l-1.5,0l0,2l-2,0l0,1.5l2,0z"/> + <path + android:fillColor="@android:color/white" + android:pathData="M14.09,10.95l1.41,-1.41l1.41,1.41l1.06,-1.06l-1.41,-1.42l1.41,-1.41l-1.06,-1.06l-1.41,1.41l-1.41,-1.41l-1.06,1.06l1.41,1.41l-1.41,1.42z"/> +</vector> diff --git a/core/tests/batterystatstests/BatteryStatsViewer/res/drawable/gm_custom_24.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/drawable/gm_custom_24.xml new file mode 100644 index 000000000000..39f9689d2ec4 --- /dev/null +++ b/core/tests/batterystatstests/BatteryStatsViewer/res/drawable/gm_custom_24.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="#d14d2c"> + <path + android:fillColor="@android:color/white" + android:pathData="M22,9L22,7h-2L20,5c0,-1.1 -0.9,-2 -2,-2L4,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2v-2h2v-2h-2v-2h2v-2h-2L20,9h2zM18,19L4,19L4,5h14v14zM6,13h5v4L6,17v-4zM12,7h4v3h-4L12,7zM6,7h5v5L6,12L6,7zM12,11h4v6h-4v-6z"/> +</vector> diff --git a/core/tests/batterystatstests/BatteryStatsViewer/res/drawable/gm_timer_24.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/drawable/gm_timer_24.xml new file mode 100644 index 000000000000..9cae545e165b --- /dev/null +++ b/core/tests/batterystatstests/BatteryStatsViewer/res/drawable/gm_timer_24.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M15,3L9,3L9,1h6v2zM11,14h2L13,8h-2v6zM21,13.01c0,4.97 -4.02,9 -9,9s-9,-4.03 -9,-9 4.03,-9 9,-9c2.12,0 4.07,0.74 5.62,1.98l1.42,-1.42c0.51,0.42 0.98,0.9 1.41,1.41L19.03,7.4C20.26,8.93 21,10.89 21,13.01zM19,13.01c0,-3.87 -3.13,-7 -7,-7s-7,3.13 -7,7 3.13,7 7,7 7,-3.13 7,-7z"/> +</vector> diff --git a/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_entry_layout.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_entry_layout.xml index 1ced825adf31..98fc581f3420 100644 --- a/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_entry_layout.xml +++ b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_entry_layout.xml @@ -25,6 +25,13 @@ android:paddingTop="8dp" android:paddingBottom="8dp"> + <ImageView + android:id="@+id/icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginEnd="8dp"/> + <TextView android:id="@+id/title" android:layout_width="0dp" @@ -34,16 +41,18 @@ <TextView android:id="@+id/amount" - android:layout_width="0dp" - android:layout_weight="0.7" + android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginStart="8dp" android:gravity="right" + android:maxLines="1" android:textAppearance="@style/TextAppearanceBody"/> <TextView android:id="@+id/percent" - android:layout_width="64dp" + android:layout_width="76dp" android:layout_height="wrap_content" android:gravity="right" + android:maxLines="1" android:textAppearance="@style/TextAppearanceBody"/> </LinearLayout> diff --git a/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_stats_viewer_layout.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_stats_viewer_layout.xml index e58a08fd362c..24d193c49219 100644 --- a/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_stats_viewer_layout.xml +++ b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_stats_viewer_layout.xml @@ -43,10 +43,40 @@ android:paddingEnd="10dp"> <include layout="@layout/battery_consumer_info_layout"/> - </LinearLayout> + </androidx.cardview.widget.CardView> + + <LinearLayout + android:id="@+id/headings" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="2dp" + android:paddingBottom="4dp"> + <FrameLayout + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1"/> + <TextView + android:layout_width="100dp" + android:layout_height="wrap_content" + android:gravity="end" + android:paddingEnd="10dp" + android:text="Total"/> + <TextView + android:layout_width="100dp" + android:layout_height="wrap_content" + android:gravity="end" + android:paddingEnd="30dp" + android:text="Apps"/> + </LinearLayout> + + <View + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="@android:color/darker_gray"/> + <androidx.recyclerview.widget.RecyclerView android:id="@+id/battery_consumer_data_view" android:layout_width="match_parent" diff --git a/core/tests/batterystatstests/BatteryStatsViewer/res/values/colors.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/values/colors.xml new file mode 100644 index 000000000000..2dbe48b6edc0 --- /dev/null +++ b/core/tests/batterystatstests/BatteryStatsViewer/res/values/colors.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 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. + --> + +<resources> + <color name="battery_consumer_bg_power_profile">#ffffff</color> + <color name="battery_consumer_bg_measured_energy">#fff5eb</color> +</resources> diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java index 8df3de3db668..f7d7098b1726 100644 --- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java @@ -18,32 +18,21 @@ package com.android.frameworks.core.batterystatsviewer; import android.content.Context; import android.os.BatteryConsumer; -import android.os.BatteryStats; import android.os.BatteryUsageStats; -import android.os.Process; import android.os.SystemBatteryConsumer; import android.os.UidBatteryConsumer; import android.os.UserHandle; - -import com.android.internal.os.BatterySipper; -import com.android.internal.os.BatteryStatsHelper; +import android.util.DebugUtils; import java.util.ArrayList; import java.util.List; public class BatteryConsumerData { - private static final String PACKAGE_CALENDAR_PROVIDER = "com.android.providers.calendar"; - private static final String PACKAGE_MEDIA_PROVIDER = "com.android.providers.media"; - private static final String PACKAGE_SYSTEMUI = "com.android.systemui"; - private static final String[] PACKAGES_SYSTEM = {PACKAGE_MEDIA_PROVIDER, - PACKAGE_CALENDAR_PROVIDER, PACKAGE_SYSTEMUI}; - - // Unit conversion: - // mAh = uC * (1/1000)(milli/micro) * (1/3600)(hours/second) - private static final double UC_2_MAH = (1.0 / 1000) * (1.0 / 3600); enum EntryType { - POWER, + POWER_MODELED, + POWER_MEASURED, + POWER_CUSTOM, DURATION, } @@ -52,260 +41,155 @@ public class BatteryConsumerData { public EntryType entryType; public double value; public double total; + public boolean isSystemBatteryConsumer; } private final BatteryConsumerInfoHelper.BatteryConsumerInfo mBatteryConsumerInfo; private final List<Entry> mEntries = new ArrayList<>(); - public BatteryConsumerData(Context context, BatteryStatsHelper batteryStatsHelper, + public BatteryConsumerData(Context context, List<BatteryUsageStats> batteryUsageStatsList, String batteryConsumerId) { BatteryUsageStats batteryUsageStats = batteryUsageStatsList.get(0); - BatteryUsageStats powerProfileModeledUsageStats = batteryUsageStatsList.get(1); - List<BatterySipper> usageList = batteryStatsHelper.getUsageList(); - BatteryStats batteryStats = batteryStatsHelper.getStats(); - - double totalPowerMah = 0; - double totalSmearedPowerMah = 0; - double totalPowerExcludeSystemMah = 0; - double totalScreenPower = 0; - double totalProportionalSmearMah = 0; - double totalCpuPowerMah = 0; - double totalSystemServiceCpuPowerMah = 0; - double totalUsagePowerMah = 0; - double totalWakeLockPowerMah = 0; - double totalMobileRadioPowerMah = 0; - double totalWifiPowerMah = 0; - double totalBluetoothPowerMah = 0; - double totalGpsPowerMah = 0; - double totalCameraPowerMah = 0; - double totalFlashlightPowerMah = 0; - double totalSensorPowerMah = 0; - double totalAudioPowerMah = 0; - double totalVideoPowerMah = 0; - - long totalCpuTimeMs = 0; - long totalCpuFgTimeMs = 0; - long totalWakeLockTimeMs = 0; - long totalWifiRunningTimeMs = 0; - long totalBluetoothRunningTimeMs = 0; - long totalGpsTimeMs = 0; - long totalCameraTimeMs = 0; - long totalFlashlightTimeMs = 0; - long totalAudioTimeMs = 0; - long totalVideoTimeMs = 0; - - BatterySipper requestedBatterySipper = null; - for (BatterySipper sipper : usageList) { - if (sipper.drainType == BatterySipper.DrainType.SCREEN) { - totalScreenPower = sipper.sumPower(); - } + BatteryUsageStats modeledBatteryUsageStats = batteryUsageStatsList.get(1); - if (batteryConsumerId(sipper).equals(batteryConsumerId)) { - requestedBatterySipper = sipper; - } + BatteryConsumer requestedBatteryConsumer = getRequestedBatteryConsumer(batteryUsageStats, + batteryConsumerId); + BatteryConsumer requestedModeledBatteryConsumer = getRequestedBatteryConsumer( + modeledBatteryUsageStats, batteryConsumerId); - totalPowerMah += sipper.sumPower(); - totalSmearedPowerMah += sipper.totalSmearedPowerMah; - totalProportionalSmearMah += sipper.proportionalSmearMah; + if (requestedBatteryConsumer == null || requestedModeledBatteryConsumer == null) { + mBatteryConsumerInfo = null; + return; + } - if (!isSystemSipper(sipper)) { - totalPowerExcludeSystemMah += sipper.totalSmearedPowerMah; + mBatteryConsumerInfo = BatteryConsumerInfoHelper.makeBatteryConsumerInfo( + context.getPackageManager(), requestedBatteryConsumer); + + double[] totalPowerByComponentMah = new double[BatteryConsumer.POWER_COMPONENT_COUNT]; + double[] totalModeledPowerByComponentMah = + new double[BatteryConsumer.POWER_COMPONENT_COUNT]; + long[] totalDurationByComponentMs = new long[BatteryConsumer.TIME_COMPONENT_COUNT]; + final int customComponentCount = + requestedBatteryConsumer.getCustomPowerComponentCount(); + double[] totalCustomPowerByComponentMah = new double[customComponentCount]; + + computeTotalPower(batteryUsageStats, totalPowerByComponentMah); + computeTotalPower(modeledBatteryUsageStats, totalModeledPowerByComponentMah); + computeTotalPowerForCustomComponent(batteryUsageStats, totalCustomPowerByComponentMah); + computeTotalDuration(batteryUsageStats, totalDurationByComponentMs); + + for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) { + final String metricTitle = getPowerMetricTitle(component); + final int powerModel = requestedBatteryConsumer.getPowerModel(component); + if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) { + addEntry(metricTitle, EntryType.POWER_MODELED, + requestedBatteryConsumer.getConsumedPower(component), + totalPowerByComponentMah[component], + mBatteryConsumerInfo.isSystemBatteryConsumer); + } else { + addEntry(metricTitle + " (measured)", EntryType.POWER_MEASURED, + requestedBatteryConsumer.getConsumedPower(component), + totalPowerByComponentMah[component], + mBatteryConsumerInfo.isSystemBatteryConsumer); + addEntry(metricTitle + " (modeled)", EntryType.POWER_MODELED, + requestedModeledBatteryConsumer.getConsumedPower(component), + totalModeledPowerByComponentMah[component], + mBatteryConsumerInfo.isSystemBatteryConsumer); } + } - totalCpuPowerMah += sipper.cpuPowerMah; - totalSystemServiceCpuPowerMah += sipper.systemServiceCpuPowerMah; - totalUsagePowerMah += sipper.usagePowerMah; - totalWakeLockPowerMah += sipper.wakeLockPowerMah; - totalMobileRadioPowerMah += sipper.mobileRadioPowerMah; - totalWifiPowerMah += sipper.wifiPowerMah; - totalBluetoothPowerMah += sipper.bluetoothPowerMah; - totalGpsPowerMah += sipper.gpsPowerMah; - totalCameraPowerMah += sipper.cameraPowerMah; - totalFlashlightPowerMah += sipper.flashlightPowerMah; - totalSensorPowerMah += sipper.sensorPowerMah; - totalAudioPowerMah += sipper.audioPowerMah; - totalVideoPowerMah += sipper.videoPowerMah; - - totalCpuTimeMs += sipper.cpuTimeMs; - totalCpuFgTimeMs += sipper.cpuFgTimeMs; - totalWakeLockTimeMs += sipper.wakeLockTimeMs; - totalWifiRunningTimeMs += sipper.wifiRunningTimeMs; - totalBluetoothRunningTimeMs += sipper.bluetoothRunningTimeMs; - totalGpsTimeMs += sipper.gpsTimeMs; - totalCameraTimeMs += sipper.cameraTimeMs; - totalFlashlightTimeMs += sipper.flashlightTimeMs; - totalAudioTimeMs += sipper.audioTimeMs; - totalVideoTimeMs += sipper.videoTimeMs; + for (int component = 0; component < customComponentCount; component++) { + final String name = requestedBatteryConsumer.getCustomPowerComponentName( + BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + component); + addEntry(name + " (custom)", EntryType.POWER_CUSTOM, + requestedBatteryConsumer.getConsumedPowerForCustomComponent( + BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + component), + totalCustomPowerByComponentMah[component], + mBatteryConsumerInfo.isSystemBatteryConsumer); } - BatteryConsumer requestedBatteryConsumer = null; + for (int component = 0; component < BatteryConsumer.TIME_COMPONENT_COUNT; component++) { + final String metricTitle = getTimeMetricTitle(component); + addEntry(metricTitle, EntryType.DURATION, + requestedBatteryConsumer.getUsageDurationMillis(component), + totalDurationByComponentMs[component], + mBatteryConsumerInfo.isSystemBatteryConsumer); + } + } + private BatteryConsumer getRequestedBatteryConsumer(BatteryUsageStats batteryUsageStats, + String batteryConsumerId) { for (BatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) { if (batteryConsumerId(consumer).equals(batteryConsumerId)) { - requestedBatteryConsumer = consumer; + return consumer; } } - - double totalModeledCpuPowerMah = 0; - BatteryConsumer requestedBatteryConsumerPowerProfileModeled = null; - for (BatteryConsumer consumer : powerProfileModeledUsageStats.getUidBatteryConsumers()) { + for (BatteryConsumer consumer : batteryUsageStats.getSystemBatteryConsumers()) { if (batteryConsumerId(consumer).equals(batteryConsumerId)) { - requestedBatteryConsumerPowerProfileModeled = consumer; + return consumer; } - - totalModeledCpuPowerMah += consumer.getConsumedPower( - BatteryConsumer.POWER_COMPONENT_CPU); } + return null; + } - if (requestedBatterySipper == null) { - mBatteryConsumerInfo = null; - return; - } + static String getPowerMetricTitle(int componentId) { + final String componentName = DebugUtils.constantToString(BatteryConsumer.class, + "POWER_COMPONENT_", componentId); + return componentName.charAt(0) + componentName.substring(1).toLowerCase().replace('_', ' ') + + " power"; + } - if (requestedBatteryConsumer == null) { - for (BatteryConsumer consumer : batteryUsageStats.getSystemBatteryConsumers()) { - if (batteryConsumerId(consumer).equals(batteryConsumerId)) { - requestedBatteryConsumer = consumer; - break; - } + static String getTimeMetricTitle(int componentId) { + final String componentName = DebugUtils.constantToString(BatteryConsumer.class, + "TIME_COMPONENT_", componentId); + return componentName.charAt(0) + componentName.substring(1).toLowerCase().replace('_', ' ') + + " time"; + } + + private void computeTotalPower(BatteryUsageStats batteryUsageStats, + double[] powerByComponentMah) { + for (BatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) { + for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; + component++) { + powerByComponentMah[component] += consumer.getConsumedPower(component); } } + } - mBatteryConsumerInfo = BatteryConsumerInfoHelper.makeBatteryConsumerInfo( - context.getPackageManager(), requestedBatterySipper); - long totalScreenMeasuredChargeUC = - batteryStats.getScreenOnMeasuredBatteryConsumptionUC(); - long uidScreenMeasuredChargeUC = - requestedBatterySipper.uidObj.getScreenOnMeasuredBatteryConsumptionUC(); - - addEntry("Total power", EntryType.POWER, - requestedBatterySipper.totalSmearedPowerMah, totalSmearedPowerMah); - maybeAddMeasuredEnergyEntry(requestedBatterySipper.drainType, batteryStats); - - addEntry("... excluding system", EntryType.POWER, - requestedBatterySipper.totalSmearedPowerMah, totalPowerExcludeSystemMah); - addEntry("Screen, smeared", EntryType.POWER, - requestedBatterySipper.screenPowerMah, totalScreenPower); - if (uidScreenMeasuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE - && totalScreenMeasuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE) { - final double measuredCharge = UC_2_MAH * uidScreenMeasuredChargeUC; - final double totalMeasuredCharge = UC_2_MAH * totalScreenMeasuredChargeUC; - addEntry("Screen, measured", EntryType.POWER, - measuredCharge, totalMeasuredCharge); - } - addEntry("Other, smeared", EntryType.POWER, - requestedBatterySipper.proportionalSmearMah, totalProportionalSmearMah); - addEntry("Excluding smeared", EntryType.POWER, - requestedBatterySipper.totalPowerMah, totalPowerMah); - if (requestedBatteryConsumer != null) { - addEntry("CPU", EntryType.POWER, - requestedBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU), - totalCpuPowerMah); - if (requestedBatteryConsumerPowerProfileModeled != null) { - addEntry("CPU (modeled)", EntryType.POWER, - requestedBatteryConsumerPowerProfileModeled.getConsumedPower( - BatteryConsumer.POWER_COMPONENT_CPU), - totalModeledCpuPowerMah); + private void computeTotalDuration(BatteryUsageStats batteryUsageStats, + long[] durationByComponentMs) { + for (BatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) { + for (int component = 0; component < BatteryConsumer.TIME_COMPONENT_COUNT; + component++) { + durationByComponentMs[component] += consumer.getUsageDurationMillis(component); } - } else { - addEntry("CPU (sipper)", EntryType.POWER, - requestedBatterySipper.cpuPowerMah, totalCpuPowerMah); } - addEntry("System services", EntryType.POWER, - requestedBatterySipper.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah); - addEntry("Wake lock", EntryType.POWER, - requestedBatterySipper.wakeLockPowerMah, totalWakeLockPowerMah); - addEntry("Mobile radio", EntryType.POWER, - requestedBatterySipper.mobileRadioPowerMah, totalMobileRadioPowerMah); - addEntry("WiFi", EntryType.POWER, - requestedBatterySipper.wifiPowerMah, totalWifiPowerMah); - addEntry("Bluetooth", EntryType.POWER, - requestedBatterySipper.bluetoothPowerMah, totalBluetoothPowerMah); - addEntry("GPS", EntryType.POWER, - requestedBatterySipper.gpsPowerMah, totalGpsPowerMah); - addEntry("Camera", EntryType.POWER, - requestedBatterySipper.cameraPowerMah, totalCameraPowerMah); - addEntry("Flashlight", EntryType.POWER, - requestedBatterySipper.flashlightPowerMah, totalFlashlightPowerMah); - addEntry("Sensors", EntryType.POWER, - requestedBatterySipper.sensorPowerMah, totalSensorPowerMah); - addEntry("Audio", EntryType.POWER, - requestedBatterySipper.audioPowerMah, totalAudioPowerMah); - addEntry("Video", EntryType.POWER, - requestedBatterySipper.videoPowerMah, totalVideoPowerMah); - - addEntry("CPU time", EntryType.DURATION, - requestedBatterySipper.cpuTimeMs, totalCpuTimeMs); - addEntry("CPU foreground time", EntryType.DURATION, - requestedBatterySipper.cpuFgTimeMs, totalCpuFgTimeMs); - addEntry("Wake lock time", EntryType.DURATION, - requestedBatterySipper.wakeLockTimeMs, totalWakeLockTimeMs); - addEntry("WiFi running time", EntryType.DURATION, - requestedBatterySipper.wifiRunningTimeMs, totalWifiRunningTimeMs); - addEntry("Bluetooth time", EntryType.DURATION, - requestedBatterySipper.bluetoothRunningTimeMs, totalBluetoothRunningTimeMs); - addEntry("GPS time", EntryType.DURATION, - requestedBatterySipper.gpsTimeMs, totalGpsTimeMs); - addEntry("Camera time", EntryType.DURATION, - requestedBatterySipper.cameraTimeMs, totalCameraTimeMs); - addEntry("Flashlight time", EntryType.DURATION, - requestedBatterySipper.flashlightTimeMs, totalFlashlightTimeMs); - addEntry("Audio time", EntryType.DURATION, - requestedBatterySipper.audioTimeMs, totalAudioTimeMs); - addEntry("Video time", EntryType.DURATION, - requestedBatterySipper.videoTimeMs, totalVideoTimeMs); } - private boolean isSystemSipper(BatterySipper sipper) { - final int uid = sipper.uidObj == null ? -1 : sipper.getUid(); - if (uid >= Process.ROOT_UID && uid < Process.FIRST_APPLICATION_UID) { - return true; - } else if (sipper.mPackages != null) { - for (final String packageName : sipper.mPackages) { - for (final String systemPackage : PACKAGES_SYSTEM) { - if (systemPackage.equals(packageName)) { - return true; - } - } + private void computeTotalPowerForCustomComponent( + BatteryUsageStats batteryUsageStats, double[] powerByComponentMah) { + for (BatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) { + final int customComponentCount = consumer.getCustomPowerComponentCount(); + for (int component = 0; + component < Math.min(customComponentCount, powerByComponentMah.length); + component++) { + powerByComponentMah[component] += consumer.getConsumedPowerForCustomComponent( + BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + component); } } - - return false; } - private void addEntry(String title, EntryType entryType, double amount, double totalAmount) { + private void addEntry(String title, EntryType entryType, double amount, double totalAmount, + boolean isSystemBatteryConsumer) { Entry entry = new Entry(); entry.title = title; entry.entryType = entryType; entry.value = amount; entry.total = totalAmount; + entry.isSystemBatteryConsumer = isSystemBatteryConsumer; mEntries.add(entry); } - private void maybeAddMeasuredEnergyEntry(BatterySipper.DrainType drainType, - BatteryStats batteryStats) { - switch (drainType) { - case AMBIENT_DISPLAY: - final long totalDozeMeasuredChargeUC = - batteryStats.getScreenDozeMeasuredBatteryConsumptionUC(); - if (totalDozeMeasuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE) { - final double measuredCharge = UC_2_MAH * totalDozeMeasuredChargeUC; - addEntry("Measured ambient display power", EntryType.POWER, measuredCharge, - measuredCharge); - } - break; - case SCREEN: - final long totalScreenMeasuredChargeUC = - batteryStats.getScreenOnMeasuredBatteryConsumptionUC(); - if (totalScreenMeasuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE) { - final double measuredCharge = UC_2_MAH * totalScreenMeasuredChargeUC; - addEntry("Measured screen power", EntryType.POWER, measuredCharge, - measuredCharge); - } - break; - } - } - public BatteryConsumerInfoHelper.BatteryConsumerInfo getBatteryConsumerInfo() { return mBatteryConsumerInfo; } @@ -314,13 +198,9 @@ public class BatteryConsumerData { return mEntries; } - public static String batteryConsumerId(BatterySipper sipper) { - return sipper.drainType + "|" + sipper.userId + "|" + sipper.getUid(); - } - public static String batteryConsumerId(BatteryConsumer consumer) { if (consumer instanceof UidBatteryConsumer) { - return BatterySipper.DrainType.APP + "|" + return "APP|" + UserHandle.getUserId(((UidBatteryConsumer) consumer).getUid()) + "|" + ((UidBatteryConsumer) consumer).getUid(); } else if (consumer instanceof SystemBatteryConsumer) { diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerInfoHelper.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerInfoHelper.java index 8ee6c604cb3e..6288e0b886d1 100644 --- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerInfoHelper.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerInfoHelper.java @@ -18,14 +18,14 @@ package com.android.frameworks.core.batterystatsviewer; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.os.BatteryConsumer; import android.os.Process; +import android.os.SystemBatteryConsumer; +import android.os.UidBatteryConsumer; +import android.util.DebugUtils; import androidx.annotation.NonNull; -import com.android.internal.os.BatterySipper; - -import java.util.Locale; - class BatteryConsumerInfoHelper { private static final String SYSTEM_SERVER_PACKAGE_NAME = "android"; @@ -37,111 +37,79 @@ class BatteryConsumerInfoHelper { public ApplicationInfo iconInfo; public CharSequence packages; public CharSequence details; + public boolean isSystemBatteryConsumer; } @NonNull public static BatteryConsumerInfo makeBatteryConsumerInfo(PackageManager packageManager, - @NonNull BatterySipper sipper) { + @NonNull BatteryConsumer batteryConsumer) { BatteryConsumerInfo info = new BatteryConsumerInfo(); - info.id = BatteryConsumerData.batteryConsumerId(sipper); - sipper.sumPower(); - info.powerMah = sipper.totalSmearedPowerMah; - switch (sipper.drainType) { - case APP: { - int uid = sipper.getUid(); - info.details = String.format("UID: %d", uid); - String packageWithHighestDrain = sipper.packageWithHighestDrain; - if (uid == Process.ROOT_UID) { - info.label = "<root>"; - } else { - String[] packages = packageManager.getPackagesForUid(uid); - String primaryPackageName = null; - if (uid == Process.SYSTEM_UID) { - primaryPackageName = SYSTEM_SERVER_PACKAGE_NAME; - } else if (packages != null) { - for (String name : packages) { - primaryPackageName = name; - if (name.equals(packageWithHighestDrain)) { - break; - } + info.id = BatteryConsumerData.batteryConsumerId(batteryConsumer); + info.powerMah = batteryConsumer.getConsumedPower(); + + if (batteryConsumer instanceof UidBatteryConsumer) { + final UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer; + int uid = uidBatteryConsumer.getUid(); + info.details = String.format("UID: %d", uid); + String packageWithHighestDrain = uidBatteryConsumer.getPackageWithHighestDrain(); + if (uid == Process.ROOT_UID) { + info.label = "<root>"; + } else { + String[] packages = packageManager.getPackagesForUid(uid); + String primaryPackageName = null; + if (uid == Process.SYSTEM_UID) { + primaryPackageName = SYSTEM_SERVER_PACKAGE_NAME; + } else if (packages != null) { + for (String name : packages) { + primaryPackageName = name; + if (name.equals(packageWithHighestDrain)) { + break; } } + } - if (primaryPackageName != null) { - try { - ApplicationInfo applicationInfo = - packageManager.getApplicationInfo(primaryPackageName, 0); - info.label = applicationInfo.loadLabel(packageManager); - info.iconInfo = applicationInfo; - } catch (PackageManager.NameNotFoundException e) { - info.label = primaryPackageName; - } - } else if (packageWithHighestDrain != null) { - info.label = packageWithHighestDrain; + if (primaryPackageName != null) { + try { + ApplicationInfo applicationInfo = + packageManager.getApplicationInfo(primaryPackageName, 0); + info.label = applicationInfo.loadLabel(packageManager); + info.iconInfo = applicationInfo; + } catch (PackageManager.NameNotFoundException e) { + info.label = primaryPackageName; } + } else if (packageWithHighestDrain != null) { + info.label = packageWithHighestDrain; + } - if (packages != null && packages.length > 0) { - StringBuilder sb = new StringBuilder(); - if (primaryPackageName != null) { - sb.append(primaryPackageName); + if (packages != null && packages.length > 0) { + StringBuilder sb = new StringBuilder(); + if (primaryPackageName != null) { + sb.append(primaryPackageName); + } + for (String packageName : packages) { + if (packageName.equals(primaryPackageName)) { + continue; } - for (String packageName : packages) { - if (packageName.equals(primaryPackageName)) { - continue; - } - if (sb.length() != 0) { - sb.append(", "); - } - sb.append(packageName); + if (sb.length() != 0) { + sb.append(", "); } - - info.packages = sb; + sb.append(packageName); } + + info.packages = sb; } - break; } - case USER: - info.label = "User"; - info.details = String.format(Locale.getDefault(), "User ID: %d", sipper.userId); - break; - case AMBIENT_DISPLAY: - info.label = "Ambient display"; - break; - case BLUETOOTH: - info.label = "Bluetooth"; - break; - case CAMERA: - info.label = "Camera"; - break; - case CELL: - info.label = "Cell"; - break; - case FLASHLIGHT: - info.label = "Flashlight"; - break; - case IDLE: - info.label = "Idle"; - break; - case MEMORY: - info.label = "Memory"; - break; - case OVERCOUNTED: - info.label = "Overcounted"; - break; - case PHONE: - info.label = "Phone"; - break; - case SCREEN: - info.label = "Screen"; - break; - case UNACCOUNTED: - info.label = "Unaccounted"; - break; - case WIFI: - info.label = "WiFi"; - break; + } else if (batteryConsumer instanceof SystemBatteryConsumer) { + final SystemBatteryConsumer systemBatteryConsumer = + (SystemBatteryConsumer) batteryConsumer; + final int drainType = systemBatteryConsumer.getDrainType(); + String name = DebugUtils.constantToString(SystemBatteryConsumer.class, "DRAIN_TYPE_", + drainType); + info.label = name.charAt(0) + name.substring(1).toLowerCase().replace('_', ' '); + info.isSystemBatteryConsumer = true; } + // Default the app icon to System Server. This includes root, dex2oat and other UIDs. if (info.iconInfo == null) { try { diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerFragment.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerFragment.java index bb11fd598511..49220877d31e 100644 --- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerFragment.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerFragment.java @@ -18,10 +18,11 @@ package com.android.frameworks.core.batterystatsviewer; import android.content.Context; import android.content.pm.PackageManager; -import android.os.BatteryStats; +import android.os.BatteryStatsManager; +import android.os.BatteryUsageStats; import android.os.Bundle; -import android.os.UserHandle; -import android.os.UserManager; +import android.os.SystemBatteryConsumer; +import android.os.UidBatteryConsumer; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -37,8 +38,6 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.android.frameworks.core.batterystatsviewer.BatteryConsumerInfoHelper.BatteryConsumerInfo; -import com.android.internal.os.BatterySipper; -import com.android.internal.os.BatteryStatsHelper; import com.android.settingslib.utils.AsyncLoaderCompat; import java.util.ArrayList; @@ -99,44 +98,39 @@ public class BatteryConsumerPickerFragment extends Fragment { private static class BatteryConsumerListLoader extends AsyncLoaderCompat<List<BatteryConsumerInfo>> { - private final BatteryStatsHelper mStatsHelper; private final int mPickerType; - private final UserManager mUserManager; + private final BatteryStatsManager mBatteryStatsManager; private final PackageManager mPackageManager; BatteryConsumerListLoader(Context context, int pickerType) { super(context); - mUserManager = context.getSystemService(UserManager.class); - mStatsHelper = new BatteryStatsHelper(context, false /* collectBatteryBroadcast */); + mBatteryStatsManager = context.getSystemService(BatteryStatsManager.class); mPickerType = pickerType; - mStatsHelper.create((Bundle) null); - mStatsHelper.clearStats(); mPackageManager = context.getPackageManager(); } @Override public List<BatteryConsumerInfo> loadInBackground() { - List<BatteryConsumerInfo> batteryConsumerList = new ArrayList<>(); + final BatteryUsageStats batteryUsageStats = mBatteryStatsManager.getBatteryUsageStats(); - mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.myUserId()); - - final List<BatterySipper> usageList = mStatsHelper.getUsageList(); - for (BatterySipper sipper : usageList) { - switch (mPickerType) { - case PICKER_TYPE_APP: - if (sipper.drainType != BatterySipper.DrainType.APP) { - continue; - } - break; - case PICKER_TYPE_DRAIN: - default: - if (sipper.drainType == BatterySipper.DrainType.APP) { - continue; - } - } - - batteryConsumerList.add( - BatteryConsumerInfoHelper.makeBatteryConsumerInfo(mPackageManager, sipper)); + List<BatteryConsumerInfo> batteryConsumerList = new ArrayList<>(); + switch (mPickerType) { + case PICKER_TYPE_APP: + for (UidBatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) { + batteryConsumerList.add( + BatteryConsumerInfoHelper.makeBatteryConsumerInfo(mPackageManager, + consumer)); + } + break; + case PICKER_TYPE_DRAIN: + default: + for (SystemBatteryConsumer consumer : + batteryUsageStats.getSystemBatteryConsumers()) { + batteryConsumerList.add( + BatteryConsumerInfoHelper.makeBatteryConsumerInfo(mPackageManager, + consumer)); + } + break; } batteryConsumerList.sort( diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java index 4ead8eef5684..74d3fb336f40 100644 --- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java @@ -18,13 +18,10 @@ package com.android.frameworks.core.batterystatsviewer; import android.content.Context; import android.content.SharedPreferences; -import android.os.BatteryStats; import android.os.BatteryStatsManager; import android.os.BatteryUsageStats; import android.os.BatteryUsageStatsQuery; import android.os.Bundle; -import android.os.UserHandle; -import android.os.UserManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -41,7 +38,6 @@ import androidx.loader.content.Loader; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.android.internal.os.BatteryStatsHelper; import com.android.settingslib.utils.AsyncLoaderCompat; import java.util.Collections; @@ -50,24 +46,24 @@ import java.util.Locale; public class BatteryStatsViewerActivity extends ComponentActivity { private static final int BATTERY_STATS_REFRESH_RATE_MILLIS = 60 * 1000; - public static final String PREF_SELECTED_BATTERY_CONSUMER = "batteryConsumerId"; - public static final int LOADER_BATTERY_STATS_HELPER = 0; - public static final int LOADER_BATTERY_USAGE_STATS = 1; + private static final int MILLIS_IN_MINUTE = 60000; + private static final String PREF_SELECTED_BATTERY_CONSUMER = "batteryConsumerId"; + private static final int LOADER_BATTERY_USAGE_STATS = 1; private BatteryStatsDataAdapter mBatteryStatsDataAdapter; - private Runnable mBatteryStatsRefresh = this::periodicBatteryStatsRefresh; + private final Runnable mBatteryStatsRefresh = this::periodicBatteryStatsRefresh; private SharedPreferences mSharedPref; private String mBatteryConsumerId; private TextView mTitleView; private TextView mDetailsView; private ImageView mIconView; private TextView mPackagesView; + private View mHeadingsView; private RecyclerView mBatteryConsumerDataView; private View mLoadingView; private View mEmptyView; - private ActivityResultLauncher<Void> mStartAppPicker = registerForActivityResult( + private final ActivityResultLauncher<Void> mStartAppPicker = registerForActivityResult( BatteryConsumerPickerActivity.CONTRACT, this::onApplicationSelected); - private BatteryStatsHelper mBatteryStatsHelper; private List<BatteryUsageStats> mBatteryUsageStats; @Override @@ -85,6 +81,7 @@ public class BatteryStatsViewerActivity extends ComponentActivity { mDetailsView = findViewById(R.id.details); mIconView = findViewById(android.R.id.icon); mPackagesView = findViewById(R.id.packages); + mHeadingsView = findViewById(R.id.headings); mBatteryConsumerDataView = findViewById(R.id.battery_consumer_data_view); mBatteryConsumerDataView.setLayoutManager(new LinearLayoutManager(this)); @@ -139,55 +136,10 @@ public class BatteryStatsViewerActivity extends ComponentActivity { private void loadBatteryStats() { LoaderManager loaderManager = LoaderManager.getInstance(this); - loaderManager.restartLoader(LOADER_BATTERY_STATS_HELPER, null, - new BatteryStatsHelperLoaderCallbacks()); loaderManager.restartLoader(LOADER_BATTERY_USAGE_STATS, null, new BatteryUsageStatsLoaderCallbacks()); } - private static class BatteryStatsHelperLoader extends AsyncLoaderCompat<BatteryStatsHelper> { - private final BatteryStatsHelper mBatteryStatsHelper; - private final UserManager mUserManager; - - BatteryStatsHelperLoader(Context context) { - super(context); - mUserManager = context.getSystemService(UserManager.class); - mBatteryStatsHelper = new BatteryStatsHelper(context, - false /* collectBatteryBroadcast */); - mBatteryStatsHelper.create((Bundle) null); - mBatteryStatsHelper.clearStats(); - } - - @Override - public BatteryStatsHelper loadInBackground() { - mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, - UserHandle.myUserId()); - return mBatteryStatsHelper; - } - - @Override - protected void onDiscardResult(BatteryStatsHelper result) { - } - } - - private class BatteryStatsHelperLoaderCallbacks implements LoaderCallbacks<BatteryStatsHelper> { - @NonNull - @Override - public Loader<BatteryStatsHelper> onCreateLoader(int id, Bundle args) { - return new BatteryStatsHelperLoader(BatteryStatsViewerActivity.this); - } - - @Override - public void onLoadFinished(@NonNull Loader<BatteryStatsHelper> loader, - BatteryStatsHelper batteryStatsHelper) { - onBatteryStatsHelperLoaded(batteryStatsHelper); - } - - @Override - public void onLoaderReset(@NonNull Loader<BatteryStatsHelper> loader) { - } - } - private static class BatteryUsageStatsLoader extends AsyncLoaderCompat<List<BatteryUsageStats>> { private final BatteryStatsManager mBatteryStatsManager; @@ -200,10 +152,13 @@ public class BatteryStatsViewerActivity extends ComponentActivity { @Override public List<BatteryUsageStats> loadInBackground() { final BatteryUsageStatsQuery queryDefault = - new BatteryUsageStatsQuery.Builder().build(); + new BatteryUsageStatsQuery.Builder() + .includePowerModels() + .build(); final BatteryUsageStatsQuery queryPowerProfileModeledOnly = new BatteryUsageStatsQuery.Builder() .powerProfileModeledOnly() + .includePowerModels() .build(); return mBatteryStatsManager.getBatteryUsageStats( List.of(queryDefault, queryPowerProfileModeledOnly)); @@ -233,22 +188,13 @@ public class BatteryStatsViewerActivity extends ComponentActivity { } } - public void onBatteryStatsHelperLoaded(BatteryStatsHelper batteryStatsHelper) { - mBatteryStatsHelper = batteryStatsHelper; - onBatteryStatsDataLoaded(); - } - private void onBatteryUsageStatsLoaded(List<BatteryUsageStats> batteryUsageStats) { mBatteryUsageStats = batteryUsageStats; onBatteryStatsDataLoaded(); } public void onBatteryStatsDataLoaded() { - if (mBatteryStatsHelper == null || mBatteryUsageStats == null) { - return; - } - - BatteryConsumerData batteryConsumerData = new BatteryConsumerData(this, mBatteryStatsHelper, + BatteryConsumerData batteryConsumerData = new BatteryConsumerData(this, mBatteryUsageStats, mBatteryConsumerId); BatteryConsumerInfoHelper.BatteryConsumerInfo @@ -256,6 +202,7 @@ public class BatteryStatsViewerActivity extends ComponentActivity { if (batteryConsumerInfo == null) { mTitleView.setText("Battery consumer not found"); mPackagesView.setVisibility(View.GONE); + mHeadingsView.setVisibility(View.GONE); } else { mTitleView.setText(batteryConsumerInfo.label); if (batteryConsumerInfo.details != null) { @@ -273,6 +220,12 @@ public class BatteryStatsViewerActivity extends ComponentActivity { } else { mPackagesView.setVisibility(View.GONE); } + + if (batteryConsumerInfo.isSystemBatteryConsumer) { + mHeadingsView.setVisibility(View.VISIBLE); + } else { + mHeadingsView.setVisibility(View.GONE); + } } mBatteryStatsDataAdapter.setEntries(batteryConsumerData.getEntries()); @@ -290,6 +243,7 @@ public class BatteryStatsViewerActivity extends ComponentActivity { private static class BatteryStatsDataAdapter extends RecyclerView.Adapter<BatteryStatsDataAdapter.ViewHolder> { public static class ViewHolder extends RecyclerView.ViewHolder { + public ImageView iconImageView; public TextView titleTextView; public TextView amountTextView; public TextView percentTextView; @@ -297,6 +251,7 @@ public class BatteryStatsViewerActivity extends ComponentActivity { ViewHolder(View itemView) { super(itemView); + iconImageView = itemView.findViewById(R.id.icon); titleTextView = itemView.findViewById(R.id.title); amountTextView = itemView.findViewById(R.id.amount); percentTextView = itemView.findViewById(R.id.percent); @@ -328,21 +283,56 @@ public class BatteryStatsViewerActivity extends ComponentActivity { public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) { BatteryConsumerData.Entry entry = mEntries.get(position); switch (entry.entryType) { - case POWER: + case POWER_MODELED: viewHolder.titleTextView.setText(entry.title); viewHolder.amountTextView.setText( String.format(Locale.getDefault(), "%.1f mAh", entry.value)); + viewHolder.iconImageView.setImageResource(R.drawable.gm_calculate_24); + viewHolder.itemView.setBackgroundResource( + R.color.battery_consumer_bg_power_profile); break; - case DURATION: + case POWER_MEASURED: viewHolder.titleTextView.setText(entry.title); viewHolder.amountTextView.setText( - String.format(Locale.getDefault(), "%,d ms", (long) entry.value)); + String.format(Locale.getDefault(), "%.1f mAh", entry.value)); + viewHolder.iconImageView.setImageResource(R.drawable.gm_amp_24); + viewHolder.itemView.setBackgroundResource( + R.color.battery_consumer_bg_measured_energy); + break; + case POWER_CUSTOM: + viewHolder.titleTextView.setText(entry.title); + viewHolder.amountTextView.setText( + String.format(Locale.getDefault(), "%.1f mAh", entry.value)); + viewHolder.iconImageView.setImageResource(R.drawable.gm_custom_24); + viewHolder.itemView.setBackgroundResource( + R.color.battery_consumer_bg_measured_energy); + break; + case DURATION: + viewHolder.titleTextView.setText(entry.title); + final long durationMs = (long) entry.value; + CharSequence text; + if (durationMs < MILLIS_IN_MINUTE) { + text = String.format(Locale.getDefault(), "%,d ms", durationMs); + } else { + text = String.format(Locale.getDefault(), "%,d m %d s", + durationMs / MILLIS_IN_MINUTE, + (durationMs % MILLIS_IN_MINUTE) / 1000); + } + + viewHolder.amountTextView.setText(text); + viewHolder.iconImageView.setImageResource(R.drawable.gm_timer_24); + viewHolder.itemView.setBackground(null); break; } - double proportion = entry.total != 0 ? entry.value * 100 / entry.total : 0; - viewHolder.percentTextView.setText(String.format(Locale.getDefault(), "%.1f%%", - proportion)); + double proportion; + if (entry.isSystemBatteryConsumer) { + proportion = entry.value != 0 ? entry.total * 100 / entry.value : 0; + } else { + proportion = entry.total != 0 ? entry.value * 100 / entry.total : 0; + } + viewHolder.percentTextView.setText( + String.format(Locale.getDefault(), "%.1f%%", proportion)); } } } |