Merge "Store whether the Dialog was previously dismissed" into sc-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f427d53..b49127a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6329,38 +6329,52 @@
     <!-- Title for the battery management group [CHAR LIMIT=40] -->
     <string name ="battery_detail_manage_title">Manage battery usage</string>
 
+    <!-- Description for battery total and background usage time for an app, i.e. 1 hr 15 min total • 39 min background from last full charge. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
+    <string name="battery_total_and_bg_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background\nfrom last full charge</string>
     <!-- Description for battery total and background usage time for an app, i.e. 1 hr 15 min total • 39 min background for past 24 hr. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
-    <string name="battery_total_and_bg_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background\nfor past 24 hr</string>
+    <string name="battery_total_and_bg_usage_24hr"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background\nfor past 24 hr</string>
     <!-- Description for battery total and background usage time in a time period for an app, i.e. 1 hr 15 min total • 39 min background for 12 am-2 am. Note: ^1, ^2 and ^3 should be used in all translations [CHAR LIMIT=120] -->
     <string name="battery_total_and_bg_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • <xliff:g id="time" example="39 min">^2</xliff:g> background\nfor <xliff:g id="time_period" example="12 am-2 am">^3</xliff:g></string>
 
-    <!-- Description for battery total usage time is less than a minute for an app [CHAR LIMIT=120] -->
-    <string name="battery_total_usage_less_minute">Total less than a minute for past 24 hr</string>
+    <!-- Description for battery total usage time is less than a minute for an app from last full charge [CHAR LIMIT=120] -->
+    <string name="battery_total_usage_less_minute">Total less than a minute from last full charge</string>
+    <!-- Description for battery total usage time is less than a minute for an app for past 24 hr [CHAR LIMIT=120] -->
+    <string name="battery_total_usage_less_minute_24hr">Total less than a minute for past 24 hr</string>
     <!-- Description for battery total usage time is less than a minute in a time period for an app, i.e. Total less than a minute for 12 am-2 am. Note: ^1 should be used in all translations[CHAR LIMIT=120] -->
     <string name="battery_total_usage_less_minute_with_period">Total less than a minute for <xliff:g id="time_period" example="12 am-2 am">^1</xliff:g></string>
 
-    <!-- Description for battery background usage time is less than a minute for an app [CHAR LIMIT=120] -->
-    <string name="battery_bg_usage_less_minute">Background less than a minute for past 24 hr</string>
+    <!-- Description for battery background usage time is less than a minute for an app from last full charge [CHAR LIMIT=120] -->
+    <string name="battery_bg_usage_less_minute">Background less than a minute from last full charge</string>
+    <!-- Description for battery background usage time is less than a minute for an app for past 24 hr [CHAR LIMIT=120] -->
+    <string name="battery_bg_usage_less_minute_24hr">Background less than a minute for past 24 hr</string>
     <!-- Description for battery background usage time is less than a minute in a time period for an app, i.e. Background less than a minute for 12 am-2 am. Note: ^1 should be used in all translations[CHAR LIMIT=120] -->
     <string name="battery_bg_usage_less_minute_with_period">Background less than a minute for <xliff:g id="time_period" example="12 am-2 am">^1</xliff:g></string>
 
+    <!-- Description for battery total usage time for an app, i.e. 1 hr 15 min total from last full charge. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
+    <string name="battery_total_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total from last full charge</string>
     <!-- Description for battery total usage time for an app, i.e. 1 hr 15 min total for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
-    <string name="battery_total_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total for past 24 hr</string>
+    <string name="battery_total_usage_24hr"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total for past 24 hr</string>
     <!-- Description for battery total usage time in a time period for an app, i.e. 1 hr 15 min total for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
     <string name="battery_total_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total for <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
 
+    <!-- Description for battery background usage time for an app, i.e. 1 hr 15 min background from last full charge. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
+    <string name="battery_bg_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background from last full charge</string>
     <!-- Description for battery background usage time for an app, i.e. 1 hr 15 min background for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
