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