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