-    <string name="battery_bg_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background for past 24 hr</string>
+    <string name="battery_bg_usage_24hr"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background for past 24 hr</string>
     <!-- Description for battery background usage time in a time period for an app, i.e. 1 hr 15 min background for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
     <string name="battery_bg_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> background for <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
 
+    <!-- Description for battery total usage with background usage time less than a minute for an app, i.e. 1 hr 15 min total • background less than a minute from last full charge. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
+    <string name="battery_total_usage_and_bg_less_minute_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute\nfrom last full charge</string>
     <!-- Description for battery total usage with background usage time less than a minute for an app, i.e. 1 hr 15 min total • background less than a minute for past 24 hr. Note: ^1 should be used in all translations [CHAR LIMIT=120] -->
-    <string name="battery_total_usage_and_bg_less_minute_usage"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute\nfor past 24 hr</string>
+    <string name="battery_total_usage_and_bg_less_minute_usage_24hr"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute\nfor past 24 hr</string>
     <!-- Description for battery total usage with background usage time less than a minute in a time period for an app, i.e. 1 hr 15 min total • background less than a minute for 12 am-2 am. Note: ^1 and ^2 should be used in all translations [CHAR LIMIT=120] -->
     <string name="battery_total_usage_and_bg_less_minute_usage_with_period"><xliff:g id="time" example="1 hr 15 min">^1</xliff:g> total • background less than a minute\nfor <xliff:g id="time_period" example="12 am-2 am">^2</xliff:g></string>
 
+    <!-- Description for no any battery usage from last full charge [CHAR LIMIT=120] -->
+    <string name="battery_not_usage">No usage from last full charge</string>
     <!-- Description for no any battery usage for past 24 hr [CHAR LIMIT=120] -->
