1 package org.robolectric.shadows; 2 3 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 4 import static android.content.pm.PackageManager.GET_ACTIVITIES; 5 import static android.content.pm.PackageManager.GET_CONFIGURATIONS; 6 import static android.content.pm.PackageManager.GET_GIDS; 7 import static android.content.pm.PackageManager.GET_INSTRUMENTATION; 8 import static android.content.pm.PackageManager.GET_INTENT_FILTERS; 9 import static android.content.pm.PackageManager.GET_META_DATA; 10 import static android.content.pm.PackageManager.GET_PERMISSIONS; 11 import static android.content.pm.PackageManager.GET_PROVIDERS; 12 import static android.content.pm.PackageManager.GET_RECEIVERS; 13 import static android.content.pm.PackageManager.GET_RESOLVED_FILTER; 14 import static android.content.pm.PackageManager.GET_SERVICES; 15 import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES; 16 import static android.content.pm.PackageManager.GET_SIGNATURES; 17 import static android.content.pm.PackageManager.GET_URI_PERMISSION_PATTERNS; 18 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; 19 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; 20 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; 21 import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS; 22 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; 23 import static android.content.pm.PackageManager.SIGNATURE_FIRST_NOT_SIGNED; 24 import static android.content.pm.PackageManager.SIGNATURE_MATCH; 25 import static android.content.pm.PackageManager.SIGNATURE_NEITHER_SIGNED; 26 import static android.content.pm.PackageManager.SIGNATURE_NO_MATCH; 27 import static android.content.pm.PackageManager.SIGNATURE_SECOND_NOT_SIGNED; 28 import static android.os.Build.VERSION_CODES.N; 29 import static java.util.Arrays.asList; 30 31 import android.Manifest; 32 import android.annotation.UserIdInt; 33 import android.content.ComponentName; 34 import android.content.Intent; 35 import android.content.IntentFilter; 36 import android.content.IntentSender; 37 import android.content.pm.ActivityInfo; 38 import android.content.pm.ApplicationInfo; 39 import android.content.pm.FeatureInfo; 40 import android.content.pm.IPackageDataObserver; 41 import android.content.pm.IPackageDeleteObserver; 42 import android.content.pm.PackageInfo; 43 import android.content.pm.PackageManager; 44 import android.content.pm.PackageManager.NameNotFoundException; 45 import android.content.pm.PackageParser; 46 import android.content.pm.PackageParser.Activity; 47 import android.content.pm.PackageParser.Component; 48 import android.content.pm.PackageParser.IntentInfo; 49 import android.content.pm.PackageParser.Package; 50 import android.content.pm.PackageParser.Service; 51 import android.content.pm.PackageStats; 52 import android.content.pm.PackageUserState; 53 import android.content.pm.PermissionGroupInfo; 54 import android.content.pm.PermissionInfo; 55 import android.content.pm.ResolveInfo; 56 import android.content.pm.ServiceInfo; 57 import android.content.pm.Signature; 58 import android.content.res.Resources; 59 import android.graphics.drawable.Drawable; 60 import android.net.Uri; 61 import android.os.Binder; 62 import android.os.Build; 63 import android.os.Process; 64 import android.os.RemoteException; 65 import android.os.UserHandle; 66 import android.util.ArraySet; 67 import android.util.Pair; 68 import com.google.common.base.Preconditions; 69 import java.util.ArrayList; 70 import java.util.Arrays; 71 import java.util.Collections; 72 import java.util.Comparator; 73 import java.util.HashMap; 74 import java.util.HashSet; 75 import java.util.Iterator; 76 import java.util.LinkedHashMap; 77 import java.util.List; 78 import java.util.Map; 79 import java.util.Set; 80 import java.util.TreeMap; 81 import org.robolectric.RuntimeEnvironment; 82 import org.robolectric.annotation.Implementation; 83 import org.robolectric.annotation.Implements; 84 import org.robolectric.util.ReflectionHelpers; 85 import org.robolectric.util.TempDirectory; 86 87 @Implements(PackageManager.class) 88 public class ShadowPackageManager { 89 90 Map<String, Boolean> permissionRationaleMap = new HashMap<>(); 91 List<FeatureInfo> systemAvailableFeatures = new ArrayList<>(); 92 final Map<String, PackageInfo> packageInfos = new LinkedHashMap<>(); 93 final Map<String, Package> packages = new LinkedHashMap<>(); 94 private Map<String, PackageInfo> packageArchiveInfo = new HashMap<>(); 95 final Map<String, PackageStats> packageStatsMap = new HashMap<>(); 96 final Map<String, String> packageInstallerMap = new HashMap<>(); 97 final Map<Integer, String[]> packagesForUid = new HashMap<>(); 98 final Map<String, Integer> uidForPackage = new HashMap<>(); 99 final Map<Integer, String> namesForUid = new HashMap<>(); 100 final Map<Integer, Integer> verificationResults = new HashMap<>(); 101 final Map<Integer, Long> verificationTimeoutExtension = new HashMap<>(); 102 final Map<String, String> currentToCanonicalNames = new HashMap<>(); 103 final Map<ComponentName, ComponentState> componentList = new LinkedHashMap<>(); 104 final Map<ComponentName, Drawable> drawableList = new LinkedHashMap<>(); 105 final Map<String, Drawable> applicationIcons = new HashMap<>(); 106 final Map<String, Boolean> systemFeatureList = new LinkedHashMap<>(); 107 final Map<IntentFilter, ComponentName> preferredActivities = new LinkedHashMap<>(); 108 final Map<Pair<String, Integer>, Drawable> drawables = new LinkedHashMap<>(); 109 final Map<String, Integer> applicationEnabledSettingMap = new HashMap<>(); 110 Map<String, PermissionInfo> extraPermissions = new HashMap<>(); 111 Map<String, PermissionGroupInfo> extraPermissionGroups = new HashMap<>(); 112 public Map<String, Resources> resources = new HashMap<>(); 113 private final Map<Intent, List<ResolveInfo>> resolveInfoForIntent = new TreeMap<>(new IntentComparator()); 114 private Set<String> deletedPackages = new HashSet<>(); 115 Map<String, IPackageDeleteObserver> pendingDeleteCallbacks = new HashMap<>(); 116 117 // From com.android.server.pm.PackageManagerService.compareSignatures(). 118 static int compareSignature(Signature[] signatures1, Signature[] signatures2) { 119 if (signatures1 == null) { 120 return (signatures2 == null) ? SIGNATURE_NEITHER_SIGNED 121 : SIGNATURE_FIRST_NOT_SIGNED; 122 } 123 if (signatures2 == null) { 124 return SIGNATURE_SECOND_NOT_SIGNED; 125 } 126 if (signatures1.length != signatures2.length) { 127 return SIGNATURE_NO_MATCH; 128 } 129 HashSet<Signature> signatures1set = new HashSet<>(asList(signatures1)); 130 HashSet<Signature> signatures2set = new HashSet<>(asList(signatures2)); 131 return signatures1set.equals(signatures2set) ? SIGNATURE_MATCH : SIGNATURE_NO_MATCH; 132 } 133 134 static String resolvePackageName(String packageName, ComponentName componentName) { 135 String classString = componentName.getClassName(); 136 int index = classString.indexOf('.'); 137 if (index == -1) { 138 classString = packageName + "." + classString; 139 } else if (index == 0) { 140 classString = packageName + classString; 141 } 142 return classString; 143 } 144 145 146 static ResolveInfo getResolveInfo(Activity activity, IntentFilter intentFilter) { 147 ResolveInfo info = new ResolveInfo(); 148 info.isDefault = intentFilter.hasCategory("Intent.CATEGORY_DEFAULT"); 149 info.activityInfo = new ActivityInfo(); 150 info.activityInfo.name = activity.info.name; 151 info.activityInfo.packageName = activity.info.packageName; 152 info.activityInfo.applicationInfo = activity.info.applicationInfo; 153 info.activityInfo.permission = activity.info.permission; 154 info.filter = new IntentFilter(intentFilter); 155 return info; 156 } 157 158 static ResolveInfo getResolveInfo(Service service, IntentFilter intentFilter) { 159 ResolveInfo info = new ResolveInfo(); 160 info.isDefault = intentFilter.hasCategory("Intent.CATEGORY_DEFAULT"); 161 info.serviceInfo = new ServiceInfo(); 162 info.serviceInfo.name = service.info.name; 163 info.serviceInfo.packageName = service.info.packageName; 164 info.serviceInfo.applicationInfo = service.info.applicationInfo; 165 info.serviceInfo.permission = service.info.permission; 166 info.filter = new IntentFilter(intentFilter); 167 return info; 168 } 169 170 private static void setUpPackageStorage(ApplicationInfo applicationInfo) { 171 TempDirectory tempDirectory = RuntimeEnvironment.getTempDirectory(); 172 if (applicationInfo.sourceDir == null) { 173 applicationInfo.sourceDir = 174 tempDirectory 175 .createIfNotExists(applicationInfo.packageName + "-sourceDir") 176 .toAbsolutePath() 177 .toString(); 178 } 179 if (applicationInfo.dataDir == null) { 180 applicationInfo.dataDir = 181 tempDirectory 182 .createIfNotExists(applicationInfo.packageName + "-dataDir") 183 .toAbsolutePath() 184 .toString(); 185 } 186 applicationInfo.publicSourceDir = applicationInfo.sourceDir; 187 188 if (RuntimeEnvironment.getApiLevel() >= N) { 189 applicationInfo.credentialProtectedDataDir = tempDirectory.createIfNotExists("userDataDir").toAbsolutePath().toString(); 190 applicationInfo.deviceProtectedDataDir = tempDirectory.createIfNotExists("deviceDataDir").toAbsolutePath().toString(); 191 } 192 } 193 194 public void addResolveInfoForIntent(Intent intent, List<ResolveInfo> info) { 195 resolveInfoForIntent.put(intent, info); 196 } 197 198 public void addResolveInfoForIntent(Intent intent, ResolveInfo info) { 199 List<ResolveInfo> infoList = resolveInfoForIntent.get(intent); 200 if (infoList == null) { 201 infoList = new ArrayList<>(); 202 resolveInfoForIntent.put(intent, infoList); 203 } 204 205 infoList.add(info); 206 } 207 208 public void removeResolveInfosForIntent(Intent intent, String packageName) { 209 List<ResolveInfo> infoList = resolveInfoForIntent.get(intent); 210 if (infoList == null) { 211 infoList = new ArrayList<>(); 212 resolveInfoForIntent.put(intent, infoList); 213 } 214 215 for (Iterator<ResolveInfo> iterator = infoList.iterator(); iterator.hasNext(); ) { 216 ResolveInfo resolveInfo = iterator.next(); 217 if (resolveInfo.activityInfo.packageName.equals(packageName)) { 218 iterator.remove(); 219 } 220 } 221 } 222 223 public Drawable getActivityIcon(Intent intent) throws NameNotFoundException { 224 return drawableList.get(intent.getComponent()); 225 } 226 227 public Drawable getActivityIcon(ComponentName componentName) throws NameNotFoundException { 228 return drawableList.get(componentName); 229 } 230 231 public void addActivityIcon(ComponentName component, Drawable drawable) { 232 drawableList.put(component, drawable); 233 } 234 235 public void addActivityIcon(Intent intent, Drawable drawable) { 236 drawableList.put(intent.getComponent(), drawable); 237 } 238 239 public void setApplicationIcon(String packageName, Drawable drawable) { 240 applicationIcons.put(packageName, drawable); 241 } 242 243 public void setApplicationEnabledSetting(String packageName, int newState, int flags) { 244 applicationEnabledSettingMap.put(packageName, newState); 245 } 246 247 public void addPreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity) { 248 preferredActivities.put(filter, activity); 249 } 250 251 public int getPreferredActivities(List<IntentFilter> outFilters, List<ComponentName> outActivities, String packageName) { 252 if (outFilters == null) { 253 return 0; 254 } 255 256 Set<IntentFilter> filters = preferredActivities.keySet(); 257 for (IntentFilter filter : outFilters) { 258 step: 259 for (IntentFilter testFilter : filters) { 260 ComponentName name = preferredActivities.get(testFilter); 261 // filter out based on the given packageName; 262 if (packageName != null && !name.getPackageName().equals(packageName)) { 263 continue step; 264 } 265 266 // Check actions 267 Iterator<String> iterator = filter.actionsIterator(); 268 while (iterator.hasNext()) { 269 if (!testFilter.matchAction(iterator.next())) { 270 continue step; 271 } 272 } 273 274 iterator = filter.categoriesIterator(); 275 while (iterator.hasNext()) { 276 if (!filter.hasCategory(iterator.next())) { 277 continue step; 278 } 279 } 280 281 if (outActivities == null) { 282 outActivities = new ArrayList<>(); 283 } 284 285 outActivities.add(name); 286 } 287 } 288 289 return 0; 290 } 291 292 /** 293 * Return the flags set in call to {@link android.app.ApplicationPackageManager#setComponentEnabledSetting(ComponentName, int, int)}. 294 * 295 * @param componentName The component name. 296 * @return The flags. 297 */ 298 public int getComponentEnabledSettingFlags(ComponentName componentName) { 299 ComponentState state = componentList.get(componentName); 300 return state != null ? state.flags : 0; 301 } 302 303 /** @deprecated - use {@link #addPackage(PackageInfo)} instead */ 304 @Deprecated 305 public void addPackage(String packageName) { 306 PackageInfo packageInfo = new PackageInfo(); 307 packageInfo.packageName = packageName; 308 309 ApplicationInfo applicationInfo = new ApplicationInfo(); 310 applicationInfo.packageName = packageName; 311 setUpPackageStorage(applicationInfo); 312 packageInfo.applicationInfo = applicationInfo; 313 addPackage(packageInfo); 314 } 315 316 public void addPackage(PackageInfo packageInfo) { 317 PackageStats packageStats = new PackageStats(packageInfo.packageName); 318 addPackage(packageInfo, packageStats); 319 } 320 321 public void addPackage(PackageInfo packageInfo, PackageStats packageStats) { 322 Preconditions.checkArgument(packageInfo.packageName.equals(packageStats.packageName)); 323 324 packageInfos.put(packageInfo.packageName, packageInfo); 325 packageStatsMap.put(packageInfo.packageName, packageStats); 326 applicationEnabledSettingMap.put(packageInfo.packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT); 327 if (packageInfo.applicationInfo != null) { 328 namesForUid.put(packageInfo.applicationInfo.uid, packageInfo.packageName); 329 } 330 } 331 332 public void addPermissionInfo(PermissionInfo permissionInfo) { 333 extraPermissions.put(permissionInfo.name, permissionInfo); 334 } 335 336 /** 337 * Allows overriding or adding permission-group elements. These would be otherwise specified by 338 * either the system (https://developer.android.com/guide/topics/permissions/requesting.html#perm-groups) 339 * or by the app itself, as part of its manifest 340 * (https://developer.android.com/guide/topics/manifest/permission-group-element.html). 341 * 342 * PermissionGroups added through this method have precedence over those specified with the same name 343 * by one of the aforementioned methods. 344 */ 345 public void addPermissionGroupInfo(PermissionGroupInfo permissionGroupInfo) { 346 extraPermissionGroups.put(permissionGroupInfo.name, permissionGroupInfo); 347 } 348 349 public void removePackage(String packageName) { 350 packages.remove(packageName); 351 packageInfos.remove(packageName); 352 } 353 354 public void setSystemFeature(String name, boolean supported) { 355 systemFeatureList.put(name, supported); 356 } 357 358 public void addDrawableResolution(String packageName, int resourceId, Drawable drawable) { 359 drawables.put(new Pair(packageName, resourceId), drawable); 360 } 361 362 public Drawable getDrawable(String packageName, int resourceId, ApplicationInfo applicationInfo) { 363 return drawables.get(new Pair(packageName, resourceId)); 364 } 365 366 public void setNameForUid(int uid, String name) { 367 namesForUid.put(uid, name); 368 } 369 370 public void setPackagesForCallingUid(String... packagesForCallingUid) { 371 packagesForUid.put(Binder.getCallingUid(), packagesForCallingUid); 372 for (String packageName : packagesForCallingUid) { 373 uidForPackage.put(packageName, Binder.getCallingUid()); 374 } 375 } 376 377 public void setPackagesForUid(int uid, String... packagesForCallingUid) { 378 packagesForUid.put(uid, packagesForCallingUid); 379 for (String packageName : packagesForCallingUid) { 380 uidForPackage.put(packageName, uid); 381 } 382 } 383 384 public void setPackageArchiveInfo(String archiveFilePath, PackageInfo packageInfo) { 385 packageArchiveInfo.put(archiveFilePath, packageInfo); 386 } 387 388 public int getVerificationResult(int id) { 389 Integer result = verificationResults.get(id); 390 if (result == null) { 391 // 0 isn't a "valid" result, so we can check for the case when verification isn't 392 // called, if needed 393 return 0; 394 } 395 return result; 396 } 397 398 public long getVerificationExtendedTimeout(int id) { 399 Long result = verificationTimeoutExtension.get(id); 400 if (result == null) { 401 return 0; 402 } 403 return result; 404 } 405 406 public void setShouldShowRequestPermissionRationale(String permission, boolean show) { 407 permissionRationaleMap.put(permission, show); 408 } 409 410 public void addSystemAvailableFeature(FeatureInfo featureInfo) { 411 systemAvailableFeatures.add(featureInfo); 412 } 413 414 public void clearSystemAvailableFeatures() { 415 systemAvailableFeatures.clear(); 416 } 417 418 public void addCurrentToCannonicalName(String currentName, String canonicalName) { 419 currentToCanonicalNames.put(currentName, canonicalName); 420 } 421 422 @Implementation 423 public List<ResolveInfo> queryBroadcastReceiversAsUser(Intent intent, int flags, UserHandle userHandle) { 424 return null; 425 } 426 427 @Implementation 428 public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags, @UserIdInt int userId) { 429 return null; 430 } 431 432 @Implementation 433 public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) { 434 List<PackageInfo> result = new ArrayList<>(); 435 for (PackageInfo packageInfo : packageInfos.values()) { 436 if (applicationEnabledSettingMap.get(packageInfo.packageName) 437 != COMPONENT_ENABLED_STATE_DISABLED 438 || (flags & MATCH_UNINSTALLED_PACKAGES) == MATCH_UNINSTALLED_PACKAGES) { 439 result.add(packageInfo); 440 } 441 } 442 443 List<PackageInfo> packages = result; 444 for (PackageInfo aPackage : packages) { 445 ApplicationInfo appInfo = aPackage.applicationInfo; 446 if (appInfo != null && archiveFilePath.equals(appInfo.sourceDir)) { 447 return aPackage; 448 } 449 } 450 return null; 451 } 452 453 @Implementation 454 public void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer) { 455 } 456 457 @Implementation 458 public void freeStorage(long freeStorageSize, IntentSender pi) { 459 } 460 461 /** 462 * Runs the callbacks pending from calls to {@link PackageManager#deletePackage(String, IPackageDeleteObserver, int)} 463 */ 464 public void doPendingUninstallCallbacks() { 465 boolean hasDeletePackagesPermission = false; 466 String[] requestedPermissions = 467 packageInfos.get(RuntimeEnvironment.application.getPackageName()).requestedPermissions; 468 if (requestedPermissions != null) { 469 for (String permission : requestedPermissions) { 470 if (Manifest.permission.DELETE_PACKAGES.equals(permission)) { 471 hasDeletePackagesPermission = true; 472 break; 473 } 474 } 475 } 476 477 for (String packageName : pendingDeleteCallbacks.keySet()) { 478 int resultCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR; 479 480 PackageInfo removed = packageInfos.get(packageName); 481 if (hasDeletePackagesPermission && removed != null) { 482 packageInfos.remove(packageName); 483 deletedPackages.add(packageName); 484 resultCode = PackageManager.DELETE_SUCCEEDED; 485 } 486 487 try { 488 pendingDeleteCallbacks.get(packageName).packageDeleted(packageName, resultCode); 489 } catch (RemoteException e) { 490 throw new RuntimeException(e); 491 } 492 } 493 pendingDeleteCallbacks.clear(); 494 } 495 496 /** 497 * Returns package names successfully deleted with {@link PackageManager#deletePackage(String, IPackageDeleteObserver, int)} 498 * Note that like real {@link PackageManager} the calling context must have {@link android.Manifest.permission#DELETE_PACKAGES} permission set. 499 */ 500 public Set<String> getDeletedPackages() { 501 return deletedPackages; 502 } 503 504 protected List<ResolveInfo> queryOverriddenIntents(Intent intent, int flags) { 505 List<ResolveInfo> result = resolveInfoForIntent.get(intent); 506 if (result == null) { 507 return Collections.emptyList(); 508 } else { 509 return result; 510 } 511 } 512 513 public void addPackage(Package appPackage) { 514 int flags = 515 GET_ACTIVITIES 516 | GET_RECEIVERS 517 | GET_SERVICES 518 | GET_PROVIDERS 519 | GET_INSTRUMENTATION 520 | GET_INTENT_FILTERS 521 | GET_SIGNATURES 522 | GET_RESOLVED_FILTER 523 | GET_META_DATA 524 | GET_GIDS 525 | MATCH_DISABLED_COMPONENTS 526 | GET_SHARED_LIBRARY_FILES 527 | GET_URI_PERMISSION_PATTERNS 528 | GET_PERMISSIONS 529 | MATCH_UNINSTALLED_PACKAGES 530 | GET_CONFIGURATIONS 531 | MATCH_DISABLED_UNTIL_USED_COMPONENTS 532 | MATCH_DIRECT_BOOT_UNAWARE 533 | MATCH_DIRECT_BOOT_AWARE; 534 535 packages.put(appPackage.packageName, appPackage); 536 PackageInfo packageInfo; 537 if (RuntimeEnvironment.getApiLevel() >= Build.VERSION_CODES.M) { 538 packageInfo = 539 PackageParser.generatePackageInfo( 540 appPackage, 541 new int[] {0}, 542 flags, 543 0, 544 0, 545 new HashSet<String>(), 546 new PackageUserState()); 547 } else if (RuntimeEnvironment.getApiLevel() >= Build.VERSION_CODES.LOLLIPOP_MR1) { 548 packageInfo = 549 ReflectionHelpers.callStaticMethod( 550 PackageParser.class, 551 "generatePackageInfo", 552 ReflectionHelpers.ClassParameter.from(Package.class, appPackage), 553 ReflectionHelpers.ClassParameter.from(int[].class, new int[] {0}), 554 ReflectionHelpers.ClassParameter.from(int.class, flags), 555 ReflectionHelpers.ClassParameter.from(long.class, 0L), 556 ReflectionHelpers.ClassParameter.from(long.class, 0L), 557 ReflectionHelpers.ClassParameter.from(ArraySet.class, new ArraySet<>()), 558 ReflectionHelpers.ClassParameter.from( 559 PackageUserState.class, new PackageUserState())); 560 } else if (RuntimeEnvironment.getApiLevel() >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 561 packageInfo = 562 ReflectionHelpers.callStaticMethod( 563 PackageParser.class, 564 "generatePackageInfo", 565 ReflectionHelpers.ClassParameter.from(Package.class, appPackage), 566 ReflectionHelpers.ClassParameter.from(int[].class, new int[] {0}), 567 ReflectionHelpers.ClassParameter.from(int.class, flags), 568 ReflectionHelpers.ClassParameter.from(long.class, 0L), 569 ReflectionHelpers.ClassParameter.from(long.class, 0L), 570 ReflectionHelpers.ClassParameter.from(HashSet.class, new HashSet<>()), 571 ReflectionHelpers.ClassParameter.from( 572 PackageUserState.class, new PackageUserState())); 573 } else { 574 packageInfo = 575 ReflectionHelpers.callStaticMethod( 576 PackageParser.class, 577 "generatePackageInfo", 578 ReflectionHelpers.ClassParameter.from(Package.class, appPackage), 579 ReflectionHelpers.ClassParameter.from(int[].class, new int[] {0}), 580 ReflectionHelpers.ClassParameter.from(int.class, flags), 581 ReflectionHelpers.ClassParameter.from(long.class, 0L), 582 ReflectionHelpers.ClassParameter.from(long.class, 0L), 583 ReflectionHelpers.ClassParameter.from(HashSet.class, new HashSet<>())); 584 } 585 586 packageInfo.applicationInfo.uid = Process.myUid(); 587 addPackage(packageInfo); 588 } 589 590 public static class IntentComparator implements Comparator<Intent> { 591 592 @Override 593 public int compare(Intent i1, Intent i2) { 594 if (i1 == null && i2 == null) return 0; 595 if (i1 == null && i2 != null) return -1; 596 if (i1 != null && i2 == null) return 1; 597 if (i1.equals(i2)) return 0; 598 String action1 = i1.getAction(); 599 String action2 = i2.getAction(); 600 if (action1 == null && action2 != null) return -1; 601 if (action1 != null && action2 == null) return 1; 602 if (action1 != null && action2 != null) { 603 if (!action1.equals(action2)) { 604 return action1.compareTo(action2); 605 } 606 } 607 Uri data1 = i1.getData(); 608 Uri data2 = i2.getData(); 609 if (data1 == null && data2 != null) return -1; 610 if (data1 != null && data2 == null) return 1; 611 if (data1 != null && data2 != null) { 612 if (!data1.equals(data2)) { 613 return data1.compareTo(data2); 614 } 615 } 616 ComponentName component1 = i1.getComponent(); 617 ComponentName component2 = i2.getComponent(); 618 if (component1 == null && component2 != null) return -1; 619 if (component1 != null && component2 == null) return 1; 620 if (component1 != null && component2 != null) { 621 if (!component1.equals(component2)) { 622 return component1.compareTo(component2); 623 } 624 } 625 String package1 = i1.getPackage(); 626 String package2 = i2.getPackage(); 627 if (package1 == null && package2 != null) return -1; 628 if (package1 != null && package2 == null) return 1; 629 if (package1 != null && package2 != null) { 630 if (!package1.equals(package2)) { 631 return package1.compareTo(package2); 632 } 633 } 634 Set<String> categories1 = i1.getCategories(); 635 Set<String> categories2 = i2.getCategories(); 636 if (categories1 == null) return categories2 == null ? 0 : -1; 637 if (categories2 == null) return 1; 638 if (categories1.size() > categories2.size()) return 1; 639 if (categories1.size() < categories2.size()) return -1; 640 String[] array1 = categories1.toArray(new String[0]); 641 String[] array2 = categories2.toArray(new String[0]); 642 Arrays.sort(array1); 643 Arrays.sort(array2); 644 for (int i = 0; i < array1.length; ++i) { 645 int val = array1[i].compareTo(array2[i]); 646 if (val != 0) return val; 647 } 648 return 0; 649 } 650 } 651 652 protected static class ComponentState { 653 public int newState; 654 public int flags; 655 656 public ComponentState(int newState, int flags) { 657 this.newState = newState; 658 this.flags = flags; 659 } 660 } 661 662 /** 663 * Get list of intent filters defined for given activity. 664 * 665 * @param componentName Name of the activity whose intent filters are to be retrieved 666 * @return the activity's intent filters 667 */ 668 public List<IntentFilter> getIntentFiltersForActivity(ComponentName componentName) 669 throws NameNotFoundException { 670 return getIntentFiltersForComponent(getAppPackage(componentName).activities, componentName); 671 } 672 673 /** 674 * Get list of intent filters defined for given service. 675 * 676 * @param componentName Name of the service whose intent filters are to be retrieved 677 * @return the service's intent filters 678 */ 679 public List<IntentFilter> getIntentFiltersForService(ComponentName componentName) 680 throws NameNotFoundException { 681 return getIntentFiltersForComponent(getAppPackage(componentName).services, componentName); 682 } 683 684 /** 685 * Get list of intent filters defined for given receiver. 686 * 687 * @param componentName Name of the receiver whose intent filters are to be retrieved 688 * @return the receiver's intent filters 689 */ 690 public List<IntentFilter> getIntentFiltersForReceiver(ComponentName componentName) 691 throws NameNotFoundException { 692 return getIntentFiltersForComponent(getAppPackage(componentName).receivers, componentName); 693 } 694 695 private static List<IntentFilter> getIntentFiltersForComponent( 696 List<? extends Component> components, ComponentName componentName) 697 throws NameNotFoundException { 698 for (Component component : components) { 699 if (component.getComponentName().equals(componentName)) { 700 return component.intents; 701 } 702 } 703 throw new NameNotFoundException("unknown component " + componentName); 704 } 705 706 private Package getAppPackage(ComponentName componentName) throws NameNotFoundException { 707 Package appPackage = this.packages.get(componentName.getPackageName()); 708 if (appPackage == null) { 709 throw new NameNotFoundException("unknown package " + componentName.getPackageName()); 710 } 711 return appPackage; 712 } 713 714 private static List<IntentFilter> convertIntentFilters( 715 List<? extends PackageParser.IntentInfo> intentInfos) { 716 List<IntentFilter> intentFilters = new ArrayList<>(intentInfos.size()); 717 for (IntentInfo intentInfo : intentInfos) { 718 intentFilters.add(intentInfo); 719 } 720 return intentFilters; 721 } 722 } 723