Merge "[Settings] WFC preference will be grey out after disconnecting the call"
diff --git a/res/layout/battery_chart_graph.xml b/res/layout/battery_chart_graph.xml
index db86693..e89c912 100644
--- a/res/layout/battery_chart_graph.xml
+++ b/res/layout/battery_chart_graph.xml
@@ -40,12 +40,14 @@
         android:contentDescription="@string/battery_usage_chart"
         android:textAppearance="?android:attr/textAppearanceSmall"
         settings:textColor="?android:attr/textColorSecondary" />
+    <!-- Use non-scalable text size from text_size_small_material -->
     <TextView
         android:id="@+id/companion_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:visibility="gone"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="?android:attr/textColorSecondary"/>
+        android:textColor="?android:attr/textColorSecondary"
+        android:textSize="14dp" />
 
 </LinearLayout>
diff --git a/res/layout/notification_history_app_layout.xml b/res/layout/notification_history_app_layout.xml
index 8f66628..24a43c6 100644
--- a/res/layout/notification_history_app_layout.xml
+++ b/res/layout/notification_history_app_layout.xml
@@ -78,13 +78,14 @@
         android:layout_height="1dp"
         android:background="?android:attr/listDivider"/>
 
-        <com.android.settings.notification.history.NotificationHistoryRecyclerView
-            android:id="@+id/notification_list"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:clipChildren="true"
-            android:clipToPadding="true"
-            android:importantForAccessibility="yes"
-            android:scrollbars="none"/>
+    <com.android.settings.notification.history.NotificationHistoryRecyclerView
+        android:id="@+id/notification_list"
+        android:layout_width="match_parent"
+        android:layout_height="500dp"
+        android:clipChildren="true"
+        android:clipToPadding="true"
+        android:clipToOutline="true"
+        android:importantForAccessibility="yes"
+        android:scrollbars="none"/>
 
 </LinearLayout>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 1b8179a..7a75883 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -437,7 +437,7 @@
     <dimen name="chartview_text_padding">6dp</dimen>
     <dimen name="chartview_divider_width">1dp</dimen>
     <dimen name="chartview_divider_height">4dp</dimen>
-    <dimen name="chartview_trapezoid_radius">3dp</dimen>
+    <dimen name="chartview_trapezoid_radius">5dp</dimen>
     <dimen name="chartview_trapezoid_margin_start">1dp</dimen>
     <dimen name="chartview_trapezoid_margin_bottom">2dp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6f2cd04..b4aea9b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6659,10 +6659,6 @@
     <string name="battery_system_usage_for">System usage for <xliff:g id="slot">%s</xliff:g></string>
     <!-- [CHAR_LIMIT=NONE] Battery app usage section header -->
     <string name="battery_app_usage_for">App usage for <xliff:g id="slot">%s</xliff:g></string>
-    <!-- [CHAR_LIMIT=NONE] Battery usage section header for a specific time slot -->
-    <string name="battery_usage_time_am">am</string>
-    <!-- [CHAR_LIMIT=NONE] Battery usage section header for a specific time slot -->
-    <string name="battery_usage_time_pm">pm</string>
     <!-- [CHAR_LIMIT=NONE] Battery usage item for total usage time less than a minute -->
     <string name="battery_usage_total_less_than_one_minute">Total: less than a min</string>
     <!-- [CHAR_LIMIT=NONE] Battery usage item for total background time less than a minute -->
@@ -13804,4 +13800,6 @@
         <item>@string/tare_alarmmanager</item>
         <item>@string/tare_jobscheduler</item>
     </string-array>
+    <!-- TARE dialog button to proceed with a value change [CHAR LIMIT=none] -->
+    <string name="tare_dialog_confirm_button_title">Confirm</string>
 </resources>
diff --git a/res/xml/smart_battery_detail.xml b/res/xml/smart_battery_detail.xml
index 9c0aac5..9795125 100644
--- a/res/xml/smart_battery_detail.xml
+++ b/res/xml/smart_battery_detail.xml
@@ -22,7 +22,7 @@
     android:title="@string/smart_battery_manager_title"
     settings:keywords="@string/keywords_battery_adaptive_preferences">
 
-    <com.android.settingslib.widget.IllustrationPreferencee
+    <com.android.settingslib.widget.IllustrationPreference
         android:key="auto_awesome_battery"
         settings:lottie_rawRes="@raw/auto_awesome_battery_lottie" />
 
diff --git a/res/xml/zen_mode_settings.xml b/res/xml/zen_mode_settings.xml
index f5589de..0629bdb 100644
--- a/res/xml/zen_mode_settings.xml
+++ b/res/xml/zen_mode_settings.xml
@@ -52,19 +52,15 @@
             android:fragment="com.android.settings.notification.zen.ZenModeSoundVibrationSettings" />
     </PreferenceCategory>
 