-    <string name="battery_not_usage">No usage for past 24 hr</string>
+    <string name="battery_not_usage_24hr">No usage for past 24 hr</string>
 
     <!-- Graph subtext displayed to user when enhanced battery estimate is being used [CHAR LIMIT=120] -->
     <string name="advanced_battery_graph_subtext">Battery left estimate is based on your device usage</string>
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index 7c2f052..2b83288 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -44,6 +44,7 @@
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState;
@@ -436,13 +437,18 @@
             long foregroundTimeMs, long backgroundTimeMs, String slotTime) {
         final long totalTimeMs = foregroundTimeMs + backgroundTimeMs;
         final CharSequence usageTimeSummary;
+        final PowerUsageFeatureProvider powerFeatureProvider =
+                FeatureFactory.getFactory(getContext()).getPowerUsageFeatureProvider(getContext());
 
         if (totalTimeMs == 0) {
-            usageTimeSummary = getText(R.string.battery_not_usage);
+            usageTimeSummary = getText(powerFeatureProvider.isChartGraphEnabled(getContext())
+                    ? R.string.battery_not_usage_24hr : R.string.battery_not_usage);
         } else if (slotTime == null) {
-            // Shows summary text with past 24 hr if slot time is null.
-            usageTimeSummary =
-                    getAppPast24HrActiveSummary(foregroundTimeMs, backgroundTimeMs, totalTimeMs);
+            // Shows summary text with past 24 hr or full charge if slot time is null.
+            usageTimeSummary = powerFeatureProvider.isChartGraphEnabled(getContext())
+                    ? getAppPast24HrActiveSummary(foregroundTimeMs, backgroundTimeMs, totalTimeMs)
+                    : getAppFullChargeActiveSummary(
+                            foregroundTimeMs, backgroundTimeMs, totalTimeMs);
         } else {
             // Shows summary text with slot time.
             usageTimeSummary = getAppActiveSummaryWithSlotTime(
@@ -451,7 +457,7 @@
         return usageTimeSummary;
     }
 
-    private CharSequence getAppPast24HrActiveSummary(
+    private CharSequence getAppFullChargeActiveSummary(
             long foregroundTimeMs, long backgroundTimeMs, long totalTimeMs) {
         // Shows background summary only if we don't have foreground usage time.
         if (foregroundTimeMs == 0 && backgroundTimeMs != 0) {
@@ -494,6 +500,49 @@
         }
     }
 
+    private CharSequence getAppPast24HrActiveSummary(
+            long foregroundTimeMs, long backgroundTimeMs, long totalTimeMs) {
+        // Shows background summary only if we don't have foreground usage time.
+        if (foregroundTimeMs == 0 && backgroundTimeMs != 0) {
+            return backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS
+                    ? getText(R.string.battery_bg_usage_less_minute_24hr)
+                    : TextUtils.expandTemplate(getText(R.string.battery_bg_usage_24hr),
+                            StringUtil.formatElapsedTime(
+                                    getContext(),
+                                    backgroundTimeMs,
+                                    /* withSeconds */ false,
+                                    /* collapseTimeUnit */ false));
+        // Shows total usage summary only if total usage time is small.
+        } else if (totalTimeMs < DateUtils.MINUTE_IN_MILLIS) {
+            return getText(R.string.battery_total_usage_less_minute_24hr);
+        // Shows different total usage summary when background usage time is small.
+        } else if (backgroundTimeMs < DateUtils.MINUTE_IN_MILLIS) {
+            return TextUtils.expandTemplate(
+                    getText(backgroundTimeMs == 0
+                            ? R.string.battery_total_usage_24hr
+                            : R.string.battery_total_usage_and_bg_less_minute_usage_24hr),
+                    StringUtil.formatElapsedTime(
+                            getContext(),
+                            totalTimeMs,
+                            /* withSeconds */ false,
+                            /* collapseTimeUnit */ false));
+        // Shows default summary.
+        } else {
+            return TextUtils.expandTemplate(
+                    getText(R.string.battery_total_and_bg_usage_24hr),
+                    StringUtil.formatElapsedTime(
+                            getContext(),
+                            totalTimeMs,
+                            /* withSeconds */ false,
+                            /* collapseTimeUnit */ false),
+                    StringUtil.formatElapsedTime(
+                            getContext(),
+                            backgroundTimeMs,
+                            /* withSeconds */ false,
+                            /* collapseTimeUnit */ false));
+        }
+    }
+
     private CharSequence getAppActiveSummaryWithSlotTime(
             long foregroundTimeMs, long backgroundTimeMs, long totalTimeMs, String slotTime) {
         // Shows background summary only if we don't have foreground usage time.
diff --git a/src/com/android/settings/fuelgauge/BatteryChartView.java b/src/com/android/settings/fuelgauge/BatteryChartView.java
index cd76d0e..1048017 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartView.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartView.java
@@ -15,6 +15,7 @@
 
 import static java.lang.Math.round;
 
+import android.accessibilityservice.AccessibilityServiceInfo;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Canvas;
@@ -28,23 +29,30 @@
 import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.TextView;
 
 import androidx.appcompat.widget.AppCompatImageView;
+import androidx.annotation.VisibleForTesting;
 
 import com.android.settings.R;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.Utils;
 
+import java.util.Arrays;
+import java.util.List;
 import java.util.Locale;
 
 /** A widget component to draw chart graph. */
 public class BatteryChartView extends AppCompatImageView implements View.OnClickListener {
     private static final String TAG = "BatteryChartView";
+    private static final List<String> ACCESSIBILITY_SERVICE_NAMES =
+        Arrays.asList("SwitchAccessService", "TalkBackService", "JustSpeakService");
     // For drawing the percentage information.
     private static final String[] PERCENTAGES = new String[] {"100%", "50%", "0%"};
     private static final int DEFAULT_TRAPEZOID_COUNT = 12;
     private static final int DEFAULT_TIMESTAMP_COUNT = 4;
+
     /** Selects all trapezoid shapes. */
     public static final int SELECTED_INDEX_ALL = -1;
     public static final int SELECTED_INDEX_INVALID = -2;
@@ -57,10 +65,11 @@
     private int mDividerWidth;
     private int mDividerHeight;
     private int mTrapezoidCount;
-    private int mSelectedIndex;
     private float mTrapezoidVOffset;
     private float mTrapezoidHOffset;
-    private boolean mIsSlotsClickable;
+    private boolean mIsSlotsClickabled;
+
+    @VisibleForTesting int mSelectedIndex;
 
     // Colors for drawing the trapezoid shape and dividers.
     private int mTrapezoidColor;
@@ -247,26 +256,37 @@
     @Override
     public void onAttachedToWindow() {
         super.onAttachedToWindow();
+        updateClickableState();
+    }
+
+    private void updateClickableState() {
         final Context context = mContext;
-        mIsSlotsClickable =
+        mIsSlotsClickabled =
             FeatureFactory.getFactory(context)
-                .getPowerUsageFeatureProvider(context)
-                .isChartGraphSlotsEnabled(context);
-        Log.d(TAG, "isChartGraphSlotsEnabled:" + mIsSlotsClickable);
+                    .getPowerUsageFeatureProvider(context)
+                    .isChartGraphSlotsEnabled(context)
+            && !isAccessibilityEnabled(context);
+        Log.d(TAG, "isChartGraphSlotsEnabled:" + mIsSlotsClickabled);
         setClickable(isClickable());
         // Initializes the trapezoid curve paint for non-clickable case.
-        if (!mIsSlotsClickable && mTrapezoidCurvePaint == null) {
+        if (!mIsSlotsClickabled && mTrapezoidCurvePaint == null) {
             mTrapezoidCurvePaint = new Paint();
             mTrapezoidCurvePaint.setAntiAlias(true);
             mTrapezoidCurvePaint.setColor(mTrapezoidSolidColor);
             mTrapezoidCurvePaint.setStyle(Paint.Style.STROKE);
             mTrapezoidCurvePaint.setStrokeWidth(mDividerWidth * 2);
         }
+        invalidate();
     }
 
     @Override
     public void setClickable(boolean clickable) {
-        super.setClickable(mIsSlotsClickable && clickable);
+        super.setClickable(mIsSlotsClickabled && clickable);
+    }
+
+    @VisibleForTesting
+    void setClickableForce(boolean clickable) {
+        super.setClickable(clickable);
     }
 
     private void initializeColors(Context context) {
@@ -412,7 +432,7 @@
             }
             // Configures the trapezoid paint color.
             final int trapezoidColor =
-                !mIsSlotsClickable
+                !mIsSlotsClickabled
                     ? mTrapezoidColor
                     : mSelectedIndex == index || mSelectedIndex == SELECTED_INDEX_ALL
                         ? mTrapezoidSolidColor : mTrapezoidColor;
@@ -469,6 +489,29 @@
                 && mLevels[trapezoidIndex + 1] != 0;
     }
 
+    @VisibleForTesting
+    static boolean isAccessibilityEnabled(Context context) {
+        final AccessibilityManager accessibilityManager =
+            context.getSystemService(AccessibilityManager.class);
+        if (!accessibilityManager.isEnabled()) {
+            return false;
+        }
+        final List<AccessibilityServiceInfo> serviceInfoList =
+            accessibilityManager.getEnabledAccessibilityServiceList(
+                AccessibilityServiceInfo.FEEDBACK_SPOKEN
+                    | AccessibilityServiceInfo.FEEDBACK_GENERIC);
+        for (AccessibilityServiceInfo info : serviceInfoList) {
+            for (String serviceName : ACCESSIBILITY_SERVICE_NAMES) {
+                final String serviceId = info.getId();
+                if (serviceId != null && serviceId.contains(serviceName)) {
+                    Log.d(TAG, "acccessibilityEnabled:" + serviceId);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     // A container class for each trapezoid left and right location.
     private static final class TrapezoidSlot {
         public float mLeft;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index 00c71df..e5ca4e3 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -128,6 +128,7 @@
     private RadioButtonPreference mUnrestrictedPreference;
     private AdvancedPowerUsageDetail mFragment;
     private SettingsActivity mTestActivity;
+    private FakeFeatureFactory mFeatureFactory;
 
     @Before
     public void setUp() {
@@ -135,7 +136,7 @@
 
         mContext = spy(RuntimeEnvironment.application);
         when(mContext.getPackageName()).thenReturn("foo");
-        FakeFeatureFactory.setupForTest();
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
 
         mFragment = spy(new AdvancedPowerUsageDetail());
         doReturn(mContext).when(mFragment).getContext();
@@ -144,6 +145,8 @@
         doReturn(APP_LABEL).when(mBundle).getString(nullable(String.class));
         when(mFragment.getArguments()).thenReturn(mBundle);
         doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+        when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+                .thenReturn(true);
 
         ShadowEntityHeaderController.setUseMock(mEntityHeaderController);
         doReturn(mEntityHeaderController).when(mEntityHeaderController)
@@ -270,6 +273,144 @@
     }
 
     @Test
+    public void testInitHeader_noUsageTimeAndGraphDisabled_hasCorrectSummary() {
+        when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+                .thenReturn(false);
+
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, /* value */ 0);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, /* value */ 0);
+        when(mFragment.getArguments()).thenReturn(bundle);
+
+        mFragment.initHeader();
+
+        ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+        verify(mEntityHeaderController).setSummary(captor.capture());
+        assertThat(captor.getValue().toString())
+                .isEqualTo("No usage from last full charge");
+    }
+
+    @Test
+    public void testInitHeader_bgTwoMinFgZeroAndGraphDisabled_hasCorrectSummary() {
+        when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+                .thenReturn(false);
+
+        final long backgroundTimeTwoMinutes = 120000;
+        final long foregroundTimeZero = 0;
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeTwoMinutes);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero);
+        when(mFragment.getArguments()).thenReturn(bundle);
+
+        mFragment.initHeader();
+
+        ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+        verify(mEntityHeaderController).setSummary(captor.capture());
+        assertThat(captor.getValue().toString())
+                .isEqualTo("2 min background from last full charge");
+    }
+
+    @Test
+    public void testInitHeader_bgLessThanAMinFgZeroAndGraphDisabled_hasCorrectSummary() {
+        when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+                .thenReturn(false);
+
+        final long backgroundTimeLessThanAMinute = 59999;
+        final long foregroundTimeZero = 0;
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(
+                AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanAMinute);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeZero);
+        when(mFragment.getArguments()).thenReturn(bundle);
+
+        mFragment.initHeader();
+
+        ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+        verify(mEntityHeaderController).setSummary(captor.capture());
+        assertThat(captor.getValue().toString())
+                .isEqualTo("Background less than a minute from last full charge");
+    }
+
+    @Test
+    public void testInitHeader_totalUsageLessThanAMinAndGraphDisabled_hasCorrectSummary() {
+        when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+                .thenReturn(false);
+
+        final long backgroundTimeLessThanHalfMinute = 20000;
+        final long foregroundTimeLessThanHalfMinute = 20000;
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(
+                AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeLessThanHalfMinute);
+        bundle.putLong(
+                AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeLessThanHalfMinute);
+        when(mFragment.getArguments()).thenReturn(bundle);
+
+        mFragment.initHeader();
+
+        ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+        verify(mEntityHeaderController).setSummary(captor.capture());
+        assertThat(captor.getValue().toString())
+                .isEqualTo("Total less than a minute from last full charge");
+    }
+
+    @Test
+    public void testInitHeader_TotalAMinutesBgLessThanAMinAndGraphDisabled_hasCorrectSummary() {
+        when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+                .thenReturn(false);
+
+        final long backgroundTimeZero = 59999;
+        final long foregroundTimeTwoMinutes = 1;
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes);
+        when(mFragment.getArguments()).thenReturn(bundle);
+
+        mFragment.initHeader();
+
+        ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+        verify(mEntityHeaderController).setSummary(captor.capture());
+        assertThat(captor.getValue().toString())
+                .isEqualTo("1 min total • background less than a minute\nfrom last full charge");
+    }
+
+    @Test
+    public void testInitHeader_TotalAMinBackgroundZeroAndGraphDisabled_hasCorrectSummary() {
+        when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+                .thenReturn(false);
+        final long backgroundTimeZero = 0;
+        final long foregroundTimeAMinutes = 60000;
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeZero);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeAMinutes);
+        when(mFragment.getArguments()).thenReturn(bundle);
+
+        mFragment.initHeader();
+
+        ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+        verify(mEntityHeaderController).setSummary(captor.capture());
+        assertThat(captor.getValue().toString())
+                .isEqualTo("1 min total from last full charge");
+    }
+
+    @Test
+    public void testInitHeader_fgTwoMinBgFourMinAndGraphDisabled_hasCorrectSummary() {
+        when(mFeatureFactory.powerUsageFeatureProvider.isChartGraphEnabled(mContext))
+                .thenReturn(false);
+        final long backgroundTimeFourMinute = 240000;
+        final long foregroundTimeTwoMinutes = 120000;
+        Bundle bundle = new Bundle(2);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, backgroundTimeFourMinute);
+        bundle.putLong(AdvancedPowerUsageDetail.EXTRA_FOREGROUND_TIME, foregroundTimeTwoMinutes);
+        when(mFragment.getArguments()).thenReturn(bundle);
+        mFragment.initHeader();
+
+        ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+        verify(mEntityHeaderController).setSummary(captor.capture());
+        assertThat(captor.getValue().toString())
+                .isEqualTo("6 min total • 4 min background\nfrom last full charge");
+    }
+
+    @Test
     public void testInitHeader_noUsageTime_hasCorrectSummary() {
         Bundle bundle = new Bundle(2);
         bundle.putLong(AdvancedPowerUsageDetail.EXTRA_BACKGROUND_TIME, /* value */ 0);
@@ -352,7 +493,7 @@
         ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
         verify(mEntityHeaderController).setSummary(captor.capture());
         assertThat(captor.getValue().toString())
-                .isEqualTo("1 min total • background less than a minute for past 24 hr");
+                .isEqualTo("1 min total • background less than a minute\nfor past 24 hr");
     }
 
     @Test
@@ -385,7 +526,7 @@
         ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
         verify(mEntityHeaderController).setSummary(captor.capture());
         assertThat(captor.getValue().toString())
-                .isEqualTo("6 min total • 4 min background for past 24 hr");
+                .isEqualTo("6 min total • 4 min background\nfor past 24 hr");
     }
 
     @Test
