--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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];
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
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";
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
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);
@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);
--- /dev/null
+/*
+ * 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;
+ }
+}
@Override
public boolean onPreferenceTreeClick(Preference preference) {
if (!(preference instanceof PowerGaugePreference)) {
- return false;
+ return super.onPreferenceTreeClick(preference);
}
PowerGaugePreference pgp = (PowerGaugePreference) preference;
BatteryEntry entry = pgp.getInfo();