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 import static android.app.admin.DevicePolicyManager.REQUIRED_APP_MANAGED_DEVICE;
23 import static android.app.admin.DevicePolicyManager.REQUIRED_APP_MANAGED_PROFILE;
24 import static android.app.admin.DevicePolicyManager.REQUIRED_APP_MANAGED_USER;
25 import static android.content.pm.PackageManager.GET_META_DATA;
26 
27 import static com.android.internal.util.Preconditions.checkArgument;
28 import static com.android.server.devicepolicy.DevicePolicyManagerService.dumpApps;
29 
30 import static java.util.Objects.requireNonNull;
31 
32 import android.annotation.ArrayRes;
33 import android.annotation.NonNull;
34 import android.annotation.UserIdInt;
35 import android.app.admin.DeviceAdminReceiver;
36 import android.app.admin.DevicePolicyManager;
37 import android.app.admin.flags.Flags;
38 import android.app.role.RoleManager;
39 import android.content.ComponentName;
40 import android.content.Context;
41 import android.content.Intent;
42 import android.content.pm.ApplicationInfo;
43 import android.content.pm.PackageInfo;
44 import android.content.pm.PackageManager;
45 import android.content.pm.ResolveInfo;
46 import android.os.Binder;
47 import android.util.ArraySet;
48 import android.util.IndentingPrintWriter;
49 import android.view.inputmethod.InputMethodInfo;
50 
51 import com.android.internal.R;
52 import com.android.internal.annotations.VisibleForTesting;
53 import com.android.server.inputmethod.InputMethodManagerInternal;
54 import com.android.server.pm.ApexManager;
55 
56 import java.util.Arrays;
57 import java.util.HashMap;
58 import java.util.HashSet;
59 import java.util.List;
60 import java.util.Map;
61 import java.util.Set;
62 
63 /**
64  * Class that provides the apps that are not required on a managed device / profile according to the
65  * overlays provided via (vendor_|)required_apps_managed_(profile|device).xml.
66  */
67 public class OverlayPackagesProvider {
68 
69     protected static final String TAG = "OverlayPackagesProvider";
70     private static final Map<String, String> sActionToMetadataKeyMap = new HashMap<>();
71 
72     static {
sActionToMetadataKeyMap.put(ACTION_PROVISION_MANAGED_USER, REQUIRED_APP_MANAGED_USER)73         sActionToMetadataKeyMap.put(ACTION_PROVISION_MANAGED_USER, REQUIRED_APP_MANAGED_USER);
sActionToMetadataKeyMap.put(ACTION_PROVISION_MANAGED_PROFILE, REQUIRED_APP_MANAGED_PROFILE)74         sActionToMetadataKeyMap.put(ACTION_PROVISION_MANAGED_PROFILE, REQUIRED_APP_MANAGED_PROFILE);
sActionToMetadataKeyMap.put(ACTION_PROVISION_MANAGED_DEVICE, REQUIRED_APP_MANAGED_DEVICE)75         sActionToMetadataKeyMap.put(ACTION_PROVISION_MANAGED_DEVICE, REQUIRED_APP_MANAGED_DEVICE);
76     }
77 
78     private static final Set<String> sAllowedActions = new HashSet<>();
79 
80     static {
81         sAllowedActions.add(ACTION_PROVISION_MANAGED_USER);
82         sAllowedActions.add(ACTION_PROVISION_MANAGED_PROFILE);
83         sAllowedActions.add(ACTION_PROVISION_MANAGED_DEVICE);
84     }
85 
86     private final PackageManager mPm;
87     private final Context mContext;
88     private final Injector mInjector;
89 
90     private final RecursiveStringArrayResourceResolver mRecursiveStringArrayResourceResolver;
91 
OverlayPackagesProvider(Context context)92     public OverlayPackagesProvider(Context context) {
93         this(
94                 context,
95                 new DefaultInjector(),
96                 new RecursiveStringArrayResourceResolver(context.getResources()));
97     }
98 
99     @VisibleForTesting
100     interface Injector {
101         @NonNull
getInputMethodListAsUser(@serIdInt int userId)102         List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId);
103 
getActiveApexPackageNameContainingPackage(String packageName)104         String getActiveApexPackageNameContainingPackage(String packageName);
105 
getDevicePolicyManagementRoleHolderPackageName(Context context)106         String getDevicePolicyManagementRoleHolderPackageName(Context context);
107     }
108 
109     private static final class DefaultInjector implements Injector {
110         @NonNull
111         @Override
getInputMethodListAsUser(@serIdInt int userId)112         public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
113             return InputMethodManagerInternal.get().getInputMethodListAsUser(userId);
114         }
115 
116         @Override
getActiveApexPackageNameContainingPackage(String packageName)117         public String getActiveApexPackageNameContainingPackage(String packageName) {
118             return ApexManager.getInstance().getActiveApexPackageNameContainingPackage(packageName);
119         }
120 
121         @Override
getDevicePolicyManagementRoleHolderPackageName(Context context)122         public String getDevicePolicyManagementRoleHolderPackageName(Context context) {
123             return Binder.withCleanCallingIdentity(() -> {
124                 RoleManager roleManager = context.getSystemService(RoleManager.class);
125                 List<String> roleHolders = roleManager.getRoleHolders(
126                         RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT);
127                 if (roleHolders.isEmpty()) {
128                     return null;
129                 }
130                 return roleHolders.get(0);
131             });
132         }
133     }
134 
135     @VisibleForTesting
OverlayPackagesProvider(Context context, Injector injector, RecursiveStringArrayResourceResolver recursiveStringArrayResourceResolver)136     OverlayPackagesProvider(Context context, Injector injector,
137             RecursiveStringArrayResourceResolver recursiveStringArrayResourceResolver) {
138         mContext = context;
139         mPm = requireNonNull(context.getPackageManager());
140         mInjector = requireNonNull(injector);
141         mRecursiveStringArrayResourceResolver = requireNonNull(
142                 recursiveStringArrayResourceResolver);
143     }
144 
145     /**
146      * Computes non-required apps. All the system apps with a launcher that are not in
147      * the required set of packages, and all mainline modules that are not declared as required
148      * via metadata in their manifests, will be considered as non-required apps.
149      * <p>
150      * Note: If an app is mistakenly listed as both required and disallowed, it will be treated as
151      * disallowed.
152      *
153      * @param admin              Which {@link DeviceAdminReceiver} this request is associated with.
154      * @param userId             The userId for which the non-required apps needs to be computed.
155      * @param provisioningAction action indicating type of provisioning, should be one of
156      *                           {@link ACTION_PROVISION_MANAGED_DEVICE}, {@link
157      *                           ACTION_PROVISION_MANAGED_PROFILE} or
158      *                           {@link ACTION_PROVISION_MANAGED_USER}.
159      * @return the set of non-required apps.
160      */
161     @NonNull
getNonRequiredApps(@onNull ComponentName admin, int userId, @NonNull String provisioningAction)162     public Set<String> getNonRequiredApps(@NonNull ComponentName admin, int userId,
163             @NonNull String provisioningAction) {
164         requireNonNull(admin);
165         checkArgument(sAllowedActions.contains(provisioningAction));
166         final Set<String> nonRequiredApps = getLaunchableApps(userId);
167         // Newly installed system apps are uninstalled when they are not required and are either
168         // disallowed or have a launcher icon.
169         nonRequiredApps.removeAll(getRequiredApps(provisioningAction, admin.getPackageName()));
170         nonRequiredApps.removeAll(getSystemInputMethods(userId));
171         nonRequiredApps.addAll(getDisallowedApps(provisioningAction));
172         nonRequiredApps.removeAll(
173                 getRequiredAppsMainlineModules(nonRequiredApps, provisioningAction));
174         nonRequiredApps.removeAll(getDeviceManagerRoleHolders());
175         return nonRequiredApps;
176     }
177 
getDeviceManagerRoleHolders()178     private Set<String> getDeviceManagerRoleHolders() {
179         HashSet<String> result = new HashSet<>();
180         String deviceManagerRoleHolderPackageName =
181                 mInjector.getDevicePolicyManagementRoleHolderPackageName(mContext);
182         if (deviceManagerRoleHolderPackageName != null) {
183             result.add(deviceManagerRoleHolderPackageName);
184         }
185         return result;
186     }
187 
188     /**
189      * Returns a subset of {@code packageNames} whose packages are mainline modules declared as
190      * required apps via their app metadata.
191      *
192      * @see DevicePolicyManager#REQUIRED_APP_MANAGED_USER
193      * @see DevicePolicyManager#REQUIRED_APP_MANAGED_DEVICE
194      * @see DevicePolicyManager#REQUIRED_APP_MANAGED_PROFILE
195      */
getRequiredAppsMainlineModules(Set<String> packageNames, String provisioningAction)196     private Set<String> getRequiredAppsMainlineModules(Set<String> packageNames,
197             String provisioningAction) {
198         final Set<String> result = new HashSet<>();
199         for (String packageName : packageNames) {
200             if (!isMainlineModule(packageName)) {
201                 continue;
202             }
203             if (!isRequiredAppDeclaredInMetadata(packageName, provisioningAction)) {
204                 continue;
205             }
206             result.add(packageName);
207         }
208         return result;
209     }
210 
isRequiredAppDeclaredInMetadata(String packageName, String provisioningAction)211     private boolean isRequiredAppDeclaredInMetadata(String packageName, String provisioningAction) {
212         PackageInfo packageInfo;
213         try {
214             packageInfo = mPm.getPackageInfo(packageName, GET_META_DATA);
215         } catch (PackageManager.NameNotFoundException e) {
216             return false;
217         }
218         if (packageInfo.applicationInfo == null || packageInfo.applicationInfo.metaData == null) {
219             return false;
220         }
221         final String metadataKey = sActionToMetadataKeyMap.get(provisioningAction);
222         return packageInfo.applicationInfo.metaData.getBoolean(metadataKey);
223     }
224 
225     /**
226      * Returns {@code true} if the provided package name is a mainline module.
227      * <p>There are 2 types of mainline modules: a regular mainline module and apk-in-apex module.
228      */
isMainlineModule(String packageName)229     private boolean isMainlineModule(String packageName) {
230         return isRegularMainlineModule(packageName) || isApkInApexMainlineModule(packageName);
231     }
232 
isRegularMainlineModule(String packageName)233     private boolean isRegularMainlineModule(String packageName) {
234         try {
235             mPm.getModuleInfo(packageName, /* flags= */ 0);
236             return true;
237         } catch (PackageManager.NameNotFoundException e) {
238             return false;
239         }
240     }
241 
isApkInApexMainlineModule(String packageName)242     private boolean isApkInApexMainlineModule(String packageName) {
243         final String apexPackageName = mInjector.getActiveApexPackageNameContainingPackage(
244                 packageName);
245         return apexPackageName != null;
246     }
247 
getLaunchableApps(int userId)248     private Set<String> getLaunchableApps(int userId) {
249         final Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
250         launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);
251         final List<ResolveInfo> resolveInfos = mPm.queryIntentActivitiesAsUser(launcherIntent,
252                 PackageManager.MATCH_UNINSTALLED_PACKAGES
253                         | PackageManager.MATCH_DISABLED_COMPONENTS
254                         | PackageManager.MATCH_DIRECT_BOOT_AWARE
255                         | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
256                 userId);
257         final Set<String> apps = new ArraySet<>();
258         for (ResolveInfo resolveInfo : resolveInfos) {
259             apps.add(resolveInfo.activityInfo.packageName);
260         }
261         return apps;
262     }
263 
getSystemInputMethods(int userId)264     private Set<String> getSystemInputMethods(int userId) {
265         final List<InputMethodInfo> inputMethods = mInjector.getInputMethodListAsUser(userId);
266         final Set<String> systemInputMethods = new ArraySet<>();
267         for (InputMethodInfo inputMethodInfo : inputMethods) {
268             ApplicationInfo applicationInfo = inputMethodInfo.getServiceInfo().applicationInfo;
269             if (applicationInfo.isSystemApp()) {
270                 systemInputMethods.add(inputMethodInfo.getPackageName());
271             }
272         }
273         return systemInputMethods;
274     }
275 
getRequiredApps(String provisioningAction, String dpcPackageName)276     private Set<String> getRequiredApps(String provisioningAction, String dpcPackageName) {
277         final Set<String> requiredApps = new ArraySet<>();
278         requiredApps.addAll(getRequiredAppsSet(provisioningAction));
279         requiredApps.addAll(getVendorRequiredAppsSet(provisioningAction));
280         requiredApps.add(dpcPackageName);
281         return requiredApps;
282     }
283 
getDisallowedApps(String provisioningAction)284     private Set<String> getDisallowedApps(String provisioningAction) {
285         final Set<String> disallowedApps = new ArraySet<>();
286         disallowedApps.addAll(getDisallowedAppsSet(provisioningAction));
287         disallowedApps.addAll(getVendorDisallowedAppsSet(provisioningAction));
288         return disallowedApps;
289     }
290 
getRequiredAppsSet(String provisioningAction)291     private Set<String> getRequiredAppsSet(String provisioningAction) {
292         final int resId = switch (provisioningAction) {
293             case ACTION_PROVISION_MANAGED_USER -> R.array.required_apps_managed_user;
294             case ACTION_PROVISION_MANAGED_PROFILE -> R.array.required_apps_managed_profile;
295             case ACTION_PROVISION_MANAGED_DEVICE -> R.array.required_apps_managed_device;
296             default -> throw new IllegalArgumentException(
297                     "Provisioning type " + provisioningAction + " not supported.");
298         };
299         return resolveStringArray(resId);
300     }
301 
getDisallowedAppsSet(String provisioningAction)302     private Set<String> getDisallowedAppsSet(String provisioningAction) {
303         final int resId = switch (provisioningAction) {
304             case ACTION_PROVISION_MANAGED_USER -> R.array.disallowed_apps_managed_user;
305             case ACTION_PROVISION_MANAGED_PROFILE -> R.array.disallowed_apps_managed_profile;
306             case ACTION_PROVISION_MANAGED_DEVICE -> R.array.disallowed_apps_managed_device;
307             default -> throw new IllegalArgumentException(
308                     "Provisioning type " + provisioningAction + " not supported.");
309         };
310         return resolveStringArray(resId);
311     }
312 
getVendorRequiredAppsSet(String provisioningAction)313     private Set<String> getVendorRequiredAppsSet(String provisioningAction) {
314         final int resId = switch (provisioningAction) {
315             case ACTION_PROVISION_MANAGED_USER -> R.array.vendor_required_apps_managed_user;
316             case ACTION_PROVISION_MANAGED_PROFILE -> R.array.vendor_required_apps_managed_profile;
317             case ACTION_PROVISION_MANAGED_DEVICE -> R.array.vendor_required_apps_managed_device;
318             default -> throw new IllegalArgumentException(
319                     "Provisioning type " + provisioningAction + " not supported.");
320         };
321         return resolveStringArray(resId);
322     }
323 
getVendorDisallowedAppsSet(String provisioningAction)324     private Set<String> getVendorDisallowedAppsSet(String provisioningAction) {
325         final int resId = switch (provisioningAction) {
326             case ACTION_PROVISION_MANAGED_USER -> R.array.vendor_disallowed_apps_managed_user;
327             case ACTION_PROVISION_MANAGED_PROFILE -> R.array.vendor_disallowed_apps_managed_profile;
328             case ACTION_PROVISION_MANAGED_DEVICE -> R.array.vendor_disallowed_apps_managed_device;
329             default -> throw new IllegalArgumentException(
330                     "Provisioning type " + provisioningAction + " not supported.");
331         };
332         return resolveStringArray(resId);
333     }
334 
resolveStringArray(@rrayRes int resId)335     private Set<String> resolveStringArray(@ArrayRes int resId) {
336         if (Flags.isRecursiveRequiredAppMergingEnabled()) {
337             return mRecursiveStringArrayResourceResolver.resolve(mContext.getPackageName(), resId);
338         } else {
339             return new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(resId)));
340         }
341     }
342 
dump(IndentingPrintWriter pw)343     void dump(IndentingPrintWriter pw) {
344         pw.println("OverlayPackagesProvider");
345         pw.increaseIndent();
346 
347         dumpApps(pw, "required_apps_managed_device",
348                 resolveStringArray(R.array.required_apps_managed_device).toArray(String[]::new));
349         dumpApps(pw, "required_apps_managed_user",
350                 resolveStringArray(R.array.required_apps_managed_user).toArray(String[]::new));
351         dumpApps(pw, "required_apps_managed_profile",
352                 resolveStringArray(R.array.required_apps_managed_profile).toArray(String[]::new));
353 
354         dumpApps(pw, "disallowed_apps_managed_device",
355                 resolveStringArray(R.array.disallowed_apps_managed_device).toArray(String[]::new));
356         dumpApps(pw, "disallowed_apps_managed_user",
357                 resolveStringArray(R.array.disallowed_apps_managed_user).toArray(String[]::new));
358         dumpApps(pw, "disallowed_apps_managed_device",
359                 resolveStringArray(R.array.disallowed_apps_managed_device).toArray(String[]::new));
360 
361         dumpApps(pw, "vendor_required_apps_managed_device",
362                 resolveStringArray(R.array.vendor_required_apps_managed_device).toArray(
363                         String[]::new));
364         dumpApps(pw, "vendor_required_apps_managed_user",
365                 resolveStringArray(R.array.vendor_required_apps_managed_user).toArray(
366                         String[]::new));
367         dumpApps(pw, "vendor_required_apps_managed_profile",
368                 resolveStringArray(R.array.vendor_required_apps_managed_profile).toArray(
369                         String[]::new));
370 
371         dumpApps(pw, "vendor_disallowed_apps_managed_user",
372                 resolveStringArray(R.array.vendor_disallowed_apps_managed_user).toArray(
373                         String[]::new));
374         dumpApps(pw, "vendor_disallowed_apps_managed_device",
375                 resolveStringArray(R.array.vendor_disallowed_apps_managed_device).toArray(
376                         String[]::new));
377         dumpApps(pw, "vendor_disallowed_apps_managed_profile",
378                 resolveStringArray(R.array.vendor_disallowed_apps_managed_profile).toArray(
379                         String[]::new));
380 
381         pw.decreaseIndent();
382     }
383 }
384