• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 package com.android.car.settings.enterprise;
17 
18 import android.annotation.Nullable;
19 import android.car.drivingstate.CarUxRestrictions;
20 import android.content.Context;
21 import android.content.pm.ApplicationInfo;
22 import android.os.UserHandle;
23 
24 import androidx.preference.PreferenceGroup;
25 
26 import com.android.car.settings.R;
27 import com.android.car.settings.common.FragmentController;
28 import com.android.car.settingslib.applications.ApplicationFeatureProvider;
29 import com.android.car.settingslib.applications.UserAppInfo;
30 import com.android.car.settingslib.enterprise.EnterpriseDefaultApps;
31 import com.android.car.ui.preference.CarUiPreference;
32 import com.android.internal.annotations.VisibleForTesting;
33 
34 import java.util.ArrayList;
35 import java.util.EnumMap;
36 import java.util.List;
37 
38 /**
39 * Controller to show the list of default apps were set by the device owner.
40 */
41 public final class EnterpriseSetDefaultAppsListPreferenceController
42         extends BaseEnterprisePrivacyPreferenceController<PreferenceGroup> {
43 
44     @Nullable
45     private EnumMap<EnterpriseDefaultApps, List<ApplicationInfo>> mAllApps;
46 
EnterpriseSetDefaultAppsListPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)47     public EnterpriseSetDefaultAppsListPreferenceController(Context context, String preferenceKey,
48             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
49         this(context, preferenceKey, fragmentController, uxRestrictions,
50                 /* applicationFeatureProvider= */ null);
51     }
52 
53     @VisibleForTesting
EnterpriseSetDefaultAppsListPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions, @Nullable ApplicationFeatureProvider applicationFeatureProvider)54     EnterpriseSetDefaultAppsListPreferenceController(Context context, String preferenceKey,
55             FragmentController fragmentController, CarUxRestrictions uxRestrictions,
56             @Nullable ApplicationFeatureProvider applicationFeatureProvider) {
57         super(context, preferenceKey, fragmentController, uxRestrictions,
58                 /* enterprisePrivacyFeatureProvider= */ null, applicationFeatureProvider);
59     }
60 
61     @Override
getPreferenceType()62     protected Class<PreferenceGroup> getPreferenceType() {
63         return PreferenceGroup.class;
64     }
65 
66     @Override
getDefaultAvailabilityStatus()67     protected int getDefaultAvailabilityStatus() {
68         if (mAllApps == null) {
69             mAllApps = listEnterpriseSetDefaultApps();
70             mLogger.d("All apps: " + mAllApps);
71         }
72 
73         return mAllApps == null || mAllApps.isEmpty() ? DISABLED_FOR_PROFILE : AVAILABLE;
74     }
75 
76     @Override
updateState(PreferenceGroup preferenceGroup)77     protected void updateState(PreferenceGroup preferenceGroup) {
78         if (mAllApps == null) {
79             // Should never happen, but better log than crash...
80             mLogger.wtf("updateState() called when mAllApps is null");
81             return;
82         }
83         mLogger.d("Updating state with " + mAllApps.size() + " types of apps");
84 
85         createPreferences(getContext(), preferenceGroup, mAllApps);
86     };
87 
88     // NOTE: methods below were copied from phone, mostly "as-is"
89 
90     @Nullable
listEnterpriseSetDefaultApps()91     private EnumMap<EnterpriseDefaultApps, List<ApplicationInfo>> listEnterpriseSetDefaultApps() {
92         // TODO(b/1703325190): to support work profiles, it should use and outer lopp:
93         //   for (UserHandle user : mUserFeatureProvider.getUserProfiles()) {
94         UserHandle user = getContext().getUser();
95         boolean hasDefaultsForUser = false;
96         EnumMap<EnterpriseDefaultApps, List<ApplicationInfo>> userMap = null;
97 
98         for (EnterpriseDefaultApps typeOfDefault : EnterpriseDefaultApps.values()) {
99             List<UserAppInfo> apps = mApplicationFeatureProvider
100                     .findPersistentPreferredActivities(user.getIdentifier(),
101                             typeOfDefault.getIntents());
102             if (apps.isEmpty()) {
103                 mLogger.v("no app of type " + typeOfDefault + " for user " + user);
104                 continue;
105             }
106             if (!hasDefaultsForUser) {
107                 hasDefaultsForUser = true;
108                 userMap = new EnumMap<>(EnterpriseDefaultApps.class);
109             }
110             ArrayList<ApplicationInfo> applicationInfos = new ArrayList<>();
111             for (UserAppInfo userAppInfo : apps) {
112                 mLogger.d("adding app of type " + typeOfDefault + ":" + userAppInfo);
113                 applicationInfos.add(userAppInfo.appInfo);
114             }
115             userMap.put(typeOfDefault, applicationInfos);
116         }
117         return userMap;
118     }
119 
createPreferences(Context prefContext, PreferenceGroup group, EnumMap<EnterpriseDefaultApps, List<ApplicationInfo>> apps)120     private void createPreferences(Context prefContext, PreferenceGroup group,
121             EnumMap<EnterpriseDefaultApps, List<ApplicationInfo>> apps) {
122         group.removeAll();
123         for (EnterpriseDefaultApps typeOfDefault : EnterpriseDefaultApps.values()) {
124             List<ApplicationInfo> appsForCategory = apps.get(typeOfDefault);
125             if (appsForCategory == null || appsForCategory.isEmpty()) {
126                 mLogger.d("No app for type " + typeOfDefault);
127                 continue;
128             }
129             CarUiPreference preference = new CarUiPreference(prefContext);
130             preference.setTitle(getTitle(prefContext, typeOfDefault, appsForCategory.size()));
131             preference.setSummary(buildSummaryString(prefContext, appsForCategory));
132             preference.setOrder(typeOfDefault.ordinal());
133             preference.setSelectable(false);
134             group.addPreference(preference);
135         }
136     }
137 
buildSummaryString(Context context, List<ApplicationInfo> apps)138     private CharSequence buildSummaryString(Context context, List<ApplicationInfo> apps) {
139         CharSequence[] appNames = new String[apps.size()];
140         for (int i = 0; i < apps.size(); i++) {
141             appNames[i] = apps.get(i).loadLabel(mPm);
142         }
143         switch (apps.size()) {
144             case 1:
145                 return appNames[0];
146             case 2:
147                 return context.getString(R.string.app_names_concatenation_template_2, appNames[0],
148                         appNames[1]);
149             default:
150                 return context.getString(R.string.app_names_concatenation_template_3, appNames[0],
151                         appNames[1], appNames[2]);
152         }
153     }
154 
getTitle(Context context, EnterpriseDefaultApps typeOfDefault, int appCount)155     private CharSequence getTitle(Context context, EnterpriseDefaultApps typeOfDefault,
156             int appCount) {
157         switch (typeOfDefault) {
158             case BROWSER:
159                 return context.getString(R.string.default_browser_title);
160             case CALENDAR:
161                 return context.getString(R.string.default_calendar_app_title);
162             case CONTACTS:
163                 return context.getString(R.string.default_contacts_app_title);
164             case PHONE:
165                 return context.getResources()
166                         .getQuantityString(R.plurals.default_phone_app_title, appCount);
167             case MAP:
168                 return context.getString(R.string.default_map_app_title);
169             case EMAIL:
170                 return context.getResources()
171                         .getQuantityString(R.plurals.default_email_app_title, appCount);
172             case CAMERA:
173                 return context.getResources()
174                         .getQuantityString(R.plurals.default_camera_app_title, appCount);
175             default:
176                 throw new IllegalStateException("Unknown type of default " + typeOfDefault);
177         }
178     }
179 }
180