-    <!-- Automatic rules -->
     <PreferenceCategory
-        android:key="zen_mode_settings_schedule"
-        android:title="@string/zen_category_schedule">
+        android:title="@string/zen_settings_general"
+        android:key="zen_mode_settings_advanced">
+
+        <!-- Automatic rules -->
         <Preference
             android:key="zen_mode_automation_settings"
             android:title="@string/zen_category_schedule"
             android:fragment="com.android.settings.notification.zen.ZenModeAutomationSettings"/>
-    </PreferenceCategory>
-
-    <PreferenceCategory
-        android:title="@string/zen_settings_general"
-        android:key="zen_mode_settings_advanced">
 
         <!-- DND duration settings -->
         <com.android.settings.notification.zen.ZenDurationDialogPreference
diff --git a/src/com/android/settings/biometrics/BiometricUtils.java b/src/com/android/settings/biometrics/BiometricUtils.java
index a98c355..7dd6385 100644
--- a/src/com/android/settings/biometrics/BiometricUtils.java
+++ b/src/com/android/settings/biometrics/BiometricUtils.java
@@ -244,7 +244,9 @@
      * @return true if the next enrollment was started
      */
     public static boolean tryStartingNextBiometricEnroll(@NonNull Activity activity,
-            int requestCode) {
+            int requestCode, String debugReason) {
+
+        Log.d(TAG, "tryStartingNextBiometricEnroll, debugReason: " + debugReason);
         final PendingIntent pendingIntent = (PendingIntent) activity.getIntent()
                 .getExtra(MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FACE);
         if (pendingIntent != null) {
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
index fa8f556..6509d4e 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
@@ -216,7 +216,8 @@
     }
 
     protected void onSkipButtonClick(View view) {
-        if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST)) {
+        if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST,
+                "edu_skip")) {
             setResult(RESULT_SKIP);
             finish();
         }
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index e9092c7..1de4bc7 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -59,28 +59,32 @@
 
     @Override
     protected void onCancelButtonClick(View view) {
-        if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST)) {
+        if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST,
+                "cancel")) {
             super.onCancelButtonClick(view);
         }
     }
 
     @Override
     protected void onSkipButtonClick(View view) {
-        if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST)) {
+        if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST,
+                "skip")) {
             super.onSkipButtonClick(view);
         }
     }
 
     @Override
     protected void onEnrollmentSkipped(@Nullable Intent data) {
-        if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST)) {
+        if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST,
+                "skipped")) {
             super.onEnrollmentSkipped(data);
         }
     }
 
     @Override
     protected void onFinishedEnrolling(@Nullable Intent data) {
-        if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST)) {
+        if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST,
+                "finished")) {
             super.onFinishedEnrolling(data);
         }
     }
diff --git a/src/com/android/settings/bluetooth/OWNERS b/src/com/android/settings/bluetooth/OWNERS
index 5e716e1..52017a8 100644
--- a/src/com/android/settings/bluetooth/OWNERS
+++ b/src/com/android/settings/bluetooth/OWNERS
@@ -2,5 +2,6 @@
 hughchen@google.com
 timhypeng@google.com
 siyuanh@google.com
+robertluo@google.com
 
 # Emergency approvers in case the above are not available
diff --git a/src/com/android/settings/connecteddevice/OWNERS b/src/com/android/settings/connecteddevice/OWNERS
new file mode 100644
index 0000000..a5fe957
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/OWNERS
@@ -0,0 +1,6 @@
+# Default reviewers for this and subdirectories.
+hughchen@google.com
+timhypeng@google.com
+robertluo@google.com
+
+# Emergency approvers in case the above are not available
diff --git a/src/com/android/settings/connecteddevice/usb/OWNERS b/src/com/android/settings/connecteddevice/usb/OWNERS
index add985c..66bf468 100644
--- a/src/com/android/settings/connecteddevice/usb/OWNERS
+++ b/src/com/android/settings/connecteddevice/usb/OWNERS
@@ -1,3 +1,6 @@
 # Default reviewers for this and subdirectories.
 zhangjerry@google.com
 badhri@google.com
+hughchen@google.com
+timhypeng@google.com
+robertluo@google.com
diff --git a/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java b/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java
index d9bd4b2..ea1ccc0 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbDefaultFragment.java
@@ -198,8 +198,9 @@
 
         @Override
         public void onTetheringStarted() {
-            Log.d(TAG, "onTetheringStarted()");
             // Set default usb functions again to make internal data persistent
+            mCurrentFunctions = mUsbBackend.getCurrentFunctions();
+            Log.d(TAG, "onTetheringStarted() : mCurrentFunctions " + mCurrentFunctions);
             mUsbBackend.setDefaultUsbFunctions(mCurrentFunctions);
         }
 
