Merge original AOSP chart into battery usage with runtime switchable

This patch is merged from ag/14111128 and seperate two different chart
design between isChratGraphEnabled() method, but we drop the options
menu in the both versions to align the new material next design.

Bug: 185187718
Bug: 185187591
Bug: 177406865
Test: make SettingsRoboTests
Test: make SettingsGoogleRoboTests
Change-Id: Ie88df6a94abf5d1652440fe35392b9f47c447537
diff --git a/res/layout/battery_usage_graph.xml b/res/layout/battery_usage_graph.xml
new file mode 100644
index 0000000..e79c7b9
--- /dev/null
+++ b/res/layout/battery_usage_graph.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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:paddingTop="16dp"
+    android:paddingStart="@dimen/preference_no_icon_padding_start"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/charge"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="16dp"
+        android:fontFamily="@*android:string/config_headlineFontFamily"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:textSize="36sp"
+        android:textColor="?android:attr/colorAccent" />
+
+    <com.android.settings.widget.UsageView
+        android:id="@+id/battery_usage"
+        android:layout_width="match_parent"
+        android:layout_height="141dp"
+        android:layout_marginBottom="16dp"
+        settings:sideLabels="@array/battery_labels"
+        android:colorAccent="?android:attr/colorAccent"
+        android:gravity="end"
+        settings:textColor="?android:attr/textColorSecondary" />
+
+    <TextView
+        android:id="@+id/bottom_summary"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="16dp"
+        android:textAppearance="?android:attr/textAppearanceSmall" />
+
+</LinearLayout>
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
index 5b9d5ec..94e35cb 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
@@ -21,6 +21,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
+import android.widget.TextView;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
@@ -29,6 +30,7 @@
 
 import com.android.settings.R;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.UsageView;
 
 /**
  * Custom preference for displaying the battery level as chart graph.
@@ -36,24 +38,45 @@
 public class BatteryHistoryPreference extends Preference {
     private static final String TAG = "BatteryHistoryPreference";
 
-    @VisibleForTesting
-    BatteryInfo mBatteryInfo;
+    @VisibleForTesting boolean mHideSummary;
+    @VisibleForTesting BatteryInfo mBatteryInfo;
 
+    private boolean mIsChartGraphEnabled;
+
+    private TextView mSummaryView;
+    private CharSequence mSummaryContent;
     private BatteryChartView mBatteryChartView;
     private BatteryChartPreferenceController mChartPreferenceController;
 
     public BatteryHistoryPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
-        final boolean isChartGraphEnabled =
+        mIsChartGraphEnabled =
             FeatureFactory.getFactory(context).getPowerUsageFeatureProvider(context)
                    .isChartGraphEnabled(context);
-        Log.i(TAG, "isChartGraphEnabled: " + isChartGraphEnabled);
-        if (isChartGraphEnabled) {
-            setLayoutResource(R.layout.battery_chart_graph);
-        }
+        Log.i(TAG, "isChartGraphEnabled: " + mIsChartGraphEnabled);
+        setLayoutResource(
+            mIsChartGraphEnabled
+                ? R.layout.battery_chart_graph
+                : R.layout.battery_usage_graph);
         setSelectable(false);
     }
 
+    public void setBottomSummary(CharSequence text) {
+        mSummaryContent = text;
+        if (mSummaryView != null) {
+            mSummaryView.setVisibility(View.VISIBLE);
+            mSummaryView.setText(mSummaryContent);
+        }
+        mHideSummary = false;
+    }
+
+    public void hideBottomSummary() {
+        if (mSummaryView != null) {
+            mSummaryView.setVisibility(View.GONE);
+        }
+        mHideSummary = true;
+    }
+
     void setBatteryUsageStats(@NonNull BatteryUsageStats batteryUsageStats) {
         BatteryInfo.getBatteryInfo(getContext(), info -> {
             mBatteryInfo = info;
@@ -75,9 +98,24 @@
         if (mBatteryInfo == null) {
             return;
         }
-        mBatteryChartView = (BatteryChartView) view.findViewById(R.id.battery_chart);
-        if (mChartPreferenceController != null) {
-            mChartPreferenceController.setBatteryChartView(mBatteryChartView);
+        if (mIsChartGraphEnabled) {
+            mBatteryChartView = (BatteryChartView) view.findViewById(R.id.battery_chart);
+            if (mChartPreferenceController != null) {
+                mChartPreferenceController.setBatteryChartView(mBatteryChartView);
+            }
+        } else {
+            final TextView chargeView = (TextView) view.findViewById(R.id.charge);
+            chargeView.setText(mBatteryInfo.batteryPercentString);
+            mSummaryView = (TextView) view.findViewById(R.id.bottom_summary);
+            if (mSummaryContent != null) {
+                mSummaryView.setText(mSummaryContent);
+            }
+            if (mHideSummary) {
+                mSummaryView.setVisibility(View.GONE);
+            }
+            final UsageView usageView = (UsageView) view.findViewById(R.id.battery_usage);
+            usageView.findViewById(R.id.label_group).setAlpha(.7f);
+            mBatteryInfo.bindHistory(usageView);
         }
         BatteryUtils.logRuntime(TAG, "onBindViewHolder", startTime);
     }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
index c3f299b..96e5011 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
@@ -17,6 +17,8 @@
 
 import android.app.settings.SettingsEnums;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.BatteryManager;
 import android.os.Bundle;
 import android.provider.SearchIndexableResource;
@@ -63,13 +65,14 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        refreshFeatureFlag(getContext());
+        final Context context = getContext();
+        refreshFeatureFlag(context);
         mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_GRAPH);
-        // Removes chart graph preference if the chart design is disabled.
-        if (!mIsChartGraphEnabled) {
-            removePreference(KEY_BATTERY_GRAPH);
+        if (mIsChartGraphEnabled) {
+            setBatteryChartPreferenceController();
+        } else {
+           updateHistPrefSummary(context);
         }
-        setBatteryChartPreferenceController();
     }
 
     @Override
@@ -128,6 +131,7 @@
         }
         updatePreference(mHistPref);
         if (mBatteryAppListPreferenceController != null && mBatteryUsageStats != null) {
+            updateHistPrefSummary(context);
             mBatteryAppListPreferenceController.refreshAppListGroup(
                     mBatteryUsageStats, /* showAllApps */true);
         }
