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