1 /* 2 * Copyright (C) 2017 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.batterytip.tips; 18 19 import android.content.Context; 20 import android.os.Parcel; 21 import android.os.Parcelable; 22 import android.util.SparseIntArray; 23 24 import androidx.annotation.DrawableRes; 25 import androidx.annotation.IntDef; 26 import androidx.annotation.Nullable; 27 import androidx.annotation.VisibleForTesting; 28 import androidx.preference.Preference; 29 30 import com.android.settings.widget.TipCardPreference; 31 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 32 33 import java.lang.annotation.Retention; 34 import java.lang.annotation.RetentionPolicy; 35 36 /** 37 * Base model for a battery tip(e.g. suggest user to turn on battery saver) 38 * 39 * <p>Each {@link BatteryTip} contains basic data(e.g. title, summary, icon) as well as the 40 * pre-defined action(e.g. turn on battery saver) 41 */ 42 public abstract class BatteryTip implements Comparable<BatteryTip>, Parcelable { 43 44 @Retention(RetentionPolicy.SOURCE) 45 @IntDef({StateType.NEW, StateType.HANDLED, StateType.INVISIBLE}) 46 public @interface StateType { 47 48 int NEW = 0; 49 int HANDLED = 1; 50 int INVISIBLE = 2; 51 } 52 53 @Retention(RetentionPolicy.SOURCE) 54 @IntDef({ 55 TipType.SUMMARY, 56 TipType.BATTERY_SAVER, 57 TipType.HIGH_DEVICE_USAGE, 58 TipType.SMART_BATTERY_MANAGER, 59 TipType.APP_RESTRICTION, 60 TipType.REDUCED_BATTERY, 61 TipType.LOW_BATTERY, 62 TipType.REMOVE_APP_RESTRICTION, 63 TipType.BATTERY_DEFENDER, 64 TipType.DOCK_DEFENDER, 65 TipType.INCOMPATIBLE_CHARGER, 66 TipType.BATTERY_WARNING 67 }) 68 public @interface TipType { 69 int SMART_BATTERY_MANAGER = 0; 70 int APP_RESTRICTION = 1; 71 int HIGH_DEVICE_USAGE = 2; 72 int BATTERY_SAVER = 3; 73 int REDUCED_BATTERY = 4; 74 int LOW_BATTERY = 5; 75 int SUMMARY = 6; 76 int REMOVE_APP_RESTRICTION = 7; 77 int BATTERY_DEFENDER = 8; 78 int DOCK_DEFENDER = 9; 79 int INCOMPATIBLE_CHARGER = 10; 80 int BATTERY_WARNING = 11; 81 } 82 83 @VisibleForTesting static final SparseIntArray TIP_ORDER; 84 85 static { 86 TIP_ORDER = new SparseIntArray(); TIP_ORDER.append(TipType.BATTERY_SAVER, 0)87 TIP_ORDER.append(TipType.BATTERY_SAVER, 0); TIP_ORDER.append(TipType.LOW_BATTERY, 1)88 TIP_ORDER.append(TipType.LOW_BATTERY, 1); TIP_ORDER.append(TipType.BATTERY_DEFENDER, 2)89 TIP_ORDER.append(TipType.BATTERY_DEFENDER, 2); TIP_ORDER.append(TipType.DOCK_DEFENDER, 3)90 TIP_ORDER.append(TipType.DOCK_DEFENDER, 3); TIP_ORDER.append(TipType.INCOMPATIBLE_CHARGER, 4)91 TIP_ORDER.append(TipType.INCOMPATIBLE_CHARGER, 4); TIP_ORDER.append(TipType.APP_RESTRICTION, 5)92 TIP_ORDER.append(TipType.APP_RESTRICTION, 5); TIP_ORDER.append(TipType.HIGH_DEVICE_USAGE, 6)93 TIP_ORDER.append(TipType.HIGH_DEVICE_USAGE, 6); TIP_ORDER.append(TipType.SUMMARY, 7)94 TIP_ORDER.append(TipType.SUMMARY, 7); TIP_ORDER.append(TipType.SMART_BATTERY_MANAGER, 8)95 TIP_ORDER.append(TipType.SMART_BATTERY_MANAGER, 8); TIP_ORDER.append(TipType.REDUCED_BATTERY, 9)96 TIP_ORDER.append(TipType.REDUCED_BATTERY, 9); TIP_ORDER.append(TipType.REMOVE_APP_RESTRICTION, 10)97 TIP_ORDER.append(TipType.REMOVE_APP_RESTRICTION, 10); TIP_ORDER.append(TipType.BATTERY_WARNING, 11)98 TIP_ORDER.append(TipType.BATTERY_WARNING, 11); 99 } 100 101 private static final String KEY_PREFIX = "key_battery_tip"; 102 103 protected int mState; 104 protected int mType; 105 protected boolean mShowDialog; 106 107 /** Whether we need to update battery tip when configuration change */ 108 protected boolean mNeedUpdate; 109 BatteryTip(Parcel in)110 public BatteryTip(Parcel in) { 111 mType = in.readInt(); 112 mState = in.readInt(); 113 mShowDialog = in.readBoolean(); 114 mNeedUpdate = in.readBoolean(); 115 } 116 BatteryTip(int type, int state, boolean showDialog)117 public BatteryTip(int type, int state, boolean showDialog) { 118 mType = type; 119 mState = state; 120 mShowDialog = showDialog; 121 mNeedUpdate = true; 122 } 123 124 @Override describeContents()125 public int describeContents() { 126 return 0; 127 } 128 129 @Override writeToParcel(Parcel dest, int flags)130 public void writeToParcel(Parcel dest, int flags) { 131 dest.writeInt(mType); 132 dest.writeInt(mState); 133 dest.writeBoolean(mShowDialog); 134 dest.writeBoolean(mNeedUpdate); 135 } 136 getTitle(Context context)137 public abstract CharSequence getTitle(Context context); 138 getSummary(Context context)139 public abstract CharSequence getSummary(Context context); 140 141 /** Gets the drawable resource id for the icon. */ 142 @DrawableRes getIconId()143 public abstract int getIconId(); 144 145 /** 146 * Update the current {@link #mState} using the new {@code tip}. 147 * 148 * @param tip used to update 149 */ updateState(BatteryTip tip)150 public abstract void updateState(BatteryTip tip); 151 152 /** 153 * Check whether data is still make sense. If not, try recover. 154 * 155 * @param context used to do validate check 156 */ validateCheck(Context context)157 public void validateCheck(Context context) { 158 // do nothing 159 } 160 161 /** Log the battery tip */ log(Context context, MetricsFeatureProvider metricsFeatureProvider)162 public abstract void log(Context context, MetricsFeatureProvider metricsFeatureProvider); 163 updatePreference(Preference preference)164 public void updatePreference(Preference preference) { 165 final Context context = preference.getContext(); 166 preference.setTitle(getTitle(context)); 167 preference.setSummary(getSummary(context)); 168 preference.setIcon(getIconId()); 169 final TipCardPreference cardPreference = castToTipCardPreferenceSafely(preference); 170 if (cardPreference != null) { 171 cardPreference.resetLayoutState(); 172 } 173 } 174 shouldShowDialog()175 public boolean shouldShowDialog() { 176 return mShowDialog; 177 } 178 needUpdate()179 public boolean needUpdate() { 180 return mNeedUpdate; 181 } 182 getKey()183 public String getKey() { 184 return KEY_PREFIX + mType; 185 } 186 getType()187 public int getType() { 188 return mType; 189 } 190 191 @StateType getState()192 public int getState() { 193 return mState; 194 } 195 isVisible()196 public boolean isVisible() { 197 return mState != StateType.INVISIBLE; 198 } 199 200 @Override compareTo(BatteryTip o)201 public int compareTo(BatteryTip o) { 202 return TIP_ORDER.get(mType) - TIP_ORDER.get(o.mType); 203 } 204 205 @Override toString()206 public String toString() { 207 return "type=" + mType + " state=" + mState; 208 } 209 210 /** Returns the converted {@link TipCardPreference} if it is valid. */ 211 @Nullable castToTipCardPreferenceSafely(Preference preference)212 public TipCardPreference castToTipCardPreferenceSafely(Preference preference) { 213 return preference instanceof TipCardPreference ? (TipCardPreference) preference : null; 214 } 215 } 216