@@ -149,6 +153,18 @@
         }
     }
 
+    private void updateHistPrefSummary(Context context) {
+        final Intent batteryIntent =
+                context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+        final boolean plugged = batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) != 0;
+        if (mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(context) && !plugged) {
+            mHistPref.setBottomSummary(
+                    mPowerUsageFeatureProvider.getAdvancedUsageScreenInfoString());
+        } else {
+            mHistPref.hideBottomSummary();
+        }
+    }
+
     private void refreshFeatureFlag(Context context) {
         if (mPowerUsageFeatureProvider == null) {
             mPowerUsageFeatureProvider = FeatureFactory.getFactory(context)
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistoryPreferenceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistoryPreferenceTest.java
new file mode 100644
index 0000000..83fcbae
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistoryPreferenceTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2021 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 static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+import com.android.settings.widget.UsageView;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BatteryHistoryPreferenceTest {
+
+    private static final String TEST_STRING = "test";
+    @Mock
+    private PreferenceViewHolder mViewHolder;
+    @Mock
+    private BatteryInfo mBatteryInfo;
+    @Mock
+    private TextView mTextView;
+    @Mock
+    private UsageView mUsageView;
+    @Mock
+    private View mLabelView;
+    private BatteryHistoryPreference mBatteryHistoryPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        final Context context = RuntimeEnvironment.application;
+        final View itemView =
+                LayoutInflater.from(context).inflate(R.layout.battery_usage_graph, null);
+
+        mBatteryHistoryPreference = new BatteryHistoryPreference(context, null);
+        mBatteryHistoryPreference.mBatteryInfo = mBatteryInfo;
+        mViewHolder = spy(PreferenceViewHolder.createInstanceForTests(itemView));
+        when(mViewHolder.findViewById(R.id.battery_usage)).thenReturn(mUsageView);
+        when(mViewHolder.findViewById(R.id.charge)).thenReturn(mTextView);
+        when(mUsageView.findViewById(anyInt())).thenReturn(mLabelView);
+    }
+
+    @Test
+    public void testOnBindViewHolder_updateBatteryUsage() {
+        mBatteryHistoryPreference.onBindViewHolder(mViewHolder);
+
+        verify(mViewHolder).findViewById(R.id.battery_usage);
+        verify(mTextView).setText(nullable(String.class));
+        verify(mBatteryInfo).bindHistory(mUsageView);
+    }
+
+    @Test
+    public void testSetBottomSummary_updatesBottomSummaryTextIfSet() {
+        mBatteryHistoryPreference.setBottomSummary(TEST_STRING);
+        mBatteryHistoryPreference.onBindViewHolder(mViewHolder);
+
+        TextView view = (TextView) mViewHolder.findViewById(R.id.bottom_summary);
+        assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(view.getText()).isEqualTo(TEST_STRING);
+        assertThat(mBatteryHistoryPreference.mHideSummary).isFalse();
+    }
+
+    @Test
+    public void testSetBottomSummary_leavesBottomSummaryTextBlankIfNotSet() {
+        mBatteryHistoryPreference.hideBottomSummary();
+        mBatteryHistoryPreference.onBindViewHolder(mViewHolder);
+
+        TextView view = (TextView) mViewHolder.findViewById(R.id.bottom_summary);
+        assertThat(view.getVisibility()).isEqualTo(View.GONE);
+        assertThat(view.getText()).isEqualTo("");
+        assertThat(mBatteryHistoryPreference.mHideSummary).isTrue();
+    }
+}