App anomaly tips on PowerUsage App list

Screenshots:
[in bg - banner] https://screenshot.googleplex.com/MzLC6LfX93TkkYf
[in bg - hints] https://screenshot.googleplex.com/9JLXNsRiVG8arAU
[in fg - banner] https://screenshot.googleplex.com/9oYbwUkeeLbQX2t
[in fg - hints] https://screenshot.googleplex.com/53DTTUCUnf8rsoE
[apps anomaly highlight hint + settings anomaly banner]
https://screenshot.googleplex.com/8NdS2VMrSzwv2DM

Bug: 291689643
Bug: 291689623
Bug: 284893240
Test: manual
Change-Id: Ic02db49cb3794ef134759d9dcec5f5ef32454a95
Merged-In: Ic02db49cb3794ef134759d9dcec5f5ef32454a95
Merged-In: I7015cdf5a96d518febb160934d780ae84fe14427
diff --git a/res/drawable/battery_hints_chip_bg.xml b/res/drawable/battery_hints_chip_bg.xml
new file mode 100644
index 0000000..e7d1d0f
--- /dev/null
+++ b/res/drawable/battery_hints_chip_bg.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2023 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.
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="@color/settingslib_dialog_background" />
+    <corners android:radius="@dimen/battery_hints_chip_corner_radius" />
+</shape>
\ No newline at end of file
diff --git a/res/drawable/battery_hints_chip_bg_ripple.xml b/res/drawable/battery_hints_chip_bg_ripple.xml
new file mode 100644
index 0000000..a8bd0b37
--- /dev/null
+++ b/res/drawable/battery_hints_chip_bg_ripple.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2023 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.
+  -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?android:attr/colorControlHighlight">
+    <item android:drawable="@drawable/battery_hints_chip_bg"/>
+</ripple>
\ No newline at end of file
diff --git a/res/layout/anomaly_app_item_preference.xml b/res/layout/anomaly_app_item_preference.xml
new file mode 100644
index 0000000..0a19849
--- /dev/null
+++ b/res/layout/anomaly_app_item_preference.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <include layout="@layout/preference_app"/>
+
+    <LinearLayout
+        android:id="@+id/warning_chip"
+        android:visibility="gone"
+        android:clickable="false"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="?android:attr/selectableItemBackground"
+        android:gravity="center_vertical"
+        android:orientation="horizontal"
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
+        <Space
+            android:layout_width="@dimen/secondary_app_icon_size"
+            android:layout_height="wrap_content" />
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:padding="8dp"
+            android:layout_marginStart="16dp"
+            android:background="@drawable/battery_hints_chip_bg_ripple">
+
+            <ImageView
+                android:layout_width="16dp"
+                android:layout_height="16dp"
+                android:layout_gravity="center_vertical|start"
+                android:contentDescription="@string/battery_hints_warning_icon_a11y"
+                android:src="@drawable/ic_battery_tips_warning_icon" />
+
+            <TextView
+                android:id="@+id/warning_info"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingHorizontal="8dp"
+                android:layout_gravity="center_vertical|start"
+                android:textAlignment="viewStart"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:textColor="?android:attr/textColorPrimary"/>
+        </LinearLayout>
+
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 78e7ca4..1ab9876 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1420,20 +1420,49 @@
         <item>color_battery_anomaly_yellow_selector</item>
     </string-array>
 
-    <!-- The following 3 arrays are for power anomaly tips card. Please keep them the same size. -->
-    <string-array name="power_anomaly_titles">
-        <item>Turn on adaptive brightness to extend battery life</item>
-        <item>Reduce screen timeout to extend battery life</item>
+    <!-- The following 4 arrays are for power anomaly tips card. Please keep them the same size. -->
+    <string-array name="power_anomaly_title_ids" translatable="false">
+        <item>battery_tips_settings_summary_brightness</item>
+        <item>battery_tips_settings_summary_screen_timeout</item>
+        <item>battery_tips_apps_summary_always_high</item>
+        <item>battery_tips_apps_summary_higher_than_usual</item>
+        <item>battery_tips_apps_summary_always_high_in_background</item>
+        <item>battery_tips_apps_summary_higher_than_usual_in_background</item>
+        <item>battery_tips_apps_summary_always_high_in_foreground</item>
+        <item>battery_tips_apps_summary_higher_than_usual_in_foreground</item>
     </string-array>
 
     <string-array name="power_anomaly_main_btn_strings" translatable="false">
         <item>@string/battery_tips_card_action_button</item>
         <item>@string/battery_tips_card_action_button</item>
+        <item>@string/battery_tips_card_action_button_check</item>
+        <item>@string/battery_tips_card_action_button_check</item>
+        <item>@string/battery_tips_card_action_button_check</item>
+        <item>@string/battery_tips_card_action_button_check</item>
+        <item>@string/battery_tips_card_action_button_check</item>
+        <item>@string/battery_tips_card_action_button_check</item>
     </string-array>
 
     <string-array name="power_anomaly_dismiss_btn_strings" translatable="false">
         <item>@string/battery_tips_card_dismiss_button</item>
         <item>@string/battery_tips_card_dismiss_button</item>
+        <item>@string/battery_tips_card_dismiss_button</item>
+        <item>@string/battery_tips_card_dismiss_button</item>
+        <item>@string/battery_tips_card_dismiss_button</item>
+        <item>@string/battery_tips_card_dismiss_button</item>
+        <item>@string/battery_tips_card_dismiss_button</item>
+        <item>@string/battery_tips_card_dismiss_button</item>
+    </string-array>
+
+    <string-array name="power_anomaly_hint_messages" translatable="false">
+        <item></item>
+        <item></item>
+        <item>@string/battery_app_item_hint</item>
+        <item>@string/battery_app_item_hint</item>
+        <item>@string/battery_app_item_hint_in_bg</item>
+        <item>@string/battery_app_item_hint_in_bg</item>
+        <item>@string/battery_app_item_hint_in_fg</item>
+        <item>@string/battery_app_item_hint_in_fg</item>
     </string-array>
 
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 4ae140e..9703124 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -382,6 +382,7 @@
     <!-- Battery tips card view component -->
     <dimen name="battery_tips_card_corner_radius_small">4dp</dimen>
     <dimen name="battery_tips_card_corner_radius_normal">24dp</dimen>
+    <dimen name="battery_hints_chip_corner_radius">8dp</dimen>
 
     <!-- Dimensions for Dream settings cards -->
     <dimen name="dream_item_min_column_width">174dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 81c6792..1961776 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -9688,12 +9688,51 @@
     <!-- Label of action button in battery tips card [CHAR LIMIT=50] -->
     <string name="battery_tips_card_action_button">View Settings</string>
 
+    <!-- Label of action button in battery tips card [CHAR LIMIT=50] -->
+    <string name="battery_tips_card_action_button_check">Check</string>
+
     <!-- Label of dismiss button in battery tips card [CHAR LIMIT=50] -->
     <string name="battery_tips_card_dismiss_button">Got it</string>
 
     <!-- Feedback card message in battery tips card [CHAR LIMIT=NONE] -->
     <string name="battery_tips_card_feedback_info">Is this message helpful?</string>
 
+    <!-- Content description for battery hints warning icon of app anomaly [CHAR LIMIT=NONE] -->
+    <string name="battery_hints_warning_icon_a11y">Battery tips warning icon</string>
+
+    <!-- Summary of settings anomaly for adaptive brightness [CHAR LIMIT=NONE] -->
+    <string name="battery_tips_settings_summary_brightness">Turn on adaptive brightness to extend battery life</string>
+
+    <!-- Summary of settings anomaly for screen timeout [CHAR LIMIT=NONE] -->
+    <string name="battery_tips_settings_summary_screen_timeout">Reduce screen timeout to extend battery life</string>
+
+    <!-- Summary of apps anomaly for always high [CHAR LIMIT=NONE] -->
+    <string name="battery_tips_apps_summary_always_high"><xliff:g id="app_label" example="Pokemon Go">%1$s</xliff:g> used more battery</string>
+
+    <!-- Summary of apps anomaly for higher than usual [CHAR LIMIT=NONE] -->
+    <string name="battery_tips_apps_summary_higher_than_usual"><xliff:g id="app_label" example="Pokemon Go">%1$s</xliff:g> used more battery than usual</string>
+
+    <!-- Summary of apps anomaly for always high in background [CHAR LIMIT=NONE] -->
+    <string name="battery_tips_apps_summary_always_high_in_background"><xliff:g id="app_label" example="Pokemon Go">%1$s</xliff:g> used more battery while in the background</string>
+
+    <!-- Summary of apps anomaly for higher than usual in background [CHAR LIMIT=NONE] -->
+    <string name="battery_tips_apps_summary_higher_than_usual_in_background"><xliff:g id="app_label" example="Pokemon Go">%1$s</xliff:g> used more battery than usual while in the background</string>
+
+    <!-- Summary of apps anomaly for always high in foreground [CHAR LIMIT=NONE] -->
+    <string name="battery_tips_apps_summary_always_high_in_foreground"><xliff:g id="app_label" example="Pokemon Go">%1$s</xliff:g> used more battery while in the foreground</string>
+
+    <!-- Summary of apps anomaly for higher than usual in foreground [CHAR LIMIT=NONE] -->
+    <string name="battery_tips_apps_summary_higher_than_usual_in_foreground"><xliff:g id="app_label" example="Pokemon Go">%1$s</xliff:g> used more battery than usual while in the foreground</string>
+
+    <!-- Label of hint for apps anomaly in battery usage [CHAR LIMIT=NONE] -->
+    <string name="battery_app_item_hint">High battery usage</string>
+
+    <!-- Label of hint for apps background anomaly in battery usage [CHAR LIMIT=NONE] -->
+    <string name="battery_app_item_hint_in_bg">High battery usage in the background</string>
+
+    <!-- Label of hint for apps foreground anomaly in battery usage [CHAR LIMIT=NONE] -->
+    <string name="battery_app_item_hint_in_fg">High battery usage in the foreground</string>
+
     <!-- Filter title for battery unrestricted[CHAR_LIMIT=50]-->
     <string name="filter_battery_unrestricted_title">Unrestricted</string>
 
