Merge changes from topic "accessibility1" into tm-qpr-dev

* changes:
  Support accessibility for battery chart (4)
  Support accessibility for battery chart (3)
  Support accessibility for battery chart (2)
  Support accessibility for battery chart (1)
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 937c16c..22ba27a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1476,10 +1476,18 @@
     <string name="fingerprint_delete_message">Do you want to delete this fingerprint?</string>
 
     <!-- Message shown in a dialog which asks the user to confirm when a single fingerprint gets deleted. [CHAR LIMIT=NONE]-->
-    <string name="fingerprint_v2_delete_message">This deletes the fingerprint images and model associated with \'<xliff:g id="fingerprint_id" example="Fingerprint 2">%1$s</xliff:g>\' that are stored on your device</string>
+    <string name="fingerprint_v2_delete_message" product="default">This deletes the fingerprint images and model associated with \'<xliff:g id="fingerprint_id" example="Fingerprint 2">%1$s</xliff:g>\' that are stored on your phone</string>
+    <!-- Message shown in a dialog which asks the user to confirm when a single fingerprint gets deleted. [CHAR LIMIT=NONE]-->
+    <string name="fingerprint_v2_delete_message" product="tablet">This deletes the fingerprint images and model associated with \'<xliff:g id="fingerprint_id" example="Fingerprint 2">%1$s</xliff:g>\' that are stored on your tablet</string>
+    <!-- Message shown in a dialog which asks the user to confirm when a single fingerprint gets deleted. [CHAR LIMIT=NONE]-->
+    <string name="fingerprint_v2_delete_message" product="device">This deletes the fingerprint images and model associated with \'<xliff:g id="fingerprint_id" example="Fingerprint 2">%1$s</xliff:g>\' that are stored on your device</string>
 
     <!-- Message shown in a dialog which asks the user to confirm when the last fingerprint gets deleted by him. [CHAR LIMIT=NONE]-->
-    <string name="fingerprint_last_delete_message">You won\'t be able to use your fingerprint to unlock your phone or verify it\'s you in apps.</string>
+    <string name="fingerprint_last_delete_message" product="default">You won\'t be able to use your fingerprint to unlock your phone or verify it\'s you in apps.</string>
+    <!-- Message shown in a dialog which asks the user to confirm when the last fingerprint gets deleted by him. [CHAR LIMIT=NONE]-->
+    <string name="fingerprint_last_delete_message" product="tablet">You won\'t be able to use your fingerprint to unlock your tablet or verify it\'s you in apps.</string>
+    <!-- Message shown in a dialog which asks the user to confirm when the last fingerprint gets deleted by him. [CHAR LIMIT=NONE]-->
+    <string name="fingerprint_last_delete_message" product="device">You won\'t be able to use your fingerprint to unlock your device or verify it\'s you in apps.</string>
     <string name="fingerprint_last_delete_message_profile_challenge">You won\'t be able to use your fingerprint to unlock your work profile, authorize purchases, or sign in to work apps.</string>
 
     <!-- Button to confirm the last removing the last fingerprint. [CHAR LIMIT=20]-->
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index 6b830c9..932c410 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
@@ -564,7 +564,13 @@
         Intent intent = BiometricUtils.getChooseLockIntent(this, getIntent());
         intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_INSECURE_OPTIONS, true);
         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, true);
