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 30 /** Controls the update for battery tips card */ 31 public class BatteryTipsController extends BasePreferenceController { 32 33 private static final String TAG = "BatteryTipsController"; 34 private static final String ROOT_PREFERENCE_KEY = "battery_tips_category"; 35 private static final String CARD_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 private OnAnomalyConfirmListener mOnAnomalyConfirmListener; 54 private OnAnomalyRejectListener mOnAnomalyRejectListener; 55 56 @VisibleForTesting BatteryTipsCardPreference mCardPreference; 57 @VisibleForTesting AnomalyEventWrapper mAnomalyEventWrapper = null; 58 @VisibleForTesting Boolean mIsAcceptable = false; 59 BatteryTipsController(Context context)60 public BatteryTipsController(Context context) { 61 super(context, ROOT_PREFERENCE_KEY); 62 final FeatureFactory featureFactory = FeatureFactory.getFeatureFactory(); 63 mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider(); 64 } 65 66 @Override getAvailabilityStatus()67 public int getAvailabilityStatus() { 68 return AVAILABLE; 69 } 70 71 @Override displayPreference(PreferenceScreen screen)72 public void displayPreference(PreferenceScreen screen) { 73 super.displayPreference(screen); 74 mCardPreference = screen.findPreference(CARD_PREFERENCE_KEY); 75 } 76 setOnAnomalyConfirmListener(OnAnomalyConfirmListener listener)77 void setOnAnomalyConfirmListener(OnAnomalyConfirmListener listener) { 78 mOnAnomalyConfirmListener = listener; 79 } 80 setOnAnomalyRejectListener(OnAnomalyRejectListener listener)81 void setOnAnomalyRejectListener(OnAnomalyRejectListener listener) { 82 mOnAnomalyRejectListener = listener; 83 } 84 acceptTipsCard()85 void acceptTipsCard() { 86 if (mAnomalyEventWrapper == null || !mIsAcceptable) { 87 return; 88 } 89 // For anomaly events with same record key, dismissed until next time full charged. 90 final String dismissRecordKey = mAnomalyEventWrapper.getDismissRecordKey(); 91 if (!TextUtils.isEmpty(dismissRecordKey)) { 92 DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, dismissRecordKey); 93 } 94 mCardPreference.setVisible(false); 95 mMetricsFeatureProvider.action( 96 /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 97 /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, 98 /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 99 /* key= */ ANOMALY_KEY, 100 /* value= */ mAnomalyEventWrapper.getAnomalyKeyNumber()); 101 } 102 handleBatteryTipsCardUpdated( AnomalyEventWrapper anomalyEventWrapper, boolean isAcceptable)103 void handleBatteryTipsCardUpdated( 104 AnomalyEventWrapper anomalyEventWrapper, boolean isAcceptable) { 105 mAnomalyEventWrapper = anomalyEventWrapper; 106 mIsAcceptable = isAcceptable; 107 if (mAnomalyEventWrapper == null) { 108 mCardPreference.setVisible(false); 109 return; 110 } 111 112 final int anomalyKeyNumber = mAnomalyEventWrapper.getAnomalyKeyNumber(); 113 114 // Update card & buttons preference 115 if (!mAnomalyEventWrapper.updateTipsCardPreference(mCardPreference)) { 116 mCardPreference.setVisible(false); 117 return; 118 } 119 120 // Set battery tips card listener 121 mCardPreference.setOnConfirmListener( 122 () -> { 123 mCardPreference.setVisible(false); 124 if (mOnAnomalyConfirmListener != null) { 125 mOnAnomalyConfirmListener.onAnomalyConfirm(); 126 } else if (mAnomalyEventWrapper.updateSystemSettingsIfAvailable() 127 || mAnomalyEventWrapper.launchSubSetting()) { 128 mMetricsFeatureProvider.action( 129 /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 130 /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, 131 /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 132 /* key= */ ANOMALY_KEY, 133 /* value= */ anomalyKeyNumber); 134 } 135 }); 136 mCardPreference.setOnRejectListener( 137 () -> { 138 mCardPreference.setVisible(false); 139 if (mOnAnomalyRejectListener != null) { 140 mOnAnomalyRejectListener.onAnomalyReject(); 141 } 142 // For anomaly events with same record key, dismissed until next time full 143 // 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 156 mCardPreference.setVisible(true); 157 mMetricsFeatureProvider.action( 158 /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 159 /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, 160 /* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, 161 /* key= */ ANOMALY_KEY, 162 /* value= */ anomalyKeyNumber); 163 } 164 } 165