1 package org.robolectric.shadows; 2 3 import static android.content.IntentFilter.MATCH_CATEGORY_MASK; 4 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; 5 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 6 import static android.content.pm.PackageManager.GET_META_DATA; 7 import static android.content.pm.PackageManager.GET_SIGNATURES; 8 import static android.content.pm.PackageManager.MATCH_ALL; 9 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; 10 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; 11 import static android.content.pm.PackageManager.SIGNATURE_UNKNOWN_PACKAGE; 12 import static android.os.Build.VERSION_CODES.JELLY_BEAN; 13 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; 14 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2; 15 import static android.os.Build.VERSION_CODES.KITKAT; 16 import static android.os.Build.VERSION_CODES.LOLLIPOP; 17 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; 18 import static android.os.Build.VERSION_CODES.M; 19 import static android.os.Build.VERSION_CODES.N; 20 import static android.os.Build.VERSION_CODES.O; 21 import static android.os.Build.VERSION_CODES.O_MR1; 22 import static android.os.Build.VERSION_CODES.P; 23 import static android.os.Build.VERSION_CODES.Q; 24 import static android.os.Build.VERSION_CODES.R; 25 26 import static org.robolectric.shadow.api.Shadow.invokeConstructor; 27 import static org.robolectric.util.ReflectionHelpers.ClassParameter.from; 28 29 import android.annotation.DrawableRes; 30 import android.annotation.NonNull; 31 import android.annotation.Nullable; 32 import android.annotation.UserIdInt; 33 import android.app.ApplicationPackageManager; 34 import android.app.admin.DevicePolicyManager; 35 import android.content.ComponentName; 36 import android.content.Context; 37 import android.content.Intent; 38 import android.content.IntentFilter; 39 import android.content.IntentSender; 40 import android.content.pm.ActivityInfo; 41 import android.content.pm.ApplicationInfo; 42 import android.content.pm.ChangedPackages; 43 import android.content.pm.ComponentInfo; 44 import android.content.pm.FeatureInfo; 45 import android.content.pm.IPackageDataObserver; 46 import android.content.pm.IPackageDeleteObserver; 47 import android.content.pm.IPackageManager; 48 import android.content.pm.IPackageStatsObserver; 49 import android.content.pm.InstrumentationInfo; 50 import android.content.pm.IntentFilterVerificationInfo; 51 import android.content.pm.ModuleInfo; 52 import android.content.pm.PackageInfo; 53 import android.content.pm.PackageItemInfo; 54 import android.content.pm.PackageManager; 55 import android.content.pm.PackageManager.NameNotFoundException; 56 import android.content.pm.PackageParser; 57 import android.content.pm.PackageParser.Activity; 58 import android.content.pm.PackageParser.Component; 59 import android.content.pm.PackageParser.Package; 60 import android.content.pm.PackageParser.PermissionGroup; 61 import android.content.pm.PackageParser.Provider; 62 import android.content.pm.PackageParser.Service; 63 import android.content.pm.PackageStats; 64 import android.content.pm.PermissionGroupInfo; 65 import android.content.pm.PermissionInfo; 66 import android.content.pm.ProviderInfo; 67 import android.content.pm.ResolveInfo; 68 import android.content.pm.ServiceInfo; 69 import android.content.pm.VerifierDeviceIdentity; 70 import android.content.res.AssetManager; 71 import android.content.res.Resources; 72 import android.graphics.drawable.Drawable; 73 import android.net.Uri; 74 import android.os.Build.VERSION; 75 import android.os.Build.VERSION_CODES; 76 import android.os.Handler; 77 import android.os.Looper; 78 import android.os.Parcel; 79 import android.os.PersistableBundle; 80 import android.os.RemoteException; 81 import android.os.UserHandle; 82 import android.os.storage.VolumeInfo; 83 84 import android.permission.IPermissionManager; 85 import android.telecom.TelecomManager; 86 import android.util.Pair; 87 import com.google.common.base.Function; 88 import java.io.File; 89 import java.util.ArrayList; 90 import java.util.Arrays; 91 import java.util.Collections; 92 import java.util.HashSet; 93 import java.util.Iterator; 94 import java.util.List; 95 import java.util.Map.Entry; 96 import java.util.Objects; 97 import java.util.Set; 98 import org.robolectric.RuntimeEnvironment; 99 import org.robolectric.annotation.HiddenApi; 100 import org.robolectric.annotation.Implementation; 101 import org.robolectric.annotation.Implements; 102 import org.robolectric.annotation.RealObject; 103 import org.robolectric.shadow.api.Shadow; 104 105 @Implements(value = ApplicationPackageManager.class, isInAndroidSdk = false, looseSignatures = true) 106 public class ShadowApplicationPackageManager extends ShadowPackageManager { 107 108 /** Package name of the Android platform. */ 109 private static final String PLATFORM_PACKAGE_NAME = "android"; 110 111 /** MIME type of Android Packages (APKs). */ 112 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; 113 114 /** {@link Uri} scheme of installed apps. */ 115 private static final String PACKAGE_SCHEME = "package"; 116 117 @RealObject private ApplicationPackageManager realObject; 118 119 private Context context; 120 121 @Implementation __constructor__(Object contextImpl, Object pm)122 protected void __constructor__(Object contextImpl, Object pm) { 123 try { 124 invokeConstructor( 125 ApplicationPackageManager.class, 126 realObject, 127 from(Class.forName(ShadowContextImpl.CLASS_NAME), contextImpl), 128 from(IPackageManager.class, pm)); 129 } catch (ClassNotFoundException e) { 130 throw new RuntimeException(e); 131 } 132 context = (Context) contextImpl; 133 } 134 135 // BEGIN-INTERNAL 136 @Implementation(minSdk = R, maxSdk = R) __constructor__( Object contextImpl, Object packageManager, Object permissionManager)137 protected void __constructor__( 138 Object contextImpl, Object packageManager, Object permissionManager) { 139 try { 140 invokeConstructor( 141 ApplicationPackageManager.class, 142 realObject, 143 from(Class.forName(ShadowContextImpl.CLASS_NAME), contextImpl), 144 from(IPackageManager.class, packageManager), 145 from(IPermissionManager.class, permissionManager)); 146 } catch (ClassNotFoundException e) { 147 throw new RuntimeException(e); 148 } 149 context = (Context) contextImpl; 150 } 151 // END-INTERNAL 152 153 @Implementation getInstalledPackages(int flags)154 public List<PackageInfo> getInstalledPackages(int flags) { 155 List<PackageInfo> result = new ArrayList<>(); 156 for (PackageInfo packageInfo : packageInfos.values()) { 157 String packageName = packageInfo.packageName; 158 159 if (applicationEnabledSettingMap.get(packageName) == COMPONENT_ENABLED_STATE_DISABLED 160 && (flags & MATCH_UNINSTALLED_PACKAGES) != MATCH_UNINSTALLED_PACKAGES 161 && (flags & MATCH_DISABLED_COMPONENTS) != MATCH_DISABLED_COMPONENTS) { 162 continue; 163 } 164 165 if (hiddenPackages.contains(packageName) && !isFlagSet(flags, MATCH_UNINSTALLED_PACKAGES)) { 166 continue; 167 } 168 169 result.add(newPackageInfo(packageInfo)); 170 } 171 172 return result; 173 } 174 175 @Implementation getActivityInfo(ComponentName component, int flags)176 protected ActivityInfo getActivityInfo(ComponentName component, int flags) 177 throws NameNotFoundException { 178 String activityName = component.getClassName(); 179 String packageName = component.getPackageName(); 180 PackageInfo packageInfo = packageInfos.get(packageName); 181 182 if (packageInfo != null) { 183 if (packageInfo.activities != null) { 184 for (ActivityInfo activity : packageInfo.activities) { 185 if (activityName.equals(activity.name)) { 186 ActivityInfo result = new ActivityInfo(activity); 187 applyFlagsToComponentInfo(result, flags); 188 189 return result; 190 } 191 } 192 } 193 194 // Activity is requested is not listed in the AndroidManifest.xml 195 ActivityInfo result = new ActivityInfo(); 196 result.name = activityName; 197 result.packageName = packageName; 198 result.applicationInfo = new ApplicationInfo(packageInfo.applicationInfo); 199 return result; 200 } 201 202 // TODO: Should throw a NameNotFoundException 203 // In the cases where an Activity from another package has been requested. 204 ActivityInfo result = new ActivityInfo(); 205 result.name = activityName; 206 result.packageName = packageName; 207 result.applicationInfo = new ApplicationInfo(); 208 result.applicationInfo.packageName = packageName; 209 result.applicationInfo.flags = ApplicationInfo.FLAG_INSTALLED; 210 return result; 211 } 212 213 @Implementation hasSystemFeature(String name)214 protected boolean hasSystemFeature(String name) { 215 return systemFeatureList.containsKey(name) ? systemFeatureList.get(name) : false; 216 } 217 218 @Implementation getComponentEnabledSetting(ComponentName componentName)219 protected int getComponentEnabledSetting(ComponentName componentName) { 220 ComponentState state = componentList.get(componentName); 221 return state != null ? state.newState : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 222 } 223 224 @Implementation getNameForUid(int uid)225 protected @Nullable String getNameForUid(int uid) { 226 return namesForUid.get(uid); 227 } 228 229 @Implementation getPackagesForUid(int uid)230 protected @Nullable String[] getPackagesForUid(int uid) { 231 String[] packageNames = packagesForUid.get(uid); 232 if (packageNames != null) { 233 return packageNames; 234 } 235 236 Set<String> results = new HashSet<>(); 237 for (PackageInfo packageInfo : packageInfos.values()) { 238 if (packageInfo.applicationInfo != null && packageInfo.applicationInfo.uid == uid) { 239 results.add(packageInfo.packageName); 240 } 241 } 242 243 return results.isEmpty() ? null : results.toArray(new String[results.size()]); 244 } 245 246 @Implementation getApplicationEnabledSetting(String packageName)247 protected int getApplicationEnabledSetting(String packageName) { 248 try { 249 getPackageInfo(packageName, -1); 250 } catch (NameNotFoundException e) { 251 throw new IllegalArgumentException(e); 252 } 253 254 return applicationEnabledSettingMap.get(packageName); 255 } 256 257 @Implementation getProviderInfo(ComponentName component, int flags)258 protected ProviderInfo getProviderInfo(ComponentName component, int flags) 259 throws NameNotFoundException { 260 String packageName = component.getPackageName(); 261 262 PackageInfo packageInfo = packageInfos.get(packageName); 263 if (packageInfo != null && packageInfo.providers != null) { 264 for (ProviderInfo provider : packageInfo.providers) { 265 if (resolvePackageName(packageName, component).equals(provider.name)) { 266 ProviderInfo result = new ProviderInfo(provider); 267 applyFlagsToComponentInfo(result, flags); 268 return result; 269 } 270 } 271 } 272 273 throw new NameNotFoundException("Package not found: " + packageName); 274 } 275 276 @Implementation setComponentEnabledSetting(ComponentName componentName, int newState, int flags)277 protected void setComponentEnabledSetting(ComponentName componentName, int newState, int flags) { 278 componentList.put(componentName, new ComponentState(newState, flags)); 279 } 280 281 @Implementation setApplicationEnabledSetting(String packageName, int newState, int flags)282 protected void setApplicationEnabledSetting(String packageName, int newState, int flags) { 283 applicationEnabledSettingMap.put(packageName, newState); 284 } 285 286 @Implementation resolveActivity(Intent intent, int flags)287 protected ResolveInfo resolveActivity(Intent intent, int flags) { 288 HashSet<ComponentName> preferredComponents = new HashSet<>(); 289 290 for (Entry<IntentFilterWrapper, ComponentName> preferred : preferredActivities.entrySet()) { 291 if ((preferred.getKey().getFilter().match(context.getContentResolver(), intent, false, "robo") 292 & MATCH_CATEGORY_MASK) 293 != 0) { 294 preferredComponents.add(preferred.getValue()); 295 } 296 } 297 List<ResolveInfo> candidates = queryIntentActivities(intent, flags); 298 299 return candidates.isEmpty() 300 ? null 301 : Collections.max(candidates, new ResolveInfoComparator(preferredComponents)); 302 } 303 304 @Implementation resolveContentProvider(String name, int flags)305 protected ProviderInfo resolveContentProvider(String name, int flags) { 306 if (name == null) { 307 return null; 308 } 309 for (PackageInfo packageInfo : packageInfos.values()) { 310 if (packageInfo.providers == null) continue; 311 312 for (ProviderInfo providerInfo : packageInfo.providers) { 313 if (name.equals(providerInfo.authority)) { // todo: support multiple authorities 314 return new ProviderInfo(providerInfo); 315 } 316 } 317 } 318 return null; 319 } 320 321 @Implementation(minSdk = LOLLIPOP) resolveContentProviderAsUser( String name, int flags, @UserIdInt int userId)322 protected ProviderInfo resolveContentProviderAsUser( 323 String name, int flags, @UserIdInt int userId) { 324 return null; 325 } 326 327 @Implementation getPackageInfo(String packageName, int flags)328 protected synchronized PackageInfo getPackageInfo(String packageName, int flags) 329 throws NameNotFoundException { 330 PackageInfo info = packageInfos.get(packageName); 331 if (info != null) { 332 if (applicationEnabledSettingMap.get(packageName) == COMPONENT_ENABLED_STATE_DISABLED 333 && (flags & MATCH_UNINSTALLED_PACKAGES) != MATCH_UNINSTALLED_PACKAGES 334 && (flags & MATCH_DISABLED_COMPONENTS) != MATCH_DISABLED_COMPONENTS) { 335 throw new NameNotFoundException("Package is disabled, can't find"); 336 } 337 if (hiddenPackages.contains(packageName) && !isFlagSet(flags, MATCH_UNINSTALLED_PACKAGES)) { 338 throw new NameNotFoundException("Package is hidden, can't find"); 339 } 340 return newPackageInfo(info); 341 } else { 342 throw new NameNotFoundException(packageName); 343 } 344 } 345 346 // There is no copy constructor for PackageInfo newPackageInfo(PackageInfo orig)347 private static PackageInfo newPackageInfo(PackageInfo orig) { 348 Parcel parcel = Parcel.obtain(); 349 orig.writeToParcel(parcel, 0); 350 parcel.setDataPosition(0); 351 return PackageInfo.CREATOR.createFromParcel(parcel); 352 } 353 354 @Implementation queryIntentServices(Intent intent, int flags)355 protected List<ResolveInfo> queryIntentServices(Intent intent, int flags) { 356 List<ResolveInfo> result = new ArrayList<>(); 357 List<ResolveInfo> resolveInfoList = queryOverriddenIntents(intent, flags); 358 if (!resolveInfoList.isEmpty()) { 359 result.addAll( 360 filterResolvedComponent( 361 resolveInfoList, flags, (resolveInfo) -> resolveInfo.serviceInfo)); 362 } 363 364 if (isExplicitIntent(intent)) { 365 ResolveInfo resolvedService = resolveServiceForExplicitIntent(intent); 366 if (resolvedService != null) { 367 result.addAll( 368 filterResolvedComponent( 369 Arrays.asList(resolvedService), flags, (resolveInfo) -> resolveInfo.serviceInfo)); 370 } 371 } else { 372 result.addAll( 373 filterResolvedComponent( 374 queryImplicitIntentServices(intent), 375 flags, 376 (resolveInfo) -> resolveInfo.serviceInfo)); 377 } 378 return result; 379 } 380 filterResolvedComponent( List<ResolveInfo> resolveInfoList, int flags, Function<ResolveInfo, ComponentInfo> componentInfoFn)381 private List<ResolveInfo> filterResolvedComponent( 382 List<ResolveInfo> resolveInfoList, 383 int flags, 384 Function<ResolveInfo, ComponentInfo> componentInfoFn) { 385 // If the flag is set, no further filtering will happen. 386 if (isFlagSet(flags, PackageManager.MATCH_ALL)) { 387 return resolveInfoList; 388 } 389 // Create a copy of the list for filtering 390 resolveInfoList = new ArrayList<>(resolveInfoList); 391 392 for (Iterator<ResolveInfo> iterator = resolveInfoList.iterator(); iterator.hasNext(); ) { 393 ResolveInfo resolveInfo = iterator.next(); 394 ComponentInfo componentInfo = componentInfoFn.apply(resolveInfo); 395 396 boolean hasSomeComponentInfo = 397 resolveInfo.activityInfo != null 398 || resolveInfo.serviceInfo != null 399 || (VERSION.SDK_INT >= VERSION_CODES.KITKAT && resolveInfo.providerInfo != null); 400 if (componentInfo == null && hasSomeComponentInfo) { 401 // wrong type of component. For backward compatibility we keep those entries that doesn't 402 // have any component. 403 iterator.remove(); 404 continue; 405 } 406 407 if (isFlagSet(flags, PackageManager.MATCH_SYSTEM_ONLY)) { 408 if (componentInfo == null || componentInfo.applicationInfo == null) { 409 // TODO: for backwards compatibility just skip filtering. In future should just remove 410 // invalid resolve infos from list 411 iterator.remove(); 412 continue; 413 } else { 414 final int applicationFlags = componentInfo.applicationInfo.flags; 415 if ((applicationFlags & ApplicationInfo.FLAG_SYSTEM) != ApplicationInfo.FLAG_SYSTEM) { 416 iterator.remove(); 417 continue; 418 } 419 } 420 } 421 if (!isFlagSet(flags, PackageManager.MATCH_DISABLED_COMPONENTS) 422 && resolveInfo != null 423 && isValidComponentInfo(componentInfo)) { 424 ComponentName componentName = 425 new ComponentName(componentInfo.applicationInfo.packageName, componentInfo.name); 426 if ((getComponentEnabledSetting(componentName) 427 & PackageManager.COMPONENT_ENABLED_STATE_DISABLED) 428 != 0) { 429 iterator.remove(); 430 continue; 431 } 432 } 433 if (!isFlagSet(flags, MATCH_UNINSTALLED_PACKAGES) 434 && resolveInfo != null 435 && isValidComponentInfo(componentInfo) 436 && hiddenPackages.contains(componentInfo.applicationInfo.packageName)) { 437 iterator.remove(); 438 continue; 439 } 440 } 441 return resolveInfoList; 442 } 443 isFlagSet(int flags, int matchFlag)444 private static boolean isFlagSet(int flags, int matchFlag) { 445 return (flags & matchFlag) == matchFlag; 446 } 447 isValidComponentInfo(ComponentInfo componentInfo)448 private static boolean isValidComponentInfo(ComponentInfo componentInfo) { 449 return componentInfo != null 450 && componentInfo.applicationInfo != null 451 && componentInfo.applicationInfo.packageName != null 452 && componentInfo.name != null; 453 } 454 455 /** Behaves as {@link #queryIntentServices(Intent, int)} and currently ignores userId. */ 456 @Implementation(minSdk = JELLY_BEAN_MR1) queryIntentServicesAsUser(Intent intent, int flags, int userId)457 protected List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) { 458 return queryIntentServices(intent, flags); 459 } 460 461 @Implementation queryIntentActivities(Intent intent, int flags)462 protected List<ResolveInfo> queryIntentActivities(Intent intent, int flags) { 463 List<ResolveInfo> result = new ArrayList<>(); 464 List<ResolveInfo> resolveInfoList = queryOverriddenIntents(intent, flags); 465 if (!resolveInfoList.isEmpty()) { 466 result.addAll( 467 filterResolvedComponent( 468 resolveInfoList, flags, (resolveInfo) -> resolveInfo.activityInfo)); 469 } 470 471 if (isExplicitIntent(intent)) { 472 ResolveInfo resolvedActivity = resolveActivityForExplicitIntent(intent); 473 if (resolvedActivity != null) { 474 result.addAll( 475 filterResolvedComponent( 476 Arrays.asList(resolvedActivity), flags, (resolveInfo) -> resolveInfo.activityInfo)); 477 } 478 } else { 479 result.addAll( 480 filterResolvedComponent( 481 queryImplicitIntentActivities(intent), 482 flags, 483 (resolveInfo) -> resolveInfo.activityInfo)); 484 } 485 return result; 486 } 487 488 /** Behaves as {@link #queryIntentActivities(Intent, int)} and currently ignores userId. */ 489 @Implementation(minSdk = JELLY_BEAN_MR1) queryIntentActivitiesAsUser(Intent intent, int flags, int userId)490 protected List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) { 491 return queryIntentActivities(intent, flags); 492 } 493 494 /** Returns true if intent has specified a specific component. */ isExplicitIntent(Intent intent)495 private static boolean isExplicitIntent(Intent intent) { 496 return getComponentForIntent(intent) != null; 497 } 498 resolveActivityForExplicitIntent(Intent intent)499 private ResolveInfo resolveActivityForExplicitIntent(Intent intent) { 500 ComponentName component = getComponentForIntent(intent); 501 for (Package appPackage : packages.values()) { 502 Activity activity = findMatchingComponent(component, appPackage.activities); 503 if (activity != null) { 504 return buildResolveInfo(activity); 505 } 506 } 507 return null; 508 } 509 resolveServiceForExplicitIntent(Intent intent)510 private ResolveInfo resolveServiceForExplicitIntent(Intent intent) { 511 ComponentName component = getComponentForIntent(intent); 512 for (Package appPackage : packages.values()) { 513 Service service = findMatchingComponent(component, appPackage.services); 514 if (service != null) { 515 return buildResolveInfo(service); 516 } 517 } 518 return null; 519 } 520 resolveReceiverForExplicitIntent(Intent intent)521 private ResolveInfo resolveReceiverForExplicitIntent(Intent intent) { 522 ComponentName component = getComponentForIntent(intent); 523 for (Package appPackage : packages.values()) { 524 Activity receiver = findMatchingComponent(component, appPackage.receivers); 525 if (receiver != null) { 526 return buildResolveInfo(receiver); 527 } 528 } 529 return null; 530 } 531 resolveContentProviderForExplicitIntent(Intent intent)532 private ResolveInfo resolveContentProviderForExplicitIntent(Intent intent) { 533 ComponentName component = getComponentForIntent(intent); 534 for (Package appPackage : packages.values()) { 535 Provider provider = findMatchingComponent(component, appPackage.providers); 536 if (provider != null) { 537 return buildResolveInfo(provider); 538 } 539 } 540 return null; 541 } 542 findMatchingComponent( ComponentName componentName, List<T> components)543 private static <T extends Component> T findMatchingComponent( 544 ComponentName componentName, List<T> components) { 545 for (T component : components) { 546 if (componentName.equals(component.getComponentName())) { 547 return component; 548 } 549 } 550 return null; 551 } 552 getComponentForIntent(Intent intent)553 private static ComponentName getComponentForIntent(Intent intent) { 554 ComponentName component = intent.getComponent(); 555 if (component == null) { 556 if (intent.getSelector() != null) { 557 intent = intent.getSelector(); 558 component = intent.getComponent(); 559 } 560 } 561 return component; 562 } 563 queryImplicitIntentContentProviders(Intent intent)564 private List<ResolveInfo> queryImplicitIntentContentProviders(Intent intent) { 565 List<ResolveInfo> resolveInfoList = new ArrayList<>(); 566 567 for (Package appPackage : packages.values()) { 568 if (intent.getPackage() == null || intent.getPackage().equals(appPackage.packageName)) { 569 for (Provider provider : appPackage.providers) { 570 IntentFilter intentFilter = matchIntentFilter(intent, provider.intents); 571 if (intentFilter != null) { 572 resolveInfoList.add(buildResolveInfo(provider)); 573 } 574 } 575 } 576 } 577 578 return resolveInfoList; 579 } 580 queryImplicitIntentActivities(Intent intent)581 private List<ResolveInfo> queryImplicitIntentActivities(Intent intent) { 582 List<ResolveInfo> resolveInfoList = new ArrayList<>(); 583 584 for (Package appPackage : packages.values()) { 585 if (intent.getPackage() == null || intent.getPackage().equals(appPackage.packageName)) { 586 for (Activity activity : appPackage.activities) { 587 IntentFilter intentFilter = matchIntentFilter(intent, activity.intents); 588 if (intentFilter != null) { 589 resolveInfoList.add(buildResolveInfo(activity, intentFilter)); 590 } 591 } 592 } 593 } 594 595 return resolveInfoList; 596 } 597 queryImplicitIntentServices(Intent intent)598 private List<ResolveInfo> queryImplicitIntentServices(Intent intent) { 599 List<ResolveInfo> resolveInfoList = new ArrayList<>(); 600 601 for (Package appPackage : packages.values()) { 602 if (intent.getPackage() == null || intent.getPackage().equals(appPackage.packageName)) { 603 for (Service service : appPackage.services) { 604 IntentFilter intentFilter = matchIntentFilter(intent, service.intents); 605 if (intentFilter != null) { 606 resolveInfoList.add(buildResolveInfo(service, intentFilter)); 607 } 608 } 609 } 610 } 611 612 return resolveInfoList; 613 } 614 queryImplicitIntentReceivers(Intent intent)615 private List<ResolveInfo> queryImplicitIntentReceivers(Intent intent) { 616 List<ResolveInfo> resolveInfoList = new ArrayList<>(); 617 618 for (Package appPackage : packages.values()) { 619 if (intent.getPackage() == null || intent.getPackage().equals(appPackage.packageName)) { 620 for (Activity activity : appPackage.receivers) { 621 IntentFilter intentFilter = matchIntentFilter(intent, activity.intents); 622 if (intentFilter != null) { 623 resolveInfoList.add(buildResolveInfo(activity, intentFilter)); 624 } 625 } 626 } 627 } 628 629 return resolveInfoList; 630 } 631 buildResolveInfo(Activity activity)632 static ResolveInfo buildResolveInfo(Activity activity) { 633 ResolveInfo resolveInfo = buildResolveInfo(activity.info); 634 resolveInfo.activityInfo = activity.info; 635 return resolveInfo; 636 } 637 buildResolveInfo(Service service)638 static ResolveInfo buildResolveInfo(Service service) { 639 ResolveInfo resolveInfo = buildResolveInfo(service.info); 640 resolveInfo.serviceInfo = service.info; 641 return resolveInfo; 642 } 643 buildResolveInfo(Provider provider)644 static ResolveInfo buildResolveInfo(Provider provider) { 645 ResolveInfo resolveInfo = buildResolveInfo(provider.info); 646 resolveInfo.providerInfo = provider.info; 647 return resolveInfo; 648 } 649 buildResolveInfo(ComponentInfo componentInfo)650 private static ResolveInfo buildResolveInfo(ComponentInfo componentInfo) { 651 ResolveInfo resolveInfo = new ResolveInfo(); 652 resolveInfo.resolvePackageName = componentInfo.applicationInfo.packageName; 653 return resolveInfo; 654 } 655 buildResolveInfo(Activity activity, IntentFilter intentFilter)656 static ResolveInfo buildResolveInfo(Activity activity, IntentFilter intentFilter) { 657 ResolveInfo info = buildResolveInfo(activity); 658 info.isDefault = intentFilter.hasCategory("Intent.CATEGORY_DEFAULT"); 659 info.filter = new IntentFilter(intentFilter); 660 return info; 661 } 662 buildResolveInfo(Service service, IntentFilter intentFilter)663 static ResolveInfo buildResolveInfo(Service service, IntentFilter intentFilter) { 664 ResolveInfo info = buildResolveInfo(service); 665 info.isDefault = intentFilter.hasCategory("Intent.CATEGORY_DEFAULT"); 666 info.serviceInfo = service.info; 667 info.filter = new IntentFilter(intentFilter); 668 return info; 669 } 670 671 @Implementation checkPermission(String permName, String pkgName)672 protected int checkPermission(String permName, String pkgName) { 673 PackageInfo permissionsInfo = packageInfos.get(pkgName); 674 if (permissionsInfo == null || permissionsInfo.requestedPermissions == null) { 675 return PackageManager.PERMISSION_DENIED; 676 } 677 678 String permission; 679 for (int i = 0; i < permissionsInfo.requestedPermissions.length; i++) { 680 permission = permissionsInfo.requestedPermissions[i]; 681 if (permission != null && permission.equals(permName)) { 682 // The package requests this permission. Now check if it's been granted to the package. 683 if (isGrantedForBackwardsCompatibility(pkgName, permissionsInfo)) { 684 return PackageManager.PERMISSION_GRANTED; 685 } 686 687 if ((permissionsInfo.requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) 688 == REQUESTED_PERMISSION_GRANTED) { 689 return PackageManager.PERMISSION_GRANTED; 690 } 691 } 692 } 693 694 return PackageManager.PERMISSION_DENIED; 695 } 696 697 /** 698 * Returns whether a permission should be treated as granted to the package for backward 699 * compatibility reasons. 700 * 701 * <p>Before Robolectric 4.0 the ShadowPackageManager treated every requested permission as 702 * automatically granted. 4.0 changes this behavior, and only treats a permission as granted if 703 * PackageInfo.requestedPermissionFlags[permissionIndex] & REQUESTED_PERMISSION_GRANTED == 704 * REQUESTED_PERMISSION_GRANTED which matches the real PackageManager's behavior. 705 * 706 * <p>Since many existing tests didn't set the requestedPermissionFlags on their {@code 707 * PackageInfo} objects, but assumed that all permissions are granted, we auto-grant all 708 * permissions if the requestedPermissionFlags is not set. If the requestedPermissionFlags is set, 709 * we assume that the test is configuring the permission grant state, and we don't override this 710 * setting. 711 */ isGrantedForBackwardsCompatibility(String pkgName, PackageInfo permissionsInfo)712 private boolean isGrantedForBackwardsCompatibility(String pkgName, PackageInfo permissionsInfo) { 713 // Note: it might be cleaner to auto-grant these permissions when the package is added to the 714 // PackageManager. But many existing tests modify the requested permissions _after_ adding the 715 // package to the PackageManager, without updating the requestedPermissionsFlags. 716 return permissionsInfo.requestedPermissionsFlags == null 717 // Robolectric uses the PackageParser to create the current test package's PackageInfo from 718 // the manifest XML. The parser populates the requestedPermissionsFlags, but doesn't grant 719 // the permissions. Several tests rely on the test package being granted all permissions, so 720 // we treat this as a special case. 721 || pkgName.equals(RuntimeEnvironment.application.getPackageName()); 722 } 723 724 @Implementation getReceiverInfo(ComponentName className, int flags)725 protected ActivityInfo getReceiverInfo(ComponentName className, int flags) 726 throws NameNotFoundException { 727 String packageName = className.getPackageName(); 728 729 PackageInfo packageInfo = packageInfos.get(packageName); 730 if (packageInfo != null && packageInfo.receivers != null) { 731 for (ActivityInfo receiver : packageInfo.receivers) { 732 if (resolvePackageName(packageName, className).equals(receiver.name)) { 733 ActivityInfo result = new ActivityInfo(receiver); 734 applyFlagsToComponentInfo(result, flags); 735 return result; 736 } 737 } 738 } 739 740 return null; 741 } 742 743 @Implementation queryBroadcastReceivers(Intent intent, int flags)744 protected List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) { 745 List<ResolveInfo> result = new ArrayList<>(); 746 List<ResolveInfo> resolveInfoList = queryOverriddenIntents(intent, flags); 747 if (!resolveInfoList.isEmpty()) { 748 result.addAll( 749 filterResolvedComponent( 750 resolveInfoList, flags, (resolveInfo) -> resolveInfo.activityInfo)); 751 } 752 753 if (isExplicitIntent(intent)) { 754 ResolveInfo resolvedReceiver = resolveReceiverForExplicitIntent(intent); 755 if (resolvedReceiver != null) { 756 result.addAll( 757 filterResolvedComponent( 758 Arrays.asList(resolvedReceiver), flags, (resolveInfo) -> resolveInfo.activityInfo)); 759 } 760 } else { 761 result.addAll( 762 filterResolvedComponent( 763 queryImplicitIntentReceivers(intent), 764 flags, 765 (resolveInfo) -> resolveInfo.activityInfo)); 766 } 767 return result; 768 } 769 matchIntentFilter( Intent intent, ArrayList<? extends PackageParser.IntentInfo> intentFilters)770 private static IntentFilter matchIntentFilter( 771 Intent intent, ArrayList<? extends PackageParser.IntentInfo> intentFilters) { 772 for (PackageParser.IntentInfo intentInfo : intentFilters) { 773 if (intentInfo.match( 774 intent.getAction(), 775 intent.getType(), 776 intent.getScheme(), 777 intent.getData(), 778 intent.getCategories(), 779 "ShadowPackageManager") 780 >= 0) { 781 return intentInfo; 782 } 783 } 784 return null; 785 } 786 787 @Implementation resolveService(Intent intent, int flags)788 protected ResolveInfo resolveService(Intent intent, int flags) { 789 List<ResolveInfo> candidates = queryIntentServices(intent, flags); 790 return candidates.isEmpty() ? null : candidates.get(0); 791 } 792 793 @Implementation getServiceInfo(ComponentName className, int flags)794 protected ServiceInfo getServiceInfo(ComponentName className, int flags) 795 throws NameNotFoundException { 796 String packageName = className.getPackageName(); 797 PackageInfo packageInfo = packageInfos.get(packageName); 798 799 if (packageInfo != null) { 800 String serviceName = className.getClassName(); 801 if (packageInfo.services != null) { 802 for (ServiceInfo service : packageInfo.services) { 803 if (serviceName.equals(service.name)) { 804 ServiceInfo result = new ServiceInfo(service); 805 applyFlagsToComponentInfo(result, flags); 806 result.applicationInfo = new ApplicationInfo(service.applicationInfo); 807 if (result.processName == null) { 808 result.processName = result.applicationInfo.processName; 809 } 810 return result; 811 } 812 } 813 } 814 throw new NameNotFoundException(serviceName); 815 } 816 return null; 817 } 818 applyFlagsToComponentInfo(ComponentInfo result, int flags)819 private void applyFlagsToComponentInfo(ComponentInfo result, int flags) 820 throws NameNotFoundException { 821 if ((flags & GET_META_DATA) == 0) { 822 result.metaData = null; 823 } 824 if ((flags & MATCH_ALL) != 0) { 825 return; 826 } 827 } 828 829 @Implementation getResourcesForApplication(@onNull ApplicationInfo applicationInfo)830 protected Resources getResourcesForApplication(@NonNull ApplicationInfo applicationInfo) 831 throws PackageManager.NameNotFoundException { 832 return getResourcesForApplication(applicationInfo.packageName); 833 } 834 835 @Implementation getInstalledApplications(int flags)836 protected List<ApplicationInfo> getInstalledApplications(int flags) { 837 List<ApplicationInfo> result = new ArrayList<>(); 838 839 for (PackageInfo packageInfo : packageInfos.values()) { 840 result.add(packageInfo.applicationInfo); 841 } 842 return result; 843 } 844 845 @Implementation getInstallerPackageName(String packageName)846 protected String getInstallerPackageName(String packageName) { 847 return packageInstallerMap.get(packageName); 848 } 849 850 @Implementation getPermissionInfo(String name, int flags)851 protected PermissionInfo getPermissionInfo(String name, int flags) throws NameNotFoundException { 852 PermissionInfo permissionInfo = extraPermissions.get(name); 853 if (permissionInfo != null) { 854 return permissionInfo; 855 } 856 857 for (PackageInfo packageInfo : packageInfos.values()) { 858 if (packageInfo.permissions != null) { 859 for (PermissionInfo permission : packageInfo.permissions) { 860 if (name.equals(permission.name)) { 861 return createCopyPermissionInfo(permission, flags); 862 } 863 } 864 } 865 } 866 867 throw new NameNotFoundException(name); 868 } 869 870 @Implementation(minSdk = M) shouldShowRequestPermissionRationale(String permission)871 protected boolean shouldShowRequestPermissionRationale(String permission) { 872 return permissionRationaleMap.containsKey(permission) 873 ? permissionRationaleMap.get(permission) 874 : false; 875 } 876 877 @Implementation getSystemAvailableFeatures()878 protected FeatureInfo[] getSystemAvailableFeatures() { 879 return systemAvailableFeatures.isEmpty() 880 ? null 881 : systemAvailableFeatures.toArray(new FeatureInfo[systemAvailableFeatures.size()]); 882 } 883 884 @Implementation verifyPendingInstall(int id, int verificationCode)885 protected void verifyPendingInstall(int id, int verificationCode) { 886 if (verificationResults.containsKey(id)) { 887 throw new IllegalStateException("Multiple verifications for id=" + id); 888 } 889 verificationResults.put(id, verificationCode); 890 } 891 892 @Implementation(minSdk = JELLY_BEAN_MR1) extendVerificationTimeout( int id, int verificationCodeAtTimeout, long millisecondsToDelay)893 protected void extendVerificationTimeout( 894 int id, int verificationCodeAtTimeout, long millisecondsToDelay) { 895 verificationTimeoutExtension.put(id, millisecondsToDelay); 896 } 897 898 @Override 899 @Implementation(maxSdk = LOLLIPOP_MR1) freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer)900 protected void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer) {} 901 902 @Implementation(minSdk = M) freeStorageAndNotify( String volumeUuid, long freeStorageSize, IPackageDataObserver observer)903 protected void freeStorageAndNotify( 904 String volumeUuid, long freeStorageSize, IPackageDataObserver observer) {} 905 906 @Implementation setInstallerPackageName(String targetPackage, String installerPackageName)907 protected void setInstallerPackageName(String targetPackage, String installerPackageName) { 908 packageInstallerMap.put(targetPackage, installerPackageName); 909 } 910 911 @Implementation(minSdk = KITKAT) queryIntentContentProviders(Intent intent, int flags)912 protected List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) { 913 List<ResolveInfo> result = new ArrayList<>(); 914 List<ResolveInfo> resolveInfoList = queryOverriddenIntents(intent, flags); 915 if (!resolveInfoList.isEmpty()) { 916 result.addAll( 917 filterResolvedComponent( 918 resolveInfoList, flags, (resolveInfo) -> resolveInfo.providerInfo)); 919 } 920 921 if (isExplicitIntent(intent)) { 922 ResolveInfo resolvedProvider = resolveContentProviderForExplicitIntent(intent); 923 if (resolvedProvider != null) { 924 result.addAll( 925 filterResolvedComponent( 926 Arrays.asList(resolvedProvider), flags, (resolveInfo) -> resolveInfo.providerInfo)); 927 } 928 } else { 929 result.addAll( 930 filterResolvedComponent( 931 queryImplicitIntentContentProviders(intent), 932 flags, 933 (resolveInfo) -> resolveInfo.providerInfo)); 934 } 935 return result; 936 } 937 938 @Implementation(minSdk = KITKAT) queryIntentContentProvidersAsUser( Intent intent, int flags, int userId)939 protected List<ResolveInfo> queryIntentContentProvidersAsUser( 940 Intent intent, int flags, int userId) { 941 return Collections.emptyList(); 942 } 943 944 @Implementation(minSdk = M) getPermissionControllerPackageName()945 protected String getPermissionControllerPackageName() { 946 return null; 947 } 948 949 @Implementation(maxSdk = JELLY_BEAN) getPackageSizeInfo(Object pkgName, Object observer)950 protected void getPackageSizeInfo(Object pkgName, Object observer) { 951 final PackageStats packageStats = packageStatsMap.get((String) pkgName); 952 new Handler(Looper.getMainLooper()) 953 .post( 954 () -> { 955 try { 956 ((IPackageStatsObserver) observer) 957 .onGetStatsCompleted(packageStats, packageStats != null); 958 } catch (RemoteException remoteException) { 959 remoteException.rethrowFromSystemServer(); 960 } 961 }); 962 } 963 964 @Implementation(minSdk = JELLY_BEAN_MR1, maxSdk = M) getPackageSizeInfo(Object pkgName, Object uid, final Object observer)965 protected void getPackageSizeInfo(Object pkgName, Object uid, final Object observer) { 966 final PackageStats packageStats = packageStatsMap.get((String) pkgName); 967 new Handler(Looper.getMainLooper()) 968 .post( 969 () -> { 970 try { 971 ((IPackageStatsObserver) observer) 972 .onGetStatsCompleted(packageStats, packageStats != null); 973 } catch (RemoteException remoteException) { 974 remoteException.rethrowFromSystemServer(); 975 } 976 }); 977 } 978 979 @Implementation(minSdk = N) getPackageSizeInfoAsUser(Object pkgName, Object uid, final Object observer)980 protected void getPackageSizeInfoAsUser(Object pkgName, Object uid, final Object observer) { 981 final PackageStats packageStats = packageStatsMap.get((String) pkgName); 982 new Handler(Looper.getMainLooper()) 983 .post( 984 () -> { 985 try { 986 ((IPackageStatsObserver) observer) 987 .onGetStatsCompleted(packageStats, packageStats != null); 988 } catch (RemoteException remoteException) { 989 remoteException.rethrowFromSystemServer(); 990 } 991 }); 992 } 993 994 @Implementation deletePackage(String packageName, IPackageDeleteObserver observer, int flags)995 protected void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) { 996 pendingDeleteCallbacks.put(packageName, observer); 997 } 998 999 @Implementation currentToCanonicalPackageNames(String[] names)1000 protected String[] currentToCanonicalPackageNames(String[] names) { 1001 String[] out = new String[names.length]; 1002 for (int i = names.length - 1; i >= 0; i--) { 1003 if (currentToCanonicalNames.containsKey(names[i])) { 1004 out[i] = currentToCanonicalNames.get(names[i]); 1005 } else { 1006 out[i] = names[i]; 1007 } 1008 } 1009 return out; 1010 } 1011 1012 @Implementation isSafeMode()1013 protected boolean isSafeMode() { 1014 return false; 1015 } 1016 1017 @Implementation getApplicationIcon(String packageName)1018 protected Drawable getApplicationIcon(String packageName) throws NameNotFoundException { 1019 return applicationIcons.get(packageName); 1020 } 1021 1022 @Implementation getApplicationIcon(ApplicationInfo info)1023 protected Drawable getApplicationIcon(ApplicationInfo info) throws NameNotFoundException { 1024 return getApplicationIcon(info.packageName); 1025 } 1026 1027 @Implementation(minSdk = LOLLIPOP) getUserBadgeForDensity(UserHandle userHandle, int i)1028 protected Drawable getUserBadgeForDensity(UserHandle userHandle, int i) { 1029 return null; 1030 } 1031 1032 @Implementation checkSignatures(String pkg1, String pkg2)1033 protected int checkSignatures(String pkg1, String pkg2) { 1034 try { 1035 PackageInfo packageInfo1 = getPackageInfo(pkg1, GET_SIGNATURES); 1036 PackageInfo packageInfo2 = getPackageInfo(pkg2, GET_SIGNATURES); 1037 return compareSignature(packageInfo1.signatures, packageInfo2.signatures); 1038 } catch (NameNotFoundException e) { 1039 return SIGNATURE_UNKNOWN_PACKAGE; 1040 } 1041 } 1042 1043 @Implementation checkSignatures(int uid1, int uid2)1044 protected int checkSignatures(int uid1, int uid2) { 1045 return 0; 1046 } 1047 1048 @Implementation queryPermissionsByGroup(String group, int flags)1049 protected List<PermissionInfo> queryPermissionsByGroup(String group, int flags) 1050 throws NameNotFoundException { 1051 List<PermissionInfo> result = new ArrayList<>(); 1052 for (PermissionInfo permissionInfo : extraPermissions.values()) { 1053 if (Objects.equals(permissionInfo.group, group)) { 1054 result.add(permissionInfo); 1055 } 1056 } 1057 1058 for (PackageInfo packageInfo : packageInfos.values()) { 1059 if (packageInfo.permissions != null) { 1060 for (PermissionInfo permission : packageInfo.permissions) { 1061 if (Objects.equals(group, permission.group)) { 1062 result.add(createCopyPermissionInfo(permission, flags)); 1063 } 1064 } 1065 } 1066 } 1067 1068 if (result.isEmpty()) { 1069 throw new NameNotFoundException(group); 1070 } 1071 1072 return result; 1073 } 1074 createCopyPermissionInfo(PermissionInfo src, int flags)1075 private static PermissionInfo createCopyPermissionInfo(PermissionInfo src, int flags) { 1076 PermissionInfo matchedPermission = new PermissionInfo(src); 1077 if ((flags & GET_META_DATA) != GET_META_DATA) { 1078 matchedPermission.metaData = null; 1079 } 1080 return matchedPermission; 1081 } 1082 1083 @Implementation getLaunchIntentForPackage(String packageName)1084 protected Intent getLaunchIntentForPackage(String packageName) { 1085 Intent intentToResolve = new Intent(Intent.ACTION_MAIN); 1086 intentToResolve.addCategory(Intent.CATEGORY_INFO); 1087 intentToResolve.setPackage(packageName); 1088 List<ResolveInfo> ris = queryIntentActivities(intentToResolve, 0); 1089 1090 if (ris == null || ris.isEmpty()) { 1091 intentToResolve.removeCategory(Intent.CATEGORY_INFO); 1092 intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER); 1093 intentToResolve.setPackage(packageName); 1094 ris = queryIntentActivities(intentToResolve, 0); 1095 } 1096 if (ris == null || ris.isEmpty()) { 1097 return null; 1098 } 1099 Intent intent = new Intent(intentToResolve); 1100 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1101 intent.setClassName(packageName, ris.get(0).activityInfo.name); 1102 return intent; 1103 } 1104 1105 //////////////////////////// 1106 1107 @Implementation(minSdk = N) getPackageInfoAsUser(String packageName, int flags, int userId)1108 protected PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId) 1109 throws NameNotFoundException { 1110 return getPackageInfo(packageName, flags); 1111 } 1112 1113 @Implementation canonicalToCurrentPackageNames(String[] names)1114 protected String[] canonicalToCurrentPackageNames(String[] names) { 1115 return new String[0]; 1116 } 1117 1118 @Implementation getPackageGids(String packageName)1119 protected int[] getPackageGids(String packageName) throws NameNotFoundException { 1120 return new int[0]; 1121 } 1122 1123 @Implementation(minSdk = N) getPackageGids(String packageName, int flags)1124 protected int[] getPackageGids(String packageName, int flags) throws NameNotFoundException { 1125 return null; 1126 } 1127 1128 @Implementation(minSdk = JELLY_BEAN_MR2) getPackageUid(String packageName, int flags)1129 protected int getPackageUid(String packageName, int flags) throws NameNotFoundException { 1130 Integer uid = uidForPackage.get(packageName); 1131 if (uid == null) { 1132 throw new NameNotFoundException(packageName); 1133 } 1134 return uid; 1135 } 1136 1137 @Implementation(minSdk = N) getPackageUidAsUser(String packageName, int userId)1138 protected int getPackageUidAsUser(String packageName, int userId) throws NameNotFoundException { 1139 return 0; 1140 } 1141 1142 @Implementation(minSdk = N) getPackageUidAsUser(String packageName, int flags, int userId)1143 protected int getPackageUidAsUser(String packageName, int flags, int userId) 1144 throws NameNotFoundException { 1145 return 0; 1146 } 1147 1148 /** @see ShadowPackageManager#addPermissionGroupInfo(android.content.pm.PermissionGroupInfo) */ 1149 @Implementation getPermissionGroupInfo(String name, int flags)1150 protected PermissionGroupInfo getPermissionGroupInfo(String name, int flags) 1151 throws NameNotFoundException { 1152 if (extraPermissionGroups.containsKey(name)) { 1153 return new PermissionGroupInfo(extraPermissionGroups.get(name)); 1154 } 1155 1156 for (Package pkg : packages.values()) { 1157 for (PermissionGroup permissionGroup : pkg.permissionGroups) { 1158 if (name.equals(permissionGroup.info.name)) { 1159 return PackageParser.generatePermissionGroupInfo(permissionGroup, flags); 1160 } 1161 } 1162 } 1163 1164 throw new NameNotFoundException(name); 1165 } 1166 1167 /** @see ShadowPackageManager#addPermissionGroupInfo(android.content.pm.PermissionGroupInfo) */ 1168 @Implementation getAllPermissionGroups(int flags)1169 protected List<PermissionGroupInfo> getAllPermissionGroups(int flags) { 1170 ArrayList<PermissionGroupInfo> allPermissionGroups = new ArrayList<PermissionGroupInfo>(); 1171 // To be consistent with Android's implementation, return at most one PermissionGroupInfo object 1172 // per permission group string 1173 HashSet<String> handledPermissionGroups = new HashSet<>(); 1174 1175 for (PermissionGroupInfo permissionGroupInfo : extraPermissionGroups.values()) { 1176 allPermissionGroups.add(new PermissionGroupInfo(permissionGroupInfo)); 1177 handledPermissionGroups.add(permissionGroupInfo.name); 1178 } 1179 1180 for (Package pkg : packages.values()) { 1181 for (PermissionGroup permissionGroup : pkg.permissionGroups) { 1182 if (!handledPermissionGroups.contains(permissionGroup.info.name)) { 1183 PermissionGroupInfo permissionGroupInfo = 1184 PackageParser.generatePermissionGroupInfo(permissionGroup, flags); 1185 allPermissionGroups.add(new PermissionGroupInfo(permissionGroupInfo)); 1186 handledPermissionGroups.add(permissionGroup.info.name); 1187 } 1188 } 1189 } 1190 1191 return allPermissionGroups; 1192 } 1193 1194 @Implementation getApplicationInfo(String packageName, int flags)1195 protected ApplicationInfo getApplicationInfo(String packageName, int flags) 1196 throws NameNotFoundException { 1197 PackageInfo info = packageInfos.get(packageName); 1198 if (info != null) { 1199 try { 1200 getPackageInfo(packageName, -1); 1201 } catch (NameNotFoundException e) { 1202 throw new IllegalArgumentException(e); 1203 } 1204 1205 if (applicationEnabledSettingMap.get(packageName) == COMPONENT_ENABLED_STATE_DISABLED 1206 && (flags & MATCH_UNINSTALLED_PACKAGES) != MATCH_UNINSTALLED_PACKAGES 1207 && (flags & MATCH_DISABLED_COMPONENTS) != MATCH_DISABLED_COMPONENTS) { 1208 throw new NameNotFoundException("Package is disabled, can't find"); 1209 } 1210 1211 if (hiddenPackages.contains(packageName) && !isFlagSet(flags, MATCH_UNINSTALLED_PACKAGES)) { 1212 throw new NameNotFoundException("Package is hidden, can't find"); 1213 } 1214 1215 if (info.applicationInfo != null) { 1216 return new ApplicationInfo(info.applicationInfo); 1217 } 1218 } 1219 throw new NameNotFoundException(packageName); 1220 } 1221 1222 @Implementation getApplicationInfoAsUser( String packageName, int flags, UserHandle userId)1223 protected ApplicationInfo getApplicationInfoAsUser( 1224 String packageName, int flags, UserHandle userId) throws NameNotFoundException { 1225 // Currently does not use the user ID. 1226 return getApplicationInfo(packageName, flags); 1227 } 1228 1229 /** 1230 * Returns all the values added via {@link 1231 * ShadowPackageManager#addSystemSharedLibraryName(String)}. 1232 */ 1233 @Implementation getSystemSharedLibraryNames()1234 protected String[] getSystemSharedLibraryNames() { 1235 return systemSharedLibraryNames.toArray(new String[systemSharedLibraryNames.size()]); 1236 } 1237 1238 @Implementation(minSdk = N) getServicesSystemSharedLibraryPackageName()1239 protected @NonNull String getServicesSystemSharedLibraryPackageName() { 1240 return null; 1241 } 1242 1243 @Implementation(minSdk = N) getSharedSystemSharedLibraryPackageName()1244 protected @NonNull String getSharedSystemSharedLibraryPackageName() { 1245 return ""; 1246 } 1247 1248 @Implementation(minSdk = N) hasSystemFeature(String name, int version)1249 protected boolean hasSystemFeature(String name, int version) { 1250 return false; 1251 } 1252 1253 @Implementation(minSdk = M) isPermissionRevokedByPolicy(String permName, String pkgName)1254 protected boolean isPermissionRevokedByPolicy(String permName, String pkgName) { 1255 return false; 1256 } 1257 1258 @Implementation addPermission(PermissionInfo info)1259 protected boolean addPermission(PermissionInfo info) { 1260 return false; 1261 } 1262 1263 @Implementation addPermissionAsync(PermissionInfo info)1264 protected boolean addPermissionAsync(PermissionInfo info) { 1265 return false; 1266 } 1267 1268 @Implementation removePermission(String name)1269 protected void removePermission(String name) {} 1270 1271 @Implementation(minSdk = M) grantRuntimePermission( String packageName, String permissionName, UserHandle user)1272 protected void grantRuntimePermission( 1273 String packageName, String permissionName, UserHandle user) { 1274 1275 if (!packageInfos.containsKey(packageName)) { 1276 throw new SecurityException("Package not found: " + packageName); 1277 } 1278 PackageInfo packageInfo = packageInfos.get(packageName); 1279 checkPermissionGrantStateInitialized(packageInfo); 1280 1281 int permissionIndex = getPermissionIndex(packageInfo, permissionName); 1282 if (permissionIndex < 0) { 1283 throw new SecurityException( 1284 "Permission " + permissionName + " not requested by package " + packageName); 1285 } 1286 1287 packageInfo.requestedPermissionsFlags[permissionIndex] |= REQUESTED_PERMISSION_GRANTED; 1288 } 1289 1290 @Implementation(minSdk = M) revokeRuntimePermission( String packageName, String permissionName, UserHandle user)1291 protected void revokeRuntimePermission( 1292 String packageName, String permissionName, UserHandle user) { 1293 1294 if (!packageInfos.containsKey(packageName)) { 1295 throw new SecurityException("Package not found: " + packageName); 1296 } 1297 PackageInfo packageInfo = packageInfos.get(packageName); 1298 checkPermissionGrantStateInitialized(packageInfo); 1299 1300 int permissionIndex = getPermissionIndex(packageInfo, permissionName); 1301 if (permissionIndex < 0) { 1302 throw new SecurityException( 1303 "Permission " + permissionName + " not requested by package " + packageName); 1304 } 1305 1306 packageInfo.requestedPermissionsFlags[permissionIndex] &= ~REQUESTED_PERMISSION_GRANTED; 1307 } 1308 checkPermissionGrantStateInitialized(PackageInfo packageInfo)1309 private void checkPermissionGrantStateInitialized(PackageInfo packageInfo) { 1310 if (packageInfo.requestedPermissionsFlags == null) { 1311 // In the real OS this would never be null, but tests don't necessarily initialize this 1312 // structure. 1313 throw new SecurityException( 1314 "Permission grant state (PackageInfo.requestedPermissionFlags) " 1315 + "is null. This operation requires this variable to be initialized."); 1316 } 1317 } 1318 1319 /** 1320 * Returns the index of the given permission in the PackageInfo.requestedPermissions array, or -1 1321 * if it's not found. 1322 */ getPermissionIndex(PackageInfo packageInfo, String permissionName)1323 private int getPermissionIndex(PackageInfo packageInfo, String permissionName) { 1324 if (packageInfo.requestedPermissions != null) { 1325 for (int i = 0; i < packageInfo.requestedPermissions.length; i++) { 1326 if (permissionName.equals(packageInfo.requestedPermissions[i])) { 1327 return i; 1328 } 1329 } 1330 } 1331 1332 return -1; 1333 } 1334 1335 @Implementation(minSdk = M) getPermissionFlags(String permissionName, String packageName, UserHandle user)1336 protected int getPermissionFlags(String permissionName, String packageName, UserHandle user) { 1337 return 0; 1338 } 1339 1340 @Implementation(minSdk = M) updatePermissionFlags( String permissionName, String packageName, int flagMask, int flagValues, UserHandle user)1341 protected void updatePermissionFlags( 1342 String permissionName, String packageName, int flagMask, int flagValues, UserHandle user) {} 1343 1344 @Implementation getUidForSharedUser(String sharedUserName)1345 protected int getUidForSharedUser(String sharedUserName) throws NameNotFoundException { 1346 return 0; 1347 } 1348 1349 @Implementation(minSdk = N) getInstalledPackagesAsUser(int flags, int userId)1350 protected List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) { 1351 List<PackageInfo> packages = new ArrayList<>(); 1352 for (String packageName : packagesForUserId.getOrDefault(userId, new ArrayList<>())) { 1353 packages.add(packageInfos.get(packageName)); 1354 } 1355 return packages; 1356 } 1357 1358 @Implementation(minSdk = JELLY_BEAN_MR2) getPackagesHoldingPermissions(String[] permissions, int flags)1359 protected List<PackageInfo> getPackagesHoldingPermissions(String[] permissions, int flags) { 1360 return null; 1361 } 1362 1363 /** Behaves as {@link #resolveActivity(Intent, int)} and currently ignores userId. */ 1364 @Implementation(minSdk = JELLY_BEAN_MR1) resolveActivityAsUser(Intent intent, int flags, int userId)1365 protected ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) { 1366 return resolveActivity(intent, flags); 1367 } 1368 1369 @Implementation queryIntentActivityOptions( ComponentName caller, Intent[] specifics, Intent intent, int flags)1370 protected List<ResolveInfo> queryIntentActivityOptions( 1371 ComponentName caller, Intent[] specifics, Intent intent, int flags) { 1372 return null; 1373 } 1374 1375 @Implementation(minSdk = N) queryBroadcastReceiversAsUser(Intent intent, int flags, int userId)1376 protected List<ResolveInfo> queryBroadcastReceiversAsUser(Intent intent, int flags, int userId) { 1377 return null; 1378 } 1379 1380 @Implementation queryContentProviders(String processName, int uid, int flags)1381 protected List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) { 1382 return null; 1383 } 1384 1385 @Implementation getInstrumentationInfo(ComponentName className, int flags)1386 protected InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags) 1387 throws NameNotFoundException { 1388 return null; 1389 } 1390 1391 @Implementation queryInstrumentation(String targetPackage, int flags)1392 protected List<InstrumentationInfo> queryInstrumentation(String targetPackage, int flags) { 1393 return null; 1394 } 1395 1396 @Nullable 1397 @Implementation getDrawable( String packageName, @DrawableRes int resId, @Nullable ApplicationInfo appInfo)1398 protected Drawable getDrawable( 1399 String packageName, @DrawableRes int resId, @Nullable ApplicationInfo appInfo) { 1400 Drawable result = drawables.get(new Pair<>(packageName, resId)); 1401 if (result != null) { 1402 return result; 1403 } 1404 return Shadow.directlyOn(realObject, ApplicationPackageManager.class) 1405 .getDrawable(packageName, resId, appInfo); 1406 } 1407 1408 @Implementation getActivityIcon(ComponentName activityName)1409 protected Drawable getActivityIcon(ComponentName activityName) throws NameNotFoundException { 1410 Drawable result = drawableList.get(activityName); 1411 if (result != null) { 1412 return result; 1413 } 1414 return Shadow.directlyOn(realObject, ApplicationPackageManager.class) 1415 .getActivityIcon(activityName); 1416 } 1417 1418 @Implementation getDefaultActivityIcon()1419 protected Drawable getDefaultActivityIcon() { 1420 return Resources.getSystem().getDrawable(com.android.internal.R.drawable.sym_def_app_icon); 1421 } 1422 1423 @Implementation getResourcesForActivity(ComponentName activityName)1424 protected Resources getResourcesForActivity(ComponentName activityName) 1425 throws NameNotFoundException { 1426 return getResourcesForApplication(activityName.getPackageName()); 1427 } 1428 @Implementation getResourcesForApplication(String appPackageName)1429 protected Resources getResourcesForApplication(String appPackageName) 1430 throws NameNotFoundException { 1431 if (context.getPackageName().equals(appPackageName)) { 1432 return context.getResources(); 1433 } else if (packageInfos.containsKey(appPackageName)) { 1434 Resources appResources = resources.get(appPackageName); 1435 if (appResources == null) { 1436 appResources = new Resources(new AssetManager(), null, null); 1437 resources.put(appPackageName, appResources); 1438 } 1439 return appResources; 1440 } 1441 throw new NameNotFoundException(appPackageName); 1442 } 1443 1444 @Implementation(minSdk = JELLY_BEAN_MR1) getResourcesForApplicationAsUser(String appPackageName, int userId)1445 protected Resources getResourcesForApplicationAsUser(String appPackageName, int userId) 1446 throws NameNotFoundException { 1447 return null; 1448 } 1449 1450 @Implementation(minSdk = M) addOnPermissionsChangeListener(Object listener)1451 protected void addOnPermissionsChangeListener(Object listener) {} 1452 1453 @Implementation(minSdk = M) removeOnPermissionsChangeListener(Object listener)1454 protected void removeOnPermissionsChangeListener(Object listener) {} 1455 1456 @Implementation(maxSdk = O_MR1) installPackage( Object packageURI, Object observer, Object flags, Object installerPackageName)1457 protected void installPackage( 1458 Object packageURI, Object observer, Object flags, Object installerPackageName) {} 1459 1460 @Implementation(minSdk = JELLY_BEAN_MR1) installExistingPackage(String packageName)1461 protected int installExistingPackage(String packageName) throws NameNotFoundException { 1462 return 0; 1463 } 1464 1465 @Implementation(minSdk = N) installExistingPackageAsUser(String packageName, int userId)1466 protected int installExistingPackageAsUser(String packageName, int userId) 1467 throws NameNotFoundException { 1468 return 0; 1469 } 1470 1471 @Implementation(minSdk = M) verifyIntentFilter(int id, int verificationCode, List<String> failedDomains)1472 protected void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains) {} 1473 1474 @Implementation(minSdk = N) getIntentVerificationStatusAsUser(String packageName, int userId)1475 protected int getIntentVerificationStatusAsUser(String packageName, int userId) { 1476 return 0; 1477 } 1478 1479 @Implementation(minSdk = N) updateIntentVerificationStatusAsUser( String packageName, int status, int userId)1480 protected boolean updateIntentVerificationStatusAsUser( 1481 String packageName, int status, int userId) { 1482 return false; 1483 } 1484 1485 @Implementation(minSdk = M) getIntentFilterVerifications(String packageName)1486 protected List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) { 1487 return null; 1488 } 1489 1490 @Implementation(minSdk = M) getAllIntentFilters(String packageName)1491 protected List<IntentFilter> getAllIntentFilters(String packageName) { 1492 return null; 1493 } 1494 1495 @Implementation(minSdk = N) getDefaultBrowserPackageNameAsUser(int userId)1496 protected String getDefaultBrowserPackageNameAsUser(int userId) { 1497 return null; 1498 } 1499 1500 @Implementation(minSdk = N) setDefaultBrowserPackageNameAsUser(String packageName, int userId)1501 protected boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) { 1502 return false; 1503 } 1504 1505 @Implementation(minSdk = M) getMoveStatus(int moveId)1506 protected int getMoveStatus(int moveId) { 1507 return 0; 1508 } 1509 1510 @Implementation(minSdk = M) registerMoveCallback(Object callback, Object handler)1511 protected void registerMoveCallback(Object callback, Object handler) {} 1512 1513 @Implementation(minSdk = M) unregisterMoveCallback(Object callback)1514 protected void unregisterMoveCallback(Object callback) {} 1515 1516 @Implementation(minSdk = M) movePackage(Object packageName, Object vol)1517 protected Object movePackage(Object packageName, Object vol) { 1518 return 0; 1519 } 1520 1521 @Implementation(minSdk = M) getPackageCurrentVolume(Object app)1522 protected Object getPackageCurrentVolume(Object app) { 1523 return null; 1524 } 1525 1526 @Implementation(minSdk = M) getPackageCandidateVolumes(ApplicationInfo app)1527 protected List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app) { 1528 return null; 1529 } 1530 1531 @Implementation(minSdk = M) movePrimaryStorage(Object vol)1532 protected Object movePrimaryStorage(Object vol) { 1533 return 0; 1534 } 1535 1536 @Implementation(minSdk = M) getPrimaryStorageCurrentVolume()1537 protected @Nullable Object getPrimaryStorageCurrentVolume() { 1538 return null; 1539 } 1540 1541 @Implementation(minSdk = M) getPrimaryStorageCandidateVolumes()1542 protected @NonNull List<VolumeInfo> getPrimaryStorageCandidateVolumes() { 1543 return null; 1544 } 1545 1546 @Implementation(minSdk = N) deletePackageAsUser( String packageName, IPackageDeleteObserver observer, int flags, int userId)1547 protected void deletePackageAsUser( 1548 String packageName, IPackageDeleteObserver observer, int flags, int userId) {} 1549 1550 @Implementation clearApplicationUserData(String packageName, IPackageDataObserver observer)1551 protected void clearApplicationUserData(String packageName, IPackageDataObserver observer) {} 1552 1553 @Implementation deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer)1554 protected void deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer) {} 1555 1556 @Implementation(minSdk = N) deleteApplicationCacheFilesAsUser( String packageName, int userId, IPackageDataObserver observer)1557 protected void deleteApplicationCacheFilesAsUser( 1558 String packageName, int userId, IPackageDataObserver observer) {} 1559 1560 @Implementation(minSdk = M) freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi)1561 protected void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi) {} 1562 1563 @Implementation(minSdk = N, maxSdk = O_MR1) setPackagesSuspendedAsUser( String[] packageNames, boolean suspended, int userId)1564 protected String[] setPackagesSuspendedAsUser( 1565 String[] packageNames, boolean suspended, int userId) { 1566 return null; 1567 } 1568 1569 @Implementation(minSdk = N) isPackageSuspendedForUser(String packageName, int userId)1570 protected boolean isPackageSuspendedForUser(String packageName, int userId) { 1571 return false; 1572 } 1573 1574 @Implementation addPackageToPreferred(String packageName)1575 protected void addPackageToPreferred(String packageName) {} 1576 1577 @Implementation removePackageFromPreferred(String packageName)1578 protected void removePackageFromPreferred(String packageName) {} 1579 1580 @Implementation getPreferredPackages(int flags)1581 protected List<PackageInfo> getPreferredPackages(int flags) { 1582 return null; 1583 } 1584 1585 @Implementation addPreferredActivity( IntentFilter filter, int match, ComponentName[] set, ComponentName activity)1586 public void addPreferredActivity( 1587 IntentFilter filter, int match, ComponentName[] set, ComponentName activity) { 1588 preferredActivities.put(new IntentFilterWrapper(filter), activity); 1589 } 1590 1591 @Implementation replacePreferredActivity( IntentFilter filter, int match, ComponentName[] set, ComponentName activity)1592 protected void replacePreferredActivity( 1593 IntentFilter filter, int match, ComponentName[] set, ComponentName activity) { 1594 addPreferredActivity(filter, match, set, activity); 1595 } 1596 1597 @Implementation getPreferredActivities( List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName)1598 public int getPreferredActivities( 1599 List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName) { 1600 if (outFilters == null) { 1601 return 0; 1602 } 1603 1604 Set<IntentFilterWrapper> filters = preferredActivities.keySet(); 1605 for (IntentFilter filter : outFilters) { 1606 step: 1607 for (IntentFilterWrapper testFilterWrapper : filters) { 1608 ComponentName name = preferredActivities.get(testFilterWrapper); 1609 IntentFilter testFilter = testFilterWrapper.getFilter(); 1610 // filter out based on the given packageName; 1611 if (packageName != null && !name.getPackageName().equals(packageName)) { 1612 continue step; 1613 } 1614 1615 // Check actions 1616 Iterator<String> iterator = filter.actionsIterator(); 1617 while (iterator.hasNext()) { 1618 if (!testFilter.matchAction(iterator.next())) { 1619 continue step; 1620 } 1621 } 1622 1623 iterator = filter.categoriesIterator(); 1624 while (iterator.hasNext()) { 1625 if (!filter.hasCategory(iterator.next())) { 1626 continue step; 1627 } 1628 } 1629 1630 if (outActivities == null) { 1631 outActivities = new ArrayList<>(); 1632 } 1633 1634 outActivities.add(name); 1635 } 1636 } 1637 1638 return 0; 1639 } 1640 1641 @Implementation clearPackagePreferredActivities(String packageName)1642 protected void clearPackagePreferredActivities(String packageName) { 1643 Iterator<ComponentName> entryIterator = preferredActivities.values().iterator(); 1644 while (entryIterator.hasNext()) { 1645 ComponentName next = entryIterator.next(); 1646 if (next.getPackageName().equals(packageName)) { 1647 entryIterator.remove(); 1648 } 1649 } 1650 } 1651 1652 @Implementation(minSdk = KITKAT) getHomeActivities(List<ResolveInfo> outActivities)1653 protected ComponentName getHomeActivities(List<ResolveInfo> outActivities) { 1654 return null; 1655 } 1656 1657 @Implementation(minSdk = N) flushPackageRestrictionsAsUser(int userId)1658 protected void flushPackageRestrictionsAsUser(int userId) {} 1659 1660 @Implementation(minSdk = LOLLIPOP) setApplicationHiddenSettingAsUser( String packageName, boolean hidden, UserHandle user)1661 protected boolean setApplicationHiddenSettingAsUser( 1662 String packageName, boolean hidden, UserHandle user) { 1663 // Note that this ignores the UserHandle parameter 1664 if (!packageInfos.containsKey(packageName)) { 1665 // Package doesn't exist 1666 return false; 1667 } 1668 if (hidden) { 1669 hiddenPackages.add(packageName); 1670 } else { 1671 hiddenPackages.remove(packageName); 1672 } 1673 return true; 1674 } 1675 1676 @Implementation(minSdk = LOLLIPOP) getApplicationHiddenSettingAsUser(String packageName, UserHandle user)1677 protected boolean getApplicationHiddenSettingAsUser(String packageName, UserHandle user) { 1678 // Note that this ignores the UserHandle parameter 1679 if (!packageInfos.containsKey(packageName)) { 1680 // Match Android behaviour of returning true if package isn't found 1681 return true; 1682 } 1683 return hiddenPackages.contains(packageName); 1684 } 1685 1686 @Implementation(minSdk = LOLLIPOP) getKeySetByAlias(String packageName, String alias)1687 protected Object getKeySetByAlias(String packageName, String alias) { 1688 return null; 1689 } 1690 1691 @Implementation(minSdk = LOLLIPOP) getSigningKeySet(String packageName)1692 protected Object getSigningKeySet(String packageName) { 1693 return null; 1694 } 1695 1696 @Implementation(minSdk = LOLLIPOP) isSignedBy(String packageName, Object ks)1697 protected boolean isSignedBy(String packageName, Object ks) { 1698 return false; 1699 } 1700 1701 @Implementation(minSdk = LOLLIPOP) isSignedByExactly(String packageName, Object ks)1702 protected boolean isSignedByExactly(String packageName, Object ks) { 1703 return false; 1704 } 1705 1706 @Implementation getVerifierDeviceIdentity()1707 protected VerifierDeviceIdentity getVerifierDeviceIdentity() { 1708 return null; 1709 } 1710 1711 @Implementation(minSdk = LOLLIPOP_MR1) isUpgrade()1712 protected boolean isUpgrade() { 1713 return false; 1714 } 1715 1716 @Implementation(minSdk = LOLLIPOP) isPackageAvailable(String packageName)1717 protected boolean isPackageAvailable(String packageName) { 1718 return false; 1719 } 1720 1721 @Implementation(minSdk = LOLLIPOP) addCrossProfileIntentFilter( IntentFilter filter, int sourceUserId, int targetUserId, int flags)1722 protected void addCrossProfileIntentFilter( 1723 IntentFilter filter, int sourceUserId, int targetUserId, int flags) {} 1724 1725 @Implementation(minSdk = LOLLIPOP) clearCrossProfileIntentFilters(int sourceUserId)1726 protected void clearCrossProfileIntentFilters(int sourceUserId) {} 1727 1728 /** 1729 * Gets the unbadged icon based on the values set by {@link 1730 * ShadowPackageManager#setUnbadgedApplicationIcon} or returns null if nothing has been set. 1731 */ 1732 @Implementation(minSdk = LOLLIPOP_MR1) loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo)1733 protected Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) { 1734 Drawable result = unbadgedApplicationIcons.get(itemInfo.packageName); 1735 if (result != null) { 1736 return result; 1737 } 1738 return Shadow.directlyOn(realObject, ApplicationPackageManager.class) 1739 .loadUnbadgedItemIcon(itemInfo, appInfo); 1740 } 1741 1742 /** 1743 * Adds a profile badge to the icon. 1744 * 1745 * <p>This implementation just returns the unbadged icon, as some default implementations add an 1746 * internal resource to the icon that is unavailable to Robolectric. 1747 */ 1748 @Implementation(minSdk = LOLLIPOP) getUserBadgedIcon(Drawable icon, UserHandle user)1749 protected Drawable getUserBadgedIcon(Drawable icon, UserHandle user) { 1750 return icon; 1751 } 1752 1753 @Implementation(minSdk = O) canRequestPackageInstalls()1754 protected boolean canRequestPackageInstalls() { 1755 return canRequestPackageInstalls; 1756 } 1757 1758 @Implementation(minSdk = O) getChangedPackages(int sequenceNumber)1759 protected Object getChangedPackages(int sequenceNumber) { 1760 if (sequenceNumber < 0 || sequenceNumberChangedPackagesMap.get(sequenceNumber).isEmpty()) { 1761 return null; 1762 } 1763 return new ChangedPackages( 1764 sequenceNumber + 1, new ArrayList<>(sequenceNumberChangedPackagesMap.get(sequenceNumber))); 1765 } 1766 1767 @Implementation(minSdk = P) getSystemTextClassifierPackageName()1768 public String getSystemTextClassifierPackageName() { 1769 return ""; 1770 } 1771 1772 @Implementation(minSdk = P) 1773 @HiddenApi setPackagesSuspended( String[] packageNames, boolean suspended, PersistableBundle appExtras, PersistableBundle launcherExtras, String dialogMessage)1774 protected String[] setPackagesSuspended( 1775 String[] packageNames, 1776 boolean suspended, 1777 PersistableBundle appExtras, 1778 PersistableBundle launcherExtras, 1779 String dialogMessage) { 1780 if (hasProfileOwnerOrDeviceOwnerOnCurrentUser()) { 1781 throw new UnsupportedOperationException(); 1782 } 1783 ArrayList<String> unupdatedPackages = new ArrayList<>(); 1784 for (String packageName : packageNames) { 1785 if (!canSuspendPackage(packageName)) { 1786 unupdatedPackages.add(packageName); 1787 continue; 1788 } 1789 PackageSetting setting = packageSettings.get(packageName); 1790 if (setting == null) { 1791 unupdatedPackages.add(packageName); 1792 continue; 1793 } 1794 setting.setSuspended(suspended, dialogMessage, appExtras, launcherExtras); 1795 } 1796 return unupdatedPackages.toArray(new String[0]); 1797 } 1798 1799 /** Returns whether the current user profile has a profile owner or a device owner. */ hasProfileOwnerOrDeviceOwnerOnCurrentUser()1800 private boolean hasProfileOwnerOrDeviceOwnerOnCurrentUser() { 1801 DevicePolicyManager devicePolicyManager = 1802 (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); 1803 return devicePolicyManager.getProfileOwner() != null 1804 || (UserHandle.of(UserHandle.myUserId()).isSystem() 1805 && devicePolicyManager.getDeviceOwner() != null); 1806 } 1807 canSuspendPackage(String packageName)1808 private boolean canSuspendPackage(String packageName) { 1809 // This code approximately mirrors PackageManagerService#canSuspendPackageForUserLocked. 1810 return !packageName.equals(context.getPackageName()) 1811 && !isPackageDeviceAdmin(packageName) 1812 && !isPackageActiveLauncher(packageName) 1813 && !isPackageRequiredInstaller(packageName) 1814 && !isPackageRequiredUninstaller(packageName) 1815 && !isPackageRequiredVerifier(packageName) 1816 && !isPackageDefaultDialer(packageName) 1817 && !packageName.equals(PLATFORM_PACKAGE_NAME); 1818 } 1819 isPackageDeviceAdmin(String packageName)1820 private boolean isPackageDeviceAdmin(String packageName) { 1821 DevicePolicyManager devicePolicyManager = 1822 (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); 1823 // Strictly speaking, this should be devicePolicyManager.getDeviceOwnerComponentOnAnyUser(), 1824 // but that method is currently not shadowed. 1825 return packageName.equals(devicePolicyManager.getDeviceOwner()); 1826 } 1827 isPackageActiveLauncher(String packageName)1828 private boolean isPackageActiveLauncher(String packageName) { 1829 Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME); 1830 ResolveInfo info = resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); 1831 return info != null && packageName.equals(info.activityInfo.packageName); 1832 } 1833 isPackageRequiredInstaller(String packageName)1834 private boolean isPackageRequiredInstaller(String packageName) { 1835 Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE); 1836 intent.addCategory(Intent.CATEGORY_DEFAULT); 1837 intent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE); 1838 ResolveInfo info = 1839 resolveActivity( 1840 intent, 1841 PackageManager.MATCH_SYSTEM_ONLY 1842 | PackageManager.MATCH_DIRECT_BOOT_AWARE 1843 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); 1844 return info != null && packageName.equals(info.activityInfo.packageName); 1845 } 1846 isPackageRequiredUninstaller(String packageName)1847 private boolean isPackageRequiredUninstaller(String packageName) { 1848 final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE); 1849 intent.addCategory(Intent.CATEGORY_DEFAULT); 1850 intent.setData(Uri.fromParts(PACKAGE_SCHEME, "foo.bar", null)); 1851 ResolveInfo info = 1852 resolveActivity( 1853 intent, 1854 PackageManager.MATCH_SYSTEM_ONLY 1855 | PackageManager.MATCH_DIRECT_BOOT_AWARE 1856 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); 1857 return info != null && packageName.equals(info.activityInfo.packageName); 1858 } 1859 isPackageRequiredVerifier(String packageName)1860 private boolean isPackageRequiredVerifier(String packageName) { 1861 final Intent intent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); 1862 List<ResolveInfo> infos = 1863 queryBroadcastReceivers( 1864 intent, 1865 PackageManager.MATCH_SYSTEM_ONLY 1866 | PackageManager.MATCH_DIRECT_BOOT_AWARE 1867 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); 1868 if (infos != null) { 1869 for (ResolveInfo info : infos) { 1870 if (packageName.equals(info.activityInfo.packageName)) { 1871 return true; 1872 } 1873 } 1874 } 1875 return false; 1876 } 1877 isPackageDefaultDialer(String packageName)1878 private boolean isPackageDefaultDialer(String packageName) { 1879 TelecomManager telecomManager = 1880 (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); 1881 return packageName.equals(telecomManager.getDefaultDialerPackage()); 1882 } 1883 1884 @HiddenApi 1885 @Implementation(minSdk = P) isPackageSuspended(String packageName)1886 protected boolean isPackageSuspended(String packageName) throws NameNotFoundException { 1887 PackageSetting setting = packageSettings.get(packageName); 1888 if (setting == null) { 1889 throw new NameNotFoundException(packageName); 1890 } 1891 return setting.isSuspended(); 1892 } 1893 1894 @Implementation(minSdk = O) isInstantApp(String packageName)1895 protected boolean isInstantApp(String packageName) { 1896 return false; 1897 } 1898 1899 @Implementation(minSdk = Q) getInstalledModules(int flags)1900 protected List<ModuleInfo> getInstalledModules(int flags) { 1901 return new ArrayList<>(); 1902 } 1903 } 1904