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