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