Merge "Show all BatteryUsageStats in BatteryStatsViewer" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
397227d71e
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
@@ -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();
|
||||
BatteryUsageStats modeledBatteryUsageStats = batteryUsageStatsList.get(1);
|
||||
|
||||
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;
|
||||
BatteryConsumer requestedBatteryConsumer = getRequestedBatteryConsumer(batteryUsageStats,
|
||||
batteryConsumerId);
|
||||
BatteryConsumer requestedModeledBatteryConsumer = getRequestedBatteryConsumer(
|
||||
modeledBatteryUsageStats, batteryConsumerId);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
if (batteryConsumerId(sipper).equals(batteryConsumerId)) {
|
||||
requestedBatterySipper = sipper;
|
||||
}
|
||||
|
||||
totalPowerMah += sipper.sumPower();
|
||||
totalSmearedPowerMah += sipper.totalSmearedPowerMah;
|
||||
totalProportionalSmearMah += sipper.proportionalSmearMah;
|
||||
|
||||
if (!isSystemSipper(sipper)) {
|
||||
totalPowerExcludeSystemMah += sipper.totalSmearedPowerMah;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BatteryConsumer requestedBatteryConsumer = null;
|
||||
|
||||
for (BatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) {
|
||||
if (batteryConsumerId(consumer).equals(batteryConsumerId)) {
|
||||
requestedBatteryConsumer = consumer;
|
||||
}
|
||||
}
|
||||
|
||||
double totalModeledCpuPowerMah = 0;
|
||||
BatteryConsumer requestedBatteryConsumerPowerProfileModeled = null;
|
||||
for (BatteryConsumer consumer : powerProfileModeledUsageStats.getUidBatteryConsumers()) {
|
||||
if (batteryConsumerId(consumer).equals(batteryConsumerId)) {
|
||||
requestedBatteryConsumerPowerProfileModeled = consumer;
|
||||
}
|
||||
|
||||
totalModeledCpuPowerMah += consumer.getConsumedPower(
|
||||
BatteryConsumer.POWER_COMPONENT_CPU);
|
||||
}
|
||||
|
||||
if (requestedBatterySipper == null) {
|
||||
if (requestedBatteryConsumer == null || requestedModeledBatteryConsumer == null) {
|
||||
mBatteryConsumerInfo = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (requestedBatteryConsumer == null) {
|
||||
for (BatteryConsumer consumer : batteryUsageStats.getSystemBatteryConsumers()) {
|
||||
if (batteryConsumerId(consumer).equals(batteryConsumerId)) {
|
||||
requestedBatteryConsumer = consumer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mBatteryConsumerInfo = BatteryConsumerInfoHelper.makeBatteryConsumerInfo(
|
||||
context.getPackageManager(), requestedBatterySipper);
|
||||
long totalScreenMeasuredChargeUC =
|
||||
batteryStats.getScreenOnMeasuredBatteryConsumptionUC();
|
||||
long uidScreenMeasuredChargeUC =
|
||||
requestedBatterySipper.uidObj.getScreenOnMeasuredBatteryConsumptionUC();
|
||||
context.getPackageManager(), requestedBatteryConsumer);
|
||||
|
||||
addEntry("Total power", EntryType.POWER,
|
||||
requestedBatterySipper.totalSmearedPowerMah, totalSmearedPowerMah);
|
||||
maybeAddMeasuredEnergyEntry(requestedBatterySipper.drainType, batteryStats);
|
||||
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];
|
||||
|
||||
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);
|
||||
}
|
||||
} 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);
|
||||
computeTotalPower(batteryUsageStats, totalPowerByComponentMah);
|
||||
computeTotalPower(modeledBatteryUsageStats, totalModeledPowerByComponentMah);
|
||||
computeTotalPowerForCustomComponent(batteryUsageStats, totalCustomPowerByComponentMah);
|
||||
computeTotalDuration(batteryUsageStats, totalDurationByComponentMs);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
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);
|
||||
}
|
||||
|
||||
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 void addEntry(String title, EntryType entryType, double amount, double totalAmount) {
|
||||
private BatteryConsumer getRequestedBatteryConsumer(BatteryUsageStats batteryUsageStats,
|
||||
String batteryConsumerId) {
|
||||
for (BatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) {
|
||||
if (batteryConsumerId(consumer).equals(batteryConsumerId)) {
|
||||
return consumer;
|
||||
}
|
||||
}
|
||||
for (BatteryConsumer consumer : batteryUsageStats.getSystemBatteryConsumers()) {
|
||||
if (batteryConsumerId(consumer).equals(batteryConsumerId)) {
|
||||
return consumer;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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 (primaryPackageName != null) {
|
||||
try {
|
||||
ApplicationInfo applicationInfo =
|
||||
packageManager.getApplicationInfo(primaryPackageName, 0);
|
||||
info.label = applicationInfo.loadLabel(packageManager);
|
||||
info.iconInfo = applicationInfo;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
info.label = primaryPackageName;
|
||||
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;
|
||||
}
|
||||
} else if (packageWithHighestDrain != null) {
|
||||
info.label = packageWithHighestDrain;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (sb.length() != 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(packageName);
|
||||
}
|
||||
|
||||
info.packages = sb;
|
||||
}
|
||||
}
|
||||
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 (packages != null && packages.length > 0) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (primaryPackageName != null) {
|
||||
sb.append(primaryPackageName);
|
||||
}
|
||||
for (String packageName : packages) {
|
||||
if (packageName.equals(primaryPackageName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sb.length() != 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(packageName);
|
||||
}
|
||||
|
||||
info.packages = sb;
|
||||
}
|
||||
}
|
||||
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 {
|
||||
|
||||
@@ -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() {
|
||||
final BatteryUsageStats batteryUsageStats = mBatteryStatsManager.getBatteryUsageStats();
|
||||
|
||||
List<BatteryConsumerInfo> batteryConsumerList = new ArrayList<>();
|
||||
|
||||
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));
|
||||
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(
|
||||
|
||||
@@ -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 POWER_MEASURED:
|
||||
viewHolder.titleTextView.setText(entry.title);
|
||||
viewHolder.amountTextView.setText(
|
||||
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);
|
||||
viewHolder.amountTextView.setText(
|
||||
String.format(Locale.getDefault(), "%,d ms", (long) entry.value));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user