1 package org.robolectric.shadows; 2 3 import static android.content.IntentFilter.MATCH_CATEGORY_MASK; 4 import static android.content.pm.ApplicationInfo.FLAG_INSTALLED; 5 import static android.content.pm.ApplicationInfo.FLAG_SYSTEM; 6 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; 7 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 8 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 9 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 10 import static android.content.pm.PackageManager.DONT_KILL_APP; 11 import static android.content.pm.PackageManager.GET_ACTIVITIES; 12 import static android.content.pm.PackageManager.GET_META_DATA; 13 import static android.content.pm.PackageManager.GET_PROVIDERS; 14 import static android.content.pm.PackageManager.GET_RECEIVERS; 15 import static android.content.pm.PackageManager.GET_RESOLVED_FILTER; 16 import static android.content.pm.PackageManager.GET_SERVICES; 17 import static android.content.pm.PackageManager.GET_SIGNATURES; 18 import static android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES; 19 import static android.content.pm.PackageManager.MATCH_ALL; 20 import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; 21 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; 22 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; 23 import static android.content.pm.PackageManager.SIGNATURE_UNKNOWN_PACKAGE; 24 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; 25 import static android.os.Build.VERSION_CODES.M; 26 import static android.os.Build.VERSION_CODES.N; 27 import static android.os.Build.VERSION_CODES.O; 28 import static android.os.Build.VERSION_CODES.O_MR1; 29 import static android.os.Build.VERSION_CODES.P; 30 import static android.os.Build.VERSION_CODES.Q; 31 import static android.os.Build.VERSION_CODES.R; 32 import static android.os.Build.VERSION_CODES.S; 33 import static android.os.Build.VERSION_CODES.S_V2; 34 import static android.os.Build.VERSION_CODES.TIRAMISU; 35 import static com.google.common.base.Preconditions.checkNotNull; 36 import static org.robolectric.annotation.GetInstallerPackageNameMode.Mode.REALISTIC; 37 import static org.robolectric.util.reflector.Reflector.reflector; 38 39 import android.Manifest.permission; 40 import android.annotation.DrawableRes; 41 import android.annotation.NonNull; 42 import android.annotation.Nullable; 43 import android.annotation.RequiresPermission; 44 import android.annotation.StringRes; 45 import android.annotation.UserIdInt; 46 import android.app.ApplicationPackageManager; 47 import android.app.admin.DevicePolicyManager; 48 import android.content.ComponentName; 49 import android.content.Context; 50 import android.content.Intent; 51 import android.content.IntentFilter; 52 import android.content.IntentSender; 53 import android.content.pm.ActivityInfo; 54 import android.content.pm.ApplicationInfo; 55 import android.content.pm.ChangedPackages; 56 import android.content.pm.ComponentInfo; 57 import android.content.pm.FeatureInfo; 58 import android.content.pm.IPackageDataObserver; 59 import android.content.pm.IPackageDeleteObserver; 60 import android.content.pm.IPackageStatsObserver; 61 import android.content.pm.InstrumentationInfo; 62 import android.content.pm.IntentFilterVerificationInfo; 63 import android.content.pm.ModuleInfo; 64 import android.content.pm.PackageInfo; 65 import android.content.pm.PackageItemInfo; 66 import android.content.pm.PackageManager; 67 import android.content.pm.PackageManager.ComponentEnabledSetting; 68 import android.content.pm.PackageManager.ComponentInfoFlags; 69 import android.content.pm.PackageManager.NameNotFoundException; 70 import android.content.pm.PackageManager.OnPermissionsChangedListener; 71 import android.content.pm.PackageManager.PackageInfoFlags; 72 import android.content.pm.PackageManager.ResolveInfoFlags; 73 import android.content.pm.PackageStats; 74 import android.content.pm.PermissionGroupInfo; 75 import android.content.pm.PermissionInfo; 76 import android.content.pm.ProviderInfo; 77 import android.content.pm.ResolveInfo; 78 import android.content.pm.ServiceInfo; 79 import android.content.pm.Signature; 80 import android.content.pm.VerifierDeviceIdentity; 81 import android.content.res.AssetManager; 82 import android.content.res.Resources; 83 import android.graphics.drawable.Drawable; 84 import android.net.Uri; 85 import android.os.Build; 86 import android.os.Build.VERSION; 87 import android.os.Build.VERSION_CODES; 88 import android.os.Handler; 89 import android.os.Looper; 90 import android.os.Parcel; 91 import android.os.PersistableBundle; 92 import android.os.RemoteException; 93 import android.os.UserHandle; 94 import android.os.storage.VolumeInfo; 95 import android.telecom.TelecomManager; 96 import android.util.Log; 97 import android.util.Pair; 98 import com.google.common.base.Function; 99 import com.google.common.base.Preconditions; 100 import com.google.common.base.Splitter; 101 import com.google.common.collect.ImmutableList; 102 import com.google.common.collect.Sets; 103 import java.io.File; 104 import java.util.ArrayList; 105 import java.util.Arrays; 106 import java.util.Collections; 107 import java.util.HashMap; 108 import java.util.HashSet; 109 import java.util.Iterator; 110 import java.util.List; 111 import java.util.Map; 112 import java.util.Objects; 113 import java.util.Set; 114 import java.util.SortedMap; 115 import java.util.concurrent.Executor; 116 import java.util.function.BiConsumer; 117 import java.util.function.Consumer; 118 import org.robolectric.RuntimeEnvironment; 119 import org.robolectric.annotation.GetInstallerPackageNameMode; 120 import org.robolectric.annotation.HiddenApi; 121 import org.robolectric.annotation.Implementation; 122 import org.robolectric.annotation.Implements; 123 import org.robolectric.annotation.RealObject; 124 import org.robolectric.config.ConfigurationRegistry; 125 import org.robolectric.util.reflector.Accessor; 126 import org.robolectric.util.reflector.Direct; 127 import org.robolectric.util.reflector.ForType; 128 129 @Implements(value = ApplicationPackageManager.class, isInAndroidSdk = false, looseSignatures = true) 130 public class ShadowApplicationPackageManager extends ShadowPackageManager { 131 /** Package name of the Android platform. */ 132 private static final String PLATFORM_PACKAGE_NAME = "android"; 133 134 /** MIME type of Android Packages (APKs). */ 135 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; 136 137 /** {@link Uri} scheme of installed apps. */ 138 private static final String PACKAGE_SCHEME = "package"; 139 140 @RealObject private ApplicationPackageManager realObject; 141 private final List<String> clearedApplicationUserDataPackages = new ArrayList<>(); 142 // A map of UserIDs to default browsers. 143 private final HashMap<Integer, String> defaultBrowsers = new HashMap<>(); 144 145 @Implementation getInstalledPackages(int flags)146 public List<PackageInfo> getInstalledPackages(int flags) { 147 return getInstalledPackages((long) flags); 148 } 149 150 @Implementation(minSdk = TIRAMISU) getInstalledPackages(Object flags)151 protected List<PackageInfo> getInstalledPackages(Object flags) { 152 return getInstalledPackages(((PackageInfoFlags) flags).getValue()); 153 } 154 getInstalledPackages(long flags)155 private List<PackageInfo> getInstalledPackages(long flags) { 156 List<PackageInfo> result = new ArrayList<>(); 157 synchronized (lock) { 158 Set<String> packageNames = null; 159 if ((flags & MATCH_UNINSTALLED_PACKAGES) == 0) { 160 packageNames = packageInfos.keySet(); 161 } else { 162 packageNames = Sets.union(packageInfos.keySet(), deletedPackages); 163 } 164 for (String packageName : packageNames) { 165 try { 166 PackageInfo packageInfo = getPackageInfo(packageName, flags); 167 result.add(packageInfo); 168 } catch (NameNotFoundException e) { 169 Log.i(TAG, String.format("Package %s filtered out: %s", packageName, e.getMessage())); 170 } 171 } 172 } 173 return result; 174 } 175 176 @Implementation(minSdk = Q) getInstalledModules(int flags)177 protected List<ModuleInfo> getInstalledModules(int flags) { 178 synchronized (lock) { 179 List<ModuleInfo> result = new ArrayList<>(); 180 for (String moduleName : moduleInfos.keySet()) { 181 try { 182 ModuleInfo moduleInfo = (ModuleInfo) getModuleInfo(moduleName, flags); 183 result.add(moduleInfo); 184 } catch (NameNotFoundException e) { 185 Log.i(TAG, String.format("Module %s filtered out: %s", moduleName, e.getMessage())); 186 } 187 } 188 return result; 189 } 190 } 191 192 @Implementation(minSdk = Q) getModuleInfo(String packageName, int flags)193 protected Object getModuleInfo(String packageName, int flags) throws NameNotFoundException { 194 synchronized (lock) { 195 // Double checks that the respective package matches and is not disabled 196 getPackageInfo(packageName, flags); 197 Object info = moduleInfos.get(packageName); 198 if (info == null) { 199 throw new NameNotFoundException("Module: " + packageName + " is not installed."); 200 } 201 202 return info; 203 } 204 } 205 206 @Implementation getActivityInfo(ComponentName component, int flags)207 protected ActivityInfo getActivityInfo(ComponentName component, int flags) 208 throws NameNotFoundException { 209 return getComponentInfo( 210 component, 211 flags, 212 packageInfo -> packageInfo.activities, 213 resolveInfo -> resolveInfo.activityInfo, 214 ActivityInfo::new); 215 } 216 getComponentInfo( ComponentName component, int flags, Function<PackageInfo, T[]> componentsInPackage, Function<ResolveInfo, T> componentInResolveInfo, Function<T, T> copyConstructor)217 private <T extends ComponentInfo> T getComponentInfo( 218 ComponentName component, 219 int flags, 220 Function<PackageInfo, T[]> componentsInPackage, 221 Function<ResolveInfo, T> componentInResolveInfo, 222 Function<T, T> copyConstructor) 223 throws NameNotFoundException { 224 String activityName = component.getClassName(); 225 String packageName = component.getPackageName(); 226 PackageInfo packageInfo = getInternalMutablePackageInfo(packageName); 227 T result = null; 228 ApplicationInfo appInfo = null; 229 // search in the manifest 230 if (packageInfo != null) { 231 if (packageInfo.applicationInfo != null) { 232 appInfo = packageInfo.applicationInfo; 233 } 234 T[] components = componentsInPackage.apply(packageInfo); 235 if (components != null) { 236 for (T activity : components) { 237 if (activityName.equals(activity.name)) { 238 result = copyConstructor.apply(activity); 239 break; 240 } 241 } 242 } 243 } 244 if (result == null) { 245 // look in the registered intents 246 outer: 247 for (List<ResolveInfo> listOfResolveInfo : resolveInfoForIntent.values()) { 248 for (ResolveInfo resolveInfo : listOfResolveInfo) { 249 T info = componentInResolveInfo.apply(resolveInfo); 250 if (isValidComponentInfo(info) 251 && component.equals(new ComponentName(info.applicationInfo.packageName, info.name))) { 252 result = copyConstructor.apply(info); 253 if (appInfo == null) { 254 // we found valid app info in the resolve info. Use it. 255 appInfo = result.applicationInfo; 256 } 257 break outer; 258 } 259 } 260 } 261 } 262 if (result == null) { 263 throw new NameNotFoundException("Component not found: " + component); 264 } 265 if (appInfo == null) { 266 appInfo = new ApplicationInfo(); 267 appInfo.packageName = packageName; 268 appInfo.flags = ApplicationInfo.FLAG_INSTALLED; 269 } else { 270 appInfo = new ApplicationInfo(appInfo); 271 } 272 result.applicationInfo = appInfo; 273 applyFlagsToComponentInfo(result, flags); 274 return result; 275 } 276 277 @Implementation hasSystemFeature(String name)278 protected boolean hasSystemFeature(String name) { 279 return systemFeatureList.containsKey(name) ? systemFeatureList.get(name) : false; 280 } 281 282 @Implementation getComponentEnabledSetting(ComponentName componentName)283 protected int getComponentEnabledSetting(ComponentName componentName) { 284 ComponentState state = componentList.get(componentName); 285 return state != null ? state.newState : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 286 } 287 288 @Implementation getNameForUid(int uid)289 protected @Nullable String getNameForUid(int uid) { 290 return namesForUid.get(uid); 291 } 292 293 @Implementation 294 @Override getPackagesForUid(int uid)295 protected @Nullable String[] getPackagesForUid(int uid) { 296 String[] packageNames = packagesForUid.get(uid); 297 if (packageNames != null) { 298 return packageNames; 299 } 300 301 Set<String> results = new HashSet<>(); 302 synchronized (lock) { 303 for (PackageInfo packageInfo : packageInfos.values()) { 304 if (packageInfo.applicationInfo != null && packageInfo.applicationInfo.uid == uid) { 305 results.add(packageInfo.packageName); 306 } 307 } 308 } 309 310 return results.isEmpty() ? null : results.toArray(new String[results.size()]); 311 } 312 313 @Implementation getApplicationEnabledSetting(String packageName)314 protected int getApplicationEnabledSetting(String packageName) { 315 synchronized (lock) { 316 if (!packageInfos.containsKey(packageName)) { 317 throw new IllegalArgumentException("Package doesn't exist: " + packageName); 318 } 319 } 320 321 return applicationEnabledSettingMap.get(packageName); 322 } 323 324 @Implementation getProviderInfo(ComponentName component, int flags)325 protected ProviderInfo getProviderInfo(ComponentName component, int flags) 326 throws NameNotFoundException { 327 return getComponentInfo( 328 component, 329 flags, 330 packageInfo -> packageInfo.providers, 331 resolveInfo -> resolveInfo.providerInfo, 332 ProviderInfo::new); 333 } 334 335 @Implementation setComponentEnabledSetting(ComponentName componentName, int newState, int flags)336 protected void setComponentEnabledSetting(ComponentName componentName, int newState, int flags) { 337 componentList.put(componentName, new ComponentState(newState, flags)); 338 } 339 340 @Implementation(minSdk = TIRAMISU) setComponentEnabledSettings(List<ComponentEnabledSetting> settings)341 protected void setComponentEnabledSettings(List<ComponentEnabledSetting> settings) { 342 for (ComponentEnabledSetting setting : settings) { 343 componentList.put( 344 setting.getComponentName(), 345 new ComponentState(setting.getEnabledState(), setting.getEnabledFlags())); 346 } 347 } 348 349 @Implementation(minSdk = Q) setSyntheticAppDetailsActivityEnabled(String packageName, boolean enabled)350 protected void setSyntheticAppDetailsActivityEnabled(String packageName, boolean enabled) { 351 ComponentName componentName = 352 new ComponentName(packageName, PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME); 353 setComponentEnabledSetting( 354 componentName, 355 enabled ? COMPONENT_ENABLED_STATE_DEFAULT : COMPONENT_ENABLED_STATE_DISABLED, 356 DONT_KILL_APP); 357 } 358 359 @Implementation(minSdk = Q) getSyntheticAppDetailsActivityEnabled(String packageName)360 protected boolean getSyntheticAppDetailsActivityEnabled(String packageName) { 361 ComponentName componentName = 362 new ComponentName(packageName, PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME); 363 int state = getComponentEnabledSetting(componentName); 364 return state == COMPONENT_ENABLED_STATE_ENABLED || state == COMPONENT_ENABLED_STATE_DEFAULT; 365 } 366 367 @Implementation setApplicationEnabledSetting(String packageName, int newState, int flags)368 protected void setApplicationEnabledSetting(String packageName, int newState, int flags) { 369 applicationEnabledSettingMap.put(packageName, newState); 370 } 371 372 @Implementation resolveActivity(Intent intent, int flags)373 protected ResolveInfo resolveActivity(Intent intent, int flags) { 374 List<ResolveInfo> candidates = queryIntentActivities(intent, flags); 375 if (candidates.isEmpty()) { 376 return null; 377 } 378 if (candidates.size() == 1) { 379 return candidates.get(0); 380 } 381 ResolveInfo persistentPreferredResolveInfo = 382 resolvePreferredActivity(intent, candidates, persistentPreferredActivities); 383 if (persistentPreferredResolveInfo != null) { 384 return persistentPreferredResolveInfo; 385 } 386 ResolveInfo preferredResolveInfo = 387 resolvePreferredActivity(intent, candidates, preferredActivities); 388 if (preferredResolveInfo != null) { 389 return preferredResolveInfo; 390 } 391 if (!shouldShowActivityChooser) { 392 return candidates.get(0); 393 } 394 ResolveInfo c1 = candidates.get(0); 395 ResolveInfo c2 = candidates.get(1); 396 if (c1.preferredOrder == c2.preferredOrder 397 && isValidComponentInfo(c1.activityInfo) 398 && isValidComponentInfo(c2.activityInfo)) { 399 // When the top pick is as good as the second and is not preferred explicitly show the 400 // chooser 401 ResolveInfo result = new ResolveInfo(); 402 result.activityInfo = new ActivityInfo(); 403 result.activityInfo.name = "ActivityResolver"; 404 result.activityInfo.packageName = "android"; 405 result.activityInfo.applicationInfo = new ApplicationInfo(); 406 result.activityInfo.applicationInfo.flags = FLAG_INSTALLED | FLAG_SYSTEM; 407 result.activityInfo.applicationInfo.packageName = "android"; 408 return result; 409 } else { 410 return c1; 411 } 412 } 413 resolvePreferredActivity( Intent intent, List<ResolveInfo> candidates, SortedMap<ComponentName, List<IntentFilter>> preferredActivities)414 private ResolveInfo resolvePreferredActivity( 415 Intent intent, 416 List<ResolveInfo> candidates, 417 SortedMap<ComponentName, List<IntentFilter>> preferredActivities) { 418 preferredActivities = mapForPackage(preferredActivities, intent.getPackage()); 419 for (ResolveInfo candidate : candidates) { 420 ActivityInfo activityInfo = candidate.activityInfo; 421 if (!isValidComponentInfo(activityInfo)) { 422 continue; 423 } 424 ComponentName candidateName = 425 new ComponentName(activityInfo.applicationInfo.packageName, activityInfo.name); 426 List<IntentFilter> intentFilters = preferredActivities.get(candidateName); 427 if (intentFilters == null) { 428 continue; 429 } 430 for (IntentFilter filter : intentFilters) { 431 if ((filter.match(getContext().getContentResolver(), intent, false, "robo") 432 & MATCH_CATEGORY_MASK) 433 != 0) { 434 return candidate; 435 } 436 } 437 } 438 return null; 439 } 440 441 @Implementation resolveContentProvider(String name, int flags)442 protected ProviderInfo resolveContentProvider(String name, int flags) { 443 if (name == null) { 444 return null; 445 } 446 synchronized (lock) { 447 for (PackageInfo packageInfo : packageInfos.values()) { 448 if (packageInfo.providers == null) { 449 continue; 450 } 451 452 for (ProviderInfo providerInfo : packageInfo.providers) { 453 for (String authority : Splitter.on(';').split(providerInfo.authority)) { 454 if (name.equals(authority)) { 455 return new ProviderInfo(providerInfo); 456 } 457 } 458 } 459 } 460 } 461 return null; 462 } 463 464 @Implementation resolveContentProviderAsUser( String name, int flags, @UserIdInt int userId)465 protected ProviderInfo resolveContentProviderAsUser( 466 String name, int flags, @UserIdInt int userId) { 467 return null; 468 } 469 470 @Implementation getPackageInfo(String packageName, int flags)471 protected PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException { 472 return getPackageInfo(packageName, (long) flags); 473 } 474 475 @Implementation(minSdk = TIRAMISU) getPackageInfo(Object packageName, Object flags)476 protected PackageInfo getPackageInfo(Object packageName, Object flags) 477 throws NameNotFoundException { 478 return getPackageInfo((String) packageName, ((PackageInfoFlags) flags).getValue()); 479 } 480 getPackageInfo(String packageName, long flags)481 private PackageInfo getPackageInfo(String packageName, long flags) throws NameNotFoundException { 482 synchronized (lock) { 483 PackageInfo info = packageInfos.get(packageName); 484 if (info == null 485 && (flags & MATCH_UNINSTALLED_PACKAGES) != 0 486 && deletedPackages.contains(packageName)) { 487 info = new PackageInfo(); 488 info.packageName = packageName; 489 info.applicationInfo = new ApplicationInfo(); 490 info.applicationInfo.packageName = packageName; 491 } 492 if (info == null) { 493 throw new NameNotFoundException(packageName); 494 } 495 info = newPackageInfo(info); 496 if (info.applicationInfo == null) { 497 return info; 498 } 499 if (hiddenPackages.contains(packageName) && !isFlagSet(flags, MATCH_UNINSTALLED_PACKAGES)) { 500 throw new NameNotFoundException("Package is hidden, can't find"); 501 } 502 applyFlagsToApplicationInfo(info.applicationInfo, flags); 503 info.activities = 504 applyFlagsToComponentInfoList(info.activities, flags, GET_ACTIVITIES, ActivityInfo::new); 505 info.services = 506 applyFlagsToComponentInfoList(info.services, flags, GET_SERVICES, ServiceInfo::new); 507 info.receivers = 508 applyFlagsToComponentInfoList(info.receivers, flags, GET_RECEIVERS, ActivityInfo::new); 509 info.providers = 510 applyFlagsToComponentInfoList(info.providers, flags, GET_PROVIDERS, ProviderInfo::new); 511 return info; 512 } 513 } 514 515 /** 516 * Starting in Android S, this method was moved from {@link android.content.pm.PackageManager} to 517 * {@link ApplicationPackageManager}. However, it was moved back to {@link 518 * android.content.pm.PackageManager} in T. 519 */ 520 @Override 521 @Implementation(minSdk = S, maxSdk = S_V2) getPackageArchiveInfo(String archiveFilePath, int flags)522 protected PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) { 523 int apiLevel = RuntimeEnvironment.getApiLevel(); 524 if (apiLevel == S || apiLevel == S_V2) { 525 526 PackageInfo shadowPackageInfo = getShadowPackageArchiveInfo(archiveFilePath, flags); 527 if (shadowPackageInfo != null) { 528 return shadowPackageInfo; 529 } else { 530 return reflector(ReflectorApplicationPackageManager.class, realObject) 531 .getPackageArchiveInfo(archiveFilePath, flags); 532 } 533 } else { 534 return super.getPackageArchiveInfo(archiveFilePath, flags); 535 } 536 } 537 538 // There is no copy constructor for PackageInfo newPackageInfo(PackageInfo orig)539 private static PackageInfo newPackageInfo(PackageInfo orig) { 540 Parcel parcel = Parcel.obtain(); 541 orig.writeToParcel(parcel, 0); 542 parcel.setDataPosition(0); 543 return PackageInfo.CREATOR.createFromParcel(parcel); 544 } 545 applyFlagsToComponentInfoList( T[] components, long flags, int activationFlag, Function<T, T> copyConstructor)546 private <T extends ComponentInfo> T[] applyFlagsToComponentInfoList( 547 T[] components, long flags, int activationFlag, Function<T, T> copyConstructor) { 548 if (components == null || (flags & activationFlag) == 0) { 549 return null; 550 } 551 List<T> returned = new ArrayList<>(components.length); 552 for (T component : components) { 553 component = copyConstructor.apply(component); 554 try { 555 applyFlagsToComponentInfo(component, flags); 556 returned.add(component); 557 } catch (NameNotFoundException e) { 558 // skip this component 559 } 560 } 561 if (returned.isEmpty()) { 562 return null; 563 } 564 @SuppressWarnings("unchecked") // component arrays are of their respective types. 565 Class<T[]> componentArrayType = (Class<T[]>) components.getClass(); 566 T[] result = Arrays.copyOf(components, returned.size(), componentArrayType); 567 return returned.toArray(result); 568 } 569 570 @Implementation queryIntentServices(Intent intent, int flags)571 protected List<ResolveInfo> queryIntentServices(Intent intent, int flags) { 572 return queryIntentComponents( 573 intent, 574 flags, 575 (pkg) -> pkg.services, 576 serviceFilters, 577 (resolveInfo, serviceInfo) -> resolveInfo.serviceInfo = serviceInfo, 578 (resolveInfo) -> resolveInfo.serviceInfo, 579 ServiceInfo::new); 580 } 581 hasSomeComponentInfo(ResolveInfo resolveInfo)582 private boolean hasSomeComponentInfo(ResolveInfo resolveInfo) { 583 584 return resolveInfo.activityInfo != null 585 || resolveInfo.serviceInfo != null 586 || resolveInfo.providerInfo != null; 587 } 588 isFlagSet(long flags, long matchFlag)589 private static boolean isFlagSet(long flags, long matchFlag) { 590 return (flags & matchFlag) == matchFlag; 591 } 592 isValidComponentInfo(ComponentInfo componentInfo)593 private static boolean isValidComponentInfo(ComponentInfo componentInfo) { 594 return componentInfo != null 595 && componentInfo.applicationInfo != null 596 && componentInfo.applicationInfo.packageName != null 597 && componentInfo.name != null; 598 } 599 600 /** Behaves as {@link #queryIntentServices(Intent, int)} and currently ignores userId. */ 601 @Implementation queryIntentServicesAsUser(Intent intent, int flags, int userId)602 protected List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) { 603 return queryIntentServices(intent, flags); 604 } 605 606 @Implementation queryIntentActivities(Intent intent, int flags)607 protected List<ResolveInfo> queryIntentActivities(Intent intent, int flags) { 608 return this.queryIntentComponents( 609 intent, 610 flags, 611 (pkg) -> pkg.activities, 612 activityFilters, 613 (resolveInfo, activityInfo) -> resolveInfo.activityInfo = activityInfo, 614 (resolveInfo) -> resolveInfo.activityInfo, 615 ActivityInfo::new); 616 } 617 queryIntentComponents( Intent intent, int flags, Function<PackageInfo, I[]> componentsInPackage, SortedMap<ComponentName, List<IntentFilter>> filters, BiConsumer<ResolveInfo, I> componentSetter, Function<ResolveInfo, I> componentInResolveInfo, Function<I, I> copyConstructor)618 private <I extends ComponentInfo> List<ResolveInfo> queryIntentComponents( 619 Intent intent, 620 int flags, 621 Function<PackageInfo, I[]> componentsInPackage, 622 SortedMap<ComponentName, List<IntentFilter>> filters, 623 BiConsumer<ResolveInfo, I> componentSetter, 624 Function<ResolveInfo, I> componentInResolveInfo, 625 Function<I, I> copyConstructor) { 626 synchronized (lock) { 627 if (intent.getComponent() != null) { 628 flags &= ~MATCH_DEFAULT_ONLY; 629 } 630 List<ResolveInfo> result = new ArrayList<>(); 631 List<ResolveInfo> resolveInfoList = queryOverriddenIntents(intent, flags); 632 if (!resolveInfoList.isEmpty()) { 633 result.addAll(resolveInfoList); 634 } 635 636 result.addAll( 637 queryComponentsInManifest(intent, componentsInPackage, filters, componentSetter)); 638 639 for (Iterator<ResolveInfo> iterator = result.iterator(); iterator.hasNext(); ) { 640 ResolveInfo resolveInfo = iterator.next(); 641 I componentInfo = componentInResolveInfo.apply(resolveInfo); 642 if (hasSomeComponentInfo(resolveInfo) && componentInfo == null) { 643 Log.d(TAG, "ResolveInfo for different component type"); 644 // different component type 645 iterator.remove(); 646 continue; 647 } 648 if (componentInfo == null) { 649 // null component? Don't filter this sh... 650 continue; 651 } 652 if (!applyFlagsToResolveInfo(resolveInfo, flags)) { 653 Log.d(TAG, "ResolveInfo doesn't match flags"); 654 iterator.remove(); 655 continue; 656 } 657 ApplicationInfo applicationInfo = componentInfo.applicationInfo; 658 if (applicationInfo == null) { 659 String packageName = null; 660 if (getComponentForIntent(intent) != null) { 661 packageName = getComponentForIntent(intent).getPackageName(); 662 } else if (intent.getPackage() != null) { 663 packageName = intent.getPackage(); 664 } else if (componentInfo.packageName != null) { 665 packageName = componentInfo.packageName; 666 } 667 if (packageName != null) { 668 PackageInfo packageInfo = packageInfos.get(packageName); 669 if (packageInfo != null && packageInfo.applicationInfo != null) { 670 applicationInfo = new ApplicationInfo(packageInfo.applicationInfo); 671 } else { 672 applicationInfo = new ApplicationInfo(); 673 applicationInfo.packageName = packageName; 674 applicationInfo.flags = FLAG_INSTALLED; 675 } 676 } 677 } else { 678 applicationInfo = new ApplicationInfo(applicationInfo); 679 } 680 componentInfo = copyConstructor.apply(componentInfo); 681 componentSetter.accept(resolveInfo, componentInfo); 682 componentInfo.applicationInfo = applicationInfo; 683 684 try { 685 applyFlagsToComponentInfo(componentInfo, flags); 686 } catch (NameNotFoundException e) { 687 Log.d(TAG, "ComponentInfo doesn't match flags:" + e.getMessage()); 688 iterator.remove(); 689 continue; 690 } 691 } 692 Collections.sort(result, new ResolveInfoComparator()); 693 return result; 694 } 695 } 696 applyFlagsToResolveInfo(ResolveInfo resolveInfo, int flags)697 private boolean applyFlagsToResolveInfo(ResolveInfo resolveInfo, int flags) { 698 if ((flags & GET_RESOLVED_FILTER) == 0) { 699 resolveInfo.filter = null; 700 } 701 return (flags & MATCH_DEFAULT_ONLY) == 0 || resolveInfo.isDefault; 702 } 703 queryComponentsInManifest( Intent intent, Function<PackageInfo, I[]> componentsInPackage, SortedMap<ComponentName, List<IntentFilter>> filters, BiConsumer<ResolveInfo, I> componentSetter)704 private <I extends ComponentInfo> ImmutableList<ResolveInfo> queryComponentsInManifest( 705 Intent intent, 706 Function<PackageInfo, I[]> componentsInPackage, 707 SortedMap<ComponentName, List<IntentFilter>> filters, 708 BiConsumer<ResolveInfo, I> componentSetter) { 709 synchronized (lock) { 710 if (isExplicitIntent(intent)) { 711 ComponentName component = getComponentForIntent(intent); 712 PackageInfo appPackage = packageInfos.get(component.getPackageName()); 713 if (appPackage == null) { 714 return ImmutableList.of(); 715 } 716 I componentInfo = findMatchingComponent(component, componentsInPackage.apply(appPackage)); 717 if (componentInfo != null) { 718 List<IntentFilter> componentFilters = filters.get(component); 719 PackageInfo targetPackage = packageInfos.get(component.getPackageName()); 720 if (RuntimeEnvironment.getApiLevel() >= TIRAMISU 721 && (intent.getAction() != null 722 || intent.getCategories() != null 723 || intent.getData() != null) 724 && componentFilters != null 725 && !component.getPackageName().equals(getContext().getPackageName()) 726 && targetPackage.applicationInfo.targetSdkVersion >= TIRAMISU) { 727 // Check if the explicit intent matches filters on the target component for T+ 728 boolean matchFound = false; 729 for (IntentFilter filter : componentFilters) { 730 if (matchIntentFilter(intent, filter) > 0) { 731 matchFound = true; 732 break; 733 } 734 } 735 if (!matchFound) { 736 Log.w( 737 TAG, 738 "Component " 739 + componentInfo 740 + " doesn't have required intent filters for " 741 + intent); 742 return ImmutableList.of(); 743 } 744 } 745 ResolveInfo resolveInfo = buildResolveInfo(componentInfo); 746 componentSetter.accept(resolveInfo, componentInfo); 747 return ImmutableList.copyOf(new ArrayList<>(Collections.singletonList(resolveInfo))); 748 } 749 750 return ImmutableList.of(); 751 } else { 752 List<ResolveInfo> resolveInfoList = new ArrayList<>(); 753 Map<ComponentName, List<IntentFilter>> filtersForPackage = 754 mapForPackage(filters, intent.getPackage()); 755 components: 756 for (Map.Entry<ComponentName, List<IntentFilter>> componentEntry : 757 filtersForPackage.entrySet()) { 758 ComponentName componentName = componentEntry.getKey(); 759 for (IntentFilter filter : componentEntry.getValue()) { 760 int match = matchIntentFilter(intent, filter); 761 if (match > 0) { 762 PackageInfo packageInfo = packageInfos.get(componentName.getPackageName()); 763 I[] componentInfoArray = componentsInPackage.apply(packageInfo); 764 if (componentInfoArray != null) { 765 for (I componentInfo : componentInfoArray) { 766 if (!componentInfo.name.equals(componentName.getClassName())) { 767 continue; 768 } 769 ResolveInfo resolveInfo = buildResolveInfo(componentInfo, filter); 770 resolveInfo.match = match; 771 componentSetter.accept(resolveInfo, componentInfo); 772 resolveInfoList.add(resolveInfo); 773 continue components; 774 } 775 } 776 } 777 } 778 } 779 return ImmutableList.copyOf(resolveInfoList); 780 } 781 } 782 } 783 784 /** Behaves as {@link #queryIntentActivities(Intent, int)} and currently ignores userId. */ 785 @Implementation queryIntentActivitiesAsUser(Intent intent, int flags, int userId)786 protected List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) { 787 return queryIntentActivities(intent, flags); 788 } 789 790 /** Behaves as {@link #queryIntentActivities(Intent, int)} and currently ignores userId. */ 791 @Implementation(minSdk = TIRAMISU) queryIntentActivitiesAsUser( Object intent, Object flags, Object userId)792 protected List<ResolveInfo> queryIntentActivitiesAsUser( 793 /*Intent*/ Object intent, /*ResolveInfoFlags*/ Object flags, /*int*/ Object userId) { 794 return queryIntentActivities((Intent) intent, (int) ((ResolveInfoFlags) flags).getValue()); 795 } 796 797 /** Returns true if intent has specified a specific component. */ isExplicitIntent(Intent intent)798 private static boolean isExplicitIntent(Intent intent) { 799 return getComponentForIntent(intent) != null; 800 } 801 findMatchingComponent( ComponentName componentName, T[] components)802 private static <T extends ComponentInfo> T findMatchingComponent( 803 ComponentName componentName, T[] components) { 804 if (components == null) { 805 return null; 806 } 807 for (T component : components) { 808 if (componentName.equals(new ComponentName(component.packageName, component.name))) { 809 return component; 810 } 811 } 812 return null; 813 } 814 getComponentForIntent(Intent intent)815 private static ComponentName getComponentForIntent(Intent intent) { 816 ComponentName component = intent.getComponent(); 817 if (component == null) { 818 if (intent.getSelector() != null) { 819 intent = intent.getSelector(); 820 component = intent.getComponent(); 821 } 822 } 823 return component; 824 } 825 buildResolveInfo(ComponentInfo componentInfo)826 private static ResolveInfo buildResolveInfo(ComponentInfo componentInfo) { 827 ResolveInfo resolveInfo = new ResolveInfo(); 828 resolveInfo.resolvePackageName = componentInfo.applicationInfo.packageName; 829 resolveInfo.labelRes = componentInfo.labelRes; 830 resolveInfo.icon = componentInfo.icon; 831 resolveInfo.nonLocalizedLabel = componentInfo.nonLocalizedLabel; 832 return resolveInfo; 833 } 834 buildResolveInfo(ComponentInfo componentInfo, IntentFilter intentFilter)835 static ResolveInfo buildResolveInfo(ComponentInfo componentInfo, IntentFilter intentFilter) { 836 ResolveInfo info = buildResolveInfo(componentInfo); 837 info.isDefault = intentFilter.hasCategory("android.intent.category.DEFAULT"); 838 info.filter = new IntentFilter(intentFilter); 839 info.priority = intentFilter.getPriority(); 840 return info; 841 } 842 843 @Implementation checkPermission(String permName, String pkgName)844 protected int checkPermission(String permName, String pkgName) { 845 PackageInfo permissionsInfo = getInternalMutablePackageInfo(pkgName); 846 if (permissionsInfo == null || permissionsInfo.requestedPermissions == null) { 847 return PackageManager.PERMISSION_DENIED; 848 } 849 850 String permission; 851 for (int i = 0; i < permissionsInfo.requestedPermissions.length; i++) { 852 permission = permissionsInfo.requestedPermissions[i]; 853 if (permission != null && permission.equals(permName)) { 854 // The package requests this permission. Now check if it's been granted to the package. 855 if (isGrantedForBackwardsCompatibility(pkgName, permissionsInfo)) { 856 return PackageManager.PERMISSION_GRANTED; 857 } 858 859 if ((permissionsInfo.requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) 860 == REQUESTED_PERMISSION_GRANTED) { 861 return PackageManager.PERMISSION_GRANTED; 862 } 863 } 864 } 865 866 return PackageManager.PERMISSION_DENIED; 867 } 868 869 /** 870 * Returns whether a permission should be treated as granted to the package for backward 871 * compatibility reasons. 872 * 873 * <p>Before Robolectric 4.0 the ShadowPackageManager treated every requested permission as 874 * automatically granted. 4.0 changes this behavior, and only treats a permission as granted if 875 * PackageInfo.requestedPermissionFlags[permissionIndex] & REQUESTED_PERMISSION_GRANTED == 876 * REQUESTED_PERMISSION_GRANTED which matches the real PackageManager's behavior. 877 * 878 * <p>Since many existing tests didn't set the requestedPermissionFlags on their {@code 879 * PackageInfo} objects, but assumed that all permissions are granted, we auto-grant all 880 * permissions if the requestedPermissionFlags is not set. If the requestedPermissionFlags is set, 881 * we assume that the test is configuring the permission grant state, and we don't override this 882 * setting. 883 */ isGrantedForBackwardsCompatibility(String pkgName, PackageInfo permissionsInfo)884 private boolean isGrantedForBackwardsCompatibility(String pkgName, PackageInfo permissionsInfo) { 885 // Note: it might be cleaner to auto-grant these permissions when the package is added to the 886 // PackageManager. But many existing tests modify the requested permissions _after_ adding the 887 // package to the PackageManager, without updating the requestedPermissionsFlags. 888 return permissionsInfo.requestedPermissionsFlags == null 889 // Robolectric uses the PackageParser to create the current test package's PackageInfo from 890 // the manifest XML. The parser populates the requestedPermissionsFlags, but doesn't grant 891 // the permissions. Several tests rely on the test package being granted all permissions, so 892 // we treat this as a special case. 893 || pkgName.equals(RuntimeEnvironment.getApplication().getPackageName()); 894 } 895 896 @Implementation getReceiverInfo(ComponentName component, int flags)897 protected ActivityInfo getReceiverInfo(ComponentName component, int flags) 898 throws NameNotFoundException { 899 return getComponentInfo( 900 component, 901 flags, 902 packageInfo -> packageInfo.receivers, 903 resolveInfo -> resolveInfo.activityInfo, 904 ActivityInfo::new); 905 } 906 907 @Implementation(minSdk = TIRAMISU) getReceiverInfo( Object component, Object flags)908 protected ActivityInfo getReceiverInfo( 909 /*ComponentName*/ Object component, /*ComponentInfoFlags*/ Object flags) 910 throws NameNotFoundException { 911 return getReceiverInfo( 912 (ComponentName) component, (int) ((ComponentInfoFlags) flags).getValue()); 913 } 914 915 @Implementation queryBroadcastReceivers(Intent intent, int flags)916 protected List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) { 917 return this.queryIntentComponents( 918 intent, 919 flags, 920 (pkg) -> pkg.receivers, 921 receiverFilters, 922 (resolveInfo, activityInfo) -> resolveInfo.activityInfo = activityInfo, 923 (resolveInfo) -> resolveInfo.activityInfo, 924 ActivityInfo::new); 925 } 926 927 @Implementation(minSdk = TIRAMISU) queryBroadcastReceivers( Object intent, Object flags)928 protected List<ResolveInfo> queryBroadcastReceivers( 929 /*Intent*/ Object intent, /*ResolveInfoFlags*/ Object flags) { 930 return queryBroadcastReceivers((Intent) intent, (int) ((ResolveInfoFlags) flags).getValue()); 931 } 932 matchIntentFilter(Intent intent, IntentFilter intentFilter)933 private static int matchIntentFilter(Intent intent, IntentFilter intentFilter) { 934 return intentFilter.match( 935 intent.getAction(), 936 intent.getType(), 937 intent.getScheme(), 938 intent.getData(), 939 intent.getCategories(), 940 TAG); 941 } 942 943 @Implementation resolveService(Intent intent, int flags)944 protected ResolveInfo resolveService(Intent intent, int flags) { 945 List<ResolveInfo> candidates = queryIntentServices(intent, flags); 946 return candidates.isEmpty() ? null : candidates.get(0); 947 } 948 949 @Implementation getServiceInfo(ComponentName component, int flags)950 protected ServiceInfo getServiceInfo(ComponentName component, int flags) 951 throws NameNotFoundException { 952 return getComponentInfo( 953 component, 954 flags, 955 packageInfo -> packageInfo.services, 956 resolveInfo -> resolveInfo.serviceInfo, 957 ServiceInfo::new); 958 } 959 960 @Implementation(minSdk = TIRAMISU) getServiceInfo( Object component, Object flags)961 protected ServiceInfo getServiceInfo( 962 /*ComponentName*/ Object component, /*ComponentInfoFlags*/ Object flags) 963 throws NameNotFoundException { 964 return getServiceInfo((ComponentName) component, (int) ((ComponentInfoFlags) flags).getValue()); 965 } 966 967 /** 968 * Modifies the component in place using. 969 * 970 * @throws NameNotFoundException when component is filtered out by a flag 971 */ applyFlagsToComponentInfo(ComponentInfo componentInfo, long flags)972 private void applyFlagsToComponentInfo(ComponentInfo componentInfo, long flags) 973 throws NameNotFoundException { 974 componentInfo.name = (componentInfo.name == null) ? "" : componentInfo.name; 975 ApplicationInfo applicationInfo = componentInfo.applicationInfo; 976 boolean isApplicationEnabled = true; 977 if (applicationInfo != null) { 978 if (applicationInfo.packageName == null) { 979 applicationInfo.packageName = componentInfo.packageName; 980 } 981 applyFlagsToApplicationInfo(componentInfo.applicationInfo, flags); 982 componentInfo.packageName = applicationInfo.packageName; 983 isApplicationEnabled = applicationInfo.enabled; 984 } 985 if ((flags & GET_META_DATA) == 0) { 986 componentInfo.metaData = null; 987 } 988 boolean isComponentEnabled = isComponentEnabled(componentInfo); 989 if ((flags & MATCH_ALL) != 0 && Build.VERSION.SDK_INT >= 23) { 990 return; 991 } 992 // Android don't override the enabled field of component with the actual value. 993 boolean isEnabledForFiltering = 994 isComponentEnabled && (Build.VERSION.SDK_INT >= 24 ? isApplicationEnabled : true); 995 if ((flags & MATCH_DISABLED_COMPONENTS) == 0 && !isEnabledForFiltering) { 996 throw new NameNotFoundException("Disabled component: " + componentInfo); 997 } 998 if (isFlagSet(flags, PackageManager.MATCH_SYSTEM_ONLY)) { 999 if (applicationInfo == null) { 1000 // TODO: for backwards compatibility just skip filtering. In future should just remove 1001 // invalid resolve infos from list 1002 } else { 1003 final int applicationFlags = applicationInfo.flags; 1004 if ((applicationFlags & ApplicationInfo.FLAG_SYSTEM) != ApplicationInfo.FLAG_SYSTEM) { 1005 throw new NameNotFoundException("Not system component: " + componentInfo); 1006 } 1007 } 1008 } 1009 if (!isFlagSet(flags, MATCH_UNINSTALLED_PACKAGES) 1010 && isValidComponentInfo(componentInfo) 1011 && hiddenPackages.contains(componentInfo.applicationInfo.packageName)) { 1012 throw new NameNotFoundException("Uninstalled package: " + componentInfo); 1013 } 1014 } 1015 1016 @Implementation getResourcesForApplication(@onNull ApplicationInfo applicationInfo)1017 protected Resources getResourcesForApplication(@NonNull ApplicationInfo applicationInfo) 1018 throws PackageManager.NameNotFoundException { 1019 synchronized (lock) { 1020 if (getContext().getPackageName().equals(applicationInfo.packageName)) { 1021 return getContext().getResources(); 1022 } else if (packageInfos.containsKey(applicationInfo.packageName)) { 1023 Resources appResources = resources.get(applicationInfo.packageName); 1024 if (appResources == null) { 1025 appResources = new Resources(new AssetManager(), null, null); 1026 resources.put(applicationInfo.packageName, appResources); 1027 } 1028 return appResources; 1029 } 1030 Resources resources = null; 1031 1032 try { 1033 resources = 1034 reflector(ReflectorApplicationPackageManager.class, realObject) 1035 .getResourcesForApplication(applicationInfo); 1036 } catch (Exception ex) { 1037 // handled below 1038 } 1039 if (resources == null) { 1040 throw new NameNotFoundException(applicationInfo.packageName); 1041 } 1042 return resources; 1043 } 1044 } 1045 1046 @Implementation getInstalledApplications(int flags)1047 protected List<ApplicationInfo> getInstalledApplications(int flags) { 1048 return getInstalledApplications((long) flags); 1049 } 1050 1051 @Implementation(minSdk = TIRAMISU) getInstalledApplications(Object flags)1052 protected List<ApplicationInfo> getInstalledApplications(Object flags) { 1053 return getInstalledApplications(((PackageManager.ApplicationInfoFlags) flags).getValue()); 1054 } 1055 getInstalledApplications(long flags)1056 private List<ApplicationInfo> getInstalledApplications(long flags) { 1057 List<PackageInfo> packageInfos = getInstalledPackages(flags); 1058 List<ApplicationInfo> result = new ArrayList<>(packageInfos.size()); 1059 1060 for (PackageInfo packageInfo : packageInfos) { 1061 if (packageInfo.applicationInfo != null) { 1062 result.add(packageInfo.applicationInfo); 1063 } 1064 } 1065 return result; 1066 } 1067 1068 @Implementation getInstallerPackageName(String packageName)1069 protected String getInstallerPackageName(String packageName) { 1070 synchronized (lock) { 1071 // In REALISTIC mode, throw exception if the package is not installed or installed but 1072 // later uninstalled 1073 if (ConfigurationRegistry.get(GetInstallerPackageNameMode.Mode.class) == REALISTIC 1074 && (!packageInstallerMap.containsKey(packageName) 1075 || !packageInfos.containsKey(packageName))) { 1076 throw new IllegalArgumentException("Package is not installed: " + packageName); 1077 } else if (!packageInstallerMap.containsKey(packageName)) { 1078 Log.w( 1079 TAG, 1080 String.format( 1081 "Call to getInstallerPackageName returns null for package: '%s'. Please run" 1082 + " setInstallerPackageName to set installer package name before making the" 1083 + " call.", 1084 packageName)); 1085 } 1086 return packageInstallerMap.get(packageName); 1087 } 1088 } 1089 1090 @Implementation(minSdk = R) getInstallSourceInfo(String packageName)1091 protected Object getInstallSourceInfo(String packageName) throws NameNotFoundException { 1092 if (!packageInstallSourceInfoMap.containsKey(packageName)) { 1093 throw new NameNotFoundException("Package is not installed: " + packageName); 1094 } else { 1095 return packageInstallSourceInfoMap.get(packageName); 1096 } 1097 } 1098 1099 @Implementation getPermissionInfo(String name, int flags)1100 protected PermissionInfo getPermissionInfo(String name, int flags) throws NameNotFoundException { 1101 PermissionInfo permissionInfo = extraPermissions.get(name); 1102 if (permissionInfo != null) { 1103 return permissionInfo; 1104 } 1105 1106 synchronized (lock) { 1107 for (PackageInfo packageInfo : packageInfos.values()) { 1108 if (packageInfo.permissions != null) { 1109 for (PermissionInfo permission : packageInfo.permissions) { 1110 if (name.equals(permission.name)) { 1111 return createCopyPermissionInfo(permission, flags); 1112 } 1113 } 1114 } 1115 } 1116 } 1117 1118 throw new NameNotFoundException(name); 1119 } 1120 1121 @Implementation(minSdk = M) shouldShowRequestPermissionRationale(String permission)1122 protected boolean shouldShowRequestPermissionRationale(String permission) { 1123 return permissionRationaleMap.containsKey(permission) 1124 ? permissionRationaleMap.get(permission) 1125 : false; 1126 } 1127 1128 @Implementation getSystemAvailableFeatures()1129 protected FeatureInfo[] getSystemAvailableFeatures() { 1130 return systemAvailableFeatures.isEmpty() 1131 ? null 1132 : systemAvailableFeatures.toArray(new FeatureInfo[systemAvailableFeatures.size()]); 1133 } 1134 1135 @Implementation verifyPendingInstall(int id, int verificationCode)1136 protected void verifyPendingInstall(int id, int verificationCode) { 1137 if (verificationResults.containsKey(id)) { 1138 throw new IllegalStateException("Multiple verifications for id=" + id); 1139 } 1140 verificationResults.put(id, verificationCode); 1141 } 1142 1143 @Implementation extendVerificationTimeout( int id, int verificationCodeAtTimeout, long millisecondsToDelay)1144 protected void extendVerificationTimeout( 1145 int id, int verificationCodeAtTimeout, long millisecondsToDelay) { 1146 synchronized (lock) { 1147 verificationTimeoutExtension.put(id, millisecondsToDelay); 1148 verificationCodeAtTimeoutExtension.put(id, verificationCodeAtTimeout); 1149 } 1150 } 1151 1152 @Override 1153 @Implementation(maxSdk = LOLLIPOP_MR1) freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer)1154 protected void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer) {} 1155 1156 @Implementation(minSdk = M) freeStorageAndNotify( String volumeUuid, long freeStorageSize, IPackageDataObserver observer)1157 protected void freeStorageAndNotify( 1158 String volumeUuid, long freeStorageSize, IPackageDataObserver observer) {} 1159 1160 @Implementation setInstallerPackageName(String targetPackage, String installerPackageName)1161 protected void setInstallerPackageName(String targetPackage, String installerPackageName) { 1162 synchronized (lock) { 1163 packageInstallerMap.put(targetPackage, installerPackageName); 1164 } 1165 } 1166 1167 @Implementation queryIntentContentProviders(Intent intent, int flags)1168 protected List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) { 1169 return this.queryIntentComponents( 1170 intent, 1171 flags, 1172 (pkg) -> pkg.providers, 1173 providerFilters, 1174 (resolveInfo, providerInfo) -> resolveInfo.providerInfo = providerInfo, 1175 (resolveInfo) -> resolveInfo.providerInfo, 1176 ProviderInfo::new); 1177 } 1178 1179 @Implementation queryIntentContentProvidersAsUser( Intent intent, int flags, int userId)1180 protected List<ResolveInfo> queryIntentContentProvidersAsUser( 1181 Intent intent, int flags, int userId) { 1182 return Collections.emptyList(); 1183 } 1184 1185 @Implementation(minSdk = M) getPermissionControllerPackageName()1186 protected String getPermissionControllerPackageName() { 1187 return null; 1188 } 1189 1190 @Implementation(maxSdk = M) getPackageSizeInfo(Object pkgName, Object uid, final Object observer)1191 protected void getPackageSizeInfo(Object pkgName, Object uid, final Object observer) { 1192 final PackageStats packageStats = packageStatsMap.get((String) pkgName); 1193 new Handler(Looper.getMainLooper()) 1194 .post( 1195 () -> { 1196 try { 1197 ((IPackageStatsObserver) observer) 1198 .onGetStatsCompleted(packageStats, packageStats != null); 1199 } catch (RemoteException remoteException) { 1200 remoteException.rethrowFromSystemServer(); 1201 } 1202 }); 1203 } 1204 1205 @Implementation(minSdk = N) getPackageSizeInfoAsUser(Object pkgName, Object uid, final Object observer)1206 protected void getPackageSizeInfoAsUser(Object pkgName, Object uid, final Object observer) { 1207 final PackageStats packageStats = packageStatsMap.get((String) pkgName); 1208 new Handler(Looper.getMainLooper()) 1209 .post( 1210 () -> { 1211 try { 1212 ((IPackageStatsObserver) observer) 1213 .onGetStatsCompleted(packageStats, packageStats != null); 1214 } catch (RemoteException remoteException) { 1215 remoteException.rethrowFromSystemServer(); 1216 } 1217 }); 1218 } 1219 1220 @Override 1221 @Implementation deletePackage(String packageName, IPackageDeleteObserver observer, int flags)1222 protected void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) { 1223 super.deletePackage(packageName, observer, flags); 1224 } 1225 1226 @Implementation currentToCanonicalPackageNames(String[] names)1227 protected String[] currentToCanonicalPackageNames(String[] names) { 1228 String[] out = new String[names.length]; 1229 for (int i = 0; i < names.length; i++) { 1230 out[i] = currentToCanonicalNames.getOrDefault(names[i], names[i]); 1231 } 1232 return out; 1233 } 1234 1235 @Implementation canonicalToCurrentPackageNames(String[] names)1236 protected String[] canonicalToCurrentPackageNames(String[] names) { 1237 String[] out = new String[names.length]; 1238 for (int i = 0; i < names.length; i++) { 1239 out[i] = canonicalToCurrentNames.getOrDefault(names[i], names[i]); 1240 } 1241 return out; 1242 } 1243 1244 @Implementation isSafeMode()1245 protected boolean isSafeMode() { 1246 return safeMode; 1247 } 1248 1249 @Implementation getApplicationIcon(String packageName)1250 protected Drawable getApplicationIcon(String packageName) throws NameNotFoundException { 1251 return applicationIcons.get(packageName); 1252 } 1253 1254 @Implementation getApplicationIcon(ApplicationInfo info)1255 protected Drawable getApplicationIcon(ApplicationInfo info) throws NameNotFoundException { 1256 return getApplicationIcon(info.packageName); 1257 } 1258 1259 @Implementation getUserBadgeForDensity(UserHandle userHandle, int i)1260 protected Drawable getUserBadgeForDensity(UserHandle userHandle, int i) { 1261 return null; 1262 } 1263 1264 @Implementation checkSignatures(String pkg1, String pkg2)1265 protected int checkSignatures(String pkg1, String pkg2) { 1266 try { 1267 PackageInfo packageInfo1 = getPackageInfo(pkg1, GET_SIGNING_CERTIFICATES | GET_SIGNATURES); 1268 PackageInfo packageInfo2 = getPackageInfo(pkg2, GET_SIGNING_CERTIFICATES | GET_SIGNATURES); 1269 int signaturesResult = compareSignature(packageInfo1.signatures, packageInfo2.signatures); 1270 // Use signatures field for older SDKs 1271 if (VERSION.SDK_INT < P) { 1272 return signaturesResult; 1273 } else { 1274 // Prefer signingInfo where populated, but fall back to signatures for compatibility 1275 Signature[] firstSignatures = 1276 packageInfo1.signingInfo == null 1277 || packageInfo1.signingInfo.getApkContentsSigners() == null 1278 || packageInfo1.signingInfo.getApkContentsSigners().length == 0 1279 ? packageInfo1.signatures 1280 : packageInfo1.signingInfo.getApkContentsSigners(); 1281 Signature[] secondSignatures = 1282 packageInfo2.signingInfo == null 1283 || packageInfo2.signingInfo.getApkContentsSigners() == null 1284 || packageInfo2.signingInfo.getApkContentsSigners().length == 0 1285 ? packageInfo2.signatures 1286 : packageInfo2.signingInfo.getApkContentsSigners(); 1287 return compareSignature(firstSignatures, secondSignatures); 1288 } 1289 } catch (NameNotFoundException e) { 1290 return SIGNATURE_UNKNOWN_PACKAGE; 1291 } 1292 } 1293 1294 @Implementation checkSignatures(int uid1, int uid2)1295 protected int checkSignatures(int uid1, int uid2) { 1296 return 0; 1297 } 1298 1299 @Implementation queryPermissionsByGroup(String group, int flags)1300 protected List<PermissionInfo> queryPermissionsByGroup(String group, int flags) 1301 throws NameNotFoundException { 1302 List<PermissionInfo> result = new ArrayList<>(); 1303 for (PermissionInfo permissionInfo : extraPermissions.values()) { 1304 if (Objects.equals(permissionInfo.group, group)) { 1305 result.add(permissionInfo); 1306 } 1307 } 1308 synchronized (lock) { 1309 for (PackageInfo packageInfo : packageInfos.values()) { 1310 if (packageInfo.permissions != null) { 1311 for (PermissionInfo permission : packageInfo.permissions) { 1312 if (Objects.equals(group, permission.group)) { 1313 result.add(createCopyPermissionInfo(permission, flags)); 1314 } 1315 } 1316 } 1317 } 1318 } 1319 1320 if (result.isEmpty()) { 1321 throw new NameNotFoundException(group); 1322 } 1323 1324 return result; 1325 } 1326 createCopyPermissionInfo(PermissionInfo src, int flags)1327 private static PermissionInfo createCopyPermissionInfo(PermissionInfo src, int flags) { 1328 PermissionInfo matchedPermission = new PermissionInfo(src); 1329 if ((flags & GET_META_DATA) != GET_META_DATA) { 1330 matchedPermission.metaData = null; 1331 } 1332 return matchedPermission; 1333 } 1334 getLaunchIntentForPackage(String packageName, String launcherCategory)1335 private Intent getLaunchIntentForPackage(String packageName, String launcherCategory) { 1336 Intent intentToResolve = new Intent(Intent.ACTION_MAIN); 1337 intentToResolve.addCategory(Intent.CATEGORY_INFO); 1338 intentToResolve.setPackage(packageName); 1339 List<ResolveInfo> ris = queryIntentActivities(intentToResolve, 0); 1340 1341 if (ris == null || ris.isEmpty()) { 1342 intentToResolve.removeCategory(Intent.CATEGORY_INFO); 1343 intentToResolve.addCategory(launcherCategory); 1344 intentToResolve.setPackage(packageName); 1345 ris = queryIntentActivities(intentToResolve, 0); 1346 } 1347 if (ris == null || ris.isEmpty()) { 1348 return null; 1349 } 1350 Intent intent = new Intent(intentToResolve); 1351 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1352 intent.setClassName(packageName, ris.get(0).activityInfo.name); 1353 return intent; 1354 } 1355 1356 @Implementation getLaunchIntentForPackage(String packageName)1357 protected Intent getLaunchIntentForPackage(String packageName) { 1358 return getLaunchIntentForPackage(packageName, Intent.CATEGORY_LAUNCHER); 1359 } 1360 1361 @Implementation getLeanbackLaunchIntentForPackage(String packageName)1362 protected Intent getLeanbackLaunchIntentForPackage(String packageName) { 1363 return getLaunchIntentForPackage(packageName, Intent.CATEGORY_LEANBACK_LAUNCHER); 1364 } 1365 1366 /** 1367 * In Android T, the type of {@code flags} changed from {@code int} to {@link PackageInfoFlags} 1368 */ 1369 @Implementation(minSdk = N) getPackageInfoAsUser(Object packageName, Object flagsObject, Object userId)1370 protected Object getPackageInfoAsUser(Object packageName, Object flagsObject, Object userId) 1371 throws NameNotFoundException { 1372 int flags; 1373 if (RuntimeEnvironment.getApiLevel() >= TIRAMISU) { 1374 flags = (int) ((PackageInfoFlags) flagsObject).getValue(); 1375 } else { 1376 flags = (int) flagsObject; 1377 } 1378 return getPackageInfo((String) packageName, flags); 1379 } 1380 1381 @Implementation getPackageGids(String packageName)1382 protected int[] getPackageGids(String packageName) throws NameNotFoundException { 1383 return new int[0]; 1384 } 1385 1386 @Implementation(minSdk = N) getPackageGids(String packageName, int flags)1387 protected int[] getPackageGids(String packageName, int flags) throws NameNotFoundException { 1388 return null; 1389 } 1390 1391 @Implementation getPackageUid(String packageName, int flags)1392 protected int getPackageUid(String packageName, int flags) throws NameNotFoundException { 1393 Integer uid = uidForPackage.get(packageName); 1394 if (uid == null) { 1395 throw new NameNotFoundException(packageName); 1396 } 1397 return uid; 1398 } 1399 1400 @Implementation(minSdk = TIRAMISU) getPackageUid(Object packageName, Object flags)1401 protected Object getPackageUid(Object packageName, Object flags) throws NameNotFoundException { 1402 return getPackageUid((String) packageName, (int) ((PackageInfoFlags) flags).getValue()); 1403 } 1404 1405 @Implementation(minSdk = N) getPackageUidAsUser(String packageName, int userId)1406 protected int getPackageUidAsUser(String packageName, int userId) throws NameNotFoundException { 1407 return 0; 1408 } 1409 1410 @Implementation(minSdk = N) getPackageUidAsUser(String packageName, int flags, int userId)1411 protected int getPackageUidAsUser(String packageName, int flags, int userId) 1412 throws NameNotFoundException { 1413 return 0; 1414 } 1415 1416 /** 1417 * @see ShadowPackageManager#addPermissionGroupInfo(android.content.pm.PermissionGroupInfo) 1418 */ 1419 @Implementation getPermissionGroupInfo(String name, int flags)1420 protected PermissionGroupInfo getPermissionGroupInfo(String name, int flags) 1421 throws NameNotFoundException { 1422 if (permissionGroups.containsKey(name)) { 1423 return new PermissionGroupInfo(permissionGroups.get(name)); 1424 } 1425 1426 throw new NameNotFoundException(name); 1427 } 1428 1429 /** 1430 * @see ShadowPackageManager#addPermissionGroupInfo(android.content.pm.PermissionGroupInfo) 1431 */ 1432 @Implementation getAllPermissionGroups(int flags)1433 protected List<PermissionGroupInfo> getAllPermissionGroups(int flags) { 1434 ArrayList<PermissionGroupInfo> allPermissionGroups = new ArrayList<PermissionGroupInfo>(); 1435 1436 for (PermissionGroupInfo permissionGroupInfo : permissionGroups.values()) { 1437 allPermissionGroups.add(new PermissionGroupInfo(permissionGroupInfo)); 1438 } 1439 1440 return allPermissionGroups; 1441 } 1442 1443 @Implementation getApplicationInfo(String packageName, int flags)1444 protected ApplicationInfo getApplicationInfo(String packageName, int flags) 1445 throws NameNotFoundException { 1446 PackageInfo packageInfo = getPackageInfo(packageName, flags); 1447 if (packageInfo.applicationInfo == null) { 1448 throw new NameNotFoundException("Package found but without application info"); 1449 } 1450 // Maybe query app infos from overridden resolveInfo as well? 1451 return packageInfo.applicationInfo; 1452 } 1453 1454 @Implementation(minSdk = TIRAMISU) getApplicationInfo(Object packageName, Object flagsObject)1455 protected ApplicationInfo getApplicationInfo(Object packageName, Object flagsObject) 1456 throws NameNotFoundException { 1457 Preconditions.checkArgument(flagsObject instanceof PackageManager.ApplicationInfoFlags); 1458 PackageManager.ApplicationInfoFlags flags = (PackageManager.ApplicationInfoFlags) flagsObject; 1459 return getApplicationInfo((String) packageName, (int) (flags).getValue()); 1460 } 1461 applyFlagsToApplicationInfo(@ullable ApplicationInfo appInfo, long flags)1462 private void applyFlagsToApplicationInfo(@Nullable ApplicationInfo appInfo, long flags) 1463 throws NameNotFoundException { 1464 if (appInfo == null) { 1465 return; 1466 } 1467 String packageName = appInfo.packageName; 1468 1469 Integer stateOverride = applicationEnabledSettingMap.get(packageName); 1470 if (stateOverride == null) { 1471 stateOverride = COMPONENT_ENABLED_STATE_DEFAULT; 1472 } 1473 appInfo.enabled = 1474 (appInfo.enabled && stateOverride == COMPONENT_ENABLED_STATE_DEFAULT) 1475 || stateOverride == COMPONENT_ENABLED_STATE_ENABLED; 1476 1477 synchronized (lock) { 1478 if (deletedPackages.contains(packageName)) { 1479 appInfo.flags &= ~FLAG_INSTALLED; 1480 } 1481 } 1482 1483 if ((flags & MATCH_ALL) != 0 && Build.VERSION.SDK_INT >= 23) { 1484 return; 1485 } 1486 if ((flags & MATCH_UNINSTALLED_PACKAGES) == 0 && (appInfo.flags & FLAG_INSTALLED) == 0) { 1487 throw new NameNotFoundException("Package not installed: " + packageName); 1488 } 1489 if ((flags & MATCH_UNINSTALLED_PACKAGES) == 0 && hiddenPackages.contains(packageName)) { 1490 throw new NameNotFoundException("Package hidden: " + packageName); 1491 } 1492 } 1493 1494 /** 1495 * Returns all the values added via {@link 1496 * ShadowPackageManager#addSystemSharedLibraryName(String)}. 1497 */ 1498 @Implementation getSystemSharedLibraryNames()1499 protected String[] getSystemSharedLibraryNames() { 1500 return systemSharedLibraryNames.toArray(new String[systemSharedLibraryNames.size()]); 1501 } 1502 1503 @Implementation(minSdk = N) getServicesSystemSharedLibraryPackageName()1504 protected @NonNull String getServicesSystemSharedLibraryPackageName() { 1505 return null; 1506 } 1507 1508 @Implementation(minSdk = N) getSharedSystemSharedLibraryPackageName()1509 protected @NonNull String getSharedSystemSharedLibraryPackageName() { 1510 return ""; 1511 } 1512 1513 @Implementation(minSdk = N) hasSystemFeature(String name, int version)1514 protected boolean hasSystemFeature(String name, int version) { 1515 return false; 1516 } 1517 1518 @Implementation(minSdk = M) isPermissionRevokedByPolicy(String permName, String pkgName)1519 protected boolean isPermissionRevokedByPolicy(String permName, String pkgName) { 1520 return false; 1521 } 1522 1523 @Implementation addPermission(PermissionInfo info)1524 protected boolean addPermission(PermissionInfo info) { 1525 return false; 1526 } 1527 1528 @Implementation addPermissionAsync(PermissionInfo info)1529 protected boolean addPermissionAsync(PermissionInfo info) { 1530 return false; 1531 } 1532 1533 @Implementation removePermission(String name)1534 protected void removePermission(String name) {} 1535 1536 @Implementation(minSdk = M) grantRuntimePermission( String packageName, String permissionName, UserHandle user)1537 protected void grantRuntimePermission( 1538 String packageName, String permissionName, UserHandle user) { 1539 Integer uid; 1540 synchronized (lock) { 1541 if (!packageInfos.containsKey(packageName)) { 1542 throw new SecurityException("Package not found: " + packageName); 1543 } 1544 PackageInfo packageInfo = packageInfos.get(packageName); 1545 checkPermissionGrantStateInitialized(packageInfo); 1546 1547 int permissionIndex = getPermissionIndex(packageInfo, permissionName); 1548 if (permissionIndex < 0) { 1549 throw new SecurityException( 1550 "Permission " + permissionName + " not requested by package " + packageName); 1551 } 1552 1553 packageInfo.requestedPermissionsFlags[permissionIndex] |= REQUESTED_PERMISSION_GRANTED; 1554 1555 uid = uidForPackage.get(packageName); 1556 } 1557 1558 if (RuntimeEnvironment.getApiLevel() >= VERSION_CODES.M && uid != null) { 1559 for (Object listener : permissionListeners) { 1560 ((OnPermissionsChangedListener) listener).onPermissionsChanged(uid); 1561 } 1562 } 1563 } 1564 1565 @Implementation(minSdk = M) revokeRuntimePermission( String packageName, String permissionName, UserHandle user)1566 protected void revokeRuntimePermission( 1567 String packageName, String permissionName, UserHandle user) { 1568 Integer uid; 1569 synchronized (lock) { 1570 if (!packageInfos.containsKey(packageName)) { 1571 throw new SecurityException("Package not found: " + packageName); 1572 } 1573 PackageInfo packageInfo = packageInfos.get(packageName); 1574 checkPermissionGrantStateInitialized(packageInfo); 1575 1576 int permissionIndex = getPermissionIndex(packageInfo, permissionName); 1577 if (permissionIndex < 0) { 1578 throw new SecurityException( 1579 "Permission " + permissionName + " not requested by package " + packageName); 1580 } 1581 1582 packageInfo.requestedPermissionsFlags[permissionIndex] &= ~REQUESTED_PERMISSION_GRANTED; 1583 1584 uid = uidForPackage.get(packageName); 1585 } 1586 1587 if (RuntimeEnvironment.getApiLevel() >= VERSION_CODES.M && uid != null) { 1588 for (Object listener : permissionListeners) { 1589 ((OnPermissionsChangedListener) listener).onPermissionsChanged(uid); 1590 } 1591 } 1592 } 1593 checkPermissionGrantStateInitialized(PackageInfo packageInfo)1594 private void checkPermissionGrantStateInitialized(PackageInfo packageInfo) { 1595 if (packageInfo.requestedPermissionsFlags == null) { 1596 // In the real OS this would never be null, but tests don't necessarily initialize this 1597 // structure. 1598 throw new SecurityException( 1599 "Permission grant state (PackageInfo.requestedPermissionFlags) " 1600 + "is null. This operation requires this variable to be initialized."); 1601 } 1602 } 1603 1604 /** 1605 * Returns the index of the given permission in the PackageInfo.requestedPermissions array, or -1 1606 * if it's not found. 1607 */ getPermissionIndex(PackageInfo packageInfo, String permissionName)1608 private int getPermissionIndex(PackageInfo packageInfo, String permissionName) { 1609 if (packageInfo.requestedPermissions != null) { 1610 for (int i = 0; i < packageInfo.requestedPermissions.length; i++) { 1611 if (permissionName.equals(packageInfo.requestedPermissions[i])) { 1612 return i; 1613 } 1614 } 1615 } 1616 1617 return -1; 1618 } 1619 1620 /** 1621 * This method differs from the real implementation in that we only return the permission flags 1622 * that were added via updatePermissionFlags, and do not perform any verification of permissions, 1623 * packages or users. 1624 */ 1625 @Implementation(minSdk = M) getPermissionFlags(String permissionName, String packageName, UserHandle user)1626 protected int getPermissionFlags(String permissionName, String packageName, UserHandle user) { 1627 if (permissionFlags.containsKey(packageName)) { 1628 return permissionFlags.get(packageName).getOrDefault(permissionName, /* defaultValue= */ 0); 1629 } 1630 1631 return 0; 1632 } 1633 1634 /** 1635 * This method differs from the real implementation in that no permission checking or package 1636 * existent checks are performed here. 1637 */ 1638 @Implementation(minSdk = M) updatePermissionFlags( String permissionName, String packageName, @PackageManager.PermissionFlags int flagMask, @PackageManager.PermissionFlags int flagValues, UserHandle user)1639 protected void updatePermissionFlags( 1640 String permissionName, 1641 String packageName, 1642 @PackageManager.PermissionFlags int flagMask, 1643 @PackageManager.PermissionFlags int flagValues, 1644 UserHandle user) { 1645 if (!permissionFlags.containsKey(packageName)) { 1646 permissionFlags.put(packageName, new HashMap<String, Integer>()); 1647 } 1648 1649 int existingFlags = 1650 permissionFlags.get(packageName).getOrDefault(permissionName, /* defaultValue= */ 0); 1651 int flagsToKeep = ~flagMask & existingFlags; 1652 int flagsToChange = flagMask & flagValues; 1653 int newFlags = flagsToKeep | flagsToChange; 1654 1655 permissionFlags.get(packageName).put(permissionName, newFlags); 1656 } 1657 1658 @Implementation getUidForSharedUser(String sharedUserName)1659 protected int getUidForSharedUser(String sharedUserName) throws NameNotFoundException { 1660 return 0; 1661 } 1662 1663 @Implementation(minSdk = N) getInstalledPackagesAsUser(int flags, int userId)1664 protected List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) { 1665 return null; 1666 } 1667 1668 @Implementation getPackagesHoldingPermissions(String[] permissions, int flags)1669 protected List<PackageInfo> getPackagesHoldingPermissions(String[] permissions, int flags) { 1670 synchronized (lock) { 1671 List<PackageInfo> packageInfosWithPermissions = new ArrayList<>(); 1672 for (PackageInfo packageInfo : packageInfos.values()) { 1673 for (String permission : permissions) { 1674 int permissionIndex = getPermissionIndex(packageInfo, permission); 1675 if (permissionIndex >= 0) { 1676 packageInfosWithPermissions.add(packageInfo); 1677 break; 1678 } 1679 } 1680 } 1681 return packageInfosWithPermissions; 1682 } 1683 } 1684 1685 @Implementation(minSdk = S) getGroupOfPlatformPermission( String permissionName, Executor executor, Consumer<String> callback)1686 public void getGroupOfPlatformPermission( 1687 String permissionName, Executor executor, Consumer<String> callback) { 1688 String permissionGroup = null; 1689 try { 1690 PermissionInfo permissionInfo = 1691 getPermissionInfo(permissionName, PackageManager.GET_META_DATA); 1692 permissionGroup = permissionInfo.group; 1693 } catch (NameNotFoundException ignored) { 1694 // fall through 1695 } 1696 final String finalPermissionGroup = permissionGroup; 1697 executor.execute(() -> callback.accept(finalPermissionGroup)); 1698 } 1699 1700 /** Behaves as {@link #resolveActivity(Intent, int)} and currently ignores userId. */ 1701 @Implementation resolveActivityAsUser(Intent intent, int flags, int userId)1702 protected ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) { 1703 return resolveActivity(intent, flags); 1704 } 1705 1706 @Implementation(minSdk = TIRAMISU) resolveActivityAsUser(Object intent, Object flags, Object userId)1707 protected ResolveInfo resolveActivityAsUser(Object intent, Object flags, Object userId) { 1708 return resolveActivity((Intent) intent, (int) ((ResolveInfoFlags) flags).getValue()); 1709 } 1710 1711 @Implementation(minSdk = TIRAMISU) resolveServiceAsUser(Object intent, Object flags, Object userId)1712 protected ResolveInfo resolveServiceAsUser(Object intent, Object flags, Object userId) { 1713 return resolveService((Intent) intent, (int) ((ResolveInfoFlags) flags).getValue()); 1714 } 1715 1716 @Implementation queryIntentActivityOptions( ComponentName caller, Intent[] specifics, Intent intent, int flags)1717 protected List<ResolveInfo> queryIntentActivityOptions( 1718 ComponentName caller, Intent[] specifics, Intent intent, int flags) { 1719 return null; 1720 } 1721 1722 @Implementation(minSdk = N) queryBroadcastReceiversAsUser(Intent intent, int flags, int userId)1723 protected List<ResolveInfo> queryBroadcastReceiversAsUser(Intent intent, int flags, int userId) { 1724 return null; 1725 } 1726 1727 @Implementation queryContentProviders(String processName, int uid, int flags)1728 protected List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) { 1729 return null; 1730 } 1731 1732 @Implementation getInstrumentationInfo(ComponentName className, int flags)1733 protected InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags) 1734 throws NameNotFoundException { 1735 return null; 1736 } 1737 1738 @Implementation queryInstrumentation(String targetPackage, int flags)1739 protected List<InstrumentationInfo> queryInstrumentation(String targetPackage, int flags) { 1740 return null; 1741 } 1742 1743 @Nullable 1744 @Implementation getDrawable( String packageName, @DrawableRes int resId, @Nullable ApplicationInfo appInfo)1745 protected Drawable getDrawable( 1746 String packageName, @DrawableRes int resId, @Nullable ApplicationInfo appInfo) { 1747 Drawable result = drawables.get(new Pair<>(packageName, resId)); 1748 if (result != null) { 1749 return result; 1750 } 1751 return reflector(ReflectorApplicationPackageManager.class, realObject) 1752 .getDrawable(packageName, resId, appInfo); 1753 } 1754 1755 /** 1756 * Returns a user stored String resource with {@code resId} corresponding to {@code packageName}. 1757 * User can store this String via {@link #addStringResource(String, int, String)}. 1758 * 1759 * <p>Real method is called if the user has not stored a String corresponding to {@code resId} and 1760 * {@code packageName}. 1761 */ 1762 @Nullable 1763 @Implementation getText(String packageName, int resId, ApplicationInfo appInfo)1764 protected CharSequence getText(String packageName, int resId, ApplicationInfo appInfo) { 1765 if (stringResources.containsKey(packageName) 1766 && stringResources.get(packageName).containsKey(resId)) { 1767 return stringResources.get(packageName).get(resId); 1768 } 1769 return reflector(ReflectorApplicationPackageManager.class, realObject) 1770 .getText(packageName, resId, appInfo); 1771 } 1772 1773 @Implementation getActivityIcon(ComponentName activityName)1774 protected Drawable getActivityIcon(ComponentName activityName) throws NameNotFoundException { 1775 Drawable result = drawableList.get(activityName); 1776 if (result != null) { 1777 return result; 1778 } 1779 return reflector(ReflectorApplicationPackageManager.class, realObject) 1780 .getActivityIcon(activityName); 1781 } 1782 1783 @Implementation getDefaultActivityIcon()1784 protected Drawable getDefaultActivityIcon() { 1785 return Resources.getSystem().getDrawable(com.android.internal.R.drawable.sym_def_app_icon); 1786 } 1787 1788 @Implementation getResourcesForActivity(ComponentName activityName)1789 protected Resources getResourcesForActivity(ComponentName activityName) 1790 throws NameNotFoundException { 1791 return getResourcesForApplication(activityName.getPackageName()); 1792 } 1793 1794 @Implementation getResourcesForApplication(String appPackageName)1795 protected Resources getResourcesForApplication(String appPackageName) 1796 throws NameNotFoundException { 1797 synchronized (lock) { 1798 if (getContext().getPackageName().equals(appPackageName)) { 1799 return getContext().getResources(); 1800 } else if (packageInfos.containsKey(appPackageName)) { 1801 Resources appResources = resources.get(appPackageName); 1802 if (appResources == null) { 1803 appResources = new Resources(new AssetManager(), null, null); 1804 resources.put(appPackageName, appResources); 1805 } 1806 return appResources; 1807 } 1808 throw new NameNotFoundException(appPackageName); 1809 } 1810 } 1811 1812 @Implementation getResourcesForApplicationAsUser(String appPackageName, int userId)1813 protected Resources getResourcesForApplicationAsUser(String appPackageName, int userId) 1814 throws NameNotFoundException { 1815 return null; 1816 } 1817 1818 @Implementation(minSdk = M) addOnPermissionsChangeListener(Object listener)1819 protected void addOnPermissionsChangeListener(Object listener) { 1820 permissionListeners.add(listener); 1821 } 1822 1823 @Implementation(minSdk = M) removeOnPermissionsChangeListener(Object listener)1824 protected void removeOnPermissionsChangeListener(Object listener) { 1825 permissionListeners.remove(listener); 1826 } 1827 1828 @Implementation(maxSdk = O_MR1) installPackage( Object packageURI, Object observer, Object flags, Object installerPackageName)1829 protected void installPackage( 1830 Object packageURI, Object observer, Object flags, Object installerPackageName) {} 1831 1832 @Implementation installExistingPackage(String packageName)1833 protected int installExistingPackage(String packageName) throws NameNotFoundException { 1834 return 0; 1835 } 1836 1837 @Implementation(minSdk = N) installExistingPackageAsUser(String packageName, int userId)1838 protected int installExistingPackageAsUser(String packageName, int userId) 1839 throws NameNotFoundException { 1840 return 0; 1841 } 1842 1843 @Implementation(minSdk = M) verifyIntentFilter(int id, int verificationCode, List<String> failedDomains)1844 protected void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains) {} 1845 1846 @Implementation(minSdk = N) getIntentVerificationStatusAsUser(String packageName, int userId)1847 protected int getIntentVerificationStatusAsUser(String packageName, int userId) { 1848 return 0; 1849 } 1850 1851 @Implementation(minSdk = N) updateIntentVerificationStatusAsUser( String packageName, int status, int userId)1852 protected boolean updateIntentVerificationStatusAsUser( 1853 String packageName, int status, int userId) { 1854 return false; 1855 } 1856 1857 @Implementation(minSdk = M) getIntentFilterVerifications(String packageName)1858 protected List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) { 1859 return null; 1860 } 1861 1862 @Implementation(minSdk = M) getAllIntentFilters(String packageName)1863 protected List<IntentFilter> getAllIntentFilters(String packageName) { 1864 return null; 1865 } 1866 1867 @Implementation(minSdk = N) getDefaultBrowserPackageNameAsUser(int userId)1868 protected String getDefaultBrowserPackageNameAsUser(int userId) { 1869 return defaultBrowsers.get(userId); 1870 } 1871 1872 @Implementation(minSdk = N) setDefaultBrowserPackageNameAsUser(String packageName, int userId)1873 protected boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) { 1874 defaultBrowsers.put(userId, packageName); 1875 return true; 1876 } 1877 1878 @Implementation(minSdk = M) getMoveStatus(int moveId)1879 protected int getMoveStatus(int moveId) { 1880 return 0; 1881 } 1882 1883 @Implementation(minSdk = M) registerMoveCallback(Object callback, Object handler)1884 protected void registerMoveCallback(Object callback, Object handler) {} 1885 1886 @Implementation(minSdk = M) unregisterMoveCallback(Object callback)1887 protected void unregisterMoveCallback(Object callback) {} 1888 1889 @Implementation(minSdk = M) movePackage(Object packageName, Object vol)1890 protected Object movePackage(Object packageName, Object vol) { 1891 return 0; 1892 } 1893 1894 @Implementation(minSdk = M) getPackageCurrentVolume(Object app)1895 protected Object getPackageCurrentVolume(Object app) { 1896 return null; 1897 } 1898 1899 @Implementation(minSdk = M) getPackageCandidateVolumes(ApplicationInfo app)1900 protected List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app) { 1901 return null; 1902 } 1903 1904 @Implementation(minSdk = M) movePrimaryStorage(Object vol)1905 protected Object movePrimaryStorage(Object vol) { 1906 return 0; 1907 } 1908 1909 @Implementation(minSdk = M) getPrimaryStorageCurrentVolume()1910 protected @Nullable Object getPrimaryStorageCurrentVolume() { 1911 return null; 1912 } 1913 1914 @Implementation(minSdk = M) getPrimaryStorageCandidateVolumes()1915 protected @NonNull List<VolumeInfo> getPrimaryStorageCandidateVolumes() { 1916 return null; 1917 } 1918 1919 @Implementation(minSdk = N) deletePackageAsUser( String packageName, IPackageDeleteObserver observer, int flags, int userId)1920 protected void deletePackageAsUser( 1921 String packageName, IPackageDeleteObserver observer, int flags, int userId) {} 1922 1923 @Implementation clearApplicationUserData(String packageName, IPackageDataObserver observer)1924 protected void clearApplicationUserData(String packageName, IPackageDataObserver observer) { 1925 clearedApplicationUserDataPackages.add(packageName); 1926 } 1927 1928 @Implementation deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer)1929 protected void deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer) {} 1930 1931 @Implementation(minSdk = N) deleteApplicationCacheFilesAsUser( String packageName, int userId, IPackageDataObserver observer)1932 protected void deleteApplicationCacheFilesAsUser( 1933 String packageName, int userId, IPackageDataObserver observer) {} 1934 1935 @Implementation(minSdk = M) freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi)1936 protected void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi) {} 1937 1938 @Implementation(minSdk = N, maxSdk = O_MR1) setPackagesSuspendedAsUser( String[] packageNames, boolean suspended, int userId)1939 protected String[] setPackagesSuspendedAsUser( 1940 String[] packageNames, boolean suspended, int userId) { 1941 return null; 1942 } 1943 1944 @Implementation(minSdk = N) isPackageSuspendedForUser(String packageName, int userId)1945 protected boolean isPackageSuspendedForUser(String packageName, int userId) { 1946 return false; 1947 } 1948 1949 @Implementation addPackageToPreferred(String packageName)1950 protected void addPackageToPreferred(String packageName) {} 1951 1952 @Implementation removePackageFromPreferred(String packageName)1953 protected void removePackageFromPreferred(String packageName) {} 1954 1955 @Implementation getPreferredPackages(int flags)1956 protected List<PackageInfo> getPreferredPackages(int flags) { 1957 return null; 1958 } 1959 1960 @Implementation addPreferredActivity( IntentFilter filter, int match, ComponentName[] set, ComponentName activity)1961 public void addPreferredActivity( 1962 IntentFilter filter, int match, ComponentName[] set, ComponentName activity) { 1963 addPreferredActivityInternal(filter, activity, preferredActivities); 1964 } 1965 1966 @Implementation replacePreferredActivity( IntentFilter filter, int match, ComponentName[] set, ComponentName activity)1967 protected void replacePreferredActivity( 1968 IntentFilter filter, int match, ComponentName[] set, ComponentName activity) { 1969 addPreferredActivity(filter, match, set, activity); 1970 } 1971 1972 @Implementation getPreferredActivities( List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName)1973 public int getPreferredActivities( 1974 List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName) { 1975 return getPreferredActivitiesInternal( 1976 outFilters, outActivities, packageName, preferredActivities); 1977 } 1978 1979 @Implementation clearPackagePreferredActivities(String packageName)1980 protected void clearPackagePreferredActivities(String packageName) { 1981 clearPackagePreferredActivitiesInternal(packageName, preferredActivities); 1982 } 1983 1984 @Implementation getHomeActivities(List<ResolveInfo> outActivities)1985 protected ComponentName getHomeActivities(List<ResolveInfo> outActivities) { 1986 return null; 1987 } 1988 1989 @Implementation(minSdk = N) flushPackageRestrictionsAsUser(int userId)1990 protected void flushPackageRestrictionsAsUser(int userId) {} 1991 1992 @Implementation setApplicationHiddenSettingAsUser( String packageName, boolean hidden, UserHandle user)1993 protected boolean setApplicationHiddenSettingAsUser( 1994 String packageName, boolean hidden, UserHandle user) { 1995 synchronized (lock) { 1996 // Note that this ignores the UserHandle parameter 1997 if (!packageInfos.containsKey(packageName)) { 1998 // Package doesn't exist 1999 return false; 2000 } 2001 if (hidden) { 2002 hiddenPackages.add(packageName); 2003 } else { 2004 hiddenPackages.remove(packageName); 2005 } 2006 2007 return true; 2008 } 2009 } 2010 2011 @Implementation getApplicationHiddenSettingAsUser(String packageName, UserHandle user)2012 protected boolean getApplicationHiddenSettingAsUser(String packageName, UserHandle user) { 2013 // Note that this ignores the UserHandle parameter 2014 synchronized (lock) { 2015 if (!packageInfos.containsKey(packageName)) { 2016 // Match Android behaviour of returning true if package isn't found 2017 return true; 2018 } 2019 return hiddenPackages.contains(packageName); 2020 } 2021 } 2022 2023 @Implementation getVerifierDeviceIdentity()2024 protected VerifierDeviceIdentity getVerifierDeviceIdentity() { 2025 return null; 2026 } 2027 2028 @Implementation(minSdk = LOLLIPOP_MR1) isUpgrade()2029 protected boolean isUpgrade() { 2030 return false; 2031 } 2032 2033 @Implementation isPackageAvailable(String packageName)2034 protected boolean isPackageAvailable(String packageName) { 2035 return false; 2036 } 2037 2038 @Implementation addCrossProfileIntentFilter( IntentFilter filter, int sourceUserId, int targetUserId, int flags)2039 protected void addCrossProfileIntentFilter( 2040 IntentFilter filter, int sourceUserId, int targetUserId, int flags) {} 2041 2042 @Implementation clearCrossProfileIntentFilters(int sourceUserId)2043 protected void clearCrossProfileIntentFilters(int sourceUserId) {} 2044 2045 /** 2046 * Gets the unbadged icon based on the values set by {@link 2047 * ShadowPackageManager#setUnbadgedApplicationIcon} or returns null if nothing has been set. 2048 */ 2049 @Implementation(minSdk = LOLLIPOP_MR1) loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo)2050 protected Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) { 2051 Drawable result = unbadgedApplicationIcons.get(itemInfo.packageName); 2052 if (result != null) { 2053 return result; 2054 } 2055 return reflector(ReflectorApplicationPackageManager.class, realObject) 2056 .loadUnbadgedItemIcon(itemInfo, appInfo); 2057 } 2058 2059 /** 2060 * Adds a profile badge to the icon. 2061 * 2062 * <p>This implementation just returns the unbadged icon, as some default implementations add an 2063 * internal resource to the icon that is unavailable to Robolectric. 2064 */ 2065 @Implementation getUserBadgedIcon(Drawable icon, UserHandle user)2066 protected Drawable getUserBadgedIcon(Drawable icon, UserHandle user) { 2067 return icon; 2068 } 2069 2070 @Implementation(minSdk = O) canRequestPackageInstalls()2071 protected boolean canRequestPackageInstalls() { 2072 return canRequestPackageInstalls; 2073 } 2074 2075 @Implementation(minSdk = O) getChangedPackages(int sequenceNumber)2076 protected Object getChangedPackages(int sequenceNumber) { 2077 if (sequenceNumber < 0 || sequenceNumberChangedPackagesMap.get(sequenceNumber).isEmpty()) { 2078 return null; 2079 } 2080 return new ChangedPackages( 2081 sequenceNumber + 1, new ArrayList<>(sequenceNumberChangedPackagesMap.get(sequenceNumber))); 2082 } 2083 2084 @Implementation(minSdk = P) getSystemTextClassifierPackageName()2085 public String getSystemTextClassifierPackageName() { 2086 return ""; 2087 } 2088 2089 @Implementation(minSdk = P) 2090 @HiddenApi setPackagesSuspended( String[] packageNames, boolean suspended, PersistableBundle appExtras, PersistableBundle launcherExtras, String dialogMessage)2091 protected String[] setPackagesSuspended( 2092 String[] packageNames, 2093 boolean suspended, 2094 PersistableBundle appExtras, 2095 PersistableBundle launcherExtras, 2096 String dialogMessage) { 2097 return setPackagesSuspended( 2098 packageNames, suspended, appExtras, launcherExtras, dialogMessage, /* dialogInfo= */ null); 2099 } 2100 2101 @Implementation(minSdk = Q) 2102 @HiddenApi setPackagesSuspended( Object packageNames, Object suspended, Object appExtras, Object launcherExtras, Object dialogInfo)2103 protected /* String[] */ Object setPackagesSuspended( 2104 /* String[] */ Object packageNames, 2105 /* boolean */ Object suspended, 2106 /* PersistableBundle */ Object appExtras, 2107 /* PersistableBundle */ Object launcherExtras, 2108 /* SuspendDialogInfo */ Object dialogInfo) { 2109 return setPackagesSuspended( 2110 (String[]) packageNames, 2111 (boolean) suspended, 2112 (PersistableBundle) appExtras, 2113 (PersistableBundle) launcherExtras, 2114 /* dialogMessage= */ null, 2115 dialogInfo); 2116 } 2117 2118 @Implementation(minSdk = R) isAutoRevokeWhitelisted()2119 protected boolean isAutoRevokeWhitelisted() { 2120 return whitelisted; 2121 } 2122 2123 /** 2124 * Sets {@code packageNames} suspension status to {@code suspended} in the package manager. 2125 * 2126 * <p>At least one of {@code dialogMessage} and {@code dialogInfo} should be null. 2127 */ setPackagesSuspended( String[] packageNames, boolean suspended, PersistableBundle appExtras, PersistableBundle launcherExtras, String dialogMessage, Object dialogInfo)2128 private String[] setPackagesSuspended( 2129 String[] packageNames, 2130 boolean suspended, 2131 PersistableBundle appExtras, 2132 PersistableBundle launcherExtras, 2133 String dialogMessage, 2134 Object dialogInfo) { 2135 if (hasProfileOwnerOrDeviceOwnerOnCurrentUser() 2136 && (VERSION.SDK_INT < VERSION_CODES.Q 2137 || !isCurrentApplicationProfileOwnerOrDeviceOwner())) { 2138 throw new UnsupportedOperationException(); 2139 } 2140 ArrayList<String> unupdatedPackages = new ArrayList<>(); 2141 for (String packageName : packageNames) { 2142 if (!canSuspendPackage(packageName)) { 2143 unupdatedPackages.add(packageName); 2144 continue; 2145 } 2146 PackageSetting setting = packageSettings.get(packageName); 2147 if (setting == null) { 2148 unupdatedPackages.add(packageName); 2149 continue; 2150 } 2151 setting.setSuspended(suspended, dialogMessage, dialogInfo, appExtras, launcherExtras); 2152 } 2153 return unupdatedPackages.toArray(new String[0]); 2154 } 2155 2156 /** Returns whether the current user profile has a profile owner or a device owner. */ isCurrentApplicationProfileOwnerOrDeviceOwner()2157 private boolean isCurrentApplicationProfileOwnerOrDeviceOwner() { 2158 String currentApplication = getContext().getPackageName(); 2159 DevicePolicyManager devicePolicyManager = 2160 (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE); 2161 return devicePolicyManager.isProfileOwnerApp(currentApplication) 2162 || devicePolicyManager.isDeviceOwnerApp(currentApplication); 2163 } 2164 2165 /** Returns whether the current user profile has a profile owner or a device owner. */ hasProfileOwnerOrDeviceOwnerOnCurrentUser()2166 private boolean hasProfileOwnerOrDeviceOwnerOnCurrentUser() { 2167 DevicePolicyManager devicePolicyManager = 2168 (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE); 2169 return devicePolicyManager.getProfileOwner() != null 2170 || (UserHandle.of(UserHandle.myUserId()).isSystem() 2171 && devicePolicyManager.getDeviceOwner() != null); 2172 } 2173 canSuspendPackage(String packageName)2174 private boolean canSuspendPackage(String packageName) { 2175 // This code approximately mirrors PackageManagerService#canSuspendPackageForUserLocked. 2176 return !packageName.equals(getContext().getPackageName()) 2177 && !isPackageDeviceAdmin(packageName) 2178 && !isPackageActiveLauncher(packageName) 2179 && !isPackageRequiredInstaller(packageName) 2180 && !isPackageRequiredUninstaller(packageName) 2181 && !isPackageRequiredVerifier(packageName) 2182 && !isPackageDefaultDialer(packageName) 2183 && !packageName.equals(PLATFORM_PACKAGE_NAME); 2184 } 2185 isPackageDeviceAdmin(String packageName)2186 private boolean isPackageDeviceAdmin(String packageName) { 2187 DevicePolicyManager devicePolicyManager = 2188 (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE); 2189 // Strictly speaking, this should be devicePolicyManager.getDeviceOwnerComponentOnAnyUser(), 2190 // but that method is currently not shadowed. 2191 return packageName.equals(devicePolicyManager.getDeviceOwner()); 2192 } 2193 isPackageActiveLauncher(String packageName)2194 private boolean isPackageActiveLauncher(String packageName) { 2195 Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME); 2196 ResolveInfo info = resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); 2197 return info != null && packageName.equals(info.activityInfo.packageName); 2198 } 2199 isPackageRequiredInstaller(String packageName)2200 private boolean isPackageRequiredInstaller(String packageName) { 2201 Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE); 2202 intent.addCategory(Intent.CATEGORY_DEFAULT); 2203 intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE); 2204 ResolveInfo info = 2205 resolveActivity( 2206 intent, 2207 PackageManager.MATCH_SYSTEM_ONLY 2208 | PackageManager.MATCH_DIRECT_BOOT_AWARE 2209 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); 2210 return info != null && packageName.equals(info.activityInfo.packageName); 2211 } 2212 isPackageRequiredUninstaller(String packageName)2213 private boolean isPackageRequiredUninstaller(String packageName) { 2214 final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE); 2215 intent.addCategory(Intent.CATEGORY_DEFAULT); 2216 intent.setData(Uri.fromParts(PACKAGE_SCHEME, "foo.bar", null)); 2217 ResolveInfo info = 2218 resolveActivity( 2219 intent, 2220 PackageManager.MATCH_SYSTEM_ONLY 2221 | PackageManager.MATCH_DIRECT_BOOT_AWARE 2222 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); 2223 return info != null && packageName.equals(info.activityInfo.packageName); 2224 } 2225 isPackageRequiredVerifier(String packageName)2226 private boolean isPackageRequiredVerifier(String packageName) { 2227 final Intent intent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); 2228 List<ResolveInfo> infos = 2229 queryBroadcastReceivers( 2230 intent, 2231 PackageManager.MATCH_SYSTEM_ONLY 2232 | PackageManager.MATCH_DIRECT_BOOT_AWARE 2233 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); 2234 if (infos != null) { 2235 for (ResolveInfo info : infos) { 2236 if (packageName.equals(info.activityInfo.packageName)) { 2237 return true; 2238 } 2239 } 2240 } 2241 return false; 2242 } 2243 isPackageDefaultDialer(String packageName)2244 private boolean isPackageDefaultDialer(String packageName) { 2245 TelecomManager telecomManager = 2246 (TelecomManager) getContext().getSystemService(Context.TELECOM_SERVICE); 2247 return packageName.equals(telecomManager.getDefaultDialerPackage()); 2248 } 2249 2250 @HiddenApi 2251 @Implementation(minSdk = Q) 2252 @RequiresPermission(permission.SUSPEND_APPS) getUnsuspendablePackages(String[] packageNames)2253 protected String[] getUnsuspendablePackages(String[] packageNames) { 2254 checkNotNull(packageNames, "packageNames cannot be null"); 2255 if (getContext().checkSelfPermission(permission.SUSPEND_APPS) 2256 != PackageManager.PERMISSION_GRANTED) { 2257 throw new SecurityException("Current process does not have " + permission.SUSPEND_APPS); 2258 } 2259 ArrayList<String> unsuspendablePackages = new ArrayList<>(); 2260 for (String packageName : packageNames) { 2261 if (!canSuspendPackage(packageName)) { 2262 unsuspendablePackages.add(packageName); 2263 } 2264 } 2265 return unsuspendablePackages.toArray(new String[0]); 2266 } 2267 2268 @HiddenApi 2269 @Implementation(minSdk = P) isPackageSuspended(String packageName)2270 protected boolean isPackageSuspended(String packageName) throws NameNotFoundException { 2271 PackageSetting setting = packageSettings.get(packageName); 2272 if (setting == null) { 2273 throw new NameNotFoundException(packageName); 2274 } 2275 return setting.isSuspended(); 2276 } 2277 2278 @Implementation(minSdk = O) isInstantApp(String packageName)2279 protected boolean isInstantApp(String packageName) { 2280 synchronized (lock) { 2281 PackageInfo pi = packageInfos.get(packageName); 2282 if (pi == null) { 2283 return false; 2284 } 2285 ApplicationInfo ai = pi.applicationInfo; 2286 if (ai == null) { 2287 return false; 2288 } 2289 return ai.isInstantApp(); 2290 } 2291 } 2292 2293 @HiddenApi 2294 @Implementation(minSdk = Q) setDistractingPackageRestrictions(String[] packages, int restrictionFlags)2295 protected String[] setDistractingPackageRestrictions(String[] packages, int restrictionFlags) { 2296 for (String pkg : packages) { 2297 distractingPackageRestrictions.put(pkg, restrictionFlags); 2298 } 2299 return new String[0]; 2300 } 2301 getContext()2302 private Context getContext() { 2303 return reflector(ReflectorApplicationPackageManager.class, realObject).getContext(); 2304 } 2305 2306 /** Stub that will always throw. */ 2307 @Implementation(minSdk = S) getProperty( String propertyName, String packageName)2308 protected Object /* PackageManager.Property */ getProperty( 2309 String propertyName, String packageName) throws NameNotFoundException { 2310 // TODO: in future read this value from parsed manifest 2311 throw new NameNotFoundException("unsupported"); 2312 } 2313 2314 /** Stub that will always throw. */ 2315 @Implementation(minSdk = S) getProperty( String propertyName, ComponentName name)2316 protected Object /* PackageManager.Property */ getProperty( 2317 String propertyName, ComponentName name) throws NameNotFoundException { 2318 // TODO: in future read this value from parsed manifest 2319 throw new NameNotFoundException("unsupported"); 2320 } 2321 2322 /** Reflector interface for {@link ApplicationPackageManager}'s internals. */ 2323 @ForType(ApplicationPackageManager.class) 2324 private interface ReflectorApplicationPackageManager { 2325 2326 @Direct getResourcesForApplication(@onNull ApplicationInfo applicationInfo)2327 Resources getResourcesForApplication(@NonNull ApplicationInfo applicationInfo); 2328 2329 @Direct getDrawable( String packageName, @DrawableRes int resId, @Nullable ApplicationInfo appInfo)2330 Drawable getDrawable( 2331 String packageName, @DrawableRes int resId, @Nullable ApplicationInfo appInfo); 2332 2333 @Direct getText(String packageName, @StringRes int resId, ApplicationInfo appInfo)2334 CharSequence getText(String packageName, @StringRes int resId, ApplicationInfo appInfo); 2335 2336 @Direct getActivityIcon(ComponentName activityName)2337 Drawable getActivityIcon(ComponentName activityName); 2338 2339 @Direct loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo)2340 Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo); 2341 2342 @Direct getPackageArchiveInfo(String archiveFilePath, int flags)2343 PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags); 2344 2345 @Accessor("mContext") getContext()2346 Context getContext(); 2347 } 2348 2349 /** Returns the list of package names that were requested to be cleared. */ getClearedApplicationUserDataPackages()2350 public List<String> getClearedApplicationUserDataPackages() { 2351 return Collections.unmodifiableList(clearedApplicationUserDataPackages); 2352 } 2353 } 2354