-        intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true);
+        if (mHasFeatureFingerprint && mHasFeatureFace) {
+            intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS, true);
+        } else if (mHasFeatureFace) {
+            intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE, true);
+        } else if (mHasFeatureFingerprint) {
+            intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
+        }
 
         if (mUserId != UserHandle.USER_NULL) {
             intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
index 9a634e0..79f0880 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.fuelgauge.batteryusage;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -69,9 +71,8 @@
     private static final int ENABLED_ICON_ALPHA = 255;
     private static final int DISABLED_ICON_ALPHA = 255 / 3;
 
-    private static final long FADE_ANIMATION_DURATION = 350L;
-    private static final long VALID_USAGE_TIME_DURATION = DateUtils.HOUR_IN_MILLIS * 2;
-    private static final long VALID_DIFF_DURATION = DateUtils.MINUTE_IN_MILLIS * 3;
+    private static final long FADE_IN_ANIMATION_DURATION = 400L;
+    private static final long FADE_OUT_ANIMATION_DURATION = 200L;
 
     // Keys for bundle instance to restore configurations.
     private static final String KEY_EXPAND_SYSTEM_INFO = "expand_system_info";
@@ -119,6 +120,10 @@
     private final CharSequence[] mNotAllowShowSummaryPackages;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
     private final Handler mHandler = new Handler(Looper.getMainLooper());
+    private final AnimatorListenerAdapter mHourlyChartFadeInAdapter =
+            createHourlyChartAnimatorListenerAdapter(/*isToShow=*/ true);
+    private final AnimatorListenerAdapter mHourlyChartFadeOutAdapter =
+            createHourlyChartAnimatorListenerAdapter(/*isToShow=*/ false);
 
     @VisibleForTesting
     final DailyChartLabelTextGenerator mDailyChartLabelTextGenerator =
@@ -384,9 +389,9 @@
 
         if (mDailyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL) {
             // Multiple days are selected, hide the hourly chart view.
-            mHourlyChartView.setVisibility(View.GONE);
+            animateBatteryHourlyChartView(/*isToShow=*/ false);
         } else {
-            mHourlyChartView.setVisibility(View.VISIBLE);
+            animateBatteryHourlyChartView(/*isToShow=*/ true);
             final BatteryChartViewModel hourlyViewModel = mHourlyViewModels.get(mDailyChartIndex);
             hourlyViewModel.setSelectedIndex(mHourlyChartIndex);
             mHourlyChartView.setViewModel(hourlyViewModel);
@@ -635,11 +640,55 @@
 
     private void animateBatteryChartViewGroup() {
         if (mBatteryChartViewGroup != null && mBatteryChartViewGroup.getAlpha() == 0) {
-            mBatteryChartViewGroup.animate().alpha(1f).setDuration(FADE_ANIMATION_DURATION)
+            mBatteryChartViewGroup.animate().alpha(1f).setDuration(FADE_IN_ANIMATION_DURATION)
                     .start();
         }
     }
 
+    private void animateBatteryHourlyChartView(final boolean isToShow) {
+        if (mHourlyChartView == null) {
+            return;
+        }
+
+        if (isToShow) {
+            mHourlyChartView.setAlpha(0f);
+            mHourlyChartView.setVisibility(View.VISIBLE);
+            mHourlyChartView.animate()
+                    .alpha(1f)
+                    .setDuration(FADE_IN_ANIMATION_DURATION)
+                    .setListener(mHourlyChartFadeInAdapter)
+                    .start();
+        } else {
+            mHourlyChartView.animate()
+                    .alpha(0f)
+                    .setDuration(FADE_OUT_ANIMATION_DURATION)
+                    .setListener(mHourlyChartFadeOutAdapter)
+                    .start();
+        }
+    }
+
+    private AnimatorListenerAdapter createHourlyChartAnimatorListenerAdapter(
+            final boolean isToShow) {
+        final int visibility = isToShow ? View.VISIBLE : View.GONE;
+
+        return new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                if (mHourlyChartView != null) {
+                    mHourlyChartView.setVisibility(visibility);
+                }
+            }
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                super.onAnimationCancel(animation);
+                if (mHourlyChartView != null) {
+                    mHourlyChartView.setVisibility(visibility);
+                }
+            }
+        };
+    }
+
     private void addFooterPreferenceIfNeeded(boolean containAppItems) {
         if (mIsFooterPrefAdded || mFooterPreference == null) {
             return;
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
index 125f879..f493ece 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
@@ -18,6 +18,7 @@
 
 import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.utcToLocalTime;
 
+import android.app.settings.SettingsEnums;
 import android.content.ContentValues;
 import android.content.Context;
 import android.os.AsyncTask;
@@ -36,6 +37,7 @@
 import com.android.settings.Utils;
 import com.android.settings.fuelgauge.BatteryUtils;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.fuelgauge.BatteryStatus;
 
 import java.time.Duration;
@@ -354,10 +356,25 @@
         insertDailyUsageDiffData(hourlyBatteryLevelsPerDay, resultMap);
         // Insert diff data [SELECTED_INDEX_ALL][SELECTED_INDEX_ALL].
         insertAllUsageDiffData(resultMap);
+        // Compute the apps number before purge. Must put before purgeLowPercentageAndFakeData.
+        final int countOfAppBeforePurge = getCountOfApps(resultMap);
         purgeLowPercentageAndFakeData(context, resultMap);
+        // Compute the apps number after purge. Must put after purgeLowPercentageAndFakeData.
+        final int countOfAppAfterPurge = getCountOfApps(resultMap);
         if (!isUsageMapValid(resultMap, hourlyBatteryLevelsPerDay)) {
             return null;
         }
+
+        final MetricsFeatureProvider metricsFeatureProvider =
+                FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+        metricsFeatureProvider.action(
+                context,
+                SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
+                countOfAppAfterPurge);
+        metricsFeatureProvider.action(
+                context,
+                SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
+                countOfAppBeforePurge - countOfAppAfterPurge);
         return resultMap;
     }
 
@@ -933,6 +950,15 @@
         return calendar.getTimeInMillis();
     }
 
