Merge "Create Advanced battery page"

This commit is contained in:
Lei Yu
2017-02-08 20:33:35 +00:00
committed by Android (Google) Code Review
15 changed files with 569 additions and 12 deletions

View File

@@ -26,6 +26,7 @@ import android.widget.TextView;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.BatteryInfo;
import com.android.settingslib.graph.UsageView;
@@ -49,12 +50,22 @@ public class BatteryHistoryPreference extends Preference {
@Override
public void performClick() {
mHelper.storeStatsHistoryInFile(BATTERY_HISTORY_FILE);
Bundle args = new Bundle();
args.putString(BatteryHistoryDetail.EXTRA_STATS, BATTERY_HISTORY_FILE);
args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST, mHelper.getBatteryBroadcast());
Utils.startWithFragment(getContext(), BatteryHistoryDetail.class.getName(), args,
null, 0, R.string.history_details_title, null);
// TODO(b/34890746): remove this since history graph is not clickable
final Context context = getContext();
final PowerUsageFeatureProvider featureProvider = FeatureFactory.getFactory(context)
.getPowerUsageFeatureProvider(context);
if (featureProvider.isAdvancedUiEnabled()) {
Utils.startWithFragment(getContext(), PowerUsageAdvanced.class.getName(), null,
null, 0, R.string.advanced_battery_title, null);
} else {
mHelper.storeStatsHistoryInFile(BATTERY_HISTORY_FILE);
Bundle args = new Bundle();
args.putString(BatteryHistoryDetail.EXTRA_STATS, BATTERY_HISTORY_FILE);
args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST, mHelper.getBatteryBroadcast());
Utils.startWithFragment(getContext(), BatteryHistoryDetail.class.getName(), args,
null, 0, R.string.history_details_title, null);
}
}
public void setStats(BatteryStatsHelper batteryStats) {

View File

@@ -20,6 +20,7 @@ import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -48,12 +49,21 @@ public class PowerGaugePreference extends TintablePreference {
mIconSize = context.getResources().getDimensionPixelSize(R.dimen.app_icon_size);
}
public PowerGaugePreference(Context context, AttributeSet attrs) {
super(context, attrs);
final Drawable icon = context.getDrawable(R.drawable.ic_battery_circle);
setIcon(icon);
setWidgetLayoutResource(R.layout.preference_widget_summary);
mIconSize = icon.getIntrinsicWidth();
}
public void setContentDescription(String name) {
mContentDescription = name;
notifyChanged();
}
public void setPercent(double percentOfMax, double percentOfTotal) {
public void setPercent(double percentOfTotal) {
mProgress = Utils.formatPercentage((int) (percentOfTotal + 0.5));
notifyChanged();
}

View File

@@ -0,0 +1,237 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.settings.fuelgauge;
import android.content.Context;
import android.os.Bundle;
import android.os.Process;
import android.provider.SearchIndexableResource;
import android.support.annotation.ColorInt;
import android.support.annotation.IntDef;
import android.support.annotation.VisibleForTesting;
import android.util.SparseArray;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatterySipper.DrainType;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
import com.android.settings.core.PreferenceController;
import com.android.settings.fuelgauge.PowerUsageAdvanced.PowerUsageData.UsageType;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PowerUsageAdvanced extends PowerUsageBase {
private static final String TAG = "AdvancedBatteryUsage";
private static final String KEY_BATTERY_GRAPH = "battery_graph";
private static final String KEY_BATTERY_APPS = "battery_apps";
private static final String KEY_BATTERY_WIFI = "battery_wifi";
private static final String KEY_BATTERY_CELL = "battery_cell";
private static final String KEY_BATTERY_BLUETOOTH = "battery_bluetooth";
private static final String KEY_BATTERY_IDLE = "battery_idle";
private static final String KEY_BATTERY_SERVICE = "battery_service";
private static final String KEY_BATTERY_SYSTEM = "battery_system";
private static final String KEY_BATTERY_USER = "battery_user";
private BatteryHistoryPreference mHistPref;
@VisibleForTesting
SparseArray<String> mUsageTypeMap;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_GRAPH);
init();
}
@Override
public void onResume() {
super.onResume();
refreshStats();
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.FUELGAUGE_BATTERY_HISTORY_DETAIL;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.power_usage_advanced;
}
@Override
protected List<PreferenceController> getPreferenceControllers(Context context) {
return null;
}
@Override
protected void refreshStats() {
super.refreshStats();
updatePreference(mHistPref);
List<PowerUsageData> dataList = parsePowerUsageData(mStatsHelper);
for (int i = 0, size = dataList.size(); i < size; i++) {
final PowerUsageData data = dataList.get(i);
final String key = mUsageTypeMap.get(data.usageType);
if (key != null) {
bindData(key, data);
}
}
}
@VisibleForTesting
@UsageType int extractUsageType(BatterySipper sipper) {
final DrainType drainType = sipper.drainType;
final int uid = sipper.getUid();
// TODO(b/34385770): add logic to extract type service
if (drainType == DrainType.WIFI) {
return UsageType.WIFI;
} else if (drainType == DrainType.BLUETOOTH) {
return UsageType.BLUETOOTH;
} else if (drainType == DrainType.IDLE) {
return UsageType.IDLE;
} else if (drainType == DrainType.USER) {
return UsageType.USER;
} else if (drainType == DrainType.CELL) {
return UsageType.CELL;
} else if (uid == Process.SYSTEM_UID || uid == Process.ROOT_UID) {
return UsageType.SYSTEM;
} else {
return UsageType.APP;
}
}
@VisibleForTesting
void init() {
// Store projection from UsageType to preference key
mUsageTypeMap = new SparseArray<>();
mUsageTypeMap.put(UsageType.APP, KEY_BATTERY_APPS);
mUsageTypeMap.put(UsageType.WIFI, KEY_BATTERY_WIFI);
mUsageTypeMap.put(UsageType.CELL, KEY_BATTERY_CELL);
mUsageTypeMap.put(UsageType.BLUETOOTH, KEY_BATTERY_BLUETOOTH);
mUsageTypeMap.put(UsageType.IDLE, KEY_BATTERY_IDLE);
mUsageTypeMap.put(UsageType.SERVICE, KEY_BATTERY_SERVICE);
mUsageTypeMap.put(UsageType.USER, KEY_BATTERY_USER);
mUsageTypeMap.put(UsageType.SYSTEM, KEY_BATTERY_SYSTEM);
}
@VisibleForTesting
List<PowerUsageData> parsePowerUsageData(BatteryStatsHelper statusHelper) {
final List<BatterySipper> batterySippers = statusHelper.getUsageList();
final Map<Integer, PowerUsageData> batteryDataMap = new HashMap<>();
for (int i = 0, size = mUsageTypeMap.size(); i < size; i++) {
@UsageType final int type = mUsageTypeMap.keyAt(i);
batteryDataMap.put(type, PowerUsageData.createBatteryUsageData(type));
}
// Accumulate power usage based on usage type
for (final BatterySipper sipper : batterySippers) {
final PowerUsageData usageData = batteryDataMap.get(extractUsageType(sipper));
usageData.totalPowerMah += sipper.totalPowerMah;
}
// TODO(b/34385770): add logic to extract the summary
final List<PowerUsageData> batteryDataList = new ArrayList<>(batteryDataMap.values());
final double totalPower = statusHelper.getTotalPower();
for (final PowerUsageData usageData : batteryDataList) {
usageData.percentage = (usageData.totalPowerMah / totalPower) * 100;
}
return batteryDataList;
}
private void bindData(String key, PowerUsageData batteryData) {
final PowerGaugePreference pref = (PowerGaugePreference) findPreference(key);
pref.setSummary(batteryData.summary);
pref.setPercent(batteryData.percentage);
}
/**
* Class that contains data used in {@link PowerGaugePreference}.
*/
@VisibleForTesting
static class PowerUsageData {
@Retention(RetentionPolicy.SOURCE)
@IntDef({UsageType.APP,
UsageType.WIFI,
UsageType.CELL,
UsageType.SERVICE,
UsageType.SYSTEM,
UsageType.BLUETOOTH,
UsageType.USER,
UsageType.IDLE})
public @interface UsageType {
int APP = 0;
int WIFI = 1;
int CELL = 2;
int SERVICE = 3;
int SYSTEM = 4;
int BLUETOOTH = 5;
int USER = 6;
int IDLE = 7;
}
public String summary;
public double percentage;
public double totalPowerMah;
@ColorInt
public int iconColor;
@UsageType
public int usageType;
private PowerUsageData(@UsageType int usageType) {
this.usageType = usageType;
totalPowerMah = 0;
}
public static PowerUsageData createBatteryUsageData(@UsageType int usageType) {
// TODO(b/34385770): add color logic in this part
return new PowerUsageData(usageType);
}
}
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
.isEnabled()) {
return null;
}
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.power_usage_advanced;
return Arrays.asList(sir);
}
};
}

View File

@@ -36,4 +36,9 @@ public interface PowerUsageFeatureProvider {
* Gets an {@link Intent} to show additional battery info.
*/
Intent getAdditionalBatteryInfoIntent();
/**
* Check whether advanced ui is enabled
*/
boolean isAdvancedUiEnabled();
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.fuelgauge;
import android.content.Intent;
public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider {
@Override
public boolean isLocationSettingEnabled(String[] packages) {
return false;
}
@Override
public boolean isAdditionalBatteryInfoEnabled() {
return false;
}
@Override
public Intent getAdditionalBatteryInfoIntent() {
return null;
}
@Override
public boolean isAdvancedUiEnabled() {
return false;
}
}

View File

@@ -413,7 +413,7 @@ public class PowerUsageSummary extends PowerUsageBase {
sipper.percent = percentOfTotal;
pref.setTitle(entry.getLabel());
pref.setOrder(i + 1);
pref.setPercent(percentOfMax, percentOfTotal);
pref.setPercent(percentOfTotal);
setUsageSummary(pref, usedTime, sipper.usageTimeMs);
if ((sipper.drainType != DrainType.APP
|| sipper.uidObj.getUid() == Process.ROOT_UID)