Fix and update battery detail page

Bug: 27205329
Change-Id: Ie984348d59c1b15bec7283a94a94489f78cacb79
This commit is contained in:
Jason Monk
2016-02-23 12:45:20 -05:00
parent 60df76b169
commit d1ea8a05b0
9 changed files with 523 additions and 9 deletions

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 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"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingEnd="56dp"
android:paddingTop="4dp"
android:orientation="vertical">
<TextView
android:id="@android:id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorSecondary" />
<com.android.settings.fuelgauge.BatteryActiveView
android:id="@+id/battery_active"
android:layout_width="match_parent"
android:layout_height="6dp" />
</LinearLayout>

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 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"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:orientation="vertical">
<TextView
android:id="@+id/charge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="36sp"
android:textColor="?android:attr/colorAccent" />
<TextView
android:id="@+id/estimation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorSecondary" />
<com.android.settingslib.graph.UsageView
android:id="@+id/battery_usage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
settings:sideLabels="@array/battery_labels"
android:colorAccent="?android:attr/colorAccent"
android:gravity="end"
settings:textColor="?android:attr/textColorSecondary" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="2dp"
android:background="?android:attr/listDivider" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include android:id="@+id/cell_network_group"
layout="@layout/battery_active_view" />
<include android:id="@+id/camera_group"
layout="@layout/battery_active_view" />
<include android:id="@+id/flashlight_group"
layout="@layout/battery_active_view" />
<include android:id="@+id/gps_group"
layout="@layout/battery_active_view" />
<include android:id="@+id/wifi_group"
layout="@layout/battery_active_view" />
<include android:id="@+id/cpu_group"
layout="@layout/battery_active_view" />
<include android:id="@+id/screen_on_group"
layout="@layout/battery_active_view" />
<include android:id="@+id/charging_group"
layout="@layout/battery_active_view" />
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2016 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.annotation.Nullable;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.SparseIntArray;
import android.view.View;
public class BatteryActiveView extends View {
private final Paint mPaint = new Paint();
private BatteryActiveProvider mProvider;
public BatteryActiveView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public void setProvider(BatteryActiveProvider provider) {
mProvider = provider;
if (getWidth() != 0) {
postInvalidate();
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (getWidth() != 0) {
postInvalidate();
}
}
@Override
protected void onDraw(Canvas canvas) {
if (mProvider == null) {
return;
}
SparseIntArray array = mProvider.getColorArray();
float period = mProvider.getPeriod();
for (int i = 0; i < array.size() - 1; i++) {
drawColor(canvas, array.keyAt(i), array.keyAt(i + 1), array.valueAt(i), period);
}
}
private void drawColor(Canvas canvas, int start, int end, int color, float period) {
if (color == 0) {
return;
}
mPaint.setColor(color);
canvas.drawRect(start / period * getWidth(), 0, end / period * getWidth(), getHeight(),
mPaint);
}
public interface BatteryActiveProvider {
boolean hasData();
long getPeriod();
SparseIntArray getColorArray();
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2016 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.os.BatteryStats.HistoryItem;
import android.telephony.ServiceState;
import android.util.SparseIntArray;
import com.android.settings.Utils;
import com.android.settings.fuelgauge.BatteryActiveView.BatteryActiveProvider;
import com.android.settingslib.BatteryInfo;
public class BatteryCellParser implements BatteryInfo.BatteryDataParser, BatteryActiveProvider {
private final SparseIntArray mData = new SparseIntArray();
private int mLastValue;
private long mLength;
private long mLastTime;
protected int getValue(HistoryItem rec) {
int bin;
if (((rec.states & HistoryItem.STATE_PHONE_STATE_MASK)
>> HistoryItem.STATE_PHONE_STATE_SHIFT)
== ServiceState.STATE_POWER_OFF) {
bin = 0;
} else if ((rec.states & HistoryItem.STATE_PHONE_SCANNING_FLAG) != 0) {
bin = 1;
} else {
bin = (rec.states & HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK)
>> HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT;
bin += 2;
}
return bin;
}
@Override
public void onParsingStarted(long startTime, long endTime) {
mLength = endTime - startTime;
}
@Override
public void onDataPoint(long time, HistoryItem record) {
int value = getValue(record);
if (value != mLastValue) {
mData.put((int) time, value);
mLastValue = value;
}
mLastTime = time;
}
@Override
public void onDataGap() {
if (mLastValue != 0) {
mData.put((int) mLastTime, 0);
mLastValue = 0;
}
}
@Override
public void onParsingDone() {
if (mLastValue != 0) {
mData.put((int) mLastTime, 0);
mLastValue = 0;
}
}
@Override
public long getPeriod() {
return mLength;
}
@Override
public boolean hasData() {
return mData.size() > 1;
}
@Override
public SparseIntArray getColorArray() {
SparseIntArray ret = new SparseIntArray();
for (int i = 0; i < mData.size(); i++) {
ret.put(mData.keyAt(i), getColor(mData.valueAt(i)));
}
return ret;
}
private int getColor(int i) {
return Utils.BADNESS_COLORS[i];
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2016 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.os.BatteryStats.HistoryItem;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import com.android.settings.fuelgauge.BatteryActiveView.BatteryActiveProvider;
import com.android.settingslib.BatteryInfo;
public class BatteryFlagParser implements BatteryInfo.BatteryDataParser, BatteryActiveProvider {
private final SparseBooleanArray mData = new SparseBooleanArray();
private final int mFlag;
private final boolean mState2;
private final int mAccentColor;
private boolean mLastSet;
private long mLength;
private long mLastTime;
public BatteryFlagParser(int accent, boolean state2, int flag) {
mAccentColor = accent;
mFlag = flag;
mState2 = state2;
}
protected boolean isSet(HistoryItem record) {
return ((mState2 ? record.states2 : record.states) & mFlag) != 0;
}
@Override
public void onParsingStarted(long startTime, long endTime) {
mLength = endTime - startTime;
}
@Override
public void onDataPoint(long time, HistoryItem record) {
boolean isSet = isSet(record);
if (isSet != mLastSet) {
mData.put((int) time, isSet);
mLastSet = isSet;
}
mLastTime = time;
}
@Override
public void onDataGap() {
if (mLastSet) {
mData.put((int) mLastTime, false);
mLastSet = false;
}
}
@Override
public void onParsingDone() {
if (mLastSet) {
mData.put((int) mLastTime, false);
mLastSet = false;
}
}
@Override
public long getPeriod() {
return mLength;
}
@Override
public boolean hasData() {
return mData.size() > 1;
}
@Override
public SparseIntArray getColorArray() {
SparseIntArray ret = new SparseIntArray();
for (int i = 0; i < mData.size(); i++) {
ret.put(mData.keyAt(i), getColor(mData.valueAt(i)));
}
return ret;
}
private int getColor(boolean b) {
if (b) {
return mAccentColor;
}
return 0;
}
}

View File

@@ -18,15 +18,21 @@ package com.android.settings.fuelgauge;
import android.content.Intent;
import android.os.BatteryStats;
import android.os.BatteryStats.HistoryItem;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.InstrumentedFragment;
import com.android.settings.R;
import com.android.settings.fuelgauge.BatteryActiveView.BatteryActiveProvider;
import com.android.settingslib.BatteryInfo;
import com.android.settingslib.graph.UsageView;
public class BatteryHistoryDetail extends InstrumentedFragment {
public static final String EXTRA_STATS = "stats";
@@ -35,21 +41,80 @@ public class BatteryHistoryDetail extends InstrumentedFragment {
private BatteryStats mStats;
private Intent mBatteryBroadcast;
private BatteryFlagParser mChargingParser;
private BatteryFlagParser mScreenOn;
private BatteryFlagParser mGpsParser;
private BatteryFlagParser mFlashlightParser;
private BatteryFlagParser mCameraParser;
private BatteryWifiParser mWifiParser;
private BatteryFlagParser mCpuParser;
private BatteryCellParser mPhoneParser;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
String histFile = getArguments().getString(EXTRA_STATS);
mStats = BatteryStatsHelper.statsFromFile(getActivity(), histFile);
mBatteryBroadcast = getArguments().getParcelable(EXTRA_BROADCAST);
TypedValue value = new TypedValue();
getContext().getTheme().resolveAttribute(android.R.attr.colorAccent, value, true);
int accentColor = getContext().getColor(value.resourceId);
mChargingParser = new BatteryFlagParser(accentColor, false,
HistoryItem.STATE_BATTERY_PLUGGED_FLAG);
mScreenOn = new BatteryFlagParser(accentColor, false,
HistoryItem.STATE_SCREEN_ON_FLAG);
mGpsParser = new BatteryFlagParser(accentColor, false,
HistoryItem.STATE_GPS_ON_FLAG);
mFlashlightParser = new BatteryFlagParser(accentColor, true,
HistoryItem.STATE2_FLASHLIGHT_FLAG);
mCameraParser = new BatteryFlagParser(accentColor, true,
HistoryItem.STATE2_CAMERA_FLAG);
mWifiParser = new BatteryWifiParser(accentColor);
mCpuParser = new BatteryFlagParser(accentColor, false,
HistoryItem.STATE_CPU_RUNNING_FLAG);
mPhoneParser = new BatteryCellParser();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.battery_history_chart, null);
BatteryHistoryChart chart = (BatteryHistoryChart)view.findViewById(
R.id.battery_history_chart);
chart.setStats(mStats, mBatteryBroadcast);
return view;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.battery_history_detail, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
updateEverything();
}
private void updateEverything() {
BatteryInfo info = BatteryInfo.getBatteryInfo(getContext(), mBatteryBroadcast, mStats,
SystemClock.elapsedRealtime() * 1000);
final View view = getView();
info.bindHistory((UsageView) view.findViewById(R.id.battery_usage), mChargingParser,
mScreenOn, mGpsParser, mFlashlightParser, mCameraParser, mWifiParser, mCpuParser,
mPhoneParser);
((TextView) view.findViewById(R.id.charge)).setText(info.batteryPercentString);
((TextView) view.findViewById(R.id.estimation)).setText(info.remainingLabel);
bindData(mChargingParser, R.string.battery_stats_charging_label, R.id.charging_group);
bindData(mScreenOn, R.string.battery_stats_screen_on_label, R.id.screen_on_group);
bindData(mGpsParser, R.string.battery_stats_gps_on_label, R.id.gps_group);
bindData(mFlashlightParser, R.string.battery_stats_flashlight_on_label,
R.id.flashlight_group);
bindData(mCameraParser, R.string.battery_stats_camera_on_label, R.id.camera_group);
bindData(mWifiParser, R.string.battery_stats_wifi_running_label, R.id.wifi_group);
bindData(mCpuParser, R.string.battery_stats_wake_lock_label, R.id.cpu_group);
bindData(mPhoneParser, R.string.battery_stats_phone_signal_label, R.id.cell_network_group);
}
private void bindData(BatteryActiveProvider provider, int label, int groupId) {
View group = getView().findViewById(groupId);
group.setVisibility(provider.hasData() ? View.VISIBLE : View.GONE);
((TextView) group.findViewById(android.R.id.title)).setText(label);
((BatteryActiveView) group.findViewById(R.id.battery_active)).setProvider(provider);
}
@Override

View File

@@ -44,10 +44,11 @@ public class BatteryHistoryPreference extends Preference {
public BatteryHistoryPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setLayoutResource(R.layout.battery_usage_graph);
setSelectable(true);
}
@Override
protected void onClick() {
public void performClick() {
mHelper.storeStatsHistoryInFile(BATTERY_HISTORY_FILE);
Bundle args = new Bundle();
args.putString(BatteryHistoryDetail.EXTRA_STATS, BATTERY_HISTORY_FILE);
@@ -66,9 +67,11 @@ public class BatteryHistoryPreference extends Preference {
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
if (mBatteryInfo == null) {
return;
}
view.itemView.setClickable(true);
view.setDividerAllowedAbove(true);
((TextView) view.findViewById(R.id.charge)).setText(mBatteryInfo.batteryPercentString);
((TextView) view.findViewById(R.id.estimation)).setText(mBatteryInfo.remainingLabel);

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2016 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.os.BatteryStats;
import android.os.BatteryStats.HistoryItem;
public class BatteryWifiParser extends BatteryFlagParser {
public BatteryWifiParser(int accentColor) {
super(accentColor, false, 0);
}
@Override
protected boolean isSet(HistoryItem record) {
switch ((record.states2 & HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK)
>> HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT) {
case BatteryStats.WIFI_SUPPL_STATE_DISCONNECTED:
case BatteryStats.WIFI_SUPPL_STATE_DORMANT:
case BatteryStats.WIFI_SUPPL_STATE_INACTIVE:
case BatteryStats.WIFI_SUPPL_STATE_INTERFACE_DISABLED:
case BatteryStats.WIFI_SUPPL_STATE_INVALID:
case BatteryStats.WIFI_SUPPL_STATE_UNINITIALIZED:
return false;
}
return true;
}
}

View File

@@ -116,7 +116,7 @@ public class PowerUsageSummary extends PowerUsageBase {
@Override
public boolean onPreferenceTreeClick(Preference preference) {
if (!(preference instanceof PowerGaugePreference)) {
return false;
return super.onPreferenceTreeClick(preference);
}
PowerGaugePreference pgp = (PowerGaugePreference) preference;
BatteryEntry entry = pgp.getInfo();