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.icu.text.ListFormatter;
22 import android.os.Parcel;
23 import android.util.ArrayMap;
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.List;
35 import java.util.Map;
36 
37 /** Tip to suggest user to restrict some bad apps */
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 =
64                 num > 0
65                         ? Utils.getApplicationLabel(context, mRestrictAppList.get(0).packageName)
66                         : "";
67 
68         Map<String, Object> arguments = new ArrayMap<>();
69         arguments.put("count", num);
70         arguments.put("label", appLabel);
71         return mState == StateType.HANDLED
72                 ? StringUtil.getIcuPluralsString(
73                         context, arguments, R.string.battery_tip_restrict_handled_title)
74                 : StringUtil.getIcuPluralsString(
75                         context, arguments, R.string.battery_tip_restrict_title);
76     }
77 
78     @Override
getSummary(Context context)79     public CharSequence getSummary(Context context) {
80         final int num = mRestrictAppList.size();
81         final CharSequence appLabel =
82                 num > 0
83                         ? Utils.getApplicationLabel(context, mRestrictAppList.get(0).packageName)
84                         : "";
85         final int resId =
86                 mState == StateType.HANDLED
87                         ? R.string.battery_tip_restrict_handled_summary
88                         : R.string.battery_tip_restrict_summary;
89         Map<String, Object> arguments = new ArrayMap<>();
90         arguments.put("count", num);
91         arguments.put("label", appLabel);
92         return StringUtil.getIcuPluralsString(context, arguments, resId);
93     }
94 
95     @Override
getIconId()96     public int getIconId() {
97         return mState == StateType.HANDLED
98                 ? R.drawable.ic_perm_device_information_theme
99                 : R.drawable.ic_battery_alert_theme;
100     }
101 
102     @Override
updateState(BatteryTip tip)103     public void updateState(BatteryTip tip) {
104         if (tip.mState == StateType.NEW) {
105             // Display it if new anomaly comes
106             mState = StateType.NEW;
107             mRestrictAppList = ((RestrictAppTip) tip).mRestrictAppList;
108             mShowDialog = true;
109         } else if (mState == StateType.NEW && tip.mState == StateType.INVISIBLE) {
110             // If anomaly becomes invisible, show it as handled
111             mState = StateType.HANDLED;
112             mShowDialog = false;
113         } else {
114             mState = tip.getState();
115             mShowDialog = tip.shouldShowDialog();
116             mRestrictAppList = ((RestrictAppTip) tip).mRestrictAppList;
117         }
118     }
119 
120     @Override
validateCheck(Context context)121     public void validateCheck(Context context) {
122         super.validateCheck(context);
123 
124         // Set it invisible if there is no valid app
125         mRestrictAppList.removeIf(AppLabelPredicate.getInstance(context));
126         if (mRestrictAppList.isEmpty()) {
127             mState = StateType.INVISIBLE;
128         }
129     }
130 
131     @Override
log(Context context, MetricsFeatureProvider metricsFeatureProvider)132     public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
133         metricsFeatureProvider.action(context, SettingsEnums.ACTION_APP_RESTRICTION_TIP, mState);
134         if (mState == StateType.NEW) {
135             for (int i = 0, size = mRestrictAppList.size(); i < size; i++) {
136                 final AppInfo appInfo = mRestrictAppList.get(i);
137                 for (Integer anomalyType : appInfo.anomalyTypes) {
138                     metricsFeatureProvider.action(
139                             SettingsEnums.PAGE_UNKNOWN,
140                             SettingsEnums.ACTION_APP_RESTRICTION_TIP_LIST,
141                             SettingsEnums.PAGE_UNKNOWN,
142                             appInfo.packageName,
143                             anomalyType);
144                 }
145             }
146         }
147     }
148 
getRestrictAppList()149     public List<AppInfo> getRestrictAppList() {
150         return mRestrictAppList;
151     }
152 
153     /** Construct the app list string(e.g. app1, app2, and app3) */
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, mRestrictAppList.get(i).packageName));
158         }
159 
160         return ListFormatter.getInstance().format(appLabels);
161     }
162 
163     @Override
toString()164     public String toString() {
165         final StringBuilder stringBuilder = new StringBuilder(super.toString());
166         stringBuilder.append(" {");
167         for (int i = 0, size = mRestrictAppList.size(); i < size; i++) {
168             final AppInfo appInfo = mRestrictAppList.get(i);
169             stringBuilder.append(" " + appInfo.toString() + " ");
170         }
171         stringBuilder.append('}');
172 
173         return stringBuilder.toString();
174     }
175 
176     @Override
writeToParcel(Parcel dest, int flags)177     public void writeToParcel(Parcel dest, int flags) {
178         super.writeToParcel(dest, flags);
179         dest.writeTypedList(mRestrictAppList);
180     }
181 
182     public static final Creator CREATOR =
183             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