@@ -423,7 +564,7 @@
         ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
         verify(mEntityHeaderController).setSummary(captor.capture());
         assertThat(captor.getValue().toString())
-                .isEqualTo("1 min total • background less than a minute for 12 am-2 am");
+                .isEqualTo("1 min total • background less than a minute\nfor 12 am-2 am");
     }
 
     @Test
@@ -458,7 +599,7 @@
         ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
         verify(mEntityHeaderController).setSummary(captor.capture());
         assertThat(captor.getValue().toString())
-                .isEqualTo("6 min total • 4 min background for 12 am-2 am");
+                .isEqualTo("6 min total • 4 min background\nfor 12 am-2 am");
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
new file mode 100644
index 0000000..877ebc2
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.Context;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.settings.testutils.FakeFeatureFactory;
+
+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;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+
+@RunWith(RobolectricTestRunner.class)
+public final class BatteryChartViewTest {
+
+    private Context mContext;
+    private BatteryChartView mBatteryChartView;
+    private FakeFeatureFactory mFeatureFactory;
+    private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+
+    @Mock private AccessibilityServiceInfo mockAccessibilityServiceInfo;
+    @Mock private AccessibilityManager mockAccessibilityManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
+        mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
+        mContext = spy(RuntimeEnvironment.application);
+        mBatteryChartView = new BatteryChartView(mContext);
+        doReturn(mockAccessibilityManager).when(mContext)
+            .getSystemService(AccessibilityManager.class);
+        doReturn("TalkBackService").when(mockAccessibilityServiceInfo).getId();
+        doReturn(Arrays.asList(mockAccessibilityServiceInfo))
+            .when(mockAccessibilityManager)
+            .getEnabledAccessibilityServiceList(anyInt());
+    }
+
+    @Test
+    public void testIsAccessibilityEnabled_disable_returnFalse() {
+        doReturn(false).when(mockAccessibilityManager).isEnabled();
+        assertThat(BatteryChartView.isAccessibilityEnabled(mContext)).isFalse();
+    }
+
+    @Test
+    public void testIsAccessibilityEnabled_emptyInfo_returnFalse() {
+        doReturn(true).when(mockAccessibilityManager).isEnabled();
+        doReturn(new ArrayList<AccessibilityServiceInfo>())
+            .when(mockAccessibilityManager)
+            .getEnabledAccessibilityServiceList(anyInt());
+
+        assertThat(BatteryChartView.isAccessibilityEnabled(mContext)).isFalse();
+    }
+
+    @Test
+    public void testIsAccessibilityEnabled_validServiceId_returnTrue() {
+        doReturn(true).when(mockAccessibilityManager).isEnabled();
+        assertThat(BatteryChartView.isAccessibilityEnabled(mContext)).isTrue();
+    }
+
+    @Test
+    public void testSetSelectedIndex_invokesCallback() {
+        final int selectedIndex[] = new int[1];
+        final int expectedIndex = 2;
+        mBatteryChartView.mSelectedIndex = 1;
+        mBatteryChartView.setOnSelectListener(
+            trapezoidIndex -> {
+                selectedIndex[0] = trapezoidIndex;
+            });
+
+        mBatteryChartView.setSelectedIndex(expectedIndex);
+
+        assertThat(mBatteryChartView.mSelectedIndex)
+            .isEqualTo(expectedIndex);
+        assertThat(selectedIndex[0]).isEqualTo(expectedIndex);
+    }
+
+    @Test
+    public void testSetSelectedIndex_sameIndex_notInvokesCallback() {
+        final int selectedIndex[] = new int[1];
+        final int expectedIndex = 1;
+        mBatteryChartView.mSelectedIndex = expectedIndex;
+        mBatteryChartView.setOnSelectListener(
+            trapezoidIndex -> {
+                selectedIndex[0] = trapezoidIndex;
+            });
+
+        mBatteryChartView.setSelectedIndex(expectedIndex);
+
+        assertThat(selectedIndex[0]).isNotEqualTo(expectedIndex);
+    }
+
+    @Test
+    public void testClickable_isChartGraphSlotsEnabledIsFalse_notClickable() {
+        mBatteryChartView.setClickableForce(true);
+        when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
+            .thenReturn(false);
+
+        mBatteryChartView.onAttachedToWindow();
+        assertThat(mBatteryChartView.isClickable()).isFalse();
+    }
+
+    @Test
+    public void testClickable_accessibilityIsDisabled_clickable() {
+        mBatteryChartView.setClickableForce(true);
+        when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
+            .thenReturn(true);
+        doReturn(false).when(mockAccessibilityManager).isEnabled();
+
+        mBatteryChartView.onAttachedToWindow();
+        assertThat(mBatteryChartView.isClickable()).isTrue();
+    }
+
+    @Test
+    public void testClickable_accessibilityIsEnabledWithoutValidId_clickable() {
+        mBatteryChartView.setClickableForce(true);
+        when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
+            .thenReturn(true);
+        doReturn(true).when(mockAccessibilityManager).isEnabled();
+        doReturn(new ArrayList<AccessibilityServiceInfo>())
+            .when(mockAccessibilityManager)
+            .getEnabledAccessibilityServiceList(anyInt());
+
+        mBatteryChartView.onAttachedToWindow();
+        assertThat(mBatteryChartView.isClickable()).isTrue();
+    }
+
+    @Test
+    public void testClickable_accessibilityIsEnabledWithValidId_notClickable() {
+        mBatteryChartView.setClickableForce(true);
+        when(mPowerUsageFeatureProvider.isChartGraphSlotsEnabled(mContext))
+            .thenReturn(true);
+        doReturn(true).when(mockAccessibilityManager).isEnabled();
+
+        mBatteryChartView.onAttachedToWindow();
+        assertThat(mBatteryChartView.isClickable()).isFalse();
+    }
+}