1 /* 2 * Copyright (C) 2019 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.bugreporthandler; 18 19 import static android.app.admin.DevicePolicyResources.Strings.Settings.PERSONAL_PROFILE_APP_SUBTEXT; 20 import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_APP_SUBTEXT; 21 import static android.provider.Settings.ACTION_BUGREPORT_HANDLER_SETTINGS; 22 23 import android.app.Activity; 24 import android.app.admin.DevicePolicyManager; 25 import android.app.settings.SettingsEnums; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.pm.ApplicationInfo; 29 import android.content.pm.PackageItemInfo; 30 import android.content.pm.PackageManager; 31 import android.content.pm.UserInfo; 32 import android.util.Log; 33 import android.util.Pair; 34 import android.view.View; 35 36 import androidx.annotation.VisibleForTesting; 37 import androidx.preference.PreferenceScreen; 38 39 import com.android.settings.R; 40 import com.android.settings.applications.defaultapps.DefaultAppPickerFragment; 41 import com.android.settings.development.DeveloperOptionAwareMixin; 42 import com.android.settingslib.applications.DefaultAppInfo; 43 import com.android.settingslib.development.DevelopmentSettingsEnabler; 44 import com.android.settingslib.widget.CandidateInfo; 45 import com.android.settingslib.widget.FooterPreference; 46 import com.android.settingslib.widget.SelectorWithWidgetPreference; 47 48 import java.util.ArrayList; 49 import java.util.List; 50 51 /** 52 * Picker for BugReportHandler. 53 */ 54 public class BugReportHandlerPicker extends DefaultAppPickerFragment implements 55 DeveloperOptionAwareMixin { 56 private static final String TAG = "BugReportHandlerPicker"; 57 58 private BugReportHandlerUtil mBugReportHandlerUtil; 59 private FooterPreference mFooter; 60 getHandlerApp(String key)61 private static String getHandlerApp(String key) { 62 int index = key.lastIndexOf('#'); 63 String handlerApp = key.substring(0, index); 64 return handlerApp; 65 } 66 getHandlerUser(String key)67 private static int getHandlerUser(String key) { 68 int index = key.lastIndexOf('#'); 69 int handlerUser = 0; 70 try { 71 handlerUser = Integer.parseInt(key.substring(index + 1)); 72 } catch (NumberFormatException nfe) { 73 Log.e(TAG, "Failed to get handlerUser"); 74 } 75 return handlerUser; 76 } 77 78 @VisibleForTesting getKey(String handlerApp, int handlerUser)79 static String getKey(String handlerApp, int handlerUser) { 80 return handlerApp + "#" + handlerUser; 81 } 82 83 @Override onAttach(Context context)84 public void onAttach(Context context) { 85 super.onAttach(context); 86 if (!DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context)) { 87 getActivity().finish(); 88 } 89 } 90 91 @Override getPreferenceScreenResId()92 protected int getPreferenceScreenResId() { 93 return R.xml.bug_report_handler_settings; 94 } 95 96 @Override addStaticPreferences(PreferenceScreen screen)97 protected void addStaticPreferences(PreferenceScreen screen) { 98 if (mFooter == null) { 99 mFooter = new FooterPreference(screen.getContext()); 100 mFooter.setIcon(R.drawable.ic_info_outline_24dp); 101 mFooter.setSingleLineTitle(false); 102 mFooter.setTitle(R.string.bug_report_handler_picker_footer_text); 103 mFooter.setSelectable(false); 104 } 105 screen.addPreference(mFooter); 106 } 107 108 @Override getCandidates()109 protected List<DefaultAppInfo> getCandidates() { 110 final Context context = getContext(); 111 final List<Pair<ApplicationInfo, Integer>> validBugReportHandlerInfos = 112 getBugReportHandlerUtil().getValidBugReportHandlerInfos(context); 113 final List<DefaultAppInfo> candidates = new ArrayList<>(); 114 for (Pair<ApplicationInfo, Integer> info : validBugReportHandlerInfos) { 115 candidates.add(createDefaultAppInfo(context, mPm, info.second, info.first)); 116 } 117 return candidates; 118 } 119 getBugReportHandlerUtil()120 private BugReportHandlerUtil getBugReportHandlerUtil() { 121 if (mBugReportHandlerUtil == null) { 122 setBugReportHandlerUtil(createDefaultBugReportHandlerUtil()); 123 } 124 return mBugReportHandlerUtil; 125 } 126 127 @VisibleForTesting setBugReportHandlerUtil(BugReportHandlerUtil bugReportHandlerUtil)128 void setBugReportHandlerUtil(BugReportHandlerUtil bugReportHandlerUtil) { 129 mBugReportHandlerUtil = bugReportHandlerUtil; 130 } 131 132 @VisibleForTesting createDefaultBugReportHandlerUtil()133 BugReportHandlerUtil createDefaultBugReportHandlerUtil() { 134 return new BugReportHandlerUtil(); 135 } 136 137 @Override getDefaultKey()138 protected String getDefaultKey() { 139 final Pair<String, Integer> pair = 140 getBugReportHandlerUtil().getCurrentBugReportHandlerAppAndUser(getContext()); 141 return getKey(pair.first, pair.second); 142 } 143 144 @Override setDefaultKey(String key)145 protected boolean setDefaultKey(String key) { 146 return getBugReportHandlerUtil().setCurrentBugReportHandlerAppAndUser(getContext(), 147 getHandlerApp(key), 148 getHandlerUser(key)); 149 } 150 151 @Override onSelectionPerformed(boolean success)152 protected void onSelectionPerformed(boolean success) { 153 super.onSelectionPerformed(success); 154 if (success) { 155 final Activity activity = getActivity(); 156 final Intent intent = activity == null ? null : activity.getIntent(); 157 if (intent != null && ACTION_BUGREPORT_HANDLER_SETTINGS.equals(intent.getAction())) { 158 // If this was started through ACTION_BUGREPORT_HANDLER_SETTINGS then return once 159 // we have chosen a new handler. 160 getActivity().finish(); 161 } 162 } else { 163 getBugReportHandlerUtil().showInvalidChoiceToast(getContext()); 164 updateCandidates(); 165 } 166 } 167 168 @Override getMetricsCategory()169 public int getMetricsCategory() { 170 return SettingsEnums.SETTINGS_BUGREPORT_HANDLER; 171 } 172 173 174 @Override bindPreferenceExtra(SelectorWithWidgetPreference pref, String key, CandidateInfo info, String defaultKey, String systemDefaultKey)175 public void bindPreferenceExtra(SelectorWithWidgetPreference pref, 176 String key, CandidateInfo info, String defaultKey, String systemDefaultKey) { 177 super.bindPreferenceExtra(pref, key, info, defaultKey, systemDefaultKey); 178 pref.setAppendixVisibility(View.GONE); 179 } 180 181 @VisibleForTesting createDefaultAppInfo(Context context, PackageManager pm, int userId, PackageItemInfo packageItemInfo)182 DefaultAppInfo createDefaultAppInfo(Context context, PackageManager pm, int userId, 183 PackageItemInfo packageItemInfo) { 184 return new BugreportHandlerAppInfo(context, pm, userId, packageItemInfo, 185 getDescription(packageItemInfo.packageName, userId)); 186 } 187 getDescription(String handlerApp, int handlerUser)188 private String getDescription(String handlerApp, int handlerUser) { 189 final Context context = getContext(); 190 if (BugReportHandlerUtil.SHELL_APP_PACKAGE.equals(handlerApp)) { 191 return context.getString(R.string.system_default_app_subtext); 192 } 193 if (mUserManager.getUserProfiles().size() < 2) { 194 return ""; 195 } 196 final UserInfo userInfo = mUserManager.getUserInfo(handlerUser); 197 DevicePolicyManager devicePolicyManager = 198 context.getSystemService(DevicePolicyManager.class); 199 200 if (userInfo != null && userInfo.isManagedProfile()) { 201 return devicePolicyManager.getResources().getString(WORK_PROFILE_APP_SUBTEXT, 202 () -> context.getString(R.string.work_profile_app_subtext)); 203 } 204 return devicePolicyManager.getResources().getString(PERSONAL_PROFILE_APP_SUBTEXT, 205 () -> context.getString(R.string.personal_profile_app_subtext)); 206 } 207 208 private static class BugreportHandlerAppInfo extends DefaultAppInfo { 209 private final Context mContext; 210 BugreportHandlerAppInfo(Context context, PackageManager pm, int userId, PackageItemInfo packageItemInfo, String summary)211 BugreportHandlerAppInfo(Context context, PackageManager pm, int userId, 212 PackageItemInfo packageItemInfo, String summary) { 213 super(context, pm, userId, packageItemInfo, summary, true /* enabled */); 214 mContext = context; 215 } 216 217 @Override getKey()218 public String getKey() { 219 if (packageItemInfo != null) { 220 return BugReportHandlerPicker.getKey(packageItemInfo.packageName, userId); 221 } else { 222 return null; 223 } 224 } 225 226 @Override loadLabel()227 public CharSequence loadLabel() { 228 if (mContext == null || packageItemInfo == null) { 229 return null; 230 } 231 if (BugReportHandlerUtil.SHELL_APP_PACKAGE.equals(packageItemInfo.packageName)) { 232 return mContext.getString(com.android.internal.R.string.android_system_label); 233 } 234 return super.loadLabel(); 235 } 236 } 237 } 238