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