diff --git a/src/com/android/settings/fuelgauge/batteryusage/AnomalyAppItemPreference.java b/src/com/android/settings/fuelgauge/batteryusage/AnomalyAppItemPreference.java
new file mode 100644
index 0000000..2f139ec
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/AnomalyAppItemPreference.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 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.batteryusage;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+
+class AnomalyAppItemPreference extends PowerGaugePreference {
+
+    private static final String TAG = "AnomalyAppItemPreference";
+
+    private CharSequence mAnomalyHintText;
+
+    AnomalyAppItemPreference(Context context) {
+        super(context, /* attrs */ null);
+        setLayoutResource(R.layout.anomaly_app_item_preference);
+    }
+
+    void setAnomalyHint(CharSequence anomalyHintText) {
+        if (!TextUtils.equals(mAnomalyHintText, anomalyHintText)) {
+            mAnomalyHintText = anomalyHintText;
+            notifyChanged();
+        }
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder viewHolder) {
+        super.onBindViewHolder(viewHolder);
+        final LinearLayout warningChipView =
+                (LinearLayout) viewHolder.findViewById(R.id.warning_chip);
+
+        if (!TextUtils.isEmpty(mAnomalyHintText)) {
+            ((TextView) warningChipView.findViewById(R.id.warning_info)).setText(mAnomalyHintText);
+            warningChipView.setVisibility(View.VISIBLE);
+        } else {
+            warningChipView.setVisibility(View.GONE);
+        }
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java b/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java
new file mode 100644
index 0000000..d535490
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2023 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.batteryusage;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Pair;
+
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.core.SubSettingLauncher;
+
+import java.util.function.Function;
+
+final class AnomalyEventWrapper {
+    private static final String TAG = "AnomalyEventWrapper";
+
+    private final Context mContext;
+    private final PowerAnomalyEvent mPowerAnomalyEvent;
+
+    private final int mCardStyleId;
+    private final int mResourceIndex;
+
+    private SubSettingLauncher mSubSettingLauncher = null;
+    private Pair<Integer, Integer> mHighlightSlotPair = null;
+    private BatteryDiffEntry mRelatedBatteryDiffEntry = null;
+
+    AnomalyEventWrapper(Context context, PowerAnomalyEvent powerAnomalyEvent) {
+        mContext = context;
+        mPowerAnomalyEvent = powerAnomalyEvent;
+        // Set basic battery tips card info
+        mCardStyleId = mPowerAnomalyEvent.getType().getNumber();
+        mResourceIndex = mPowerAnomalyEvent.getKey().getNumber();
+    }
+
+    private <T> T getInfo(Function<WarningBannerInfo, T> warningBannerInfoSupplier,
+            Function<WarningItemInfo, T> warningItemInfoSupplier) {
+        if (warningBannerInfoSupplier != null && mPowerAnomalyEvent.hasWarningBannerInfo()) {
+            return warningBannerInfoSupplier.apply(mPowerAnomalyEvent.getWarningBannerInfo());
+        } else if (warningItemInfoSupplier != null && mPowerAnomalyEvent.hasWarningItemInfo()) {
+            return warningItemInfoSupplier.apply(mPowerAnomalyEvent.getWarningItemInfo());
+        }
+        return null;
+    }
+
+    private int getResourceId(int resourceId, int resourceIndex, String defType) {
+        final String key = getStringFromArrayResource(resourceId, resourceIndex);
+        return TextUtils.isEmpty(key) ? 0
+                : mContext.getResources().getIdentifier(key, defType, mContext.getPackageName());
+    }
+
+    private String getString(Function<WarningBannerInfo, String> warningBannerInfoSupplier,
+            Function<WarningItemInfo, String> warningItemInfoSupplier,
+            int resourceId, int resourceIndex) {
+        final String string = getInfo(warningBannerInfoSupplier, warningItemInfoSupplier);
+        return (!TextUtils.isEmpty(string) || resourceId <= 0) ? string
+                : getStringFromArrayResource(resourceId, resourceIndex);
+    }
+
+    private String getStringFromArrayResource(int resourceId, int resourceIndex) {
+        if (resourceId <= 0 || resourceIndex < 0) {
+            return null;
+        }
+        final String[] stringArray = mContext.getResources().getStringArray(resourceId);
+        return (resourceIndex >= 0 && resourceIndex < stringArray.length)
+                ? stringArray[resourceIndex] : null;
+    }
+
+    void setRelatedBatteryDiffEntry(BatteryDiffEntry batteryDiffEntry) {
+        mRelatedBatteryDiffEntry = batteryDiffEntry;
+    }
+
+    String getEventId() {
+        return mPowerAnomalyEvent.hasEventId() ? mPowerAnomalyEvent.getEventId() : null;
+    }
+
+    int getIconResId() {
+        return getResourceId(R.array.battery_tips_card_icons, mCardStyleId, "drawable");
+    }
+
+    int getColorResId() {
+        return getResourceId(R.array.battery_tips_card_colors, mCardStyleId, "color");
+    }
+
+    String getTitleString() {
+        final String protoTitleString = getInfo(WarningBannerInfo::getTitleString,
+                WarningItemInfo::getTitleString);
+        if (!TextUtils.isEmpty(protoTitleString)) {
+            return protoTitleString;
+        }
+        final int titleFormatResId = getResourceId(R.array.power_anomaly_title_ids,
+                mResourceIndex, "string");
+        if (mPowerAnomalyEvent.hasWarningBannerInfo()) {
+            return mContext.getString(titleFormatResId);
+        } else if (mPowerAnomalyEvent.hasWarningItemInfo() && mRelatedBatteryDiffEntry != null) {
+            final String appLabel = mRelatedBatteryDiffEntry.getAppLabel();
+            return mContext.getString(titleFormatResId, appLabel);
+        }
+        return null;
+    }
+
+    String getMainBtnString() {
+        return getString(WarningBannerInfo::getMainButtonString,
+                WarningItemInfo::getMainButtonString,
+                R.array.power_anomaly_main_btn_strings, mResourceIndex);
+    }
+
+    String getDismissBtnString() {
+        return getString(WarningBannerInfo::getCancelButtonString,
+                WarningItemInfo::getCancelButtonString,
+                R.array.power_anomaly_dismiss_btn_strings, mResourceIndex);
+    }
+
+    String getAnomalyHintString() {
+        return getStringFromArrayResource(R.array.power_anomaly_hint_messages, mResourceIndex);
+    }
+
+    String getDismissRecordKey() {
+        return mPowerAnomalyEvent.getDismissRecordKey();
+    }
+
+    boolean hasAnomalyEntryKey() {
+        return getAnomalyEntryKey() != null;
+    }
+
+    String getAnomalyEntryKey() {
+        return mPowerAnomalyEvent.hasWarningItemInfo()
+                && mPowerAnomalyEvent.getWarningItemInfo().hasItemKey()
+                ? mPowerAnomalyEvent.getWarningItemInfo().getItemKey() : null;
+    }
+
+    boolean hasSubSettingLauncher() {
+        if (mSubSettingLauncher == null) {
+            mSubSettingLauncher = getSubSettingLauncher();
+        }
+        return mSubSettingLauncher != null;
+    }
+
+    SubSettingLauncher getSubSettingLauncher() {
+        if (mSubSettingLauncher != null) {
+            return mSubSettingLauncher;
+        }
+        final String destinationClassName = getInfo(
+                WarningBannerInfo::getMainButtonDestination, null);
+        if (!TextUtils.isEmpty(destinationClassName)) {
+            final Integer sourceMetricsCategory = getInfo(
+                    WarningBannerInfo::getMainButtonSourceMetricsCategory, null);
+            final String preferenceHighlightKey = getInfo(
+                    WarningBannerInfo::getMainButtonSourceHighlightKey, null);
+            Bundle arguments = Bundle.EMPTY;
+            if (!TextUtils.isEmpty(preferenceHighlightKey)) {
+                arguments = new Bundle(1);
+                arguments.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY,
+                        preferenceHighlightKey);
+            }
+            mSubSettingLauncher = new SubSettingLauncher(mContext)
+                    .setDestination(destinationClassName)
+                    .setSourceMetricsCategory(sourceMetricsCategory)
+                    .setArguments(arguments);
+        }
+        return mSubSettingLauncher;
+    }
+
+    boolean hasHighlightSlotPair(BatteryLevelData batteryLevelData) {
+        if (mHighlightSlotPair == null) {
+            mHighlightSlotPair = getHighlightSlotPair(batteryLevelData);
+        }
+        return mHighlightSlotPair != null;
+    }
+
+    Pair<Integer, Integer> getHighlightSlotPair(BatteryLevelData batteryLevelData) {
+        if (mHighlightSlotPair != null) {
+            return mHighlightSlotPair;
+        }
+        if (!mPowerAnomalyEvent.hasWarningItemInfo()) {
+            return null;
+        }
+        final WarningItemInfo warningItemInfo = mPowerAnomalyEvent.getWarningItemInfo();
+        final Long startTimestamp = warningItemInfo.hasStartTimestamp()
+                ? warningItemInfo.getStartTimestamp() : null;
+        final Long endTimestamp = warningItemInfo.hasEndTimestamp()
+                ? warningItemInfo.getEndTimestamp() : null;
+        if (startTimestamp != null && endTimestamp != null) {
+            mHighlightSlotPair = batteryLevelData
+                    .getIndexByTimestamps(startTimestamp, endTimestamp);
+            if (mHighlightSlotPair.first == BatteryChartViewModel.SELECTED_INDEX_INVALID
+                    || mHighlightSlotPair.second == BatteryChartViewModel.SELECTED_INDEX_INVALID) {
+                // Drop invalid mHighlightSlotPair index
+                mHighlightSlotPair = null;
+            }
+        }
+        return mHighlightSlotPair;
+    }
+
+    boolean updateTipsCardPreference(BatteryTipsCardPreference preference) {
+        final String titleString = getTitleString();
+        if (TextUtils.isEmpty(titleString)) {
+            return false;
+        }
+        preference.setTitle(titleString);
+        preference.setIconResourceId(getIconResId());
+        preference.setMainButtonStrokeColorResourceId(getColorResId());
+        preference.setMainButtonLabel(getMainBtnString());
+        preference.setDismissButtonLabel(getDismissBtnString());
+        return true;
+    }
+
+    boolean launchSubSetting() {
+        if (!hasSubSettingLauncher()) {
+            return false;
+        }
+        // Navigate to sub setting page
+        mSubSettingLauncher.launch();
+        return true;
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
index 1893096..844241e 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
@@ -221,14 +221,20 @@
         refreshUi();
     }
 
+    boolean isHighlightSlotFocused() {
+        return (mDailyHighlightSlotIndex != BatteryChartViewModel.SELECTED_INDEX_INVALID
+                && mDailyHighlightSlotIndex == mDailyChartIndex
+                && mHourlyHighlightSlotIndex != BatteryChartViewModel.SELECTED_INDEX_INVALID
+                && mHourlyHighlightSlotIndex == mHourlyChartIndex);
+    }
+
     void onHighlightSlotIndexUpdate(int dailyHighlightSlotIndex, int hourlyHighlightSlotIndex) {
-        if (mDailyHighlightSlotIndex == dailyHighlightSlotIndex
-                && mHourlyHighlightSlotIndex == hourlyHighlightSlotIndex) {
-            return;
-        }
         mDailyHighlightSlotIndex = dailyHighlightSlotIndex;
         mHourlyHighlightSlotIndex = hourlyHighlightSlotIndex;
         refreshUi();
+        if (mOnSelectedIndexUpdatedListener != null) {
+            mOnSelectedIndexUpdatedListener.onSelectedIndexUpdated();
+        }
     }
 
     void selectHighlightSlotIndex() {
@@ -405,7 +411,7 @@
         final String slotInformation = getSlotInformation();
         return slotInformation == null
                 ? mPrefContext.getString(
-                       R.string.battery_usage_breakdown_title_since_last_full_charge)
+                        R.string.battery_usage_breakdown_title_since_last_full_charge)
                 : mPrefContext.getString(
                         R.string.battery_usage_breakdown_title_for_slot, slotInformation);
     }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreference.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreference.java
index e98077c..47d2ac3 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreference.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreference.java
@@ -120,12 +120,10 @@
     public void onClick(View view) {
         final int viewId = view.getId();
         if (viewId == R.id.main_button || viewId == R.id.tips_card) {
-            setVisible(false);
             if (mOnConfirmListener != null) {
                 mOnConfirmListener.onConfirm();
             }
         } else if (viewId == R.id.dismiss_button) {
-            setVisible(false);
             if (mOnRejectListener != null) {
                 mOnRejectListener.onReject();
             }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java
index 400e70a..39ed0dc 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java
@@ -18,21 +18,15 @@
 
 import android.app.settings.SettingsEnums;
 import android.content.Context;
-import android.os.Bundle;
 import android.text.TextUtils;
 
 import androidx.preference.PreferenceScreen;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.settings.R;
-import com.android.settings.SettingsActivity;
 import com.android.settings.core.BasePreferenceController;
-import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
-import java.util.function.Function;
-
 /** Controls the update for battery tips card */
 public class BatteryTipsController extends BasePreferenceController {
 
@@ -59,6 +53,10 @@
 
     @VisibleForTesting
     BatteryTipsCardPreference mCardPreference;
+    @VisibleForTesting
+    AnomalyEventWrapper mAnomalyEventWrapper = null;
+    @VisibleForTesting
+    Boolean mIsAcceptable = false;
 
     public BatteryTipsController(Context context) {
         super(context, ROOT_PREFERENCE_KEY);
@@ -85,132 +83,56 @@
         mOnAnomalyRejectListener = listener;
     }
 
-    private <T> T getInfo(PowerAnomalyEvent powerAnomalyEvent,
-                          Function<WarningBannerInfo, T> warningBannerInfoSupplier,
-                          Function<WarningItemInfo, T> warningItemInfoSupplier) {
-        if (warningBannerInfoSupplier != null && powerAnomalyEvent.hasWarningBannerInfo()) {
-            return warningBannerInfoSupplier.apply(powerAnomalyEvent.getWarningBannerInfo());
-        } else if (warningItemInfoSupplier != null && powerAnomalyEvent.hasWarningItemInfo()) {
-            return warningItemInfoSupplier.apply(powerAnomalyEvent.getWarningItemInfo());
+    void acceptTipsCard() {
+        if (mAnomalyEventWrapper == null || !mIsAcceptable) {
+            return;
         }
-        return null;
-    }
-
-    private String getStringFromResource(int resourceId, int resourceIndex) {
-        if (resourceId < 0) {
-            return null;
+        // For anomaly events with same record key, dismissed until next time full charged.
+        final String dismissRecordKey = mAnomalyEventWrapper.getDismissRecordKey();
+        if (!TextUtils.isEmpty(dismissRecordKey)) {
+            DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, dismissRecordKey);
         }
-        final String[] stringArray = mContext.getResources().getStringArray(resourceId);
-        return (resourceIndex >= 0 && resourceIndex < stringArray.length)
-                ? stringArray[resourceIndex] : null;
+        mCardPreference.setVisible(false);
+        mMetricsFeatureProvider.action(
+                mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
+                mAnomalyEventWrapper.getEventId());
     }
 
-    private int getResourceId(int resourceId, int resourceIndex, String defType) {
-        final String key = getStringFromResource(resourceId, resourceIndex);
-        return TextUtils.isEmpty(key) ? 0
-                : mContext.getResources().getIdentifier(key, defType, mContext.getPackageName());
-    }
-
-    private String getString(PowerAnomalyEvent powerAnomalyEvent,
-                             Function<WarningBannerInfo, String> warningBannerInfoSupplier,
-                             Function<WarningItemInfo, String> warningItemInfoSupplier,
-                             int resourceId, int resourceIndex) {
-        String string =
-                getInfo(powerAnomalyEvent, warningBannerInfoSupplier, warningItemInfoSupplier);
-        return (!TextUtils.isEmpty(string) || resourceId < 0) ? string
-                : getStringFromResource(resourceId, resourceIndex);
-    }
-
-    /** Generate a key string of current anomaly to record as dismissed in sharedPreferences. */
-    public static String getDismissRecordKey(PowerAnomalyEvent event) {
-        if (!event.hasKey()) {
-            return null;
-        }
-        switch (event.getKey()){
-            case KEY_APP:
-                return event.hasWarningItemInfo()
-                        && event.getWarningItemInfo().hasDismissRecordKey()
-                        ? event.getWarningItemInfo().getDismissRecordKey() : null;
-            default:
-                return event.getKey().name();
-        }
-    }
-
-    void handleBatteryTipsCardUpdated(PowerAnomalyEvent powerAnomalyEvent) {
-        if (powerAnomalyEvent == null) {
+    void handleBatteryTipsCardUpdated(
+            AnomalyEventWrapper anomalyEventWrapper, boolean isAcceptable) {
+        mAnomalyEventWrapper = anomalyEventWrapper;
+        mIsAcceptable = isAcceptable;
+        if (mAnomalyEventWrapper == null) {
             mCardPreference.setVisible(false);
             return;
         }
 
-        // Get card icon and color styles
-        final int cardStyleId = powerAnomalyEvent.getType().getNumber();
-        final int iconResId = getResourceId(
-                R.array.battery_tips_card_icons, cardStyleId, "drawable");
-        final int colorResId = getResourceId(
-                R.array.battery_tips_card_colors, cardStyleId, "color");
-
         // Get card preference strings and navigate fragment info
-        final String eventId = powerAnomalyEvent.hasEventId()
-                ? powerAnomalyEvent.getEventId() : null;
-        final PowerAnomalyKey powerAnomalyKey = powerAnomalyEvent.hasKey()
-                ? powerAnomalyEvent.getKey() : null;
-        final int resourceIndex = powerAnomalyKey != null ? powerAnomalyKey.getNumber() : -1;
+        final String eventId = mAnomalyEventWrapper.getEventId();
 
-        final String titleString = getString(powerAnomalyEvent, WarningBannerInfo::getTitleString,
-                WarningItemInfo::getTitleString, R.array.power_anomaly_titles, resourceIndex);
-        if (titleString.isEmpty()) {
+        // Update card & buttons preference
+        if (!mAnomalyEventWrapper.updateTipsCardPreference(mCardPreference)) {
             mCardPreference.setVisible(false);
             return;
         }
 
-        final String mainBtnString = getString(powerAnomalyEvent,
-                WarningBannerInfo::getMainButtonString, WarningItemInfo::getMainButtonString,
-                R.array.power_anomaly_main_btn_strings, resourceIndex);
-        final String dismissBtnString = getString(powerAnomalyEvent,
-                WarningBannerInfo::getCancelButtonString, WarningItemInfo::getCancelButtonString,
-                R.array.power_anomaly_dismiss_btn_strings, resourceIndex);
-
-        final String destinationClassName = getInfo(powerAnomalyEvent,
-                WarningBannerInfo::getMainButtonDestination, null);
-        final Integer sourceMetricsCategory = getInfo(powerAnomalyEvent,
-                WarningBannerInfo::getMainButtonSourceMetricsCategory, null);
-        final String preferenceHighlightKey = getInfo(powerAnomalyEvent,
-                WarningBannerInfo::getMainButtonSourceHighlightKey, null);
-
-        // Update card preference and main button fragment launcher
-        mCardPreference.setTitle(titleString);
-        mCardPreference.setIconResourceId(iconResId);
-        mCardPreference.setMainButtonStrokeColorResourceId(colorResId);
-        mCardPreference.setMainButtonLabel(mainBtnString);
-        mCardPreference.setDismissButtonLabel(dismissBtnString);
-
         // Set battery tips card listener
         mCardPreference.setOnConfirmListener(() -> {
+            mCardPreference.setVisible(false);
             if (mOnAnomalyConfirmListener != null) {
                 mOnAnomalyConfirmListener.onAnomalyConfirm();
-            } else if (!TextUtils.isEmpty(destinationClassName)) {
-                // Navigate to sub setting page
-                Bundle arguments = Bundle.EMPTY;
-                if (!TextUtils.isEmpty(preferenceHighlightKey)) {
-                    arguments = new Bundle(1);
-                    arguments.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY,
-                            preferenceHighlightKey);
-                }
-                new SubSettingLauncher(mContext)
-                        .setDestination(destinationClassName)
-                        .setSourceMetricsCategory(sourceMetricsCategory)
-                        .setArguments(arguments)
-                        .launch();
+            } else if (mAnomalyEventWrapper.launchSubSetting()) {
+                mMetricsFeatureProvider.action(
+                        mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, eventId);
             }
-            mMetricsFeatureProvider.action(
-                    mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, eventId);
         });
         mCardPreference.setOnRejectListener(() -> {
+            mCardPreference.setVisible(false);
             if (mOnAnomalyRejectListener != null) {
                 mOnAnomalyRejectListener.onAnomalyReject();
             }
             // For anomaly events with same record key, dismissed until next time full charged.
-            final String dismissRecordKey = getDismissRecordKey(powerAnomalyEvent);
+            final String dismissRecordKey = mAnomalyEventWrapper.getDismissRecordKey();
             if (!TextUtils.isEmpty(dismissRecordKey)) {
                 DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, dismissRecordKey);
             }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
index 8aa31e2..b237ef6 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
@@ -53,6 +53,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 
 /** Controller for battery usage breakdown preference group. */
@@ -93,6 +94,14 @@
     BatteryDiffData mBatteryDiffData;
     @VisibleForTesting
     String mPercentLessThanThresholdText;
+    @VisibleForTesting
+    boolean mIsHighlightSlot;
+    @VisibleForTesting
+    String mAnomalyEventId;
+    @VisibleForTesting
+    String mAnomalyEntryKey;
+    @VisibleForTesting
+    String mAnomalyHintString;
 
     public BatteryUsageBreakdownController(
             Context context, Lifecycle lifecycle, SettingsActivity activity,
@@ -137,6 +146,12 @@
         return false;
     }
 
+    private String getActionKey(String packageName) {
+        final String actionKey = TextUtils.isEmpty(packageName)
+                ? PACKAGE_NAME_NONE : packageName;
+        return mAnomalyEventId == null ? actionKey : actionKey + "|"  + mAnomalyEventId;
+    }
+
     @Override
     public boolean handlePreferenceTreeClick(Preference preference) {
         if (!(preference instanceof PowerGaugePreference)) {
@@ -151,7 +166,7 @@
                         ? SettingsEnums.ACTION_BATTERY_USAGE_SYSTEM_ITEM
                         : SettingsEnums.ACTION_BATTERY_USAGE_APP_ITEM,
                 /* pageId */ SettingsEnums.OPEN_BATTERY_USAGE,
-                TextUtils.isEmpty(packageName) ? PACKAGE_NAME_NONE : packageName,
+                getActionKey(packageName),
                 (int) Math.round(diffEntry.getPercentage()));
         Log.d(TAG, String.format("handleClick() label=%s key=%s package=%s",
                 diffEntry.getAppLabel(), diffEntry.getKey(), packageName));
@@ -211,9 +226,23 @@
      *                            used when showing the footer.
      */
     void handleBatteryUsageUpdated(
-            BatteryDiffData slotUsageData, String slotTimestamp, boolean isAllUsageDataEmpty) {
+            BatteryDiffData slotUsageData, String slotTimestamp,
+            boolean isAllUsageDataEmpty, boolean isHighlightSlot,
+            Optional<AnomalyEventWrapper> optionalAnomalyEventWrapper) {
         mBatteryDiffData = slotUsageData;
         mSlotTimestamp = slotTimestamp;
+        mIsHighlightSlot = isHighlightSlot;
+
+        if (optionalAnomalyEventWrapper != null) {
+            final AnomalyEventWrapper anomalyEventWrapper =
+                    optionalAnomalyEventWrapper.orElse(null);
+            mAnomalyEventId = anomalyEventWrapper != null
+                    ? anomalyEventWrapper.getEventId() : null;
+            mAnomalyEntryKey = anomalyEventWrapper != null
+                    ? anomalyEventWrapper.getAnomalyEntryKey() : null;
+            mAnomalyHintString = anomalyEventWrapper != null
+                    ? anomalyEventWrapper.getAnomalyHintString() : null;
+        }
 
         showCategoryTitle(slotTimestamp);
         showSpinnerAndAppList();
@@ -278,15 +307,15 @@
                 continue;
             }
             final String prefKey = entry.getKey();
-            PowerGaugePreference pref = mAppListPreferenceGroup.findPreference(prefKey);
+            AnomalyAppItemPreference pref = mAppListPreferenceGroup.findPreference(prefKey);
             if (pref != null) {
                 isAdded = true;
             } else {
-                pref = (PowerGaugePreference) mPreferenceCache.get(prefKey);
+                pref = (AnomalyAppItemPreference) mPreferenceCache.get(prefKey);
             }
-            // Creates new innstance if cached preference is not found.
+            // Creates new instance if cached preference is not found.
             if (pref == null) {
-                pref = new PowerGaugePreference(mPrefContext);
+                pref = new AnomalyAppItemPreference(mPrefContext);
                 pref.setKey(prefKey);
                 mPreferenceCache.put(prefKey, pref);
             }
@@ -294,6 +323,10 @@
             pref.setTitle(appLabel);
             pref.setOrder(prefIndex);
             pref.setSingleLineTitle(true);
+            // Updates App item preference style
+            pref.setAnomalyHint(mIsHighlightSlot && mAnomalyEntryKey != null
+                    && mAnomalyEntryKey.equals(entry.getKey())
+                    ? mAnomalyHintString : null);
             // Sets the BatteryDiffEntry to preference for launching detailed page.
             pref.setBatteryDiffEntry(entry);
             pref.setSelectable(entry.validForRestriction());
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoader.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoader.java
index ece9960..658f104 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoader.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageDataLoader.java
@@ -28,6 +28,7 @@
 
 import com.android.settings.fuelgauge.BatteryUsageHistoricalLogEntry.Action;
 import com.android.settings.fuelgauge.batteryusage.bugreport.BatteryUsageLogUtils;
+import com.android.settings.overlay.FeatureFactory;
 
 import java.util.List;
 import java.util.Map;
@@ -138,6 +139,8 @@
                 // No app usage data or battery diff data at this time.
                 loadAppUsageData(context);
                 preprocessBatteryUsageSlots(context);
+                FeatureFactory.getFactory(context).getPowerUsageFeatureProvider(context)
+                        .detectSettingsAnomaly(context, /* displayDrain= */ 0);
             }
             Log.d(TAG, String.format(
                     "loadUsageDataSafely() in %d/ms", System.currentTimeMillis() - start));
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
index 4e8e396..fb92a76 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
@@ -52,6 +52,7 @@
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.function.Predicate;
 
 /** Advanced power usage. */
 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
@@ -92,9 +93,9 @@
     @VisibleForTesting
     BatteryUsageBreakdownController mBatteryUsageBreakdownController;
     @VisibleForTesting
-    PowerAnomalyEvent mPowerAnomalyEvent;
-    @VisibleForTesting
     Optional<BatteryLevelData> mBatteryLevelData;
+    @VisibleForTesting
+    Optional<AnomalyEventWrapper> mHighlightEventWrapper;
 
     @Override
     public void onCreate(Bundle icicle) {
@@ -188,7 +189,7 @@
             mIsChartDataLoaded = true;
             mBatteryLevelData = null;
             mBatteryUsageMap = null;
-            mPowerAnomalyEvent = null;
+            mHighlightEventWrapper = null;
             restartLoader(LoaderIndex.BATTERY_LEVEL_DATA_LOADER, bundle,
                     mBatteryLevelDataLoaderCallbacks);
         }
@@ -239,8 +240,13 @@
             mScreenOnTimeController.handleSceenOnTimeUpdated(
                     slotUsageData.getScreenOnTime(), slotInformation);
         }
+        // Hide card tips if the related highlight slot was clicked.
+        if (isAppsAnomalyEventFocused()) {
+            mBatteryTipsController.acceptTipsCard();
+        }
         mBatteryUsageBreakdownController.handleBatteryUsageUpdated(
-                slotUsageData, slotInformation, isBatteryUsageMapNullOrEmpty());
+                slotUsageData, slotInformation, isBatteryUsageMapNullOrEmpty(),
+                isAppsAnomalyEventFocused(), mHighlightEventWrapper);
         Log.d(TAG, String.format("Battery usage list shows in %d millis",
                 System.currentTimeMillis() - mResumeTimestamp));
     }
@@ -262,49 +268,95 @@
             return;
         }
         Log.d(TAG, "anomalyEventList = " + anomalyEventList);
-        final PowerAnomalyEvent displayEvent =
-                getHighestScoreAnomalyEvent(getContext(), anomalyEventList);
-        onDisplayAnomalyEventUpdated(displayEvent);
+
+        final Set<String> dismissedPowerAnomalyKeys =
+                DatabaseUtils.getDismissedPowerAnomalyKeys(getContext());
+        Log.d(TAG, "dismissedPowerAnomalyKeys = " + dismissedPowerAnomalyKeys);
+
+        // Choose an app anomaly event with highest score to show highlight slot
+        final PowerAnomalyEvent highlightEvent =
+                getAnomalyEvent(anomalyEventList, PowerAnomalyEvent::hasWarningItemInfo);
+        // Choose an event never dismissed to show as card.
+        // If the slot is already highlighted, the tips card should be the corresponding app
+        // or settings anomaly event.
+        final PowerAnomalyEvent tipsCardEvent =
+                getAnomalyEvent(anomalyEventList,
+                        event -> !dismissedPowerAnomalyKeys.contains(event.getDismissRecordKey())
+                                && (event.equals(highlightEvent) || !event.hasWarningItemInfo()));
+        onDisplayAnomalyEventUpdated(tipsCardEvent, highlightEvent);
     }
 
     @VisibleForTesting
-    void onDisplayAnomalyEventUpdated(PowerAnomalyEvent event) {
-        mPowerAnomalyEvent = event;
+    void onDisplayAnomalyEventUpdated(
+            PowerAnomalyEvent tipsCardEvent, PowerAnomalyEvent highlightEvent) {
         if (mBatteryTipsController == null
                 || mBatteryChartPreferenceController == null
                 || mBatteryUsageBreakdownController == null) {
             return;
         }
 
+        final boolean isSameAnomalyEvent = (tipsCardEvent == highlightEvent);
         // Update battery tips card preference & behaviour
         mBatteryTipsController.setOnAnomalyConfirmListener(null);
         mBatteryTipsController.setOnAnomalyRejectListener(null);
-        mBatteryTipsController.handleBatteryTipsCardUpdated(mPowerAnomalyEvent);
+        final AnomalyEventWrapper tipsCardEventWrapper = (tipsCardEvent == null) ? null :
+                new AnomalyEventWrapper(getContext(), tipsCardEvent);
+        if (tipsCardEventWrapper != null) {
+            tipsCardEventWrapper.setRelatedBatteryDiffEntry(
+                    findRelatedBatteryDiffEntry(tipsCardEventWrapper));
+        }
+        mBatteryTipsController.handleBatteryTipsCardUpdated(
+                tipsCardEventWrapper, isSameAnomalyEvent);
 
         // Update highlight slot effect in battery chart view
         Pair<Integer, Integer> highlightSlotIndexPair = Pair.create(
                 BatteryChartViewModel.SELECTED_INDEX_INVALID,
                 BatteryChartViewModel.SELECTED_INDEX_INVALID);
-        if (mPowerAnomalyEvent != null && mPowerAnomalyEvent.hasWarningItemInfo()) {
-            final WarningItemInfo warningItemInfo = mPowerAnomalyEvent.getWarningItemInfo();
-            final Long startTimestamp = warningItemInfo.hasStartTimestamp()
-                    ? warningItemInfo.getStartTimestamp() : null;
-            final Long endTimestamp = warningItemInfo.hasEndTimestamp()
-                    ? warningItemInfo.getEndTimestamp() : null;
-            if (startTimestamp != null && endTimestamp != null) {
-                highlightSlotIndexPair = mBatteryLevelData.map(levelData ->
-                                levelData.getIndexByTimestamps(startTimestamp, endTimestamp))
-                        .orElse(highlightSlotIndexPair);
-                mBatteryTipsController.setOnAnomalyConfirmListener(
-                        mBatteryChartPreferenceController::selectHighlightSlotIndex);
-                mBatteryTipsController.setOnAnomalyRejectListener(
-                        () -> onDisplayAnomalyEventUpdated(null));
+        mHighlightEventWrapper = Optional.ofNullable(isSameAnomalyEvent ? tipsCardEventWrapper :
+                ((highlightEvent != null)
+                        ? new AnomalyEventWrapper(getContext(), highlightEvent) : null));
+        if (mBatteryLevelData != null && mBatteryLevelData.isPresent()
+                && mHighlightEventWrapper.isPresent()
+                && mHighlightEventWrapper.get().hasHighlightSlotPair(mBatteryLevelData.get())) {
+            highlightSlotIndexPair = mHighlightEventWrapper.get()
+                    .getHighlightSlotPair(mBatteryLevelData.get());
+            if (isSameAnomalyEvent) {
+                // For main button, focus on highlight slot when clicked
+                mBatteryTipsController.setOnAnomalyConfirmListener(() -> {
+                    mBatteryChartPreferenceController.selectHighlightSlotIndex();
+                    mBatteryTipsController.acceptTipsCard();
+                });
             }
         }
         mBatteryChartPreferenceController.onHighlightSlotIndexUpdate(
                 highlightSlotIndexPair.first, highlightSlotIndexPair.second);
     }
 
+    @VisibleForTesting
+    BatteryDiffEntry findRelatedBatteryDiffEntry(AnomalyEventWrapper eventWrapper) {
+        if (eventWrapper == null
+                || mBatteryLevelData == null || mBatteryLevelData.isEmpty()
+                || !eventWrapper.hasHighlightSlotPair(mBatteryLevelData.get())
+                || !eventWrapper.hasAnomalyEntryKey()
+                || mBatteryUsageMap == null) {
+            return null;
+        }
+        final Pair<Integer, Integer> highlightSlotIndexPair =
+                eventWrapper.getHighlightSlotPair(mBatteryLevelData.get());
+        final BatteryDiffData relatedDiffData = mBatteryUsageMap
+                .get(highlightSlotIndexPair.first).get(highlightSlotIndexPair.second);
+        final String anomalyEntryKey = eventWrapper.getAnomalyEntryKey();
+        if (relatedDiffData == null || anomalyEntryKey == null) {
+            return null;
+        }
+        for (BatteryDiffEntry entry : relatedDiffData.getAppDiffEntryList()) {
+            if (anomalyEntryKey.equals(entry.getKey())) {
+                return entry;
+            }
+        }
+        return null;
+    }
+
     private void setBatteryChartPreferenceController() {
         if (mHistPref != null && mBatteryChartPreferenceController != null) {
             mHistPref.setChartPreferenceController(mBatteryChartPreferenceController);
@@ -319,6 +371,11 @@
                 && allBatteryDiffData.getSystemDiffEntryList().isEmpty());
     }
 
+    private boolean isAppsAnomalyEventFocused() {
+        return mBatteryChartPreferenceController != null
+                && mBatteryChartPreferenceController.isHighlightSlotFocused();
+    }
+
     private void logScreenUsageTime() {
         final BatteryDiffData allBatteryDiffData = getAllBatteryDiffData(mBatteryUsageMap);
         if (allBatteryDiffData == null) {
@@ -339,25 +396,22 @@
     }
 
     @VisibleForTesting
-    static PowerAnomalyEvent getHighestScoreAnomalyEvent(
-            Context context, PowerAnomalyEventList anomalyEventList) {
+    static PowerAnomalyEvent getAnomalyEvent(
+            PowerAnomalyEventList anomalyEventList, Predicate<PowerAnomalyEvent> predicate) {
         if (anomalyEventList == null || anomalyEventList.getPowerAnomalyEventsCount() == 0) {
             return null;
         }
-        final Set<String> dismissedPowerAnomalyKeys =
-                DatabaseUtils.getDismissedPowerAnomalyKeys(context);
-        Log.d(TAG, "dismissedPowerAnomalyKeys = " + dismissedPowerAnomalyKeys);
 
-        final PowerAnomalyEvent highestScoreEvent = anomalyEventList.getPowerAnomalyEventsList()
+        final PowerAnomalyEvent filterAnomalyEvent = anomalyEventList.getPowerAnomalyEventsList()
                 .stream()
-                .filter(event -> !dismissedPowerAnomalyKeys.contains(
-                        BatteryTipsController.getDismissRecordKey(event)))
+                .filter(predicate)
                 .max(Comparator.comparing(PowerAnomalyEvent::getScore))
                 .orElse(null);
-        Log.d(TAG, "highestScoreAnomalyEvent = " + highestScoreEvent);
-        return highestScoreEvent;
+        Log.d(TAG, "filterAnomalyEvent = " + filterAnomalyEvent);
+        return filterAnomalyEvent;
     }
 
+
     private static BatteryDiffData getAllBatteryDiffData(
             Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap) {
         return batteryUsageMap == null ? null : batteryUsageMap
diff --git a/src/com/android/settings/fuelgauge/protos/power_anomaly_event.proto b/src/com/android/settings/fuelgauge/protos/power_anomaly_event.proto
index 99df215..caa9c35 100644
--- a/src/com/android/settings/fuelgauge/protos/power_anomaly_event.proto
+++ b/src/com/android/settings/fuelgauge/protos/power_anomaly_event.proto
@@ -18,6 +18,7 @@
     WarningBannerInfo warning_banner_info = 6;
     WarningItemInfo warning_item_info = 7;
   }
+  optional string dismiss_record_key = 8;
 }
 
 // NOTE: Please DO NOT delete enum items or change enum values. Use [deprecated = true] instead.
@@ -32,11 +33,16 @@
 // NOTE: Please DO NOT delete enum items or change enum values. Use [deprecated = true] instead.
 // The enum value will be used to decide pre-defined title and button labels.
 //
-// Next id: 3
+// Next id: 8
 enum PowerAnomalyKey{
   KEY_BRIGHTNESS = 0;
   KEY_SCREEN_TIMEOUT = 1;
-  KEY_APP = 2;
+  KEY_APP_TOTAL_ALWAYS_HIGH = 2;
+  KEY_APP_TOTAL_HIGHER_THAN_USUAL = 3;
+  KEY_APP_BACKGROUND_ALWAYS_HIGH = 4;
+  KEY_APP_BACKGROUND_HIGHER_THAN_USUAL = 5;
+  KEY_APP_FOREGROUND_ALWAYS_HIGH = 6;
+  KEY_APP_FOREGROUND_HIGHER_THAN_USUAL = 7;
 }
 
 message WarningBannerInfo {
@@ -60,6 +66,5 @@
   optional string description_string = 5;
   optional string main_button_string = 6;
   optional string cancel_button_string = 7;
-  optional string dismiss_record_key = 8;
-  optional string item_key = 9;
+  optional string item_key = 8;
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapperTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapperTest.java
new file mode 100644
index 0000000..60e0af0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapperTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 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.batteryusage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+
+import com.android.settings.testutils.BatteryTestUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.TimeZone;
+
+@RunWith(RobolectricTestRunner.class)
+public class AnomalyEventWrapperTest {
+    private AnomalyEventWrapper mAnomalyEventWrapper;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
+        mContext = spy(RuntimeEnvironment.application);
+    }
+
+    @Test
+    public void getDismissRecordKey_returnExpectedResult() {
+        mAnomalyEventWrapper = new AnomalyEventWrapper(mContext,
+                BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent());
+        assertThat(mAnomalyEventWrapper.getDismissRecordKey())
+                .isEqualTo("KEY_BRIGHTNESS");
+
+        mAnomalyEventWrapper = new AnomalyEventWrapper(mContext,
+                BatteryTestUtils.createScreenTimeoutAnomalyEvent());
+        assertThat(mAnomalyEventWrapper.getDismissRecordKey())
+                .isEqualTo("KEY_SCREEN_TIMEOUT");
+
+        mAnomalyEventWrapper = new AnomalyEventWrapper(mContext,
+                BatteryTestUtils.createAppAnomalyEvent());
+        assertThat(mAnomalyEventWrapper.getDismissRecordKey())
+                .isEqualTo("KEY_APP_1");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java
index 630ff45..63cb1b3 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -58,13 +59,14 @@
     private BatteryTipsCardPreference mBatteryTipsCardPreference;
     private PowerUsageAdvanced mPowerUsageAdvanced;
     private BatteryTipsController mBatteryTipsController;
+    private BatteryChartPreferenceController mBatteryChartPreferenceController;
 
     @Mock
     private View mFakeView;
     @Mock
-    private BatteryChartPreferenceController mBatteryChartPreferenceController;
-    @Mock
     private BatteryUsageBreakdownController mBatteryUsageBreakdownController;
+    @Mock
+    private BatteryDiffEntry mFakeEntry;
 
     @Before
     public void setUp() {
@@ -73,8 +75,13 @@
         mFeatureFactory = FakeFeatureFactory.setupForTest();
         mBatteryTipsCardPreference = new BatteryTipsCardPreference(mContext, /*attrs=*/ null);
         mBatteryTipsController = new BatteryTipsController(mContext);
+        mBatteryChartPreferenceController =
+                spy(new BatteryChartPreferenceController(mContext, null, null));
+        mBatteryChartPreferenceController.mPrefContext = mContext;
         mBatteryTipsController.mCardPreference = mBatteryTipsCardPreference;
-        mPowerUsageAdvanced = new PowerUsageAdvanced();
+
+        mPowerUsageAdvanced = spy(new PowerUsageAdvanced());
+        doReturn(mContext).when(mPowerUsageAdvanced).getContext();
         mPowerUsageAdvanced.mBatteryTipsController = mBatteryTipsController;
         mPowerUsageAdvanced.mBatteryChartPreferenceController = mBatteryChartPreferenceController;
         mPowerUsageAdvanced.mBatteryUsageBreakdownController = mBatteryUsageBreakdownController;
@@ -82,6 +89,7 @@
                 1694354400000L, 1,      // 2023-09-10 22:00:00
                 1694361600000L, 2,      // 2023-09-11 00:00:00
                 1694368800000L, 3)));    // 2023-09-11 02:00:00
+        doReturn("TestEntriesKey").when(mFakeEntry).getKey();
     }
 
     @Test
@@ -99,7 +107,8 @@
         when(mFakeView.getId()).thenReturn(R.id.main_button);
         doNothing().when(mContext).startActivity(captor.capture());
 
-        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(adaptiveBrightnessAnomaly);
+        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(
+                adaptiveBrightnessAnomaly, adaptiveBrightnessAnomaly);
         mBatteryTipsCardPreference.onClick(mFakeView);
 
         assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
@@ -110,18 +119,21 @@
         assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, -1))
                 .isEqualTo(SettingsEnums.DISPLAY);
         verify(mFeatureFactory.metricsFeatureProvider).action(
+                mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, "BrightnessAnomaly");
+        verify(mFeatureFactory.metricsFeatureProvider).action(
                 mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, "BrightnessAnomaly");
     }
 
     @Test
-    public void onClick_dismissBtn_cardDismissAndLogged() {
+    public void onClick_dismissBtnOfSettingsAnomaly_cardDismissAndLogged() {
         final PowerAnomalyEvent screenTimeoutAnomaly =
                 BatteryTestUtils.createScreenTimeoutAnomalyEvent();
         DatabaseUtils.removeDismissedPowerAnomalyKeys(mContext);
         when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
         when(mFakeView.getId()).thenReturn(R.id.dismiss_button);
 
-        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(screenTimeoutAnomaly);
+        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(
+                screenTimeoutAnomaly, screenTimeoutAnomaly);
         mBatteryTipsCardPreference.onClick(mFakeView);
 
         assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
@@ -129,6 +141,8 @@
         assertThat(DatabaseUtils.getDismissedPowerAnomalyKeys(mContext))
                 .contains(PowerAnomalyKey.KEY_SCREEN_TIMEOUT.name());
         verify(mFeatureFactory.metricsFeatureProvider).action(
+                mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, "ScreenTimeoutAnomaly");
+        verify(mFeatureFactory.metricsFeatureProvider).action(
                 mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS, "ScreenTimeoutAnomaly");
     }
 
@@ -137,30 +151,40 @@
         final PowerAnomalyEvent appsAnomaly = BatteryTestUtils.createAppAnomalyEvent();
         when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
         when(mFakeView.getId()).thenReturn(R.id.main_button);
+        doNothing().when(mBatteryChartPreferenceController).selectHighlightSlotIndex();
+        when(mPowerUsageAdvanced.findRelatedBatteryDiffEntry(any())).thenReturn(mFakeEntry);
 
-        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(appsAnomaly);
+        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(appsAnomaly, appsAnomaly);
         mBatteryTipsCardPreference.onClick(mFakeView);
 
         assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
         verify(mContext, never()).startActivity(any(Intent.class));
+        verify(mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(
+                eq(1), eq(0));
         verify(mBatteryChartPreferenceController).selectHighlightSlotIndex();
         verify(mFeatureFactory.metricsFeatureProvider).action(
+                mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, "AppAnomaly");
+        verify(mFeatureFactory.metricsFeatureProvider).action(
                 mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, "AppAnomaly");
     }
 
     @Test
-    public void onClick_dismissBtnOfAppsAnomaly_removeHighlightSlotIndex() {
+    public void onClick_dismissBtnOfAppsAnomaly_keepHighlightSlotIndex() {
         final PowerAnomalyEvent appsAnomaly = BatteryTestUtils.createAppAnomalyEvent();
         when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
         when(mFakeView.getId()).thenReturn(R.id.dismiss_button);
+        when(mPowerUsageAdvanced.findRelatedBatteryDiffEntry(any())).thenReturn(mFakeEntry);
 
-        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(appsAnomaly);
+        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(appsAnomaly, appsAnomaly);
         mBatteryTipsCardPreference.onClick(mFakeView);
 
         assertThat(mBatteryTipsCardPreference.isVisible()).isFalse();
+        verify(mContext, never()).startActivity(any(Intent.class));
         verify(mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(
-                eq(BatteryChartViewModel.SELECTED_INDEX_INVALID),
-                eq(BatteryChartViewModel.SELECTED_INDEX_INVALID));
+                eq(1), eq(0));
+        verify(mBatteryChartPreferenceController, never()).selectHighlightSlotIndex();
+        verify(mFeatureFactory.metricsFeatureProvider).action(
+                mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, "AppAnomaly");
         verify(mFeatureFactory.metricsFeatureProvider).action(
                 mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS, "AppAnomaly");
     }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsControllerTest.java
index 913c00a..b8afe98 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsControllerTest.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.fuelgauge.batteryusage;
 
-import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -70,30 +68,18 @@
 
     @Test
     public void handleBatteryTipsCardUpdated_null_hidePreference() {
-        mBatteryTipsController.handleBatteryTipsCardUpdated(/* powerAnomalyEvents= */ null);
+        mBatteryTipsController.handleBatteryTipsCardUpdated(/* powerAnomalyEvents= */ null, false);
 
         verify(mBatteryTipsCardPreference).setVisible(false);
     }
 
     @Test
-    public void getDismissRecordKey_returnExpectedResult() {
-        assertThat(BatteryTipsController.getDismissRecordKey(
-                BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent()))
-                .isEqualTo("KEY_BRIGHTNESS");
-        assertThat(BatteryTipsController.getDismissRecordKey(
-                BatteryTestUtils.createScreenTimeoutAnomalyEvent()))
-                .isEqualTo("KEY_SCREEN_TIMEOUT");
-        assertThat(BatteryTipsController.getDismissRecordKey(
-                BatteryTestUtils.createAppAnomalyEvent()))
-                .isEqualTo("KEY_APP_1");
-    }
-
-    @Test
     public void handleBatteryTipsCardUpdated_adaptiveBrightnessAnomaly_showAnomaly() {
         PowerAnomalyEvent event = BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent();
         when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
 
-        mBatteryTipsController.handleBatteryTipsCardUpdated(event);
+        mBatteryTipsController.handleBatteryTipsCardUpdated(
+                new AnomalyEventWrapper(mContext, event), false);
 
         // Check pre-defined string
         verify(mBatteryTipsCardPreference).setTitle(
@@ -114,7 +100,8 @@
         PowerAnomalyEvent event = BatteryTestUtils.createScreenTimeoutAnomalyEvent();
         when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
 
-        mBatteryTipsController.handleBatteryTipsCardUpdated(event);
+        mBatteryTipsController.handleBatteryTipsCardUpdated(
+                new AnomalyEventWrapper(mContext, event), false);
 
         verify(mBatteryTipsCardPreference).setTitle("Reduce screen timeout to extend battery life");
         verify(mBatteryTipsCardPreference).setIconResourceId(R.drawable.ic_battery_tips_lightbulb);
@@ -139,7 +126,8 @@
                 .build();
         when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
 
-        mBatteryTipsController.handleBatteryTipsCardUpdated(event);
+        mBatteryTipsController.handleBatteryTipsCardUpdated(
+                new AnomalyEventWrapper(mContext, event), false);
 
         verify(mBatteryTipsCardPreference).setTitle(testTitle);
         verify(mBatteryTipsCardPreference).setIconResourceId(R.drawable.ic_battery_tips_lightbulb);
@@ -157,10 +145,13 @@
         PowerAnomalyEvent event = BatteryTestUtils.createAppAnomalyEvent();
         when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
 
-        mBatteryTipsController.handleBatteryTipsCardUpdated(event);
+        AnomalyEventWrapper eventWrapper = new AnomalyEventWrapper(mContext, event);
+        eventWrapper.setRelatedBatteryDiffEntry(
+                new BatteryDiffEntry(mContext, "", "Chrome", 0));
+        mBatteryTipsController.handleBatteryTipsCardUpdated(eventWrapper, false);
 
         verify(mBatteryTipsCardPreference).setTitle(
-                "Chrome used more battery than usual in foreground");
+                "Chrome used more battery than usual");
         verify(mBatteryTipsCardPreference).setIconResourceId(
                 R.drawable.ic_battery_tips_warning_icon);
         verify(mBatteryTipsCardPreference).setMainButtonStrokeColorResourceId(
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
index d89c06b..a721ad4 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
@@ -69,7 +69,7 @@
     @Mock
     private BatteryHistEntry mBatteryHistEntry;
     @Mock
-    private PowerGaugePreference mPowerGaugePreference;
+    private AnomalyAppItemPreference mAnomalyAppItemPreference;
 
     private Context mContext;
     private FakeFeatureFactory mFeatureFactory;
@@ -123,13 +123,14 @@
         BatteryDiffEntry.sResourceCache.put(
                 "fakeBatteryDiffEntryKey",
                 new BatteryEntry.NameAndIcon("fakeName", /*icon=*/ null, /*iconId=*/ 1));
+        doReturn(mAnomalyAppItemPreference).when(mAppListPreferenceGroup).findPreference(PREF_KEY);
     }
 
     @Test
     public void onDestroy_clearPreferenceCacheAndPreferenceGroupRemoveAll() {
         // Ensures the testing environment is correct.
         mBatteryUsageBreakdownController.mPreferenceCache.put(
-                PREF_KEY, mPowerGaugePreference);
+                PREF_KEY, mAnomalyAppItemPreference);
         assertThat(mBatteryUsageBreakdownController.mPreferenceCache).hasSize(1);
 
         mBatteryUsageBreakdownController.onDestroy();
@@ -178,7 +179,6 @@
         doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
         doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
         doReturn(PREF_KEY).when(mBatteryDiffEntry).getKey();
-        doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).findPreference(PREF_KEY);
 
         mBatteryUsageBreakdownController.addAllPreferences();
 
@@ -188,27 +188,25 @@
     @Test
     public void removeAndCacheAllUnusedPreferences_removePref_buildCacheAndRemoveAllPreference() {
         doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount();
-        doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).getPreference(0);
+        doReturn(mAnomalyAppItemPreference).when(mAppListPreferenceGroup).getPreference(0);
         doReturn(PREF_KEY2).when(mBatteryHistEntry).getKey();
-        doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
-        doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).findPreference(PREF_KEY);
+        doReturn(PREF_KEY).when(mAnomalyAppItemPreference).getKey();
         // Ensures the testing data is correct.
         assertThat(mBatteryUsageBreakdownController.mPreferenceCache).isEmpty();
 
         mBatteryUsageBreakdownController.removeAndCacheAllUnusedPreferences();
 
         assertThat(mBatteryUsageBreakdownController.mPreferenceCache.get(PREF_KEY))
-                .isEqualTo(mPowerGaugePreference);
-        verify(mAppListPreferenceGroup).removePreference(mPowerGaugePreference);
+                .isEqualTo(mAnomalyAppItemPreference);
+        verify(mAppListPreferenceGroup).removePreference(mAnomalyAppItemPreference);
     }
 
     @Test
     public void removeAndCacheAllUnusedPreferences_keepPref_KeepAllPreference() {
         doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount();
-        doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).getPreference(0);
+        doReturn(mAnomalyAppItemPreference).when(mAppListPreferenceGroup).getPreference(0);
         doReturn(PREF_KEY).when(mBatteryDiffEntry).getKey();
-        doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
-        doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).findPreference(PREF_KEY);
+        doReturn(PREF_KEY).when(mAnomalyAppItemPreference).getKey();
         // Ensures the testing data is correct.
         assertThat(mBatteryUsageBreakdownController.mPreferenceCache).isEmpty();
 
@@ -232,10 +230,10 @@
     @Test
     public void handlePreferenceTreeClick_forAppEntry_returnTrue() {
         mBatteryDiffEntry.mConsumerType = ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY;
-        doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
+        doReturn(mBatteryDiffEntry).when(mAnomalyAppItemPreference).getBatteryDiffEntry();
 
         assertThat(mBatteryUsageBreakdownController.handlePreferenceTreeClick(
-                mPowerGaugePreference)).isTrue();
+                mAnomalyAppItemPreference)).isTrue();
         verify(mMetricsFeatureProvider)
                 .action(
                         SettingsEnums.OPEN_BATTERY_USAGE,
@@ -248,10 +246,10 @@
     @Test
     public void handlePreferenceTreeClick_forSystemEntry_returnTrue() {
         mBatteryDiffEntry.mConsumerType = ConvertUtils.CONSUMER_TYPE_UID_BATTERY;
-        doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
+        doReturn(mBatteryDiffEntry).when(mAnomalyAppItemPreference).getBatteryDiffEntry();
 
         assertThat(mBatteryUsageBreakdownController.handlePreferenceTreeClick(
-                mPowerGaugePreference)).isTrue();
+                mAnomalyAppItemPreference)).isTrue();
         verify(mMetricsFeatureProvider)
                 .action(
                         SettingsEnums.OPEN_BATTERY_USAGE,
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
index f06dc63..cd594d3 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
@@ -72,6 +72,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
         mContext = spy(RuntimeEnvironment.application);
         ConvertUtils.sUsageSource = ConvertUtils.EMPTY_USAGE_SOURCE;
         when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvancedTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvancedTest.java
index 953c2d4..9753bd2 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvancedTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvancedTest.java
@@ -20,8 +20,8 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.ArgumentMatchers.notNull;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
@@ -41,7 +41,9 @@
 
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.TimeZone;
+import java.util.function.Predicate;
 
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = ShadowDashboardFragment.class)
@@ -50,6 +52,9 @@
     private Context mContext;
     private PowerUsageAdvanced mPowerUsageAdvanced;
 
+    private Predicate<PowerAnomalyEvent> mCardFilterPredicate;
+    private Predicate<PowerAnomalyEvent> mSlotFilterPredicate;
+
     @Mock
     private BatteryTipsController mBatteryTipsController;
     @Mock
@@ -65,7 +70,7 @@
         TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
         mContext = spy(RuntimeEnvironment.application);
 
-        mPowerUsageAdvanced = new PowerUsageAdvanced();
+        mPowerUsageAdvanced = spy(new PowerUsageAdvanced());
         mPowerUsageAdvanced.mBatteryTipsController = mBatteryTipsController;
         mPowerUsageAdvanced.mBatteryChartPreferenceController = mBatteryChartPreferenceController;
         mPowerUsageAdvanced.mScreenOnTimeController = mScreenOnTimeController;
@@ -74,43 +79,63 @@
                 1694354400000L, 1,      // 2023-09-10 22:00:00
                 1694361600000L, 2,      // 2023-09-11 00:00:00
                 1694368800000L, 3)));    // 2023-09-11 02:00:00