+    private static int getCountOfApps(final Map<Integer, Map<Integer, BatteryDiffData>> resultMap) {
+        final BatteryDiffData diffDataList =
+                resultMap.get(SELECTED_INDEX_ALL).get(SELECTED_INDEX_ALL);
+        return diffDataList == null
+                ? 0
+                : diffDataList.getAppDiffEntryList().size()
+                        + diffDataList.getSystemDiffEntryList().size();
+    }
+
     private static boolean contains(String target, Set<CharSequence> packageNames) {
         if (target != null && packageNames != null) {
             for (CharSequence packageName : packageNames) {
diff --git a/tests/componenttests/src/com/android/settings/biometrics/BiometricEnrollActivityTest.java b/tests/componenttests/src/com/android/settings/biometrics/BiometricEnrollActivityTest.java
index 0ef57a0..c5e3a19 100644
--- a/tests/componenttests/src/com/android/settings/biometrics/BiometricEnrollActivityTest.java
+++ b/tests/componenttests/src/com/android/settings/biometrics/BiometricEnrollActivityTest.java
@@ -20,6 +20,11 @@
 
 import static androidx.test.espresso.intent.Intents.intended;
 import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent;
+import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra;
+
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS;
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE;
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -83,6 +88,13 @@
         try (ActivityScenario<BiometricEnrollActivity> scenario =
                      ActivityScenario.launch(getIntent())) {
             intended(hasComponent(ChooseLockGeneric.class.getName()));
+            if (mHasFace && mHasFingerprint) {
+                intended(hasExtra(EXTRA_KEY_FOR_BIOMETRICS, true));
+            } else if (mHasFace) {
+                intended(hasExtra(EXTRA_KEY_FOR_FACE, true));
+            } else if (mHasFingerprint) {
+                intended(hasExtra(EXTRA_KEY_FOR_FINGERPRINT, true));
+            }
         }
     }
 
@@ -109,11 +121,9 @@
                             response.getGatekeeperPasswordHandle());
                 }).get();
 
