1 /* 2 * Copyright (C) 2018 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.app.settings.SettingsEnums; 20 import android.content.Context; 21 import android.content.res.Resources; 22 import android.icu.text.ListFormatter; 23 import android.os.Parcel; 24 25 import androidx.annotation.VisibleForTesting; 26 27 import com.android.settings.R; 28 import com.android.settings.Utils; 29 import com.android.settings.fuelgauge.batterytip.AppInfo; 30 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 31 import com.android.settingslib.utils.StringUtil; 32 33 import java.util.ArrayList; 34 import java.util.HashMap; 35 import java.util.List; 36 import java.util.Map; 37 38 /** 39 * Tip to suggest user to restrict some bad apps 40 */ 41 public class RestrictAppTip extends BatteryTip { 42 private List<AppInfo> mRestrictAppList; 43 RestrictAppTip(@tateType int state, List<AppInfo> restrictApps)44 public RestrictAppTip(@StateType int state, List<AppInfo> restrictApps) { 45 super(TipType.APP_RESTRICTION, state, state == StateType.NEW /* showDialog */); 46 mRestrictAppList = restrictApps; 47 mNeedUpdate = false; 48 } 49 RestrictAppTip(@tateType int state, AppInfo appInfo)50 public RestrictAppTip(@StateType int state, AppInfo appInfo) { 51 super(TipType.APP_RESTRICTION, state, state == StateType.NEW /* showDialog */); 52 mRestrictAppList = new ArrayList<>(); 53 mRestrictAppList.add(appInfo); 54 mNeedUpdate = false; 55 } 56 57 @VisibleForTesting RestrictAppTip(Parcel in)58 RestrictAppTip(Parcel in) { 59 super(in); 60 mRestrictAppList = in.createTypedArrayList(AppInfo.CREATOR); 61 } 62 63 @Override getTitle(Context context)64 public CharSequence getTitle(Context context) { 65 final int num = mRestrictAppList.size(); 66 final CharSequence appLabel = num > 0 ? Utils.getApplicationLabel(context, 67 mRestrictAppList.get(0).packageName) : ""; 68 69 Map<String, Object> arguments = new HashMap<>(); 70 arguments.put("count", num); 71 arguments.put("label", appLabel); 72 return mState == StateType.HANDLED 73 ? StringUtil.getIcuPluralsString(context, arguments, 74 R.string.battery_tip_restrict_handled_title) 75 : StringUtil.getIcuPluralsString(context, arguments, 76 R.string.battery_tip_restrict_title); 77 } 78 79 @Override getSummary(Context context)80 public CharSequence getSummary(Context context) { 81 final int num = mRestrictAppList.size(); 82 final CharSequence appLabel = num > 0 ? Utils.getApplicationLabel(context, 83 mRestrictAppList.get(0).packageName) : ""; 84 final int resId = mState == StateType.HANDLED 85 ? R.string.battery_tip_restrict_handled_summary 86 : R.string.battery_tip_restrict_summary; 87 Map<String, Object> arguments = new HashMap<>(); 88 arguments.put("count", num); 89 arguments.put("label", appLabel); 90 return StringUtil.getIcuPluralsString(context, arguments, resId); 91 } 92 93 @Override getIconId()94 public int getIconId() { 95 return mState == StateType.HANDLED 96 ? R.drawable.ic_perm_device_information_theme 97 : R.drawable.ic_battery_alert_theme; 98 } 99 100 @Override updateState(BatteryTip tip)101 public void updateState(BatteryTip tip) { 102 if (tip.mState == StateType.NEW) { 103 // Display it if new anomaly comes 104 mState = StateType.NEW; 105 mRestrictAppList = ((RestrictAppTip) tip).mRestrictAppList; 106 mShowDialog = true; 107 } else if (mState == StateType.NEW && tip.mState == StateType.INVISIBLE) { 108 // If anomaly becomes invisible, show it as handled 109 mState = StateType.HANDLED; 110 mShowDialog = false; 111 } else { 112 mState = tip.getState(); 113 mShowDialog = tip.shouldShowDialog(); 114 mRestrictAppList = ((RestrictAppTip) tip).mRestrictAppList; 115 } 116 } 117 118 @Override validateCheck(Context context)119 public void validateCheck(Context context) { 120 super.validateCheck(context); 121 122 // Set it invisible if there is no valid app 123 mRestrictAppList.removeIf(AppLabelPredicate.getInstance(context)); 124 if (mRestrictAppList.isEmpty()) { 125 mState = StateType.INVISIBLE; 126 } 127 } 128 129 @Override log(Context context, MetricsFeatureProvider metricsFeatureProvider)130 public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) { 131 metricsFeatureProvider.action(context, SettingsEnums.ACTION_APP_RESTRICTION_TIP, 132 mState); 133 if (mState == StateType.NEW) { 134 for (int i = 0, size = mRestrictAppList.size(); i < size; i++) { 135 final AppInfo appInfo = mRestrictAppList.get(i); 136 for (Integer anomalyType : appInfo.anomalyTypes) { 137 metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN, 138 SettingsEnums.ACTION_APP_RESTRICTION_TIP_LIST, 139 SettingsEnums.PAGE_UNKNOWN, 140 appInfo.packageName, 141 anomalyType); 142 } 143 } 144 } 145 } 146 getRestrictAppList()147 public List<AppInfo> getRestrictAppList() { 148 return mRestrictAppList; 149 } 150 151 /** 152 * Construct the app list string(e.g. app1, app2, and app3) 153 */ getRestrictAppsString(Context context)154 public CharSequence getRestrictAppsString(Context context) { 155 final List<CharSequence> appLabels = new ArrayList<>(); 156 for (int i = 0, size = mRestrictAppList.size(); i < size; i++) { 157 appLabels.add(Utils.getApplicationLabel(context, 158 mRestrictAppList.get(i).packageName)); 159 } 160 161 return ListFormatter.getInstance().format(appLabels); 162 } 163 164 @Override toString()165 public String toString() { 166 final StringBuilder stringBuilder = new StringBuilder(super.toString()); 167 stringBuilder.append(" {"); 168 for (int i = 0, size = mRestrictAppList.size(); i < size; i++) { 169 final AppInfo appInfo = mRestrictAppList.get(i); 170 stringBuilder.append(" " + appInfo.toString() + " "); 171 } 172 stringBuilder.append('}'); 173 174 return stringBuilder.toString(); 175 } 176 177 @Override writeToParcel(Parcel dest, int flags)178 public void writeToParcel(Parcel dest, int flags) { 179 super.writeToParcel(dest, flags); 180 dest.writeTypedList(mRestrictAppList); 181 } 182 183 public static final Creator CREATOR = new Creator() { 184 public BatteryTip createFromParcel(Parcel in) { 185 return new RestrictAppTip(in); 186 } 187 188 public BatteryTip[] newArray(int size) { 189 return new RestrictAppTip[size]; 190 } 191 }; 192 } 193