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