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