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