Create Advanced battery page

The advanced page shows two major parts, one is the battery usage
graph and the other is battery usage list. In usage list, each item
shows basic info of battery usage of one type(e.g. Apps, System)

Bug: 34385770
Test: RunSettingsRoboTests

Change-Id: I22475a489285787afa775af8d5ae3340eff1eed9
diff --git a/src/com/android/settings/TintablePreference.java b/src/com/android/settings/TintablePreference.java
index 45f43fb..2e1fd3d 100644
--- a/src/com/android/settings/TintablePreference.java
+++ b/src/com/android/settings/TintablePreference.java
@@ -17,17 +17,23 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
+import android.support.annotation.ColorInt;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceViewHolder;
 import android.util.AttributeSet;
 import android.widget.ImageView;
 
 public class TintablePreference extends Preference {
-
+    @ColorInt
     private int mTintColor;
 
     public TintablePreference(Context context, AttributeSet attrs) {
         super(context, attrs);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TintablePreference);
+        mTintColor = a.getColor(R.styleable.TintablePreference_android_tint, 0);
+        a.recycle();
     }
 
     public void setTint(int color) {
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
index 0f36ab1..7cf0780 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
@@ -26,6 +26,7 @@
 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 @@
 
     @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) {
diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
index 9371a19..1d3d62b 100644
--- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java
+++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
@@ -20,6 +20,7 @@
 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 @@
         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();
     }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
new file mode 100644
index 0000000..4ccf9f7
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
@@ -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);
+                }
+            };
+
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index de16fe5..3c1b197 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -36,4 +36,9 @@
    * Gets an {@link Intent} to show additional battery info.
    */
   Intent getAdditionalBatteryInfoIntent();
+
+  /**
+   * Check whether advanced ui is enabled
+   */
+  boolean isAdvancedUiEnabled();
 }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
new file mode 100644
index 0000000..b29900e
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -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;
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 2745292..c0c92f0 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -413,7 +413,7 @@
                 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)
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index c45bf0e..4c81e30 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -37,6 +37,7 @@
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProviderImpl;
 import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
+import com.android.settings.fuelgauge.PowerUsageFeatureProviderImpl;
 import com.android.settings.localepicker.LocaleFeatureProvider;
 import com.android.settings.localepicker.LocaleFeatureProviderImpl;
 import com.android.settings.search2.SearchFeatureProvider;
@@ -59,6 +60,7 @@
     private SearchFeatureProvider mSearchFeatureProvider;
     private SecurityFeatureProvider mSecurityFeatureProvider;
     private SuggestionFeatureProvider mSuggestionFeatureProvider;
+    private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
 
     @Override
     public SupportFeatureProvider getSupportFeatureProvider(Context context) {
@@ -75,7 +77,10 @@
 
     @Override
     public PowerUsageFeatureProvider getPowerUsageFeatureProvider(Context context) {
-        return null;
+        if (mPowerUsageFeatureProvider == null) {
+            mPowerUsageFeatureProvider = new PowerUsageFeatureProviderImpl();
+        }
+        return mPowerUsageFeatureProvider;
     }
 
     @Override
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index cbbc0b5..f8384e9 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -47,6 +47,7 @@
 import com.android.settings.display.ScreenZoomSettings;
 import com.android.settings.enterprise.EnterprisePrivacySettings;
 import com.android.settings.fuelgauge.BatterySaverSettings;
+import com.android.settings.fuelgauge.PowerUsageAdvanced;
 import com.android.settings.fuelgauge.PowerUsageDetail;
 import com.android.settings.fuelgauge.PowerUsageSummary;
 import com.android.settings.gestures.DoubleTapPowerSettings;
@@ -127,6 +128,7 @@
         addIndex(PowerUsageSummary.class,
                 R.xml.power_usage_summary, R.drawable.ic_settings_battery);
         addIndex(PowerUsageDetail.class, NO_DATA_RES_ID, R.drawable.ic_settings_battery);
+        addIndex(PowerUsageAdvanced.class, NO_DATA_RES_ID, R.drawable.ic_settings_battery);
         addIndex(BatterySaverSettings.class,
                 R.xml.battery_saver_settings, R.drawable.ic_settings_battery);
         addIndex(AdvancedAppSettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_applications);