-
-
         try (ActivityScenario<BiometricEnrollActivity> scenario =
                      ActivityScenario.launch(intent)) {
-            intended(hasComponent(mHasFace
+            intended(hasComponent(mHasFace && !mHasFingerprint
                     ? FaceEnrollIntroduction.class.getName()
                     : FingerprintEnrollIntroduction.class.getName()));
         }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
index 883b0e7..84f9310 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
@@ -18,9 +18,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.settings.SettingsEnums;
 import android.content.ContentValues;
 import android.content.Context;
 import android.text.format.DateUtils;
@@ -28,6 +31,7 @@
 import com.android.settings.fuelgauge.BatteryUtils;
 import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -52,6 +56,7 @@
     private Context mContext;
 
     private FakeFeatureFactory mFeatureFactory;
+    private MetricsFeatureProvider mMetricsFeatureProvider;
     private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
 
     @Before
@@ -61,6 +66,7 @@
 
         mContext = spy(RuntimeEnvironment.application);
         mFeatureFactory = FakeFeatureFactory.setupForTest();
+        mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
         mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
     }
 
@@ -75,6 +81,10 @@
         assertThat(DataProcessor.getBatteryLevelData(
                 mContext, /*handler=*/ null, new HashMap<>(), /*asyncResponseDelegate=*/ null))
                 .isNull();
+        verify(mMetricsFeatureProvider, never())
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT);
+        verify(mMetricsFeatureProvider, never())
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT);
     }
 
     @Test
@@ -88,6 +98,10 @@
         assertThat(DataProcessor.getBatteryLevelData(
                 mContext, /*handler=*/ null, batteryHistoryMap, /*asyncResponseDelegate=*/ null))
                 .isNull();
+        verify(mMetricsFeatureProvider, never())
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT);
+        verify(mMetricsFeatureProvider, never())
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT);
     }
 
     @Test
@@ -421,6 +435,10 @@
 
         assertThat(DataProcessor.getBatteryUsageMap(
                 mContext, hourlyBatteryLevelsPerDay, new HashMap<>())).isNull();
+        verify(mMetricsFeatureProvider, never())
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT);
+        verify(mMetricsFeatureProvider, never())
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT);
     }
 
     @Test
@@ -549,6 +567,10 @@
                 resultDiffData.getSystemDiffEntryList().get(0), currentUserId, /*uid=*/ 3L,
                 ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 25.0,
                 /*foregroundUsageTimeInMs=*/ 50, /*backgroundUsageTimeInMs=*/ 60);
+        verify(mMetricsFeatureProvider)
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT, 3);
+        verify(mMetricsFeatureProvider)
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT, 0);
     }
 
     @Test
@@ -640,6 +662,10 @@
                 /*backgroundUsageTimeInMs=*/ 0);
         assertThat(resultMap.get(0).get(0)).isNotNull();
         assertThat(resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL)).isNotNull();
+        verify(mMetricsFeatureProvider)
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT, 2);
+        verify(mMetricsFeatureProvider)
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT, 0);
     }
 
     @Test
@@ -701,6 +727,10 @@
                 .isEqualTo(entry.mConsumePower * ratio);
         assertThat(resultMap.get(0).get(0)).isNotNull();
         assertThat(resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL)).isNotNull();
+        verify(mMetricsFeatureProvider)
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT, 1);
+        verify(mMetricsFeatureProvider)
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT, 0);
     }
 
     @Test
@@ -772,6 +802,10 @@
                 resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 2L,
                 ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 50.0,
                 /*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 20);
+        verify(mMetricsFeatureProvider)
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT, 1);
+        verify(mMetricsFeatureProvider)
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT, 1);
     }
 
     @Test
@@ -843,6 +877,10 @@
         assertThat(resultEntry.mBackgroundUsageTimeInMs).isEqualTo(20);
         resultEntry = resultDiffData.getAppDiffEntryList().get(1);
         assertThat(resultEntry.mBackgroundUsageTimeInMs).isEqualTo(0);
+        verify(mMetricsFeatureProvider)
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT, 2);
+        verify(mMetricsFeatureProvider)
+                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT, 0);
     }
 
     private static Map<Long, Map<String, BatteryHistEntry>> createHistoryMap(