• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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.server.devicepolicy;
18 
19 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE;
20 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
21 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
22 
23 import static com.android.internal.util.Preconditions.checkNotNull;
24 
25 import android.annotation.NonNull;
26 import android.annotation.UserIdInt;
27 import android.app.admin.DeviceAdminReceiver;
28 import android.content.ComponentName;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.content.pm.ApplicationInfo;
32 import android.content.pm.PackageManager;
33 import android.content.pm.ResolveInfo;
34 import android.util.ArraySet;
35 import android.view.inputmethod.InputMethodInfo;
36 import android.view.inputmethod.InputMethodSystemProperty;
37 
38 import com.android.internal.R;
39 import com.android.internal.annotations.VisibleForTesting;
40 import com.android.server.inputmethod.InputMethodManagerInternal;
41 
42 import java.util.Arrays;
43 import java.util.List;
44 import java.util.Set;
45 
46 /**
47  * Class that provides the apps that are not required on a managed device / profile according to the
48  * overlays provided via (vendor_|)required_apps_managed_(profile|device).xml.
49  */
50 public class OverlayPackagesProvider {
51 
52     protected static final String TAG = "OverlayPackagesProvider";
53 
54     private final PackageManager mPm;
55     private final Context mContext;
56     private final Injector mInjector;
57 
OverlayPackagesProvider(Context context)58     public OverlayPackagesProvider(Context context) {
59         this(context, new DefaultInjector());
60     }
61 
62     @VisibleForTesting
63     interface Injector {
isPerProfileImeEnabled()64         boolean isPerProfileImeEnabled();
65         @NonNull
getInputMethodListAsUser(@serIdInt int userId)66         List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId);
67     }
68 
69     private static final class DefaultInjector implements Injector {
70         @Override
isPerProfileImeEnabled()71         public boolean isPerProfileImeEnabled() {
72             return InputMethodSystemProperty.PER_PROFILE_IME_ENABLED;
73         }
74 
75         @NonNull
76         @Override
getInputMethodListAsUser(@serIdInt int userId)77         public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
78             return InputMethodManagerInternal.get().getInputMethodListAsUser(userId);
79         }
80     }
81 
82     @VisibleForTesting
OverlayPackagesProvider(Context context, Injector injector)83     OverlayPackagesProvider(Context context, Injector injector) {
84         mContext = context;
85         mPm = checkNotNull(context.getPackageManager());
86         mInjector = checkNotNull(injector);
87     }
88 
89     /**
90      * Computes non-required apps. All the system apps with a launcher that are not in
91      * the required set of packages will be considered as non-required apps.
92      *
93      * Note: If an app is mistakenly listed as both required and disallowed, it will be treated as
94      * disallowed.
95      *
96      * @param admin              Which {@link DeviceAdminReceiver} this request is associated with.
97      * @param userId             The userId for which the non-required apps needs to be computed.
98      * @param provisioningAction action indicating type of provisioning, should be one of
99      *                           {@link ACTION_PROVISION_MANAGED_DEVICE}, {@link
100      *                           ACTION_PROVISION_MANAGED_PROFILE} or
101      *                           {@link ACTION_PROVISION_MANAGED_USER}.
102      * @return the set of non-required apps.
103      */
104     @NonNull
getNonRequiredApps(@onNull ComponentName admin, int userId, @NonNull String provisioningAction)105     public Set<String> getNonRequiredApps(@NonNull ComponentName admin, int userId,
106             @NonNull String provisioningAction) {
107         final Set<String> nonRequiredApps = getLaunchableApps(userId);
108         // Newly installed system apps are uninstalled when they are not required and are either
109         // disallowed or have a launcher icon.
110         nonRequiredApps.removeAll(getRequiredApps(provisioningAction, admin.getPackageName()));
111         if (mInjector.isPerProfileImeEnabled()) {
112             nonRequiredApps.removeAll(getSystemInputMethods(userId));
113         } else if (ACTION_PROVISION_MANAGED_DEVICE.equals(provisioningAction)
114                 || ACTION_PROVISION_MANAGED_USER.equals(provisioningAction)) {
115             // Don't delete the system input method packages in case of Device owner provisioning.
116             nonRequiredApps.removeAll(getSystemInputMethods(userId));
117         }
118         nonRequiredApps.addAll(getDisallowedApps(provisioningAction));
119         return nonRequiredApps;
120     }
121 
getLaunchableApps(int userId)122     private Set<String> getLaunchableApps(int userId) {
123         final Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
124         launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);
125         final List<ResolveInfo> resolveInfos = mPm.queryIntentActivitiesAsUser(launcherIntent,
126                 PackageManager.MATCH_UNINSTALLED_PACKAGES
127                         | PackageManager.MATCH_DISABLED_COMPONENTS
128                         | PackageManager.MATCH_DIRECT_BOOT_AWARE
129                         | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
130                 userId);
131         final Set<String> apps = new ArraySet<>();
132         for (ResolveInfo resolveInfo : resolveInfos) {
133             apps.add(resolveInfo.activityInfo.packageName);
134         }
135         return apps;
136     }
137 
getSystemInputMethods(int userId)138     private Set<String> getSystemInputMethods(int userId) {
139         final List<InputMethodInfo> inputMethods = mInjector.getInputMethodListAsUser(userId);
140         final Set<String> systemInputMethods = new ArraySet<>();
141         for (InputMethodInfo inputMethodInfo : inputMethods) {
142             ApplicationInfo applicationInfo = inputMethodInfo.getServiceInfo().applicationInfo;
143             if (applicationInfo.isSystemApp()) {
144                 systemInputMethods.add(inputMethodInfo.getPackageName());
145             }
146         }
147         return systemInputMethods;
148     }
149 
getRequiredApps(String provisioningAction, String dpcPackageName)150     private Set<String> getRequiredApps(String provisioningAction, String dpcPackageName) {
151         final Set<String> requiredApps = new ArraySet<>();
152         requiredApps.addAll(getRequiredAppsSet(provisioningAction));
153         requiredApps.addAll(getVendorRequiredAppsSet(provisioningAction));
154         requiredApps.add(dpcPackageName);
155         return requiredApps;
156     }
157 
getDisallowedApps(String provisioningAction)158     private Set<String> getDisallowedApps(String provisioningAction) {
159         final Set<String> disallowedApps = new ArraySet<>();
160         disallowedApps.addAll(getDisallowedAppsSet(provisioningAction));
161         disallowedApps.addAll(getVendorDisallowedAppsSet(provisioningAction));
162         return disallowedApps;
163     }
164 
getRequiredAppsSet(String provisioningAction)165     private Set<String> getRequiredAppsSet(String provisioningAction) {
166         final int resId;
167         switch (provisioningAction) {
168             case ACTION_PROVISION_MANAGED_USER:
169                 resId = R.array.required_apps_managed_user;
170                 break;
171             case ACTION_PROVISION_MANAGED_PROFILE:
172                 resId = R.array.required_apps_managed_profile;
173                 break;
174             case ACTION_PROVISION_MANAGED_DEVICE:
175                 resId = R.array.required_apps_managed_device;
176                 break;
177             default:
178                 throw new IllegalArgumentException("Provisioning type "
179                         + provisioningAction + " not supported.");
180         }
181         return new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(resId)));
182     }
183 
getDisallowedAppsSet(String provisioningAction)184     private Set<String> getDisallowedAppsSet(String provisioningAction) {
185         final int resId;
186         switch (provisioningAction) {
187             case ACTION_PROVISION_MANAGED_USER:
188                 resId = R.array.disallowed_apps_managed_user;
189                 break;
190             case ACTION_PROVISION_MANAGED_PROFILE:
191                 resId = R.array.disallowed_apps_managed_profile;
192                 break;
193             case ACTION_PROVISION_MANAGED_DEVICE:
194                 resId = R.array.disallowed_apps_managed_device;
195                 break;
196             default:
197                 throw new IllegalArgumentException("Provisioning type "
198                         + provisioningAction + " not supported.");
199         }
200         return new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(resId)));
201     }
202 
getVendorRequiredAppsSet(String provisioningAction)203     private Set<String> getVendorRequiredAppsSet(String provisioningAction) {
204         final int resId;
205         switch (provisioningAction) {
206             case ACTION_PROVISION_MANAGED_USER:
207                 resId = R.array.vendor_required_apps_managed_user;
208                 break;
209             case ACTION_PROVISION_MANAGED_PROFILE:
210                 resId = R.array.vendor_required_apps_managed_profile;
211                 break;
212             case ACTION_PROVISION_MANAGED_DEVICE:
213                 resId = R.array.vendor_required_apps_managed_device;
214                 break;
215             default:
216                 throw new IllegalArgumentException("Provisioning type "
217                         + provisioningAction + " not supported.");
218         }
219         return new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(resId)));
220     }
221 
getVendorDisallowedAppsSet(String provisioningAction)222     private Set<String> getVendorDisallowedAppsSet(String provisioningAction) {
223         final int resId;
224         switch (provisioningAction) {
225             case ACTION_PROVISION_MANAGED_USER:
226                 resId = R.array.vendor_disallowed_apps_managed_user;
227                 break;
228             case ACTION_PROVISION_MANAGED_PROFILE:
229                 resId = R.array.vendor_disallowed_apps_managed_profile;
230                 break;
231             case ACTION_PROVISION_MANAGED_DEVICE:
232                 resId = R.array.vendor_disallowed_apps_managed_device;
233                 break;
234             default:
235                 throw new IllegalArgumentException("Provisioning type "
236                         + provisioningAction + " not supported.");
237         }
238         return new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(resId)));
239     }
240 }
241