Merge "BatteryStatsViewer UI improvements:" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
54fc08e8cb
@@ -15,6 +15,7 @@ android_app {
|
|||||||
"androidx.appcompat_appcompat",
|
"androidx.appcompat_appcompat",
|
||||||
"androidx.cardview_cardview",
|
"androidx.cardview_cardview",
|
||||||
"androidx.recyclerview_recyclerview",
|
"androidx.recyclerview_recyclerview",
|
||||||
|
"androidx.swiperefreshlayout_swiperefreshlayout",
|
||||||
"com.google.android.material_material",
|
"com.google.android.material_material",
|
||||||
],
|
],
|
||||||
platform_apis: true,
|
platform_apis: true,
|
||||||
|
|||||||
@@ -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="M19,4H5v2l6,6 -6,6v2h14v-3h-9l5,-5 -5,-5h9V4z"/>
|
||||||
|
</vector>
|
||||||
@@ -30,7 +30,8 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginEnd="8dp"/>
|
android:layout_marginEnd="8dp"
|
||||||
|
android:paddingBottom="8dp"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
@@ -40,7 +41,7 @@
|
|||||||
android:textAppearance="@style/TextAppearanceBody"/>
|
android:textAppearance="@style/TextAppearanceBody"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/amount"
|
android:id="@+id/value1"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
@@ -49,7 +50,7 @@
|
|||||||
android:textAppearance="@style/TextAppearanceBody"/>
|
android:textAppearance="@style/TextAppearanceBody"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/percent"
|
android:id="@+id/value2"
|
||||||
android:layout_width="76dp"
|
android:layout_width="76dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="right"
|
android:gravity="right"
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
<!--
|
|
||||||
~ Copyright (C) 2020 The Android Open Source Project
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabLayout
|
|
||||||
android:id="@+id/tab_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"/>
|
|
||||||
|
|
||||||
<androidx.viewpager.widget.ViewPager
|
|
||||||
android:id="@+id/pager"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -14,22 +14,15 @@
|
|||||||
~ See the License for the specific language governing permissions and
|
~ See the License for the specific language governing permissions and
|
||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
<FrameLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/swipe_refresh"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/list_view"
|
android:id="@+id/list_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"/>
|
||||||
android:visibility="gone"/>
|
|
||||||
|
|
||||||
<ProgressBar
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
style="?android:attr/progressBarStyleLarge"
|
|
||||||
android:id="@+id/loading_view"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:indeterminate="true"/>
|
|
||||||
</FrameLayout>
|
|
||||||
|
|||||||
@@ -14,94 +14,89 @@
|
|||||||
~ See the License for the specific language governing permissions and
|
~ See the License for the specific language governing permissions and
|
||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
<FrameLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/swipe_refresh"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
<LinearLayout
|
||||||
style="@style/LoadTestCardView"
|
|
||||||
android:id="@+id/app_card"
|
android:id="@+id/app_card"
|
||||||
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="10dp"
|
android:visibility="invisible">
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:padding="20dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.cardview.widget.CardView
|
||||||
|
style="@style/LoadTestCardView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:layout_marginTop="10dp"
|
||||||
android:minHeight="80dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:paddingStart="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:paddingEnd="10dp">
|
android:layout_marginStart="10dp"
|
||||||
|
android:padding="20dp">
|
||||||
|
|
||||||
<include layout="@layout/battery_consumer_info_layout"/>
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:minHeight="80dp"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
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="76dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="end"
|
||||||
|
android:paddingEnd="20dp"
|
||||||
|
android:text="Total"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="76dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="end"
|
||||||
|
android:paddingEnd="20dp"
|
||||||
|
android:text="Apps"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
<LinearLayout
|
android:background="@android:color/darker_gray"/>
|
||||||
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>
|
</LinearLayout>
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:background="@android:color/darker_gray"/>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/battery_consumer_data_view"
|
android:id="@+id/battery_consumer_data_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1"/>
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/empty_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:text="No battery stats available"/>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<TextView
|
||||||
android:id="@+id/loading_view"
|
android:id="@+id/empty_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="#AAFFFFFF">
|
android:gravity="center"
|
||||||
<ProgressBar
|
android:visibility="gone"
|
||||||
style="?android:attr/progressBarStyleLarge"
|
android:text="No battery stats available"/>
|
||||||
android:layout_width="wrap_content"
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:indeterminate="true"/>
|
|
||||||
</FrameLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
|
|||||||
@@ -28,29 +28,54 @@ import java.util.List;
|
|||||||
|
|
||||||
public class BatteryConsumerData {
|
public class BatteryConsumerData {
|
||||||
|
|
||||||
|
public static final String UID_BATTERY_CONSUMER_ID_PREFIX = "APP|";
|
||||||
|
public static final String AGGREGATE_BATTERY_CONSUMER_ID = "SYS|";
|
||||||
|
|
||||||
enum EntryType {
|
enum EntryType {
|
||||||
POWER_MODELED,
|
UID_TOTAL_POWER,
|
||||||
POWER_MEASURED,
|
UID_POWER_MODELED,
|
||||||
POWER_CUSTOM,
|
UID_POWER_MEASURED,
|
||||||
DURATION,
|
UID_POWER_CUSTOM,
|
||||||
|
UID_DURATION,
|
||||||
|
DEVICE_TOTAL_POWER,
|
||||||
|
DEVICE_POWER_MODELED,
|
||||||
|
DEVICE_POWER_MEASURED,
|
||||||
|
DEVICE_POWER_CUSTOM,
|
||||||
|
DEVICE_DURATION,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ConsumerType {
|
||||||
|
UID_BATTERY_CONSUMER,
|
||||||
|
DEVICE_POWER_COMPONENT,
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Entry {
|
public static class Entry {
|
||||||
public String title;
|
|
||||||
public EntryType entryType;
|
public EntryType entryType;
|
||||||
public double value;
|
public String title;
|
||||||
public double total;
|
public double value1;
|
||||||
public boolean isSystemBatteryConsumer;
|
public double value2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final BatteryConsumerInfoHelper.BatteryConsumerInfo mBatteryConsumerInfo;
|
private BatteryConsumerInfoHelper.BatteryConsumerInfo mBatteryConsumerInfo;
|
||||||
private final List<Entry> mEntries = new ArrayList<>();
|
private final List<Entry> mEntries = new ArrayList<>();
|
||||||
|
|
||||||
public BatteryConsumerData(Context context,
|
public BatteryConsumerData(Context context,
|
||||||
List<BatteryUsageStats> batteryUsageStatsList, String batteryConsumerId) {
|
List<BatteryUsageStats> batteryUsageStatsList, String batteryConsumerId) {
|
||||||
|
switch (getConsumerType(batteryConsumerId)) {
|
||||||
|
case UID_BATTERY_CONSUMER:
|
||||||
|
populateForUidBatteryConsumer(context, batteryUsageStatsList, batteryConsumerId);
|
||||||
|
break;
|
||||||
|
case DEVICE_POWER_COMPONENT:
|
||||||
|
populateForAggregateBatteryConsumer(context, batteryUsageStatsList);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void populateForUidBatteryConsumer(
|
||||||
|
Context context, List<BatteryUsageStats> batteryUsageStatsList,
|
||||||
|
String batteryConsumerId) {
|
||||||
BatteryUsageStats batteryUsageStats = batteryUsageStatsList.get(0);
|
BatteryUsageStats batteryUsageStats = batteryUsageStatsList.get(0);
|
||||||
BatteryUsageStats modeledBatteryUsageStats = batteryUsageStatsList.get(1);
|
BatteryUsageStats modeledBatteryUsageStats = batteryUsageStatsList.get(1);
|
||||||
|
|
||||||
BatteryConsumer requestedBatteryConsumer = getRequestedBatteryConsumer(batteryUsageStats,
|
BatteryConsumer requestedBatteryConsumer = getRequestedBatteryConsumer(batteryUsageStats,
|
||||||
batteryConsumerId);
|
batteryConsumerId);
|
||||||
BatteryConsumer requestedModeledBatteryConsumer = getRequestedBatteryConsumer(
|
BatteryConsumer requestedModeledBatteryConsumer = getRequestedBatteryConsumer(
|
||||||
@@ -62,7 +87,7 @@ public class BatteryConsumerData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mBatteryConsumerInfo = BatteryConsumerInfoHelper.makeBatteryConsumerInfo(
|
mBatteryConsumerInfo = BatteryConsumerInfoHelper.makeBatteryConsumerInfo(
|
||||||
requestedBatteryConsumer, batteryConsumerId, context.getPackageManager());
|
batteryUsageStats, batteryConsumerId, context.getPackageManager());
|
||||||
|
|
||||||
double[] totalPowerByComponentMah = new double[BatteryConsumer.POWER_COMPONENT_COUNT];
|
double[] totalPowerByComponentMah = new double[BatteryConsumer.POWER_COMPONENT_COUNT];
|
||||||
double[] totalModeledPowerByComponentMah =
|
double[] totalModeledPowerByComponentMah =
|
||||||
@@ -77,56 +102,152 @@ public class BatteryConsumerData {
|
|||||||
computeTotalPowerForCustomComponent(batteryUsageStats, totalCustomPowerByComponentMah);
|
computeTotalPowerForCustomComponent(batteryUsageStats, totalCustomPowerByComponentMah);
|
||||||
computeTotalDuration(batteryUsageStats, totalDurationByComponentMs);
|
computeTotalDuration(batteryUsageStats, totalDurationByComponentMs);
|
||||||
|
|
||||||
|
if (isPowerProfileModelsOnly(requestedBatteryConsumer)) {
|
||||||
|
addEntry("Consumed", EntryType.UID_TOTAL_POWER,
|
||||||
|
requestedBatteryConsumer.getConsumedPower(),
|
||||||
|
batteryUsageStats.getAggregateBatteryConsumer(
|
||||||
|
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS)
|
||||||
|
.getConsumedPower());
|
||||||
|
} else {
|
||||||
|
addEntry("Consumed (measured)", EntryType.UID_TOTAL_POWER,
|
||||||
|
requestedBatteryConsumer.getConsumedPower(),
|
||||||
|
batteryUsageStats.getAggregateBatteryConsumer(
|
||||||
|
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS)
|
||||||
|
.getConsumedPower());
|
||||||
|
addEntry("Consumed (modeled)", EntryType.UID_TOTAL_POWER,
|
||||||
|
requestedModeledBatteryConsumer.getConsumedPower(),
|
||||||
|
modeledBatteryUsageStats.getAggregateBatteryConsumer(
|
||||||
|
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS)
|
||||||
|
.getConsumedPower());
|
||||||
|
}
|
||||||
|
|
||||||
for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
|
for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
|
||||||
final String metricTitle = getPowerMetricTitle(component);
|
final String metricTitle = getPowerMetricTitle(component);
|
||||||
final int powerModel = requestedBatteryConsumer.getPowerModel(component);
|
final int powerModel = requestedBatteryConsumer.getPowerModel(component);
|
||||||
if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
|
if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
|
||||||
addEntry(metricTitle, EntryType.POWER_MODELED,
|
addEntry(metricTitle, EntryType.UID_POWER_MODELED,
|
||||||
requestedBatteryConsumer.getConsumedPower(component),
|
requestedBatteryConsumer.getConsumedPower(component),
|
||||||
totalPowerByComponentMah[component],
|
totalPowerByComponentMah[component]
|
||||||
mBatteryConsumerInfo.isSystemBatteryConsumer);
|
);
|
||||||
} else {
|
} else {
|
||||||
addEntry(metricTitle + " (measured)", EntryType.POWER_MEASURED,
|
addEntry(metricTitle + " (measured)", EntryType.UID_POWER_MEASURED,
|
||||||
requestedBatteryConsumer.getConsumedPower(component),
|
requestedBatteryConsumer.getConsumedPower(component),
|
||||||
totalPowerByComponentMah[component],
|
totalPowerByComponentMah[component]
|
||||||
mBatteryConsumerInfo.isSystemBatteryConsumer);
|
);
|
||||||
addEntry(metricTitle + " (modeled)", EntryType.POWER_MODELED,
|
addEntry(metricTitle + " (modeled)", EntryType.UID_POWER_MODELED,
|
||||||
requestedModeledBatteryConsumer.getConsumedPower(component),
|
requestedModeledBatteryConsumer.getConsumedPower(component),
|
||||||
totalModeledPowerByComponentMah[component],
|
totalModeledPowerByComponentMah[component]
|
||||||
mBatteryConsumerInfo.isSystemBatteryConsumer);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int component = 0; component < customComponentCount; component++) {
|
for (int component = 0; component < customComponentCount; component++) {
|
||||||
final String name = requestedBatteryConsumer.getCustomPowerComponentName(
|
final String name = requestedBatteryConsumer.getCustomPowerComponentName(
|
||||||
BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + component);
|
BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + component);
|
||||||
addEntry(name + " (custom)", EntryType.POWER_CUSTOM,
|
addEntry(name + " (custom)", EntryType.UID_POWER_CUSTOM,
|
||||||
requestedBatteryConsumer.getConsumedPowerForCustomComponent(
|
requestedBatteryConsumer.getConsumedPowerForCustomComponent(
|
||||||
BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + component),
|
BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + component),
|
||||||
totalCustomPowerByComponentMah[component],
|
totalCustomPowerByComponentMah[component]
|
||||||
mBatteryConsumerInfo.isSystemBatteryConsumer);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
|
for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
|
||||||
final String metricTitle = getTimeMetricTitle(component);
|
final String metricTitle = getTimeMetricTitle(component);
|
||||||
addEntry(metricTitle, EntryType.DURATION,
|
addEntry(metricTitle, EntryType.UID_DURATION,
|
||||||
requestedBatteryConsumer.getUsageDurationMillis(component),
|
requestedBatteryConsumer.getUsageDurationMillis(component),
|
||||||
totalDurationByComponentMs[component],
|
totalDurationByComponentMs[component]
|
||||||
mBatteryConsumerInfo.isSystemBatteryConsumer);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mBatteryConsumerInfo = BatteryConsumerInfoHelper.makeBatteryConsumerInfo(batteryUsageStats,
|
||||||
|
batteryConsumerId, context.getPackageManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void populateForAggregateBatteryConsumer(Context context,
|
||||||
|
List<BatteryUsageStats> batteryUsageStatsList) {
|
||||||
|
BatteryUsageStats batteryUsageStats = batteryUsageStatsList.get(0);
|
||||||
|
BatteryUsageStats modeledBatteryUsageStats = batteryUsageStatsList.get(1);
|
||||||
|
|
||||||
|
final BatteryConsumer deviceBatteryConsumer =
|
||||||
|
batteryUsageStats.getAggregateBatteryConsumer(
|
||||||
|
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE);
|
||||||
|
BatteryConsumer appsBatteryConsumer =
|
||||||
|
batteryUsageStats.getAggregateBatteryConsumer(
|
||||||
|
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS);
|
||||||
|
|
||||||
|
BatteryConsumer modeledDeviceBatteryConsumer =
|
||||||
|
modeledBatteryUsageStats.getAggregateBatteryConsumer(
|
||||||
|
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE);
|
||||||
|
BatteryConsumer modeledAppsBatteryConsumer =
|
||||||
|
modeledBatteryUsageStats.getAggregateBatteryConsumer(
|
||||||
|
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS);
|
||||||
|
|
||||||
|
if (isPowerProfileModelsOnly(deviceBatteryConsumer)) {
|
||||||
|
addEntry("Consumed", EntryType.DEVICE_TOTAL_POWER,
|
||||||
|
deviceBatteryConsumer.getConsumedPower(),
|
||||||
|
appsBatteryConsumer.getConsumedPower());
|
||||||
|
} else {
|
||||||
|
addEntry("Consumed (measured)", EntryType.DEVICE_TOTAL_POWER,
|
||||||
|
deviceBatteryConsumer.getConsumedPower(),
|
||||||
|
appsBatteryConsumer.getConsumedPower());
|
||||||
|
addEntry("Consumed (modeled)", EntryType.DEVICE_TOTAL_POWER,
|
||||||
|
modeledDeviceBatteryConsumer.getConsumedPower(),
|
||||||
|
modeledAppsBatteryConsumer.getConsumedPower());
|
||||||
|
}
|
||||||
|
|
||||||
|
mBatteryConsumerInfo = BatteryConsumerInfoHelper.makeBatteryConsumerInfo(batteryUsageStats,
|
||||||
|
AGGREGATE_BATTERY_CONSUMER_ID, context.getPackageManager());
|
||||||
|
|
||||||
|
|
||||||
|
for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
|
||||||
|
final String metricTitle = getPowerMetricTitle(component);
|
||||||
|
final int powerModel = deviceBatteryConsumer.getPowerModel(component);
|
||||||
|
if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
|
||||||
|
addEntry(metricTitle, EntryType.DEVICE_POWER_MODELED,
|
||||||
|
deviceBatteryConsumer.getConsumedPower(component),
|
||||||
|
appsBatteryConsumer.getConsumedPower(component));
|
||||||
|
} else {
|
||||||
|
addEntry(metricTitle + " (measured)", EntryType.DEVICE_POWER_MEASURED,
|
||||||
|
deviceBatteryConsumer.getConsumedPower(component),
|
||||||
|
appsBatteryConsumer.getConsumedPower(component));
|
||||||
|
addEntry(metricTitle + " (modeled)", EntryType.DEVICE_POWER_MODELED,
|
||||||
|
modeledDeviceBatteryConsumer.getConsumedPower(component),
|
||||||
|
modeledAppsBatteryConsumer.getConsumedPower(component));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final int customComponentCount =
|
||||||
|
deviceBatteryConsumer.getCustomPowerComponentCount();
|
||||||
|
for (int component = 0; component < customComponentCount; component++) {
|
||||||
|
final String name = deviceBatteryConsumer.getCustomPowerComponentName(
|
||||||
|
BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + component);
|
||||||
|
addEntry(name + " (custom)", EntryType.DEVICE_POWER_CUSTOM,
|
||||||
|
deviceBatteryConsumer.getConsumedPowerForCustomComponent(
|
||||||
|
BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + component),
|
||||||
|
appsBatteryConsumer.getConsumedPowerForCustomComponent(
|
||||||
|
BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + component));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
|
||||||
|
final String metricTitle = getTimeMetricTitle(component);
|
||||||
|
addEntry(metricTitle, EntryType.DEVICE_DURATION,
|
||||||
|
deviceBatteryConsumer.getUsageDurationMillis(component), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPowerProfileModelsOnly(BatteryConsumer batteryConsumer) {
|
||||||
|
for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
|
||||||
|
if (batteryConsumer.getPowerModel(component)
|
||||||
|
!= BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BatteryConsumer getRequestedBatteryConsumer(BatteryUsageStats batteryUsageStats,
|
private BatteryConsumer getRequestedBatteryConsumer(BatteryUsageStats batteryUsageStats,
|
||||||
String batteryConsumerId) {
|
String batteryConsumerId) {
|
||||||
for (int scope = 0;
|
for (UidBatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) {
|
||||||
scope < BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT;
|
|
||||||
scope++) {
|
|
||||||
if (batteryConsumerId(scope).equals(batteryConsumerId)) {
|
|
||||||
return batteryUsageStats.getAggregateBatteryConsumer(scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (BatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) {
|
|
||||||
if (batteryConsumerId(consumer).equals(batteryConsumerId)) {
|
if (batteryConsumerId(consumer).equals(batteryConsumerId)) {
|
||||||
return consumer;
|
return consumer;
|
||||||
}
|
}
|
||||||
@@ -136,17 +257,27 @@ public class BatteryConsumerData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static String getPowerMetricTitle(int componentId) {
|
static String getPowerMetricTitle(int componentId) {
|
||||||
final String componentName = DebugUtils.constantToString(BatteryConsumer.class,
|
return getPowerComponentName(componentId);
|
||||||
"POWER_COMPONENT_", componentId);
|
|
||||||
return componentName.charAt(0) + componentName.substring(1).toLowerCase().replace('_', ' ')
|
|
||||||
+ " power";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getTimeMetricTitle(int componentId) {
|
static String getTimeMetricTitle(int componentId) {
|
||||||
final String componentName = DebugUtils.constantToString(BatteryConsumer.class,
|
return getPowerComponentName(componentId) + " time";
|
||||||
"POWER_COMPONENT_", componentId);
|
}
|
||||||
return componentName.charAt(0) + componentName.substring(1).toLowerCase().replace('_', ' ')
|
|
||||||
+ " time";
|
private static String getPowerComponentName(int componentId) {
|
||||||
|
switch (componentId) {
|
||||||
|
case BatteryConsumer.POWER_COMPONENT_CPU:
|
||||||
|
return "CPU";
|
||||||
|
case BatteryConsumer.POWER_COMPONENT_GNSS:
|
||||||
|
return "GNSS";
|
||||||
|
case BatteryConsumer.POWER_COMPONENT_WIFI:
|
||||||
|
return "Wi-Fi";
|
||||||
|
default:
|
||||||
|
String componentName = DebugUtils.constantToString(BatteryConsumer.class,
|
||||||
|
"POWER_COMPONENT_", componentId);
|
||||||
|
return componentName.charAt(0) + componentName.substring(1).toLowerCase()
|
||||||
|
.replace('_', ' ');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void computeTotalPower(BatteryUsageStats batteryUsageStats,
|
private void computeTotalPower(BatteryUsageStats batteryUsageStats,
|
||||||
@@ -183,14 +314,12 @@ public class BatteryConsumerData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addEntry(String title, EntryType entryType, double amount, double totalAmount,
|
private void addEntry(String title, EntryType entryType, double value1, double value2) {
|
||||||
boolean isSystemBatteryConsumer) {
|
|
||||||
Entry entry = new Entry();
|
Entry entry = new Entry();
|
||||||
entry.title = title;
|
entry.title = title;
|
||||||
entry.entryType = entryType;
|
entry.entryType = entryType;
|
||||||
entry.value = amount;
|
entry.value1 = value1;
|
||||||
entry.total = totalAmount;
|
entry.value2 = value2;
|
||||||
entry.isSystemBatteryConsumer = isSystemBatteryConsumer;
|
|
||||||
mEntries.add(entry);
|
mEntries.add(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,18 +331,15 @@ public class BatteryConsumerData {
|
|||||||
return mEntries;
|
return mEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String batteryConsumerId(BatteryConsumer consumer) {
|
public static ConsumerType getConsumerType(String batteryConsumerId) {
|
||||||
if (consumer instanceof UidBatteryConsumer) {
|
if (batteryConsumerId.startsWith(UID_BATTERY_CONSUMER_ID_PREFIX)) {
|
||||||
return "APP|"
|
return ConsumerType.UID_BATTERY_CONSUMER;
|
||||||
+ UserHandle.getUserId(((UidBatteryConsumer) consumer).getUid()) + "|"
|
|
||||||
+ ((UidBatteryConsumer) consumer).getUid();
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
return ConsumerType.DEVICE_POWER_COMPONENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String batteryConsumerId(
|
public static String batteryConsumerId(UidBatteryConsumer consumer) {
|
||||||
@BatteryUsageStats.AggregateBatteryConsumerScope int scope) {
|
return UID_BATTERY_CONSUMER_ID_PREFIX + UserHandle.getUserId(consumer.getUid()) + "|"
|
||||||
return "SYS|" + scope;
|
+ consumer.getUid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,18 +16,16 @@
|
|||||||
|
|
||||||
package com.android.frameworks.core.batterystatsviewer;
|
package com.android.frameworks.core.batterystatsviewer;
|
||||||
|
|
||||||
import static com.android.frameworks.core.batterystatsviewer.BatteryConsumerData.batteryConsumerId;
|
|
||||||
|
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.BatteryConsumer;
|
|
||||||
import android.os.BatteryUsageStats;
|
import android.os.BatteryUsageStats;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.UidBatteryConsumer;
|
import android.os.UidBatteryConsumer;
|
||||||
import android.util.DebugUtils;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
class BatteryConsumerInfoHelper {
|
class BatteryConsumerInfoHelper {
|
||||||
|
|
||||||
private static final String SYSTEM_SERVER_PACKAGE_NAME = "android";
|
private static final String SYSTEM_SERVER_PACKAGE_NAME = "android";
|
||||||
@@ -39,93 +37,110 @@ class BatteryConsumerInfoHelper {
|
|||||||
public ApplicationInfo iconInfo;
|
public ApplicationInfo iconInfo;
|
||||||
public CharSequence packages;
|
public CharSequence packages;
|
||||||
public CharSequence details;
|
public CharSequence details;
|
||||||
public boolean isSystemBatteryConsumer;
|
public BatteryConsumerData.ConsumerType consumerType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static BatteryConsumerInfo makeBatteryConsumerInfo(
|
public static BatteryConsumerInfo makeBatteryConsumerInfo(
|
||||||
@NonNull BatteryConsumer batteryConsumer, String batteryConsumerId,
|
@NonNull BatteryUsageStats batteryUsageStats, String batteryConsumerId,
|
||||||
PackageManager packageManager) {
|
PackageManager packageManager) {
|
||||||
BatteryConsumerInfo info = new BatteryConsumerInfo();
|
BatteryConsumerData.ConsumerType consumerType = BatteryConsumerData.getConsumerType(
|
||||||
info.id = batteryConsumerId;
|
batteryConsumerId);
|
||||||
info.powerMah = batteryConsumer.getConsumedPower();
|
switch (consumerType) {
|
||||||
|
case UID_BATTERY_CONSUMER:
|
||||||
if (batteryConsumer instanceof UidBatteryConsumer) {
|
final List<UidBatteryConsumer> consumers =
|
||||||
final UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer;
|
batteryUsageStats.getUidBatteryConsumers();
|
||||||
int uid = uidBatteryConsumer.getUid();
|
for (UidBatteryConsumer consumer : consumers) {
|
||||||
info.details = String.format("UID: %d", uid);
|
if (BatteryConsumerData.batteryConsumerId(consumer).equals(batteryConsumerId)) {
|
||||||
String packageWithHighestDrain = uidBatteryConsumer.getPackageWithHighestDrain();
|
return makeBatteryConsumerInfo(consumer, packageManager);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
if (primaryPackageName != null) {
|
case DEVICE_POWER_COMPONENT:
|
||||||
try {
|
return makeAggregateBatteryConsumerInfo(batteryUsageStats);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Default the app icon to System Server. This includes root, dex2oat and other UIDs.
|
|
||||||
if (info.iconInfo == null) {
|
|
||||||
try {
|
|
||||||
info.iconInfo =
|
|
||||||
packageManager.getApplicationInfo(SYSTEM_SERVER_PACKAGE_NAME, 0);
|
|
||||||
} catch (PackageManager.NameNotFoundException nameNotFoundException) {
|
|
||||||
// Won't happen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int scope = 0;
|
|
||||||
scope < BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT;
|
|
||||||
scope++) {
|
|
||||||
if (batteryConsumerId(scope).equals(batteryConsumerId)) {
|
|
||||||
final String name = DebugUtils.constantToString(BatteryUsageStats.class,
|
|
||||||
"AGGREGATE_BATTERY_CONSUMER_SCOPE_", scope)
|
|
||||||
.replace('_', ' ');
|
|
||||||
info.label = name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BatteryConsumerInfo info = new BatteryConsumerInfo();
|
||||||
|
info.id = batteryConsumerId;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BatteryConsumerInfo makeBatteryConsumerInfo(
|
||||||
|
UidBatteryConsumer uidBatteryConsumer, PackageManager packageManager) {
|
||||||
|
BatteryConsumerInfo info = new BatteryConsumerInfo();
|
||||||
|
info.consumerType = BatteryConsumerData.ConsumerType.UID_BATTERY_CONSUMER;
|
||||||
|
info.id = BatteryConsumerData.batteryConsumerId(uidBatteryConsumer);
|
||||||
|
info.powerMah = uidBatteryConsumer.getConsumedPower();
|
||||||
|
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 (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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Default the app icon to System Server. This includes root, dex2oat and other UIDs.
|
||||||
|
if (info.iconInfo == null) {
|
||||||
|
try {
|
||||||
|
info.iconInfo =
|
||||||
|
packageManager.getApplicationInfo(SYSTEM_SERVER_PACKAGE_NAME, 0);
|
||||||
|
} catch (PackageManager.NameNotFoundException nameNotFoundException) {
|
||||||
|
// Won't happen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BatteryConsumerInfo makeAggregateBatteryConsumerInfo(
|
||||||
|
BatteryUsageStats batteryUsageStats) {
|
||||||
|
BatteryConsumerInfo info = new BatteryConsumerInfo();
|
||||||
|
info.consumerType = BatteryConsumerData.ConsumerType.DEVICE_POWER_COMPONENT;
|
||||||
|
info.id = BatteryConsumerData.AGGREGATE_BATTERY_CONSUMER_ID;
|
||||||
|
info.powerMah = batteryUsageStats.getConsumedPower();
|
||||||
|
info.label = "Device";
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import android.content.Intent;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.BatteryStatsManager;
|
import android.os.BatteryStatsManager;
|
||||||
import android.os.BatteryUsageStats;
|
import android.os.BatteryUsageStats;
|
||||||
|
import android.os.BatteryUsageStatsQuery;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.UidBatteryConsumer;
|
import android.os.UidBatteryConsumer;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -35,10 +36,12 @@ import androidx.loader.app.LoaderManager;
|
|||||||
import androidx.loader.content.Loader;
|
import androidx.loader.content.Loader;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
|
||||||
import com.android.settingslib.utils.AsyncLoaderCompat;
|
import com.android.settingslib.utils.AsyncLoaderCompat;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -50,10 +53,11 @@ import java.util.Locale;
|
|||||||
public class BatteryConsumerPickerActivity extends ComponentActivity {
|
public class BatteryConsumerPickerActivity extends ComponentActivity {
|
||||||
private static final String PREF_SELECTED_BATTERY_CONSUMER = "batteryConsumerId";
|
private static final String PREF_SELECTED_BATTERY_CONSUMER = "batteryConsumerId";
|
||||||
private static final int BATTERY_STATS_REFRESH_RATE_MILLIS = 60 * 1000;
|
private static final int BATTERY_STATS_REFRESH_RATE_MILLIS = 60 * 1000;
|
||||||
|
private static final String FORCE_FRESH_STATS = "force_fresh_stats";
|
||||||
private BatteryConsumerListAdapter mBatteryConsumerListAdapter;
|
private BatteryConsumerListAdapter mBatteryConsumerListAdapter;
|
||||||
private RecyclerView mAppList;
|
private RecyclerView mAppList;
|
||||||
private View mLoadingView;
|
private SwipeRefreshLayout mSwipeRefreshLayout;
|
||||||
private final Runnable mBatteryStatsRefresh = this::loadBatteryStats;
|
private final Runnable mBatteryStatsRefresh = this::refreshPeriodically;
|
||||||
|
|
||||||
private interface OnBatteryConsumerSelectedListener {
|
private interface OnBatteryConsumerSelectedListener {
|
||||||
void onBatteryConsumerSelected(String batteryConsumerId);
|
void onBatteryConsumerSelected(String batteryConsumerId);
|
||||||
@@ -64,8 +68,11 @@ public class BatteryConsumerPickerActivity extends ComponentActivity {
|
|||||||
super.onCreate(icicle);
|
super.onCreate(icicle);
|
||||||
|
|
||||||
setContentView(R.layout.battery_consumer_picker_layout);
|
setContentView(R.layout.battery_consumer_picker_layout);
|
||||||
mLoadingView = findViewById(R.id.loading_view);
|
|
||||||
|
|
||||||
|
mSwipeRefreshLayout = findViewById(R.id.swipe_refresh);
|
||||||
|
mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_green_light);
|
||||||
|
mSwipeRefreshLayout.setRefreshing(true);
|
||||||
|
mSwipeRefreshLayout.setOnRefreshListener(this::onRefresh);
|
||||||
mAppList = findViewById(R.id.list_view);
|
mAppList = findViewById(R.id.list_view);
|
||||||
mAppList.setLayoutManager(new LinearLayoutManager(this));
|
mAppList.setLayoutManager(new LinearLayoutManager(this));
|
||||||
mBatteryConsumerListAdapter =
|
mBatteryConsumerListAdapter =
|
||||||
@@ -97,7 +104,7 @@ public class BatteryConsumerPickerActivity extends ComponentActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
loadBatteryStats();
|
refreshPeriodically();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -106,42 +113,54 @@ public class BatteryConsumerPickerActivity extends ComponentActivity {
|
|||||||
getMainThreadHandler().removeCallbacks(mBatteryStatsRefresh);
|
getMainThreadHandler().removeCallbacks(mBatteryStatsRefresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadBatteryStats() {
|
private void refreshPeriodically() {
|
||||||
LoaderManager.getInstance(this).restartLoader(0, null,
|
loadBatteryUsageStats(false);
|
||||||
new BatteryConsumerListLoaderCallbacks());
|
|
||||||
getMainThreadHandler().postDelayed(mBatteryStatsRefresh, BATTERY_STATS_REFRESH_RATE_MILLIS);
|
getMainThreadHandler().postDelayed(mBatteryStatsRefresh, BATTERY_STATS_REFRESH_RATE_MILLIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onRefresh() {
|
||||||
|
loadBatteryUsageStats(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadBatteryUsageStats(boolean forceFreshStats) {
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putBoolean(FORCE_FRESH_STATS, forceFreshStats);
|
||||||
|
LoaderManager.getInstance(this).restartLoader(0, args,
|
||||||
|
new BatteryConsumerListLoaderCallbacks());
|
||||||
|
}
|
||||||
|
|
||||||
private static class BatteryConsumerListLoader extends
|
private static class BatteryConsumerListLoader extends
|
||||||
AsyncLoaderCompat<List<BatteryConsumerInfoHelper.BatteryConsumerInfo>> {
|
AsyncLoaderCompat<List<BatteryConsumerInfoHelper.BatteryConsumerInfo>> {
|
||||||
private final BatteryStatsManager mBatteryStatsManager;
|
private final BatteryStatsManager mBatteryStatsManager;
|
||||||
private final PackageManager mPackageManager;
|
private final PackageManager mPackageManager;
|
||||||
|
private final boolean mForceFreshStats;
|
||||||
|
|
||||||
BatteryConsumerListLoader(Context context) {
|
BatteryConsumerListLoader(Context context, boolean forceFreshStats) {
|
||||||
super(context);
|
super(context);
|
||||||
mBatteryStatsManager = context.getSystemService(BatteryStatsManager.class);
|
mBatteryStatsManager = context.getSystemService(BatteryStatsManager.class);
|
||||||
mPackageManager = context.getPackageManager();
|
mPackageManager = context.getPackageManager();
|
||||||
|
mForceFreshStats = forceFreshStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<BatteryConsumerInfoHelper.BatteryConsumerInfo> loadInBackground() {
|
public List<BatteryConsumerInfoHelper.BatteryConsumerInfo> loadInBackground() {
|
||||||
final BatteryUsageStats batteryUsageStats = mBatteryStatsManager.getBatteryUsageStats();
|
final BatteryUsageStatsQuery query = mForceFreshStats
|
||||||
|
? new BatteryUsageStatsQuery.Builder().setMaxStatsAgeMs(0).build()
|
||||||
|
: BatteryUsageStatsQuery.DEFAULT;
|
||||||
|
final BatteryUsageStats batteryUsageStats =
|
||||||
|
mBatteryStatsManager.getBatteryUsageStats(query);
|
||||||
List<BatteryConsumerInfoHelper.BatteryConsumerInfo> batteryConsumerList =
|
List<BatteryConsumerInfoHelper.BatteryConsumerInfo> batteryConsumerList =
|
||||||
new ArrayList<>();
|
new ArrayList<>();
|
||||||
|
|
||||||
for (int scope = 0;
|
batteryConsumerList.add(
|
||||||
scope < BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_COUNT;
|
BatteryConsumerInfoHelper.makeBatteryConsumerInfo(
|
||||||
scope++) {
|
batteryUsageStats,
|
||||||
batteryConsumerList.add(
|
BatteryConsumerData.AGGREGATE_BATTERY_CONSUMER_ID,
|
||||||
BatteryConsumerInfoHelper.makeBatteryConsumerInfo(
|
mPackageManager));
|
||||||
batteryUsageStats.getAggregateBatteryConsumer(scope),
|
|
||||||
BatteryConsumerData.batteryConsumerId(scope),
|
|
||||||
mPackageManager));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (UidBatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) {
|
for (UidBatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) {
|
||||||
batteryConsumerList.add(
|
batteryConsumerList.add(
|
||||||
BatteryConsumerInfoHelper.makeBatteryConsumerInfo(consumer,
|
BatteryConsumerInfoHelper.makeBatteryConsumerInfo(batteryUsageStats,
|
||||||
BatteryConsumerData.batteryConsumerId(consumer),
|
BatteryConsumerData.batteryConsumerId(consumer),
|
||||||
mPackageManager));
|
mPackageManager));
|
||||||
}
|
}
|
||||||
@@ -166,7 +185,8 @@ public class BatteryConsumerPickerActivity extends ComponentActivity {
|
|||||||
@Override
|
@Override
|
||||||
public Loader<List<BatteryConsumerInfoHelper.BatteryConsumerInfo>> onCreateLoader(int id,
|
public Loader<List<BatteryConsumerInfoHelper.BatteryConsumerInfo>> onCreateLoader(int id,
|
||||||
Bundle args) {
|
Bundle args) {
|
||||||
return new BatteryConsumerListLoader(BatteryConsumerPickerActivity.this);
|
return new BatteryConsumerListLoader(BatteryConsumerPickerActivity.this,
|
||||||
|
args.getBoolean(FORCE_FRESH_STATS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -174,8 +194,7 @@ public class BatteryConsumerPickerActivity extends ComponentActivity {
|
|||||||
@NonNull Loader<List<BatteryConsumerInfoHelper.BatteryConsumerInfo>> loader,
|
@NonNull Loader<List<BatteryConsumerInfoHelper.BatteryConsumerInfo>> loader,
|
||||||
List<BatteryConsumerInfoHelper.BatteryConsumerInfo> batteryConsumerList) {
|
List<BatteryConsumerInfoHelper.BatteryConsumerInfo> batteryConsumerList) {
|
||||||
mBatteryConsumerListAdapter.setBatteryConsumerList(batteryConsumerList);
|
mBatteryConsumerListAdapter.setBatteryConsumerList(batteryConsumerList);
|
||||||
mAppList.setVisibility(View.VISIBLE);
|
mSwipeRefreshLayout.setRefreshing(false);
|
||||||
mLoadingView.setVisibility(View.GONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -187,7 +206,8 @@ public class BatteryConsumerPickerActivity extends ComponentActivity {
|
|||||||
public class BatteryConsumerListAdapter
|
public class BatteryConsumerListAdapter
|
||||||
extends RecyclerView.Adapter<BatteryConsumerViewHolder> {
|
extends RecyclerView.Adapter<BatteryConsumerViewHolder> {
|
||||||
private final OnBatteryConsumerSelectedListener mListener;
|
private final OnBatteryConsumerSelectedListener mListener;
|
||||||
private List<BatteryConsumerInfoHelper.BatteryConsumerInfo> mBatteryConsumerList;
|
private List<BatteryConsumerInfoHelper.BatteryConsumerInfo> mBatteryConsumerList =
|
||||||
|
Collections.emptyList();
|
||||||
|
|
||||||
public BatteryConsumerListAdapter(OnBatteryConsumerSelectedListener listener) {
|
public BatteryConsumerListAdapter(OnBatteryConsumerSelectedListener listener) {
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import androidx.loader.app.LoaderManager.LoaderCallbacks;
|
|||||||
import androidx.loader.content.Loader;
|
import androidx.loader.content.Loader;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
|
|
||||||
import com.android.settingslib.utils.AsyncLoaderCompat;
|
import com.android.settingslib.utils.AsyncLoaderCompat;
|
||||||
|
|
||||||
@@ -48,10 +49,10 @@ public class BatteryStatsViewerActivity extends ComponentActivity {
|
|||||||
|
|
||||||
private static final int BATTERY_STATS_REFRESH_RATE_MILLIS = 60 * 1000;
|
private static final int BATTERY_STATS_REFRESH_RATE_MILLIS = 60 * 1000;
|
||||||
private static final int MILLIS_IN_MINUTE = 60000;
|
private static final int MILLIS_IN_MINUTE = 60000;
|
||||||
private static final int LOADER_BATTERY_USAGE_STATS = 1;
|
private static final String FORCE_FRESH_STATS = "force_fresh_stats";
|
||||||
|
|
||||||
private BatteryStatsDataAdapter mBatteryStatsDataAdapter;
|
private BatteryStatsDataAdapter mBatteryStatsDataAdapter;
|
||||||
private final Runnable mBatteryStatsRefresh = this::loadBatteryStats;
|
private final Runnable mBatteryStatsRefresh = this::refreshPeriodically;
|
||||||
private String mBatteryConsumerId;
|
private String mBatteryConsumerId;
|
||||||
private TextView mTitleView;
|
private TextView mTitleView;
|
||||||
private TextView mDetailsView;
|
private TextView mDetailsView;
|
||||||
@@ -59,7 +60,8 @@ public class BatteryStatsViewerActivity extends ComponentActivity {
|
|||||||
private TextView mPackagesView;
|
private TextView mPackagesView;
|
||||||
private View mHeadingsView;
|
private View mHeadingsView;
|
||||||
private RecyclerView mBatteryConsumerDataView;
|
private RecyclerView mBatteryConsumerDataView;
|
||||||
private View mLoadingView;
|
private SwipeRefreshLayout mSwipeRefreshLayout;
|
||||||
|
private View mCardView;
|
||||||
private View mEmptyView;
|
private View mEmptyView;
|
||||||
private List<BatteryUsageStats> mBatteryUsageStats;
|
private List<BatteryUsageStats> mBatteryUsageStats;
|
||||||
|
|
||||||
@@ -71,6 +73,12 @@ public class BatteryStatsViewerActivity extends ComponentActivity {
|
|||||||
|
|
||||||
setContentView(R.layout.battery_stats_viewer_layout);
|
setContentView(R.layout.battery_stats_viewer_layout);
|
||||||
|
|
||||||
|
mSwipeRefreshLayout = findViewById(R.id.swipe_refresh);
|
||||||
|
mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_green_light);
|
||||||
|
mSwipeRefreshLayout.setRefreshing(true);
|
||||||
|
mSwipeRefreshLayout.setOnRefreshListener(this::onRefresh);
|
||||||
|
|
||||||
|
mCardView = findViewById(R.id.app_card);
|
||||||
mTitleView = findViewById(android.R.id.title);
|
mTitleView = findViewById(android.R.id.title);
|
||||||
mDetailsView = findViewById(R.id.details);
|
mDetailsView = findViewById(R.id.details);
|
||||||
mIconView = findViewById(android.R.id.icon);
|
mIconView = findViewById(android.R.id.icon);
|
||||||
@@ -82,18 +90,13 @@ public class BatteryStatsViewerActivity extends ComponentActivity {
|
|||||||
mBatteryStatsDataAdapter = new BatteryStatsDataAdapter();
|
mBatteryStatsDataAdapter = new BatteryStatsDataAdapter();
|
||||||
mBatteryConsumerDataView.setAdapter(mBatteryStatsDataAdapter);
|
mBatteryConsumerDataView.setAdapter(mBatteryStatsDataAdapter);
|
||||||
|
|
||||||
mLoadingView = findViewById(R.id.loading_view);
|
|
||||||
mEmptyView = findViewById(R.id.empty_view);
|
mEmptyView = findViewById(R.id.empty_view);
|
||||||
|
|
||||||
LoaderManager loaderManager = LoaderManager.getInstance(this);
|
|
||||||
loaderManager.restartLoader(LOADER_BATTERY_USAGE_STATS, null,
|
|
||||||
new BatteryUsageStatsLoaderCallbacks());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
loadBatteryStats();
|
refreshPeriodically();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -102,32 +105,46 @@ public class BatteryStatsViewerActivity extends ComponentActivity {
|
|||||||
getMainThreadHandler().removeCallbacks(mBatteryStatsRefresh);
|
getMainThreadHandler().removeCallbacks(mBatteryStatsRefresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadBatteryStats() {
|
private void refreshPeriodically() {
|
||||||
LoaderManager loaderManager = LoaderManager.getInstance(this);
|
loadBatteryUsageStats(false);
|
||||||
loaderManager.restartLoader(LOADER_BATTERY_USAGE_STATS, null,
|
|
||||||
new BatteryUsageStatsLoaderCallbacks());
|
|
||||||
getMainThreadHandler().postDelayed(mBatteryStatsRefresh, BATTERY_STATS_REFRESH_RATE_MILLIS);
|
getMainThreadHandler().postDelayed(mBatteryStatsRefresh, BATTERY_STATS_REFRESH_RATE_MILLIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onRefresh() {
|
||||||
|
loadBatteryUsageStats(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadBatteryUsageStats(boolean forceFreshStats) {
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putBoolean(FORCE_FRESH_STATS, forceFreshStats);
|
||||||
|
LoaderManager.getInstance(this).restartLoader(0, args,
|
||||||
|
new BatteryUsageStatsLoaderCallbacks());
|
||||||
|
}
|
||||||
|
|
||||||
private static class BatteryUsageStatsLoader extends
|
private static class BatteryUsageStatsLoader extends
|
||||||
AsyncLoaderCompat<List<BatteryUsageStats>> {
|
AsyncLoaderCompat<List<BatteryUsageStats>> {
|
||||||
private final BatteryStatsManager mBatteryStatsManager;
|
private final BatteryStatsManager mBatteryStatsManager;
|
||||||
|
private final boolean mForceFreshStats;
|
||||||
|
|
||||||
BatteryUsageStatsLoader(Context context) {
|
BatteryUsageStatsLoader(Context context, boolean forceFreshStats) {
|
||||||
super(context);
|
super(context);
|
||||||
mBatteryStatsManager = context.getSystemService(BatteryStatsManager.class);
|
mBatteryStatsManager = context.getSystemService(BatteryStatsManager.class);
|
||||||
|
mForceFreshStats = forceFreshStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<BatteryUsageStats> loadInBackground() {
|
public List<BatteryUsageStats> loadInBackground() {
|
||||||
|
final int maxStatsAgeMs = mForceFreshStats ? 0 : BATTERY_STATS_REFRESH_RATE_MILLIS;
|
||||||
final BatteryUsageStatsQuery queryDefault =
|
final BatteryUsageStatsQuery queryDefault =
|
||||||
new BatteryUsageStatsQuery.Builder()
|
new BatteryUsageStatsQuery.Builder()
|
||||||
.includePowerModels()
|
.includePowerModels()
|
||||||
|
.setMaxStatsAgeMs(maxStatsAgeMs)
|
||||||
.build();
|
.build();
|
||||||
final BatteryUsageStatsQuery queryPowerProfileModeledOnly =
|
final BatteryUsageStatsQuery queryPowerProfileModeledOnly =
|
||||||
new BatteryUsageStatsQuery.Builder()
|
new BatteryUsageStatsQuery.Builder()
|
||||||
.powerProfileModeledOnly()
|
.powerProfileModeledOnly()
|
||||||
.includePowerModels()
|
.includePowerModels()
|
||||||
|
.setMaxStatsAgeMs(maxStatsAgeMs)
|
||||||
.build();
|
.build();
|
||||||
return mBatteryStatsManager.getBatteryUsageStats(
|
return mBatteryStatsManager.getBatteryUsageStats(
|
||||||
List.of(queryDefault, queryPowerProfileModeledOnly));
|
List.of(queryDefault, queryPowerProfileModeledOnly));
|
||||||
@@ -143,7 +160,8 @@ public class BatteryStatsViewerActivity extends ComponentActivity {
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Loader<List<BatteryUsageStats>> onCreateLoader(int id, Bundle args) {
|
public Loader<List<BatteryUsageStats>> onCreateLoader(int id, Bundle args) {
|
||||||
return new BatteryUsageStatsLoader(BatteryStatsViewerActivity.this);
|
return new BatteryUsageStatsLoader(BatteryStatsViewerActivity.this,
|
||||||
|
args.getBoolean(FORCE_FRESH_STATS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -194,7 +212,8 @@ public class BatteryStatsViewerActivity extends ComponentActivity {
|
|||||||
mPackagesView.setVisibility(View.GONE);
|
mPackagesView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (batteryConsumerInfo.isSystemBatteryConsumer) {
|
if (batteryConsumerInfo.consumerType
|
||||||
|
== BatteryConsumerData.ConsumerType.DEVICE_POWER_COMPONENT) {
|
||||||
mHeadingsView.setVisibility(View.VISIBLE);
|
mHeadingsView.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
mHeadingsView.setVisibility(View.GONE);
|
mHeadingsView.setVisibility(View.GONE);
|
||||||
@@ -210,7 +229,8 @@ public class BatteryStatsViewerActivity extends ComponentActivity {
|
|||||||
mBatteryConsumerDataView.setVisibility(View.VISIBLE);
|
mBatteryConsumerDataView.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mLoadingView.setVisibility(View.GONE);
|
mCardView.setVisibility(View.VISIBLE);
|
||||||
|
mSwipeRefreshLayout.setRefreshing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class BatteryStatsDataAdapter extends
|
private static class BatteryStatsDataAdapter extends
|
||||||
@@ -218,16 +238,16 @@ public class BatteryStatsViewerActivity extends ComponentActivity {
|
|||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
public ImageView iconImageView;
|
public ImageView iconImageView;
|
||||||
public TextView titleTextView;
|
public TextView titleTextView;
|
||||||
public TextView amountTextView;
|
public TextView value1TextView;
|
||||||
public TextView percentTextView;
|
public TextView value2TextView;
|
||||||
|
|
||||||
ViewHolder(View itemView) {
|
ViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
|
|
||||||
iconImageView = itemView.findViewById(R.id.icon);
|
iconImageView = itemView.findViewById(R.id.icon);
|
||||||
titleTextView = itemView.findViewById(R.id.title);
|
titleTextView = itemView.findViewById(R.id.title);
|
||||||
amountTextView = itemView.findViewById(R.id.amount);
|
value1TextView = itemView.findViewById(R.id.value1);
|
||||||
percentTextView = itemView.findViewById(R.id.percent);
|
value2TextView = itemView.findViewById(R.id.value2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,57 +275,108 @@ public class BatteryStatsViewerActivity extends ComponentActivity {
|
|||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
|
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
|
||||||
BatteryConsumerData.Entry entry = mEntries.get(position);
|
BatteryConsumerData.Entry entry = mEntries.get(position);
|
||||||
|
|
||||||
switch (entry.entryType) {
|
switch (entry.entryType) {
|
||||||
case POWER_MODELED:
|
case UID_TOTAL_POWER:
|
||||||
viewHolder.titleTextView.setText(entry.title);
|
setTitleIconAndBackground(viewHolder, entry.title,
|
||||||
viewHolder.amountTextView.setText(
|
R.drawable.gm_sum_24, 0);
|
||||||
String.format(Locale.getDefault(), "%.1f mAh", entry.value));
|
setPowerText(viewHolder.value1TextView, entry.value1);
|
||||||
viewHolder.iconImageView.setImageResource(R.drawable.gm_calculate_24);
|
setProportionText(viewHolder.value2TextView, entry);
|
||||||
viewHolder.itemView.setBackgroundResource(
|
break;
|
||||||
|
case UID_POWER_MODELED:
|
||||||
|
setTitleIconAndBackground(viewHolder, entry.title,
|
||||||
|
R.drawable.gm_calculate_24,
|
||||||
R.color.battery_consumer_bg_power_profile);
|
R.color.battery_consumer_bg_power_profile);
|
||||||
|
setPowerText(viewHolder.value1TextView, entry.value1);
|
||||||
|
setProportionText(viewHolder.value2TextView, entry);
|
||||||
break;
|
break;
|
||||||
case POWER_MEASURED:
|
case UID_POWER_MEASURED:
|
||||||
viewHolder.titleTextView.setText(entry.title);
|
setTitleIconAndBackground(viewHolder, entry.title,
|
||||||
viewHolder.amountTextView.setText(
|
R.drawable.gm_amp_24,
|
||||||
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);
|
R.color.battery_consumer_bg_measured_energy);
|
||||||
|
setPowerText(viewHolder.value1TextView, entry.value1);
|
||||||
|
setProportionText(viewHolder.value2TextView, entry);
|
||||||
break;
|
break;
|
||||||
case POWER_CUSTOM:
|
case UID_POWER_CUSTOM:
|
||||||
viewHolder.titleTextView.setText(entry.title);
|
setTitleIconAndBackground(viewHolder, entry.title,
|
||||||
viewHolder.amountTextView.setText(
|
R.drawable.gm_custom_24,
|
||||||
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);
|
R.color.battery_consumer_bg_measured_energy);
|
||||||
|
setPowerText(viewHolder.value1TextView, entry.value1);
|
||||||
|
setProportionText(viewHolder.value2TextView, entry);
|
||||||
break;
|
break;
|
||||||
case DURATION:
|
case UID_DURATION:
|
||||||
viewHolder.titleTextView.setText(entry.title);
|
setTitleIconAndBackground(viewHolder, entry.title,
|
||||||
final long durationMs = (long) entry.value;
|
R.drawable.gm_timer_24, 0);
|
||||||
CharSequence text;
|
setDurationText(viewHolder.value1TextView, (long) entry.value1);
|
||||||
if (durationMs < MILLIS_IN_MINUTE) {
|
setProportionText(viewHolder.value2TextView, entry);
|
||||||
text = String.format(Locale.getDefault(), "%,d ms", durationMs);
|
break;
|
||||||
} else {
|
case DEVICE_TOTAL_POWER:
|
||||||
text = String.format(Locale.getDefault(), "%,d m %d s",
|
setTitleIconAndBackground(viewHolder, entry.title,
|
||||||
durationMs / MILLIS_IN_MINUTE,
|
R.drawable.gm_sum_24, 0);
|
||||||
(durationMs % MILLIS_IN_MINUTE) / 1000);
|
setPowerText(viewHolder.value1TextView, entry.value1);
|
||||||
}
|
setPowerText(viewHolder.value2TextView, entry.value2);
|
||||||
|
break;
|
||||||
viewHolder.amountTextView.setText(text);
|
case DEVICE_POWER_MODELED:
|
||||||
viewHolder.iconImageView.setImageResource(R.drawable.gm_timer_24);
|
setTitleIconAndBackground(viewHolder, entry.title,
|
||||||
viewHolder.itemView.setBackground(null);
|
R.drawable.gm_calculate_24,
|
||||||
|
R.color.battery_consumer_bg_power_profile);
|
||||||
|
setPowerText(viewHolder.value1TextView, entry.value1);
|
||||||
|
setPowerText(viewHolder.value2TextView, entry.value2);
|
||||||
|
break;
|
||||||
|
case DEVICE_POWER_MEASURED:
|
||||||
|
setTitleIconAndBackground(viewHolder, entry.title,
|
||||||
|
R.drawable.gm_amp_24,
|
||||||
|
R.color.battery_consumer_bg_measured_energy);
|
||||||
|
setPowerText(viewHolder.value1TextView, entry.value1);
|
||||||
|
setPowerText(viewHolder.value2TextView, entry.value2);
|
||||||
|
break;
|
||||||
|
case DEVICE_POWER_CUSTOM:
|
||||||
|
setTitleIconAndBackground(viewHolder, entry.title,
|
||||||
|
R.drawable.gm_custom_24,
|
||||||
|
R.color.battery_consumer_bg_measured_energy);
|
||||||
|
setPowerText(viewHolder.value1TextView, entry.value1);
|
||||||
|
setPowerText(viewHolder.value2TextView, entry.value2);
|
||||||
|
break;
|
||||||
|
case DEVICE_DURATION:
|
||||||
|
setTitleIconAndBackground(viewHolder, entry.title,
|
||||||
|
R.drawable.gm_timer_24, 0);
|
||||||
|
setDurationText(viewHolder.value1TextView, (long) entry.value1);
|
||||||
|
viewHolder.value2TextView.setVisibility(View.GONE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
double proportion;
|
private void setTitleIconAndBackground(ViewHolder viewHolder, String title, int icon,
|
||||||
if (entry.isSystemBatteryConsumer) {
|
int background) {
|
||||||
proportion = entry.value != 0 ? entry.total * 100 / entry.value : 0;
|
viewHolder.titleTextView.setText(title);
|
||||||
} else {
|
viewHolder.iconImageView.setImageResource(icon);
|
||||||
proportion = entry.total != 0 ? entry.value * 100 / entry.total : 0;
|
viewHolder.itemView.setBackgroundResource(background);
|
||||||
}
|
}
|
||||||
viewHolder.percentTextView.setText(
|
|
||||||
|
private void setProportionText(TextView textView, BatteryConsumerData.Entry entry) {
|
||||||
|
final double proportion = entry.value2 != 0 ? entry.value1 * 100 / entry.value2 : 0;
|
||||||
|
textView.setText(
|
||||||
String.format(Locale.getDefault(), "%.1f%%", proportion));
|
String.format(Locale.getDefault(), "%.1f%%", proportion));
|
||||||
|
textView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPowerText(TextView textView, double powerMah) {
|
||||||
|
textView.setText(String.format(Locale.getDefault(), "%.1f", powerMah));
|
||||||
|
textView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDurationText(TextView textView, long durationMs) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
textView.setText(text);
|
||||||
|
textView.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user