diff --git a/src/com/android/settings/development/tare/TareFactorDialogFragment.java b/src/com/android/settings/development/tare/TareFactorDialogFragment.java
new file mode 100644
index 0000000..d6ef22d
--- /dev/null
+++ b/src/com/android/settings/development/tare/TareFactorDialogFragment.java
@@ -0,0 +1,109 @@
+/*
+ * 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.development.tare;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.text.InputType;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.EditText;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+
+/**
+ * Dialog Fragment for changing tare factor values
+ */
+public class TareFactorDialogFragment extends DialogFragment {
+
+    private static final String TAG = "TareDialogFragment";
+
+    private final String mFactorKey;
+    private final String mFactorTitle;
+    private final int mFactorValue;
+    private int mFactorEditedValue;
+
+    private EditText mFactorValueView;
+
+    /**
+     * @param title        the title that will show at the top of the Dialog for the Factor
+     * @param key          the key of the Factor being initialized.
+     * @param defaultValue the initial value set for the Factor before any changes
+     */
+    public TareFactorDialogFragment(@NonNull String title, @NonNull String key, int defaultValue) {
+        mFactorTitle = title;
+        mFactorKey = key;
+        mFactorValue = defaultValue;
+    }
+
+    /**
+     * Gets the current value of the Factor
+     */
+    private String getFactorValue() {
+        // TODO: Get value from locally cached copy
+        return Integer.toString(mFactorEditedValue);
+    }
+
+    @NonNull
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(
+                getActivity())
+                .setTitle(mFactorTitle)
+                .setView(createDialogView())
+                .setPositiveButton(R.string.tare_dialog_confirm_button_title, (dialog, which) -> {
+
+                    final String stringValue = mFactorValueView.getText().toString();
+                    mFactorEditedValue = mFactorValue;
+                    try {
+                        mFactorEditedValue = Integer.parseInt(stringValue);
+                    } catch (NumberFormatException e) {
+                        Log.e(TAG, "Error converting '" + stringValue + "' to integer. Using "
+                                + mFactorValue + " instead", e);
+                    }
+                    // TODO: Update csv with new factor value
+                })
+                .setNegativeButton(android.R.string.cancel, (dialog, which) -> {
+                    // TODO: Add proper dismiss for negative button press
+                });
+
+        return builder.create();
+    }
+
+    /**
+     * Creates a view for the factor Dialog that currently
+     * is linked to the basic dialog_edittext.xml layout.
+     */
+    private View createDialogView() {
+        final LayoutInflater layoutInflater = (LayoutInflater) getActivity()
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        View layout = layoutInflater.inflate(R.layout.dialog_edittext, null);
+        mFactorValueView = layout.findViewById(R.id.edittext);
+        mFactorValueView.setInputType(InputType.TYPE_CLASS_NUMBER);
+        mFactorValueView.setText(getFactorValue());
+        Utils.setEditTextCursorPosition(mFactorValueView);
+
+        return layout;
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryChartView.java b/src/com/android/settings/fuelgauge/BatteryChartView.java
index a98c644..7bc60b2 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartView.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartView.java
@@ -57,7 +57,8 @@
         Arrays.asList("SwitchAccessService", "TalkBackService", "JustSpeakService");
 
     private static final int DEFAULT_TRAPEZOID_COUNT = 12;
-    private static final int DEFAULT_TIMESTAMP_COUNT = 5;
+    private static final int DEFAULT_TIMESTAMP_COUNT = 4;
+    private static final int TIMESTAMP_GAPS_COUNT = DEFAULT_TIMESTAMP_COUNT - 1;
     private static final int DIVIDER_COLOR = Color.parseColor("#CDCCC5");
     private static final long UPDATE_STATE_DELAYED_TIME = 500L;
 
@@ -91,7 +92,7 @@
         new Rect[] {new Rect(), new Rect(), new Rect()};
     // For drawing the timestamp information.
     private final Rect[] mTimestampsBounds =
-        new Rect[] {new Rect(), new Rect(), new Rect(), new Rect(), new Rect()};
+        new Rect[] {new Rect(), new Rect(), new Rect(), new Rect()};
 
     @VisibleForTesting
     Handler mHandler = new Handler();
@@ -198,13 +199,14 @@
         if (mTimestamps == null) {
             mTimestamps = new String[DEFAULT_TIMESTAMP_COUNT];
         }
-        final long timeSlotOffset = DateUtils.HOUR_IN_MILLIS * 6;
+        final long timeSlotOffset =
+            DateUtils.HOUR_IN_MILLIS * (/*total 24 hours*/ 24 / TIMESTAMP_GAPS_COUNT);
         final boolean is24HourFormat = DateFormat.is24HourFormat(getContext());
         for (int index = 0; index < DEFAULT_TIMESTAMP_COUNT; index++) {
             mTimestamps[index] =
                 ConvertUtils.utcToLocalTimeHour(
                     getContext(),
-                    latestTimestamp - (4 - index) * timeSlotOffset,
+                    latestTimestamp - (TIMESTAMP_GAPS_COUNT - index) * timeSlotOffset,
                     is24HourFormat);
         }
         requestLayout();
@@ -426,8 +428,9 @@
             final float[] xOffsets = new float[DEFAULT_TIMESTAMP_COUNT];
             final float baselineX = mDividerWidth * .5f;
             final float offsetX = mDividerWidth + unitWidth;
+            final int slotBarOffset = (/*total 12 bars*/ 12) / TIMESTAMP_GAPS_COUNT;
             for (int index = 0; index < DEFAULT_TIMESTAMP_COUNT; index++) {
-                xOffsets[index] = baselineX + index * offsetX * 3;
+                xOffsets[index] = baselineX + index * offsetX * slotBarOffset;
             }
             drawTimestamp(canvas, xOffsets);
         }
