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