+        doReturn(mContext).when(mPowerUsageAdvanced).getContext();
+        mSlotFilterPredicate = PowerAnomalyEvent::hasWarningItemInfo;
     }
 
     @Test
-    public void getHighestScoreAnomalyEvent_withEmptyOrNullList_getNull() {
-        assertThat(PowerUsageAdvanced.getHighestScoreAnomalyEvent(mContext, null)).isNull();
-        assertThat(PowerUsageAdvanced.getHighestScoreAnomalyEvent(
-                mContext, BatteryTestUtils.createEmptyPowerAnomalyEventList())).isNull();
+    public void getFilterAnomalyEvent_withEmptyOrNullList_getNull() {
+        prepareCardFilterPredicate(null);
+        assertThat(PowerUsageAdvanced
+                .getAnomalyEvent(null, mCardFilterPredicate)).isNull();
+        assertThat(PowerUsageAdvanced
+                .getAnomalyEvent(null, mSlotFilterPredicate)).isNull();
+        assertThat(PowerUsageAdvanced.getAnomalyEvent(
+                BatteryTestUtils.createEmptyPowerAnomalyEventList(), mCardFilterPredicate))
+                .isNull();
+        assertThat(PowerUsageAdvanced.getAnomalyEvent(
+                BatteryTestUtils.createEmptyPowerAnomalyEventList(), mSlotFilterPredicate))
+                .isNull();
     }
 
     @Test
-    public void getHighestScoreAnomalyEvent_withoutDismissed_getHighestScoreEvent() {
+    public void getFilterAnomalyEvent_withoutDismissed_getHighestScoreEvent() {
         final PowerAnomalyEventList powerAnomalyEventList =
                 BatteryTestUtils.createNonEmptyPowerAnomalyEventList();
 
-        final PowerAnomalyEvent highestScoreEvent =
-                PowerUsageAdvanced.getHighestScoreAnomalyEvent(mContext, powerAnomalyEventList);
+        final PowerAnomalyEvent slotEvent =
+                PowerUsageAdvanced.getAnomalyEvent(powerAnomalyEventList,
+                        mSlotFilterPredicate);
+        prepareCardFilterPredicate(slotEvent);
+        final PowerAnomalyEvent cardEvent =
+                PowerUsageAdvanced.getAnomalyEvent(powerAnomalyEventList,
+                        mCardFilterPredicate);
 
-        assertThat(highestScoreEvent)
-                .isEqualTo(BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent());
+        assertThat(cardEvent).isEqualTo(BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent());
+        assertThat(slotEvent).isNull();
     }
 
     @Test
-    public void getHighestScoreAnomalyEvent_withBrightnessDismissed_getScreenTimeout() {
+    public void getFilterAnomalyEvent_withBrightnessDismissed_getScreenTimeout() {
         final PowerAnomalyEventList powerAnomalyEventList =
                 BatteryTestUtils.createNonEmptyPowerAnomalyEventList();
         DatabaseUtils.removeDismissedPowerAnomalyKeys(mContext);
         DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, PowerAnomalyKey.KEY_BRIGHTNESS.name());
 
-        final PowerAnomalyEvent highestScoreEvent =
-                PowerUsageAdvanced.getHighestScoreAnomalyEvent(mContext, powerAnomalyEventList);
+        final PowerAnomalyEvent slotEvent =
+                PowerUsageAdvanced.getAnomalyEvent(powerAnomalyEventList,
+                        mSlotFilterPredicate);
+        prepareCardFilterPredicate(slotEvent);
+        final PowerAnomalyEvent cardEvent =
+                PowerUsageAdvanced.getAnomalyEvent(powerAnomalyEventList,
+                        mCardFilterPredicate);
 
-        assertThat(highestScoreEvent)
-                .isEqualTo(BatteryTestUtils.createScreenTimeoutAnomalyEvent());
+        assertThat(cardEvent).isEqualTo(BatteryTestUtils.createScreenTimeoutAnomalyEvent());
+        assertThat(slotEvent).isNull();
     }
 
     @Test
-    public void getHighestScoreAnomalyEvent_withAllDismissed_getNull() {
+    public void getFilterAnomalyEvent_withAllDismissed_getNull() {
         final PowerAnomalyEventList powerAnomalyEventList =
                 BatteryTestUtils.createNonEmptyPowerAnomalyEventList();
         DatabaseUtils.removeDismissedPowerAnomalyKeys(mContext);
@@ -118,20 +143,26 @@
             DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, key.name());
         }
 
-        final PowerAnomalyEvent highestScoreEvent =
-                PowerUsageAdvanced.getHighestScoreAnomalyEvent(mContext, powerAnomalyEventList);
+        final PowerAnomalyEvent slotEvent =
+                PowerUsageAdvanced.getAnomalyEvent(powerAnomalyEventList,
+                        mSlotFilterPredicate);
+        prepareCardFilterPredicate(slotEvent);
+        final PowerAnomalyEvent cardEvent =
+                PowerUsageAdvanced.getAnomalyEvent(powerAnomalyEventList,
+                        mCardFilterPredicate);
 
-        assertThat(highestScoreEvent).isNull();
+        assertThat(cardEvent).isNull();
+        assertThat(slotEvent).isNull();
     }
 
     @Test
     public void onDisplayAnomalyEventUpdated_withSettingsAnomalyEvent_skipHighlightSlotEffect() {
         final PowerAnomalyEvent event = BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent();
 
-        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(event);
+        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(event, event);
 
-        assertThat(mPowerUsageAdvanced.mPowerAnomalyEvent).isEqualTo(event);
-        verify(mBatteryTipsController).handleBatteryTipsCardUpdated(eq(event));
+        assertThat(mPowerUsageAdvanced.mHighlightEventWrapper.get().getEventId())
+                .isEqualTo(event.getEventId());
         verify(mPowerUsageAdvanced.mBatteryTipsController).setOnAnomalyConfirmListener(isNull());
         verify(mPowerUsageAdvanced.mBatteryTipsController).setOnAnomalyRejectListener(isNull());
         verify(mPowerUsageAdvanced.mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(
@@ -140,46 +171,44 @@
     }
 
     @Test
-    public void onDisplayAnomalyEventUpdated_withAppAnomalyEvent_setHighlightSlotEffect() {
+    public void onDisplayAnomalyEventUpdated_onlyAppAnomalyEvent_setHighlightSlotEffect() {
         final PowerAnomalyEvent event = BatteryTestUtils.createAppAnomalyEvent();
 
-        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(event);
+        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(event, event);
 
-        assertThat(mPowerUsageAdvanced.mPowerAnomalyEvent).isEqualTo(event);
-        verify(mBatteryTipsController).handleBatteryTipsCardUpdated(eq(event));
+        assertThat(mPowerUsageAdvanced.mHighlightEventWrapper.get().getEventId())
+                .isEqualTo(event.getEventId());
         verify(mBatteryTipsController).setOnAnomalyConfirmListener(isNull());
         verify(mBatteryTipsController).setOnAnomalyRejectListener(isNull());
-
-        assertThat(event.getWarningItemInfo().hasStartTimestamp()).isTrue();
-        assertThat(event.getWarningItemInfo().hasEndTimestamp()).isTrue();
         assertThat(mPowerUsageAdvanced.mBatteryLevelData.get().getIndexByTimestamps(
                 event.getWarningItemInfo().getStartTimestamp(),
                 event.getWarningItemInfo().getEndTimestamp()
         )).isEqualTo(Pair.create(1, 0));
         verify(mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(eq(1), eq(0));
         verify(mBatteryTipsController).setOnAnomalyConfirmListener(notNull());
-        verify(mBatteryTipsController).setOnAnomalyRejectListener(notNull());
     }
 
     @Test
-    public void onDisplayAnomalyEventUpdated_withNull_removeHighlightSlotEffect() {
-        final PowerAnomalyEvent event = BatteryTestUtils.createAppAnomalyEvent();
+    public void onDisplayAnomalyEventUpdated_withSettingsCardAndAppsSlotEvent_showExpected() {
+        final PowerAnomalyEvent settingsEvent =
+                BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent();
+        final PowerAnomalyEvent appsEvent =
+                BatteryTestUtils.createAppAnomalyEvent();
 
-        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(event);
-        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(null);
+        mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(settingsEvent, appsEvent);
 
-        assertThat(mPowerUsageAdvanced.mPowerAnomalyEvent).isNull();
-        verify(mBatteryTipsController, times(2))
-                .setOnAnomalyConfirmListener(isNull());
-        verify(mBatteryTipsController, times(2))
-                .setOnAnomalyRejectListener(isNull());
-        verify(mBatteryTipsController).setOnAnomalyConfirmListener(notNull());
-        verify(mBatteryTipsController).setOnAnomalyRejectListener(notNull());
-
-        verify(mBatteryChartPreferenceController)
-                .onHighlightSlotIndexUpdate(eq(1), eq(0));
-        verify(mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(
-                eq(BatteryChartViewModel.SELECTED_INDEX_INVALID),
-                eq(BatteryChartViewModel.SELECTED_INDEX_INVALID));
+        assertThat(mPowerUsageAdvanced.mHighlightEventWrapper.get().getEventId())
+                .isEqualTo(appsEvent.getEventId());
+        verify(mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(eq(1), eq(0));
+        verify(mBatteryTipsController).setOnAnomalyConfirmListener(isNull());
+        verify(mBatteryTipsController).setOnAnomalyRejectListener(isNull());
     }
-}
+
+    private void prepareCardFilterPredicate(PowerAnomalyEvent slotEvent) {
+        final Set<String> dismissedPowerAnomalyKeys =
+                DatabaseUtils.getDismissedPowerAnomalyKeys(mContext);
+        mCardFilterPredicate = event -> !dismissedPowerAnomalyKeys.contains(
+                event.getDismissRecordKey())
+                && (event.equals(slotEvent) || !event.hasWarningItemInfo());
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
index 1035560..e98ea1b 100644
--- a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
@@ -247,6 +247,7 @@
                 .setEventId("BrightnessAnomaly")
                 .setType(PowerAnomalyType.TYPE_SETTINGS_BANNER)
                 .setKey(PowerAnomalyKey.KEY_BRIGHTNESS)
+                .setDismissRecordKey(PowerAnomalyKey.KEY_BRIGHTNESS.name())
                 .setScore(1.2f)
                 .setWarningBannerInfo(WarningBannerInfo.newBuilder()
                         .setMainButtonDestination(DisplaySettings.class.getName())
@@ -264,6 +265,7 @@
                 .setEventId("ScreenTimeoutAnomaly")
                 .setType(PowerAnomalyType.TYPE_SETTINGS_BANNER)
                 .setKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT)
+                .setDismissRecordKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT.name())
                 .setScore(1.1f)
                 .setWarningBannerInfo(WarningBannerInfo.newBuilder()
                         .setMainButtonDestination(ScreenTimeoutSettings.class.getName())
@@ -280,15 +282,12 @@
         return PowerAnomalyEvent.newBuilder()
                 .setEventId("AppAnomaly")
                 .setType(PowerAnomalyType.TYPE_APPS_ITEM)
-                .setKey(PowerAnomalyKey.KEY_APP)
+                .setKey(PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL)
+                .setDismissRecordKey("KEY_APP_1")
                 .setScore(2.0f)
                 .setWarningItemInfo(WarningItemInfo.newBuilder()
-                        .setDismissRecordKey("KEY_APP_1")
                         .setStartTimestamp(1694361600000L)  // 2023-09-11 00:00:00
                         .setEndTimestamp(1694368800000L)    // 2023-09-11 02:00:00
-                        .setTitleString("Chrome used more battery than usual in foreground")
-                        .setMainButtonString("Check")
-                        .setCancelButtonString("Got it")
                         .build())
                 .build();
     }