1 /* 2 * Copyright (C) 2017 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.enterprise; 18 19 import static android.app.admin.DevicePolicyResources.Strings.Settings.PERSONAL_CATEGORY_HEADER; 20 import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_CATEGORY_HEADER; 21 22 import android.app.admin.DevicePolicyManager; 23 import android.content.Context; 24 import android.content.pm.ApplicationInfo; 25 import android.content.pm.PackageManager; 26 import android.content.pm.UserInfo; 27 import android.os.UserHandle; 28 29 import androidx.preference.Preference; 30 import androidx.preference.PreferenceCategory; 31 import androidx.preference.PreferenceGroup; 32 import androidx.preference.PreferenceScreen; 33 34 import com.android.settings.R; 35 import com.android.settings.SettingsPreferenceFragment; 36 import com.android.settings.applications.ApplicationFeatureProvider; 37 import com.android.settings.applications.EnterpriseDefaultApps; 38 import com.android.settings.applications.UserAppInfo; 39 import com.android.settings.core.PreferenceControllerMixin; 40 import com.android.settings.overlay.FeatureFactory; 41 import com.android.settings.users.UserFeatureProvider; 42 import com.android.settingslib.core.AbstractPreferenceController; 43 import com.android.settingslib.utils.StringUtil; 44 import com.android.settingslib.utils.ThreadUtils; 45 46 import java.util.ArrayList; 47 import java.util.Collections; 48 import java.util.EnumMap; 49 import java.util.List; 50 51 52 /** 53 * PreferenceController that builds a dynamic list of default apps set by device or profile owner. 54 */ 55 public class EnterpriseSetDefaultAppsListPreferenceController extends 56 AbstractPreferenceController implements PreferenceControllerMixin { 57 private final PackageManager mPm; 58 private final SettingsPreferenceFragment mParent; 59 private final ApplicationFeatureProvider mApplicationFeatureProvider; 60 private final EnterprisePrivacyFeatureProvider mEnterprisePrivacyFeatureProvider; 61 private final UserFeatureProvider mUserFeatureProvider; 62 63 private List<UserInfo> mUsers = Collections.emptyList(); 64 private List<EnumMap<EnterpriseDefaultApps, List<ApplicationInfo>>> mApps = 65 Collections.emptyList(); 66 EnterpriseSetDefaultAppsListPreferenceController(Context context, SettingsPreferenceFragment parent, PackageManager packageManager)67 public EnterpriseSetDefaultAppsListPreferenceController(Context context, 68 SettingsPreferenceFragment parent, PackageManager packageManager) { 69 super(context); 70 mPm = packageManager; 71 mParent = parent; 72 final FeatureFactory factory = FeatureFactory.getFeatureFactory(); 73 mApplicationFeatureProvider = factory.getApplicationFeatureProvider(); 74 mEnterprisePrivacyFeatureProvider = factory.getEnterprisePrivacyFeatureProvider(); 75 mUserFeatureProvider = factory.getUserFeatureProvider(); 76 buildAppList(); 77 } 78 79 /** 80 * Builds data for UI. Updates mUsers and mApps so that they contain non-empty list. 81 */ buildAppList()82 private void buildAppList() { 83 mUsers = new ArrayList<>(); 84 mApps = new ArrayList<>(); 85 for (UserHandle user : mUserFeatureProvider.getUserProfiles()) { 86 boolean hasDefaultsForUser = false; 87 EnumMap<EnterpriseDefaultApps, List<ApplicationInfo>> userMap = null; 88 89 for (EnterpriseDefaultApps typeOfDefault : EnterpriseDefaultApps.values()) { 90 List<UserAppInfo> apps = mApplicationFeatureProvider. 91 findPersistentPreferredActivities(user.getIdentifier(), 92 typeOfDefault.getIntents()); 93 if (apps.isEmpty()) { 94 continue; 95 } 96 if (!hasDefaultsForUser) { 97 hasDefaultsForUser = true; 98 mUsers.add(apps.get(0).userInfo); 99 userMap = new EnumMap<>(EnterpriseDefaultApps.class); 100 mApps.add(userMap); 101 } 102 ArrayList<ApplicationInfo> applicationInfos = new ArrayList<>(); 103 for (UserAppInfo userAppInfo : apps) { 104 applicationInfos.add(userAppInfo.appInfo); 105 } 106 userMap.put(typeOfDefault, applicationInfos); 107 } 108 } 109 ThreadUtils.postOnMainThread(() -> updateUi()); 110 } 111 112 @Override isAvailable()113 public boolean isAvailable() { 114 return true; 115 } 116 117 @Override getPreferenceKey()118 public String getPreferenceKey() { 119 return null; 120 } 121 updateUi()122 private void updateUi() { 123 final Context prefContext = mParent.getPreferenceManager().getContext(); 124 final PreferenceScreen screen = mParent.getPreferenceScreen(); 125 if (screen == null) { 126 return; 127 } 128 if (!mEnterprisePrivacyFeatureProvider.isInCompMode() && mUsers.size() == 1) { 129 createPreferences(prefContext, screen, mApps.get(0)); 130 } else { 131 DevicePolicyManager devicePolicyManager = 132 mContext.getSystemService(DevicePolicyManager.class); 133 for (int i = 0; i < mUsers.size(); i++) { 134 final UserInfo userInfo = mUsers.get(i); 135 final PreferenceCategory category = new PreferenceCategory(prefContext); 136 screen.addPreference(category); 137 if (userInfo.isManagedProfile()) { 138 category.setTitle(devicePolicyManager.getResources().getString( 139 WORK_CATEGORY_HEADER, 140 () -> mContext.getString( 141 com.android.settingslib.R.string.category_work))); 142 } else { 143 category.setTitle(devicePolicyManager.getResources().getString( 144 PERSONAL_CATEGORY_HEADER, 145 () -> mContext.getString( 146 com.android.settingslib.R.string.category_personal))); 147 } 148 category.setOrder(i); 149 createPreferences(prefContext, category, mApps.get(i)); 150 } 151 } 152 } 153 createPreferences(Context prefContext, PreferenceGroup group, EnumMap<EnterpriseDefaultApps, List<ApplicationInfo>> apps)154 private void createPreferences(Context prefContext, PreferenceGroup group, 155 EnumMap<EnterpriseDefaultApps, List<ApplicationInfo>> apps) { 156 if (group == null) { 157 return; 158 } 159 for (EnterpriseDefaultApps typeOfDefault : EnterpriseDefaultApps.values()) { 160 final List<ApplicationInfo> appsForCategory = apps.get(typeOfDefault); 161 if (appsForCategory == null || appsForCategory.isEmpty()) { 162 continue; 163 } 164 final Preference preference = new Preference(prefContext); 165 preference.setTitle(getTitle(prefContext, typeOfDefault, appsForCategory.size())); 166 preference.setSummary(buildSummaryString(prefContext, appsForCategory)); 167 preference.setOrder(typeOfDefault.ordinal()); 168 preference.setSelectable(false); 169 group.addPreference(preference); 170 } 171 } 172 buildSummaryString(Context context, List<ApplicationInfo> apps)173 private CharSequence buildSummaryString(Context context, List<ApplicationInfo> apps) { 174 final CharSequence[] appNames = new String[apps.size()]; 175 for (int i = 0; i < apps.size(); i++) { 176 appNames[i] = apps.get(i).loadLabel(mPm); 177 } 178 if (apps.size() == 1) { 179 return appNames[0]; 180 } else if (apps.size() == 2) { 181 return context.getString(R.string.app_names_concatenation_template_2, appNames[0], 182 appNames[1]); 183 } else { 184 return context.getString(R.string.app_names_concatenation_template_3, appNames[0], 185 appNames[1], appNames[2]); 186 } 187 } 188 getTitle(Context context, EnterpriseDefaultApps typeOfDefault, int appCount)189 private String getTitle(Context context, EnterpriseDefaultApps typeOfDefault, int appCount) { 190 switch (typeOfDefault) { 191 case BROWSER: 192 return context.getString(R.string.default_browser_title); 193 case CALENDAR: 194 return context.getString(R.string.default_calendar_app_title); 195 case CONTACTS: 196 return context.getString(R.string.default_contacts_app_title); 197 case PHONE: 198 return StringUtil.getIcuPluralsString(context, appCount, 199 R.string.default_phone_app_title); 200 case MAP: 201 return context.getString(R.string.default_map_app_title); 202 case EMAIL: 203 return StringUtil.getIcuPluralsString(context, appCount, 204 R.string.default_email_app_title); 205 case CAMERA: 206 return StringUtil.getIcuPluralsString(context, appCount, 207 R.string.default_camera_app_title); 208 default: 209 throw new IllegalStateException("Unknown type of default " + typeOfDefault); 210 } 211 } 212 213 } 214