1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.fuelgauge.batteryusage; 18 19 import android.app.settings.SettingsEnums; 20 import android.content.Context; 21 import android.text.TextUtils; 22 23 import androidx.preference.PreferenceScreen; 24 25 import com.android.internal.annotations.VisibleForTesting; 26 import com.android.settings.core.BasePreferenceController; 27 import com.android.settings.overlay.FeatureFactory; 28 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 29 import com.android.settingslib.widget.BannerMessagePreference; 30 31 /** Controls the update for battery tips card */ 32 public class BatteryTipsController extends BasePreferenceController { 33 34 private static final String TAG = "BatteryTipsController"; 35 private static final String PREFERENCE_KEY = "battery_tips_card"; 36 37 @VisibleForTesting static final String ANOMALY_KEY = "anomaly_key"; 38 39 private final MetricsFeatureProvider mMetricsFeatureProvider; 40 41 /** A callback listener for the battery tips is confirmed. */ 42 interface OnAnomalyConfirmListener { 43 /** The callback function for the battery tips is confirmed. */ onAnomalyConfirm()44 void onAnomalyConfirm(); 45 } 46 47 /** A callback listener for the battery tips is rejected. */ 48 interface OnAnomalyRejectListener { 49 /** The callback function for the battery tips is rejected. */ onAnomalyReject()50 void onAnomalyReject(); 51 } 52 53 @VisibleForTesting OnAnomalyConfirmListener mOnAnomalyConfirmListener; 54 @VisibleForTesting OnAnomalyRejectListener mOnAnomalyRejectListener; 55 @VisibleForTesting BannerMessagePreference mCardPreference; 56 @VisibleForTesting AnomalyEventWrapper mAnomalyEventWrapper = null; 57 @VisibleForTesting Boolean mIsAcceptable = false; 58 BatteryTipsController(Context context)59 public BatteryTipsController(Context context) { 60 super(context, PREFERENCE_KEY); 61 final FeatureFactory featureFactory = FeatureFactory.getFeatureFactory(); 62 mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider(); 63 } 64 65 @Override getAvailabilityStatus()66 public int getAvailabilityStatus() { 67 return AVAILABLE; 68 } 69 70 @Override displayPreference(PreferenceScreen screen)71 public void displayPreference(PreferenceScreen screen) { 72 super.displayPreference(screen); 73 mCardPreference = screen.findPreference(PREFERENCE_KEY); 74 75 // Set preference as invisible since there is no default tips. 76 mCardPreference.setVisible(false); 77 } 78 setOnAnomalyConfirmListener(OnAnomalyConfirmListener listener)79 void setOnAnomalyConfirmListener(OnAnomalyConfirmListener listener) { 80 mOnAnomalyConfirmListener = listener; 81 } 82 setOnAnomalyRejectListener(OnAnomalyRejectListener listener)83 void setOnAnomalyRejectListener(OnAnomalyRejectListener listener) { 84 mOnAnomalyRejectListener = listener; 85 } 86 acceptTipsCard()87 void acceptTipsCard() { 88 if (mAnomalyEventWrapper == null || !mIsAcceptable) { 89 return; 90 } 91 // For anomaly events with same record key, dismissed until next time full charged. 92 final String dismissRecordKey = mAnomalyEventWrapper.getDismissRecordKey(); 93 if (!TextUtils.isEmpty(dismissRecordKey)) { 94 DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, dismissRecordKey); 95 } 96 mCardPreference.setVisible(false); 97 mMetricsFeatureProvider.action( 98 /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 99 /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, 100 /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 101 /* key= */ ANOMALY_KEY, 102 /* value= */ mAnomalyEventWrapper.getAnomalyKeyNumber()); 103 } 104 handleBatteryTipsCardUpdated( AnomalyEventWrapper anomalyEventWrapper, boolean isAcceptable)105 void handleBatteryTipsCardUpdated( 106 AnomalyEventWrapper anomalyEventWrapper, boolean isAcceptable) { 107 mAnomalyEventWrapper = anomalyEventWrapper; 108 mIsAcceptable = isAcceptable; 109 if (mAnomalyEventWrapper == null) { 110 mCardPreference.setVisible(false); 111 return; 112 } 113 114 final int anomalyKeyNumber = mAnomalyEventWrapper.getAnomalyKeyNumber(); 115 116 // Update card & buttons preference 117 if (!mAnomalyEventWrapper.updateTipsCardPreference(mCardPreference)) { 118 mCardPreference.setVisible(false); 119 return; 120 } 121 122 mCardPreference.setNegativeButtonOnClickListener( 123 view -> onBatteryTipsCardDismiss(anomalyKeyNumber)); 124 mCardPreference.setPositiveButtonOnClickListener( 125 view -> onBatteryTipsCardAccept(anomalyKeyNumber)); 126 127 mCardPreference.setPositiveButtonVisible(true); 128 mCardPreference.setNegativeButtonVisible(true); 129 mCardPreference.setVisible(true); 130 mMetricsFeatureProvider.action( 131 /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 132 /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, 133 /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 134 /* key= */ ANOMALY_KEY, 135 /* value= */ anomalyKeyNumber); 136 } 137 onBatteryTipsCardDismiss(final int anomalyKeyNumber)138 private void onBatteryTipsCardDismiss(final int anomalyKeyNumber) { 139 mCardPreference.setVisible(false); 140 if (mOnAnomalyRejectListener != null) { 141 mOnAnomalyRejectListener.onAnomalyReject(); 142 } 143 // For anomaly events with same record key, dismissed until next time full charged. 144 final String dismissRecordKey = mAnomalyEventWrapper.getDismissRecordKey(); 145 if (!TextUtils.isEmpty(dismissRecordKey)) { 146 DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, dismissRecordKey); 147 } 148 mMetricsFeatureProvider.action( 149 /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 150 /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS, 151 /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 152 /* key= */ ANOMALY_KEY, 153 /* value= */ anomalyKeyNumber); 154 } 155 onBatteryTipsCardAccept(final int anomalyKeyNumber)156 private void onBatteryTipsCardAccept(final int anomalyKeyNumber) { 157 mCardPreference.setVisible(false); 158 if (mOnAnomalyConfirmListener != null) { 159 mOnAnomalyConfirmListener.onAnomalyConfirm(); 160 } else if (mAnomalyEventWrapper.updateSystemSettingsIfAvailable() 161 || mAnomalyEventWrapper.launchSubSetting()) { 162 mMetricsFeatureProvider.action( 163 /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 164 /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, 165 /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 166 /* key= */ ANOMALY_KEY, 167 /* value= */ anomalyKeyNumber); 168 } 169 } 170 } 171