• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
18 
19 import android.app.settings.SettingsEnums;
20 import android.content.Context;
21 import android.content.pm.ApplicationInfo;
22 import android.content.pm.PackageManager;
23 import android.os.Bundle;
24 import android.os.UserHandle;
25 import android.util.IconDrawableFactory;
26 import android.util.Log;
27 import android.util.SparseLongArray;
28 
29 import androidx.annotation.VisibleForTesting;
30 import androidx.preference.CheckBoxPreference;
31 import androidx.preference.Preference;
32 import androidx.preference.PreferenceGroup;
33 
34 import com.android.settings.R;
35 import com.android.settings.Utils;
36 import com.android.settings.core.InstrumentedPreferenceFragment;
37 import com.android.settings.core.SubSettingLauncher;
38 import com.android.settings.dashboard.DashboardFragment;
39 import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
40 import com.android.settings.fuelgauge.batterytip.AppInfo;
41 import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
42 import com.android.settings.fuelgauge.batterytip.BatteryTipDialogFragment;
43 import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
44 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
45 import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
46 import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
47 import com.android.settings.widget.AppCheckBoxPreference;
48 import com.android.settingslib.core.AbstractPreferenceController;
49 import com.android.settingslib.utils.StringUtil;
50 import com.android.settingslib.widget.FooterPreferenceMixinCompat;
51 
52 import java.util.List;
53 
54 /**
55  * Fragment to show a list of anomaly apps, where user could handle these anomalies
56  */
57 public class RestrictedAppDetails extends DashboardFragment implements
58         BatteryTipPreferenceController.BatteryTipListener {
59 
60     public static final String TAG = "RestrictedAppDetails";
61 
62     @VisibleForTesting
63     static final String EXTRA_APP_INFO_LIST = "app_info_list";
64     private static final String KEY_PREF_RESTRICTED_APP_LIST = "restrict_app_list";
65     private static final long TIME_NULL = -1;
66 
67     @VisibleForTesting
68     List<AppInfo> mAppInfos;
69     @VisibleForTesting
70     IconDrawableFactory mIconDrawableFactory;
71     @VisibleForTesting
72     PreferenceGroup mRestrictedAppListGroup;
73     @VisibleForTesting
74     BatteryUtils mBatteryUtils;
75     @VisibleForTesting
76     PackageManager mPackageManager;
77     @VisibleForTesting
78     BatteryDatabaseManager mBatteryDatabaseManager;
79     private final FooterPreferenceMixinCompat mFooterPreferenceMixin =
80             new FooterPreferenceMixinCompat(this, getSettingsLifecycle());
81 
startRestrictedAppDetails(InstrumentedPreferenceFragment fragment, List<AppInfo> appInfos)82     public static void startRestrictedAppDetails(InstrumentedPreferenceFragment fragment,
83             List<AppInfo> appInfos) {
84         final Bundle args = new Bundle();
85         args.putParcelableList(EXTRA_APP_INFO_LIST, appInfos);
86 
87         new SubSettingLauncher(fragment.getContext())
88                 .setDestination(RestrictedAppDetails.class.getName())
89                 .setArguments(args)
90                 .setTitleRes(R.string.restricted_app_title)
91                 .setSourceMetricsCategory(fragment.getMetricsCategory())
92                 .launch();
93     }
94 
95     @Override
onCreate(Bundle icicle)96     public void onCreate(Bundle icicle) {
97         super.onCreate(icicle);
98         final Context context = getContext();
99 
100         mFooterPreferenceMixin.createFooterPreference().setTitle(
101                 R.string.restricted_app_detail_footer);
102         mRestrictedAppListGroup = (PreferenceGroup) findPreference(KEY_PREF_RESTRICTED_APP_LIST);
103         mAppInfos = getArguments().getParcelableArrayList(EXTRA_APP_INFO_LIST);
104         mPackageManager = context.getPackageManager();
105         mIconDrawableFactory = IconDrawableFactory.newInstance(context);
106         mBatteryUtils = BatteryUtils.getInstance(context);
107         mBatteryDatabaseManager = BatteryDatabaseManager.getInstance(context);
108 
109         refreshUi();
110     }
111 
112     @Override
onPreferenceTreeClick(Preference preference)113     public boolean onPreferenceTreeClick(Preference preference) {
114 
115         return super.onPreferenceTreeClick(preference);
116     }
117 
118     @Override
getLogTag()119     protected String getLogTag() {
120         return TAG;
121     }
122 
123     @Override
getPreferenceScreenResId()124     protected int getPreferenceScreenResId() {
125         return R.xml.restricted_apps_detail;
126     }
127 
128     @Override
createPreferenceControllers(Context context)129     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
130         return null;
131     }
132 
133     @Override
getMetricsCategory()134     public int getMetricsCategory() {
135         return SettingsEnums.FUELGAUGE_RESTRICTED_APP_DETAILS;
136     }
137 
138     @Override
getHelpResource()139     public int getHelpResource() {
140         return R.string.help_uri_restricted_apps;
141     }
142 
143     @VisibleForTesting
refreshUi()144     void refreshUi() {
145         mRestrictedAppListGroup.removeAll();
146         final Context context = getPrefContext();
147         final SparseLongArray timestampArray = mBatteryDatabaseManager
148                 .queryActionTime(AnomalyDatabaseHelper.ActionType.RESTRICTION);
149         final long now = System.currentTimeMillis();
150 
151         for (int i = 0, size = mAppInfos.size(); i < size; i++) {
152             final CheckBoxPreference checkBoxPreference = new AppCheckBoxPreference(context);
153             final AppInfo appInfo = mAppInfos.get(i);
154             try {
155                 final ApplicationInfo applicationInfo = mPackageManager.getApplicationInfoAsUser(
156                         appInfo.packageName, 0 /* flags */, UserHandle.getUserId(appInfo.uid));
157                 checkBoxPreference.setChecked(
158                         mBatteryUtils.isForceAppStandbyEnabled(appInfo.uid, appInfo.packageName));
159                 checkBoxPreference.setTitle(mPackageManager.getApplicationLabel(applicationInfo));
160                 checkBoxPreference.setIcon(
161                         Utils.getBadgedIcon(mIconDrawableFactory, mPackageManager,
162                                 appInfo.packageName,
163                                 UserHandle.getUserId(appInfo.uid)));
164                 checkBoxPreference.setKey(getKeyFromAppInfo(appInfo));
165                 checkBoxPreference.setOnPreferenceChangeListener((pref, value) -> {
166                     final BatteryTipDialogFragment fragment = createDialogFragment(appInfo,
167                             (Boolean) value);
168                     fragment.setTargetFragment(this, 0 /* requestCode */);
169                     fragment.show(getFragmentManager(), TAG);
170 
171                     return false;
172                 });
173 
174                 final long timestamp = timestampArray.get(appInfo.uid, TIME_NULL);
175                 if (timestamp != TIME_NULL) {
176                     checkBoxPreference.setSummary(getString(R.string.restricted_app_time_summary,
177                             StringUtil.formatRelativeTime(context, now - timestamp, false)));
178                 }
179                 final CharSequence test = checkBoxPreference.getSummaryOn();
180                 mRestrictedAppListGroup.addPreference(checkBoxPreference);
181             } catch (PackageManager.NameNotFoundException e) {
182                 Log.e(TAG, "Can't find package: " + appInfo.packageName);
183             }
184         }
185     }
186 
187     @Override
onBatteryTipHandled(BatteryTip batteryTip)188     public void onBatteryTipHandled(BatteryTip batteryTip) {
189         final AppInfo appInfo;
190         final boolean isRestricted = batteryTip instanceof RestrictAppTip;
191         if (isRestricted) {
192             appInfo = ((RestrictAppTip) batteryTip).getRestrictAppList().get(0);
193         } else {
194             appInfo = ((UnrestrictAppTip) batteryTip).getUnrestrictAppInfo();
195         }
196 
197         CheckBoxPreference preference = (CheckBoxPreference) mRestrictedAppListGroup
198                 .findPreference(getKeyFromAppInfo(appInfo));
199         if (preference != null) {
200             preference.setChecked(isRestricted);
201         }
202     }
203 
204     @VisibleForTesting
createDialogFragment(AppInfo appInfo, boolean toRestrict)205     BatteryTipDialogFragment createDialogFragment(AppInfo appInfo, boolean toRestrict) {
206         final BatteryTip batteryTip = toRestrict
207                 ? new RestrictAppTip(BatteryTip.StateType.NEW, appInfo)
208                 : new UnrestrictAppTip(BatteryTip.StateType.NEW, appInfo);
209 
210         return BatteryTipDialogFragment.newInstance(
211                 batteryTip, getMetricsCategory());
212     }
213 
214     @VisibleForTesting
getKeyFromAppInfo(AppInfo appInfo)215     String getKeyFromAppInfo(AppInfo appInfo) {
216         return appInfo.uid + "," + appInfo.packageName;
217     }
218 }
219