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