OSDN Git Service

Fix and update battery detail page
authorJason Monk <jmonk@google.com>
Tue, 23 Feb 2016 17:45:20 +0000 (12:45 -0500)
committerJason Monk <jmonk@google.com>
Tue, 23 Feb 2016 17:45:20 +0000 (12:45 -0500)
Bug: 27205329
Change-Id: Ie984348d59c1b15bec7283a94a94489f78cacb79

res/layout/battery_active_view.xml [new file with mode: 0644]
res/layout/battery_history_detail.xml [new file with mode: 0644]
src/com/android/settings/fuelgauge/BatteryActiveView.java [new file with mode: 0644]
src/com/android/settings/fuelgauge/BatteryCellParser.java [new file with mode: 0644]
src/com/android/settings/fuelgauge/BatteryFlagParser.java [new file with mode: 0644]
src/com/android/settings/fuelgauge/BatteryHistoryDetail.java
src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
src/com/android/settings/fuelgauge/BatteryWifiParser.java [new file with mode: 0644]
src/com/android/settings/fuelgauge/PowerUsageSummary.java

diff --git a/res/layout/battery_active_view.xml b/res/layout/battery_active_view.xml
new file mode 100644 (file)
index 0000000..b5ada00
--- /dev/null
@@ -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>
diff --git a/res/layout/battery_history_detail.xml b/res/layout/battery_history_detail.xml
new file mode 100644 (file)
index 0000000..d1563bf
--- /dev/null
@@ -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>
diff --git a/src/com/android/settings/fuelgauge/BatteryActiveView.java b/src/com/android/settings/fuelgauge/BatteryActiveView.java
new file mode 100644 (file)
index 0000000..4856b3d
--- /dev/null
@@ -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();
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryCellParser.java b/src/com/android/settings/fuelgauge/BatteryCellParser.java
new file mode 100644 (file)
index 0000000..aaac024
--- /dev/null
@@ -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];
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryFlagParser.java b/src/com/android/settings/fuelgauge/BatteryFlagParser.java
new file mode 100644 (file)
index 0000000..cd5d89b
--- /dev/null
@@ -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;
+    }
+}
index af13551..b2cb73a 100644 (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
index 7aafeba..ba93f98 100644 (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);
diff --git a/src/com/android/settings/fuelgauge/BatteryWifiParser.java b/src/com/android/settings/fuelgauge/BatteryWifiParser.java
new file mode 100644 (file)
index 0000000..014c069
--- /dev/null
@@ -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;
+    }
+}
index a0d276f..bc44eeb 100644 (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();