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