@@ -439,13 +442,15 @@
             mTimestamps[0],
             xOffsets[0] - mTimestampsBounds[0].left,
             getTimestampY(0), mTextPaint);
+        final int latestIndex = DEFAULT_TIMESTAMP_COUNT - 1;
         // Draws the last timestamp info.
         canvas.drawText(
-            mTimestamps[4],
-            xOffsets[4] - mTimestampsBounds[4].width() - mTimestampsBounds[4].left,
-            getTimestampY(4), mTextPaint);
+            mTimestamps[latestIndex],
+            xOffsets[latestIndex] - mTimestampsBounds[latestIndex].width()
+                    - mTimestampsBounds[latestIndex].left,
+            getTimestampY(latestIndex), mTextPaint);
         // Draws the rest of timestamp info since it is located in the center.
-        for (int index = 1; index <= 3; index++) {
+        for (int index = 1; index <= DEFAULT_TIMESTAMP_COUNT - 2; index++) {
             canvas.drawText(
                 mTimestamps[index],
                 xOffsets[index] -
diff --git a/src/com/android/settings/fuelgauge/BatteryInfo.java b/src/com/android/settings/fuelgauge/BatteryInfo.java
index 92151c0..4433da2 100644
--- a/src/com/android/settings/fuelgauge/BatteryInfo.java
+++ b/src/com/android/settings/fuelgauge/BatteryInfo.java
@@ -25,6 +25,7 @@
 import android.os.BatteryUsageStats;
 import android.os.SystemClock;
 import android.text.format.Formatter;
+import android.util.Log;
 import android.util.SparseIntArray;
 
 import androidx.annotation.NonNull;
@@ -42,6 +43,7 @@
 import com.android.settingslib.utils.StringUtil;
 
 public class BatteryInfo {
+    private static final String TAG = "BatteryInfo";
 
     public CharSequence chargeLabel;
     public CharSequence remainingLabel;
@@ -155,8 +157,13 @@
                 if (batteryUsageStats != null) {
                     stats = batteryUsageStats;
                 } else {
-                    stats = context.getSystemService(BatteryStatsManager.class)
-                            .getBatteryUsageStats();
+                    try {
+                        stats = context.getSystemService(BatteryStatsManager.class)
+                                .getBatteryUsageStats();
+                    } catch (RuntimeException e) {
+                        Log.e(TAG, "getBatteryInfo() from getBatteryUsageStats()", e);
+                        return null;
+                    }
                 }
                 return getBatteryInfo(context, stats, shortString);
             }
diff --git a/src/com/android/settings/fuelgauge/BatteryUsageStatsLoader.java b/src/com/android/settings/fuelgauge/BatteryUsageStatsLoader.java
index d35ef82..0acc54e 100644
--- a/src/com/android/settings/fuelgauge/BatteryUsageStatsLoader.java
+++ b/src/com/android/settings/fuelgauge/BatteryUsageStatsLoader.java
@@ -20,6 +20,7 @@
 import android.os.BatteryStatsManager;
 import android.os.BatteryUsageStats;
 import android.os.BatteryUsageStatsQuery;
+import android.util.Log;
 
 import com.android.settingslib.utils.AsyncLoaderCompat;
 
@@ -27,6 +28,7 @@
  * Loader to get new {@link BatteryUsageStats} in the background
  */
 public class BatteryUsageStatsLoader extends AsyncLoaderCompat<BatteryUsageStats> {
+    private static final String TAG = "BatteryUsageStatsLoader";
     private final BatteryStatsManager mBatteryStatsManager;
     private final boolean mIncludeBatteryHistory;
 
@@ -42,7 +44,12 @@
         if (mIncludeBatteryHistory) {
             builder.includeBatteryHistory();
         }
-        return mBatteryStatsManager.getBatteryUsageStats(builder.build());
+        try {
+            return mBatteryStatsManager.getBatteryUsageStats(builder.build());
+        } catch (RuntimeException e) {
+            Log.e(TAG, "loadInBackground() for getBatteryUsageStats()", e);
+            return null;
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index d521ed1..f8f01b9 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -368,8 +368,14 @@
     public BatteryInfo getBatteryInfo(final String tag) {
         final BatteryStatsManager systemService = mContext.getSystemService(
                 BatteryStatsManager.class);
-        final BatteryUsageStats batteryUsageStats = systemService.getBatteryUsageStats(
-                new BatteryUsageStatsQuery.Builder().includeBatteryHistory().build());
+        BatteryUsageStats batteryUsageStats;
+        try {
+            batteryUsageStats = systemService.getBatteryUsageStats(
+                    new BatteryUsageStatsQuery.Builder().includeBatteryHistory().build());
+        } catch (RuntimeException e) {
+            Log.e(TAG, "getBatteryInfo() from getBatteryUsageStats()", e);
+            return null;
+        }
 
         final long startTime = System.currentTimeMillis();
 
diff --git a/src/com/android/settings/fuelgauge/ConvertUtils.java b/src/com/android/settings/fuelgauge/ConvertUtils.java
index 001e9e9..827ac92 100644
--- a/src/com/android/settings/fuelgauge/ConvertUtils.java
+++ b/src/com/android/settings/fuelgauge/ConvertUtils.java
@@ -19,6 +19,7 @@
 import android.os.BatteryUsageStats;
 import android.os.LocaleList;
 import android.os.UserHandle;
+import android.text.format.DateFormat;
 import android.text.format.DateUtils;
 import android.util.Log;
 
@@ -26,10 +27,8 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.text.SimpleDateFormat;
 import java.time.Duration;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -76,19 +75,6 @@
     public static final int CONSUMER_TYPE_USER_BATTERY = 2;
     public static final int CONSUMER_TYPE_SYSTEM_BATTERY = 3;
 
-    // For language is changed.
-    @VisibleForTesting static Locale sLocale;
-    @VisibleForTesting static Locale sLocaleForHour;
-    // For time zone is changed.
-    @VisibleForTesting static String sZoneId;
-    @VisibleForTesting static String sZoneIdForHour;
-    private static boolean sIs24HourFormat;
-
-    @VisibleForTesting
-    static SimpleDateFormat sSimpleDateFormat;
-    @VisibleForTesting
-    static SimpleDateFormat sSimpleDateFormatForHour;
-
     private ConvertUtils() {}
 
     public static ContentValues convert(
@@ -136,36 +122,21 @@
 
     /** Converts UTC timestamp to human readable local time string. */
     public static String utcToLocalTime(Context context, long timestamp) {
-        final Locale currentLocale = getLocale(context);
-        final String currentZoneId = TimeZone.getDefault().getID();
-        if (!currentZoneId.equals(sZoneId)
-                || !currentLocale.equals(sLocale)
-                || sSimpleDateFormat == null) {
-            sLocale = currentLocale;
-            sZoneId = currentZoneId;
-            sSimpleDateFormat =
-                new SimpleDateFormat("MMM dd,yyyy HH:mm:ss", currentLocale);
-        }
-        return sSimpleDateFormat.format(new Date(timestamp));
+        final Locale locale = getLocale(context);
+        final String pattern =
+            DateFormat.getBestDateTimePattern(locale, "MMM dd,yyyy HH:mm:ss");
+        return DateFormat.format(pattern, timestamp).toString();
     }
 
     /** Converts UTC timestamp to local time hour data. */
     public static String utcToLocalTimeHour(
             Context context, long timestamp, boolean is24HourFormat) {
-        final Locale currentLocale = getLocale(context);
-        final String currentZoneId = TimeZone.getDefault().getID();
-        if (!currentZoneId.equals(sZoneIdForHour)
-                || !currentLocale.equals(sLocaleForHour)
-                || sIs24HourFormat != is24HourFormat
-                || sSimpleDateFormatForHour == null) {
-            sLocaleForHour = currentLocale;
-            sZoneIdForHour = currentZoneId;
-            sIs24HourFormat = is24HourFormat;
-            sSimpleDateFormatForHour = new SimpleDateFormat(
-                    sIs24HourFormat ? "HH" : "h", currentLocale);
-        }
-        return sSimpleDateFormatForHour.format(new Date(timestamp))
-            .toLowerCase(currentLocale);
+        final Locale locale = getLocale(context);
+        // e.g. for 12-hour format: 9 pm
+        // e.g. for 24-hour format: 09:00
+        final String skeleton = is24HourFormat ? "HHm" : "ha";
+        final String pattern = DateFormat.getBestDateTimePattern(locale, skeleton);
+        return DateFormat.format(pattern, timestamp).toString().toLowerCase(locale);
     }
 
     /** Gets indexed battery usage data for each corresponding time slot. */
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 19a8011..638aaa5 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -25,6 +25,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.provider.Settings.Global;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.loader.app.LoaderManager;
@@ -103,6 +104,10 @@
 
                 @Override
                 public void onLoadFinished(Loader<BatteryInfo> loader, BatteryInfo batteryInfo) {
+                    if (batteryInfo == null) {
+                        Log.w(TAG, "mBatteryInfoLoaderCallbacks: batteryInfo = null");
+                        return;
+                    }
                     mBatteryHeaderPreferenceController.updateHeaderPreference(batteryInfo);
                     mBatteryHeaderPreferenceController.updateHeaderByBatteryTips(
                             mBatteryTipPreferenceController.getCurrentBatteryTip(), batteryInfo);
@@ -126,6 +131,10 @@
                 @Override
                 public void onLoadFinished(Loader<List<BatteryTip>> loader,
                         List<BatteryTip> data) {
+                    if (mBatteryInfo == null) {
+                        Log.w(TAG, "mBatteryTipsCallbacks: batteryInfo = null");
+                        return;
+                    }
                     mBatteryTipPreferenceController.updateBatteryTips(data);
                     mBatteryHeaderPreferenceController.updateHeaderByBatteryTips(
                             mBatteryTipPreferenceController.getCurrentBatteryTip(), mBatteryInfo);
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
index 7d11ba5..b6806e8 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.os.BatteryUsageStats;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 
@@ -67,16 +68,17 @@
         final BatteryInfo batteryInfo = mBatteryUtils.getBatteryInfo(TAG);
         final Context context = getContext();
 
+        tips.add(new EarlyWarningDetector(policy, context).detect());
+        if (batteryInfo == null) {
+            Log.w(TAG, "loadInBackground() batteryInfo = null");
+            return tips;
+        }
+
         tips.add(new LowBatteryDetector(context, policy, batteryInfo).detect());
         tips.add(new HighUsageDetector(context, policy, mBatteryUsageStats, batteryInfo).detect());
         tips.add(new SmartBatteryDetector(
                 context, policy, batteryInfo, context.getContentResolver()).detect());
-        tips.add(new EarlyWarningDetector(policy, context).detect());
         tips.add(new BatteryDefenderDetector(batteryInfo).detect());
-        // Disable this feature now since it introduces false positive cases. We will try to improve
-        // it in the future.
-        // tips.add(new RestrictAppDetector(context, policy).detect());
-
         Collections.sort(tips);
         return tips;
     }
diff --git a/src/com/android/settings/notification/history/NotificationHistoryAdapter.java b/src/com/android/settings/notification/history/NotificationHistoryAdapter.java
index 0683ef7..dfa8a30 100644
--- a/src/com/android/settings/notification/history/NotificationHistoryAdapter.java
+++ b/src/com/android/settings/notification/history/NotificationHistoryAdapter.java
@@ -72,6 +72,11 @@
     }
 
     @Override
+    public long getItemId(int position) {
+        return mValues.get(position).hashCode();
+    }
+
+    @Override
     public void onBindViewHolder(final @NonNull NotificationHistoryViewHolder holder,
             int position) {
         final HistoricalNotification hn = mValues.get(position);
diff --git a/src/com/android/settings/notification/history/NotificationHistoryRecyclerView.java b/src/com/android/settings/notification/history/NotificationHistoryRecyclerView.java
index 06c74bc..224c31d 100644
--- a/src/com/android/settings/notification/history/NotificationHistoryRecyclerView.java
+++ b/src/com/android/settings/notification/history/NotificationHistoryRecyclerView.java
@@ -40,7 +40,6 @@
         ItemTouchHelper touchHelper = new ItemTouchHelper(
                 new DismissTouchHelper(0, ItemTouchHelper.START | ItemTouchHelper.END));
         touchHelper.attachToRecyclerView(this);
-        setNestedScrollingEnabled(false);
     }
 
     public void setOnItemSwipeDeleteListener(OnItemSwipeDeleteListener listener) {
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java
index eee6398..2317c97 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDefaultFragmentTest.java
@@ -183,7 +183,7 @@
 
     @Test
     public void onTetheringStarted_currentFunctionsIsRndis_setsRndisAsDefaultUsbFunctions() {
-        mFragment.mCurrentFunctions = UsbManager.FUNCTION_RNDIS;
+        when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_RNDIS);
 
         mFragment.mOnStartTetheringCallback.onTetheringStarted();
 
@@ -192,7 +192,7 @@
 
     @Test
     public void onTetheringStarted_currentFunctionsIsNcm_setsNcmAsDefaultUsbFunctions() {
-        mFragment.mCurrentFunctions = UsbManager.FUNCTION_NCM;
+        when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_NCM);
 
         mFragment.mOnStartTetheringCallback.onTetheringStarted();
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
index fd4e82d..43fbe81 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
@@ -50,7 +50,6 @@
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -65,7 +64,6 @@
 import java.util.Locale;
 import java.util.List;
 import java.util.Map;
-import java.util.TimeZone;
 
 @RunWith(RobolectricTestRunner.class)
 public final class BatteryChartPreferenceControllerTest {
@@ -125,37 +123,6 @@
             createBatteryHistoryMap());
     }
 
-    @Ignore
-    @Test
-    public void testOnResume_uiModeIsChanged_clearBatteryDiffEntryCache() {
-        doReturn(mResources).when(mContext).getResources();
-        doReturn(mConfiguration).when(mResources).getConfiguration();
-        mConfiguration.uiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
-        // Ensures the testing environment is correct.
-        assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
-        mBatteryChartPreferenceController.onResume();
-        // Changes the uiMode in the configuration.
-        mConfiguration.uiMode = Configuration.UI_MODE_NIGHT_YES;
-
-        mBatteryChartPreferenceController.onResume();
-        assertThat(BatteryDiffEntry.sResourceCache).isEmpty();
-    }
-
-    @Ignore
-    @Test
-    public void testOnResume_uiModeIsNotChanged_notClearBatteryDiffEntryCache() {
-        doReturn(mResources).when(mContext).getResources();
-        doReturn(mConfiguration).when(mResources).getConfiguration();
-        mConfiguration.uiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
-        // Ensures the testing environment is correct.
-        assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
-
-        mBatteryChartPreferenceController.onResume();
-        assertThat(BatteryDiffEntry.sResourceCache).isNotEmpty();
-        verify(mMetricsFeatureProvider)
-                .action(mContext, SettingsEnums.OPEN_BATTERY_USAGE);
-    }
-
     @Test
     public void testOnDestroy_activityIsChanging_clearBatteryEntryCache() {
         doReturn(true).when(mSettingsActivity).isChangingConfigurations();
@@ -579,12 +546,12 @@
         // Verifies the title in the preference group.
         verify(mBatteryChartPreferenceController.mAppListPrefGroup)
             .setTitle(captor.capture());
-        assertThat(captor.getValue()).isEqualTo("App usage for 4 - 7");
+        assertThat(captor.getValue()).isNotEqualTo("App usage for past 24 hr");
         // Verifies the title in the expandable divider.
         captor = ArgumentCaptor.forClass(String.class);
         verify(mBatteryChartPreferenceController.mExpandDividerPreference)
             .setTitle(captor.capture());
-        assertThat(captor.getValue()).isEqualTo("System usage for 4 - 7");
+        assertThat(captor.getValue()).isNotEqualTo("System usage for past 24 hr");
     }
 
     @Test
@@ -722,9 +689,6 @@
             new long[] {1619196786769L, 0L, 1619247636826L};
         ConvertUtils.utcToLocalTimeHour(
             mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
-        // Simulates the locale in GMT.
-        ConvertUtils.sSimpleDateFormatForHour
-             .setTimeZone(TimeZone.getTimeZone("GMT"));
     }
 
     private BatteryChartPreferenceController createController() {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
index d19a012..0b75e79 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
@@ -33,7 +33,6 @@
 import com.android.settings.testutils.FakeFeatureFactory;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -44,7 +43,6 @@
 import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.Locale;
-import java.util.TimeZone;
 
 @RunWith(RobolectricTestRunner.class)
 public final class BatteryChartViewTest {
@@ -233,21 +231,4 @@
         verify(mBatteryChartView.mHandler)
             .postDelayed(mBatteryChartView.mUpdateClickableStateRun, 500L);
     }
-
-    @Ignore
-    @Test
-    public void testSetLatestTimestamp_generateExpectedTimestamps() {
-        final long timestamp = 1619196786769L;
-        ConvertUtils.sSimpleDateFormatForHour = null;
-        // Invokes the method first to create the SimpleDateFormat.
-        ConvertUtils.utcToLocalTimeHour(
-            mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
-        ConvertUtils.sSimpleDateFormatForHour
-            .setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
-        final String[] expectedTimestamps = new String[] {"00", "06", "12", "18", "00"};
-
-        mBatteryChartView.setLatestTimestamp(timestamp);
-
-        assertThat(mBatteryChartView.mTimestamps).isEqualTo(expectedTimestamps);
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java
index 0b1a1e3..8ae5048 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java
@@ -30,7 +30,6 @@
 import com.android.settings.testutils.FakeFeatureFactory;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -317,71 +316,6 @@
             .isEqualTo(entry.mConsumePower * ratio);
     }
 
-    @Ignore
-    @Test
-    public void testUtcToLocalTime_returnExpectedResult() {
-        ConvertUtils.sZoneId = null;
-        ConvertUtils.sLocale = null;
-        final long timestamp = 1619196786769L;
-        final String expectedZoneId = "America/Los_Angeles";
-        ConvertUtils.sSimpleDateFormat = null;
-        // Invokes the method first to create the SimpleDateFormat.
-        ConvertUtils.utcToLocalTime(mContext, /*timestamp=*/ 0);
-        ConvertUtils.sSimpleDateFormat
-            .setTimeZone(TimeZone.getTimeZone(expectedZoneId));
-        mContext.getResources().getConfiguration().setLocales(
-            new LocaleList(new Locale("en_US")));
-
-        assertThat(ConvertUtils.utcToLocalTime(mContext, timestamp))
-            .isEqualTo("Apr 24,2021 00:53:06");
-        assertThat(ConvertUtils.sZoneId).isNotEqualTo(expectedZoneId);
-        assertThat(ConvertUtils.sLocale).isEqualTo(new Locale("en_US"));
-    }
-
-    @Ignore
-    @Test
-    public void testUtcToLocalTimeHour_12HourFormat_returnExpectedResult() {
-        ConvertUtils.sZoneIdForHour = null;
-        ConvertUtils.sLocaleForHour = null;
-        final long timestamp = 1619000086769L;
-        final String expectedZoneId = "America/Los_Angeles";
-        ConvertUtils.sSimpleDateFormatForHour = null;
-        // Invokes the method first to create the SimpleDateFormat.
-        ConvertUtils.utcToLocalTimeHour(
-            mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
-        ConvertUtils.sSimpleDateFormatForHour
-            .setTimeZone(TimeZone.getTimeZone(expectedZoneId));
-        mContext.getResources().getConfiguration().setLocales(
-            new LocaleList(new Locale("en_US")));
-
-        assertThat(ConvertUtils.utcToLocalTimeHour(
-            mContext, timestamp, /*is24HourFormat=*/ false)).isEqualTo("6");
-        assertThat(ConvertUtils.sZoneIdForHour).isNotEqualTo(expectedZoneId);
-        assertThat(ConvertUtils.sLocaleForHour).isEqualTo(new Locale("en_US"));
-    }
-
-    @Ignore
-    @Test
-    public void testUtcToLocalTimeHour_24HourFormat_returnExpectedResult() {
-        ConvertUtils.sZoneIdForHour = null;
-        ConvertUtils.sLocaleForHour = null;
-        final long timestamp = 1619000086769L;
-        final String expectedZoneId = "America/Los_Angeles";
-        ConvertUtils.sSimpleDateFormatForHour = null;
-        // Invokes the method first to create the SimpleDateFormat.
-        ConvertUtils.utcToLocalTimeHour(
-            mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
-        ConvertUtils.sSimpleDateFormatForHour
-            .setTimeZone(TimeZone.getTimeZone(expectedZoneId));
-        mContext.getResources().getConfiguration().setLocales(
-            new LocaleList(new Locale("en_US")));
-
-        assertThat(ConvertUtils.utcToLocalTimeHour(
-            mContext, timestamp, /*is24HourFormat=*/ true)).isEqualTo("18");
-        assertThat(ConvertUtils.sZoneIdForHour).isNotEqualTo(expectedZoneId);
-        assertThat(ConvertUtils.sLocaleForHour).isEqualTo(new Locale("en_US"));
-    }
-
     @Test
     public void getLocale_nullContext_returnDefaultLocale() {
         assertThat(ConvertUtils.getLocale(/*context=*/ null))