ApplicationPackageManager.java revision 742a67127366c376fdf188ff99ba30b27d3bf90c
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.app; 18 19import android.content.ComponentName; 20import android.content.ContentResolver; 21import android.content.Intent; 22import android.content.IntentFilter; 23import android.content.IntentSender; 24import android.content.pm.ActivityInfo; 25import android.content.pm.ApplicationInfo; 26import android.content.pm.ComponentInfo; 27import android.content.pm.FeatureInfo; 28import android.content.pm.IPackageDataObserver; 29import android.content.pm.IPackageDeleteObserver; 30import android.content.pm.IPackageInstallObserver; 31import android.content.pm.IPackageManager; 32import android.content.pm.IPackageMoveObserver; 33import android.content.pm.IPackageStatsObserver; 34import android.content.pm.InstrumentationInfo; 35import android.content.pm.PackageInfo; 36import android.content.pm.PackageManager; 37import android.content.pm.ParceledListSlice; 38import android.content.pm.PermissionGroupInfo; 39import android.content.pm.PermissionInfo; 40import android.content.pm.ProviderInfo; 41import android.content.pm.ResolveInfo; 42import android.content.pm.ServiceInfo; 43import android.content.pm.UserInfo; 44import android.content.pm.ManifestDigest; 45import android.content.pm.VerifierDeviceIdentity; 46import android.content.res.Resources; 47import android.content.res.XmlResourceParser; 48import android.graphics.drawable.Drawable; 49import android.net.Uri; 50import android.os.Process; 51import android.os.RemoteException; 52import android.util.Log; 53 54import java.lang.ref.WeakReference; 55import java.util.ArrayList; 56import java.util.HashMap; 57import java.util.Iterator; 58import java.util.List; 59 60/*package*/ 61final class ApplicationPackageManager extends PackageManager { 62 private static final String TAG = "ApplicationPackageManager"; 63 private final static boolean DEBUG = false; 64 private final static boolean DEBUG_ICONS = false; 65 66 @Override 67 public PackageInfo getPackageInfo(String packageName, int flags) 68 throws NameNotFoundException { 69 try { 70 PackageInfo pi = mPM.getPackageInfo(packageName, flags); 71 if (pi != null) { 72 return pi; 73 } 74 } catch (RemoteException e) { 75 throw new RuntimeException("Package manager has died", e); 76 } 77 78 throw new NameNotFoundException(packageName); 79 } 80 81 @Override 82 public String[] currentToCanonicalPackageNames(String[] names) { 83 try { 84 return mPM.currentToCanonicalPackageNames(names); 85 } catch (RemoteException e) { 86 throw new RuntimeException("Package manager has died", e); 87 } 88 } 89 90 @Override 91 public String[] canonicalToCurrentPackageNames(String[] names) { 92 try { 93 return mPM.canonicalToCurrentPackageNames(names); 94 } catch (RemoteException e) { 95 throw new RuntimeException("Package manager has died", e); 96 } 97 } 98 99 @Override 100 public Intent getLaunchIntentForPackage(String packageName) { 101 // First see if the package has an INFO activity; the existence of 102 // such an activity is implied to be the desired front-door for the 103 // overall package (such as if it has multiple launcher entries). 104 Intent intentToResolve = new Intent(Intent.ACTION_MAIN); 105 intentToResolve.addCategory(Intent.CATEGORY_INFO); 106 intentToResolve.setPackage(packageName); 107 List<ResolveInfo> ris = queryIntentActivities(intentToResolve, 0); 108 109 // Otherwise, try to find a main launcher activity. 110 if (ris == null || ris.size() <= 0) { 111 // reuse the intent instance 112 intentToResolve.removeCategory(Intent.CATEGORY_INFO); 113 intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER); 114 intentToResolve.setPackage(packageName); 115 ris = queryIntentActivities(intentToResolve, 0); 116 } 117 if (ris == null || ris.size() <= 0) { 118 return null; 119 } 120 Intent intent = new Intent(intentToResolve); 121 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 122 intent.setClassName(ris.get(0).activityInfo.packageName, 123 ris.get(0).activityInfo.name); 124 return intent; 125 } 126 127 @Override 128 public int[] getPackageGids(String packageName) 129 throws NameNotFoundException { 130 try { 131 int[] gids = mPM.getPackageGids(packageName); 132 if (gids == null || gids.length > 0) { 133 return gids; 134 } 135 } catch (RemoteException e) { 136 throw new RuntimeException("Package manager has died", e); 137 } 138 139 throw new NameNotFoundException(packageName); 140 } 141 142 @Override 143 public PermissionInfo getPermissionInfo(String name, int flags) 144 throws NameNotFoundException { 145 try { 146 PermissionInfo pi = mPM.getPermissionInfo(name, flags); 147 if (pi != null) { 148 return pi; 149 } 150 } catch (RemoteException e) { 151 throw new RuntimeException("Package manager has died", e); 152 } 153 154 throw new NameNotFoundException(name); 155 } 156 157 @Override 158 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) 159 throws NameNotFoundException { 160 try { 161 List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags); 162 if (pi != null) { 163 return pi; 164 } 165 } catch (RemoteException e) { 166 throw new RuntimeException("Package manager has died", e); 167 } 168 169 throw new NameNotFoundException(group); 170 } 171 172 @Override 173 public PermissionGroupInfo getPermissionGroupInfo(String name, 174 int flags) throws NameNotFoundException { 175 try { 176 PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags); 177 if (pgi != null) { 178 return pgi; 179 } 180 } catch (RemoteException e) { 181 throw new RuntimeException("Package manager has died", e); 182 } 183 184 throw new NameNotFoundException(name); 185 } 186 187 @Override 188 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) { 189 try { 190 return mPM.getAllPermissionGroups(flags); 191 } catch (RemoteException e) { 192 throw new RuntimeException("Package manager has died", e); 193 } 194 } 195 196 @Override 197 public ApplicationInfo getApplicationInfo(String packageName, int flags) 198 throws NameNotFoundException { 199 try { 200 ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags); 201 if (ai != null) { 202 return ai; 203 } 204 } catch (RemoteException e) { 205 throw new RuntimeException("Package manager has died", e); 206 } 207 208 throw new NameNotFoundException(packageName); 209 } 210 211 @Override 212 public ActivityInfo getActivityInfo(ComponentName className, int flags) 213 throws NameNotFoundException { 214 try { 215 ActivityInfo ai = mPM.getActivityInfo(className, flags); 216 if (ai != null) { 217 return ai; 218 } 219 } catch (RemoteException e) { 220 throw new RuntimeException("Package manager has died", e); 221 } 222 223 throw new NameNotFoundException(className.toString()); 224 } 225 226 @Override 227 public ActivityInfo getReceiverInfo(ComponentName className, int flags) 228 throws NameNotFoundException { 229 try { 230 ActivityInfo ai = mPM.getReceiverInfo(className, flags); 231 if (ai != null) { 232 return ai; 233 } 234 } catch (RemoteException e) { 235 throw new RuntimeException("Package manager has died", e); 236 } 237 238 throw new NameNotFoundException(className.toString()); 239 } 240 241 @Override 242 public ServiceInfo getServiceInfo(ComponentName className, int flags) 243 throws NameNotFoundException { 244 try { 245 ServiceInfo si = mPM.getServiceInfo(className, flags); 246 if (si != null) { 247 return si; 248 } 249 } catch (RemoteException e) { 250 throw new RuntimeException("Package manager has died", e); 251 } 252 253 throw new NameNotFoundException(className.toString()); 254 } 255 256 @Override 257 public ProviderInfo getProviderInfo(ComponentName className, int flags) 258 throws NameNotFoundException { 259 try { 260 ProviderInfo pi = mPM.getProviderInfo(className, flags); 261 if (pi != null) { 262 return pi; 263 } 264 } catch (RemoteException e) { 265 throw new RuntimeException("Package manager has died", e); 266 } 267 268 throw new NameNotFoundException(className.toString()); 269 } 270 271 @Override 272 public String[] getSystemSharedLibraryNames() { 273 try { 274 return mPM.getSystemSharedLibraryNames(); 275 } catch (RemoteException e) { 276 throw new RuntimeException("Package manager has died", e); 277 } 278 } 279 280 @Override 281 public FeatureInfo[] getSystemAvailableFeatures() { 282 try { 283 return mPM.getSystemAvailableFeatures(); 284 } catch (RemoteException e) { 285 throw new RuntimeException("Package manager has died", e); 286 } 287 } 288 289 @Override 290 public boolean hasSystemFeature(String name) { 291 try { 292 return mPM.hasSystemFeature(name); 293 } catch (RemoteException e) { 294 throw new RuntimeException("Package manager has died", e); 295 } 296 } 297 298 @Override 299 public int checkPermission(String permName, String pkgName) { 300 try { 301 return mPM.checkPermission(permName, pkgName); 302 } catch (RemoteException e) { 303 throw new RuntimeException("Package manager has died", e); 304 } 305 } 306 307 @Override 308 public boolean addPermission(PermissionInfo info) { 309 try { 310 return mPM.addPermission(info); 311 } catch (RemoteException e) { 312 throw new RuntimeException("Package manager has died", e); 313 } 314 } 315 316 @Override 317 public boolean addPermissionAsync(PermissionInfo info) { 318 try { 319 return mPM.addPermissionAsync(info); 320 } catch (RemoteException e) { 321 throw new RuntimeException("Package manager has died", e); 322 } 323 } 324 325 @Override 326 public void removePermission(String name) { 327 try { 328 mPM.removePermission(name); 329 } catch (RemoteException e) { 330 throw new RuntimeException("Package manager has died", e); 331 } 332 } 333 334 @Override 335 public int checkSignatures(String pkg1, String pkg2) { 336 try { 337 return mPM.checkSignatures(pkg1, pkg2); 338 } catch (RemoteException e) { 339 throw new RuntimeException("Package manager has died", e); 340 } 341 } 342 343 @Override 344 public int checkSignatures(int uid1, int uid2) { 345 try { 346 return mPM.checkUidSignatures(uid1, uid2); 347 } catch (RemoteException e) { 348 throw new RuntimeException("Package manager has died", e); 349 } 350 } 351 352 @Override 353 public String[] getPackagesForUid(int uid) { 354 try { 355 return mPM.getPackagesForUid(uid); 356 } catch (RemoteException e) { 357 throw new RuntimeException("Package manager has died", e); 358 } 359 } 360 361 @Override 362 public String getNameForUid(int uid) { 363 try { 364 return mPM.getNameForUid(uid); 365 } catch (RemoteException e) { 366 throw new RuntimeException("Package manager has died", e); 367 } 368 } 369 370 @Override 371 public int getUidForSharedUser(String sharedUserName) 372 throws NameNotFoundException { 373 try { 374 int uid = mPM.getUidForSharedUser(sharedUserName); 375 if(uid != -1) { 376 return uid; 377 } 378 } catch (RemoteException e) { 379 throw new RuntimeException("Package manager has died", e); 380 } 381 throw new NameNotFoundException("No shared userid for user:"+sharedUserName); 382 } 383 384 @SuppressWarnings("unchecked") 385 @Override 386 public List<PackageInfo> getInstalledPackages(int flags) { 387 try { 388 final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>(); 389 PackageInfo lastItem = null; 390 ParceledListSlice<PackageInfo> slice; 391 392 do { 393 final String lastKey = lastItem != null ? lastItem.packageName : null; 394 slice = mPM.getInstalledPackages(flags, lastKey); 395 lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR); 396 } while (!slice.isLastSlice()); 397 398 return packageInfos; 399 } catch (RemoteException e) { 400 throw new RuntimeException("Package manager has died", e); 401 } 402 } 403 404 @SuppressWarnings("unchecked") 405 @Override 406 public List<ApplicationInfo> getInstalledApplications(int flags) { 407 try { 408 final List<ApplicationInfo> applicationInfos = new ArrayList<ApplicationInfo>(); 409 ApplicationInfo lastItem = null; 410 ParceledListSlice<ApplicationInfo> slice; 411 412 do { 413 final String lastKey = lastItem != null ? lastItem.packageName : null; 414 slice = mPM.getInstalledApplications(flags, lastKey); 415 lastItem = slice.populateList(applicationInfos, ApplicationInfo.CREATOR); 416 } while (!slice.isLastSlice()); 417 418 return applicationInfos; 419 } catch (RemoteException e) { 420 throw new RuntimeException("Package manager has died", e); 421 } 422 } 423 424 @Override 425 public ResolveInfo resolveActivity(Intent intent, int flags) { 426 try { 427 return mPM.resolveIntent( 428 intent, 429 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 430 flags); 431 } catch (RemoteException e) { 432 throw new RuntimeException("Package manager has died", e); 433 } 434 } 435 436 @Override 437 public List<ResolveInfo> queryIntentActivities(Intent intent, 438 int flags) { 439 try { 440 return mPM.queryIntentActivities( 441 intent, 442 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 443 flags); 444 } catch (RemoteException e) { 445 throw new RuntimeException("Package manager has died", e); 446 } 447 } 448 449 @Override 450 public List<ResolveInfo> queryIntentActivityOptions( 451 ComponentName caller, Intent[] specifics, Intent intent, 452 int flags) { 453 final ContentResolver resolver = mContext.getContentResolver(); 454 455 String[] specificTypes = null; 456 if (specifics != null) { 457 final int N = specifics.length; 458 for (int i=0; i<N; i++) { 459 Intent sp = specifics[i]; 460 if (sp != null) { 461 String t = sp.resolveTypeIfNeeded(resolver); 462 if (t != null) { 463 if (specificTypes == null) { 464 specificTypes = new String[N]; 465 } 466 specificTypes[i] = t; 467 } 468 } 469 } 470 } 471 472 try { 473 return mPM.queryIntentActivityOptions(caller, specifics, 474 specificTypes, intent, intent.resolveTypeIfNeeded(resolver), 475 flags); 476 } catch (RemoteException e) { 477 throw new RuntimeException("Package manager has died", e); 478 } 479 } 480 481 @Override 482 public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) { 483 try { 484 return mPM.queryIntentReceivers( 485 intent, 486 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 487 flags); 488 } catch (RemoteException e) { 489 throw new RuntimeException("Package manager has died", e); 490 } 491 } 492 493 @Override 494 public ResolveInfo resolveService(Intent intent, int flags) { 495 try { 496 return mPM.resolveService( 497 intent, 498 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 499 flags); 500 } catch (RemoteException e) { 501 throw new RuntimeException("Package manager has died", e); 502 } 503 } 504 505 @Override 506 public List<ResolveInfo> queryIntentServices(Intent intent, int flags) { 507 try { 508 return mPM.queryIntentServices( 509 intent, 510 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 511 flags); 512 } catch (RemoteException e) { 513 throw new RuntimeException("Package manager has died", e); 514 } 515 } 516 517 @Override 518 public ProviderInfo resolveContentProvider(String name, 519 int flags) { 520 try { 521 return mPM.resolveContentProvider(name, flags); 522 } catch (RemoteException e) { 523 throw new RuntimeException("Package manager has died", e); 524 } 525 } 526 527 @Override 528 public List<ProviderInfo> queryContentProviders(String processName, 529 int uid, int flags) { 530 try { 531 return mPM.queryContentProviders(processName, uid, flags); 532 } catch (RemoteException e) { 533 throw new RuntimeException("Package manager has died", e); 534 } 535 } 536 537 @Override 538 public InstrumentationInfo getInstrumentationInfo( 539 ComponentName className, int flags) 540 throws NameNotFoundException { 541 try { 542 InstrumentationInfo ii = mPM.getInstrumentationInfo( 543 className, flags); 544 if (ii != null) { 545 return ii; 546 } 547 } catch (RemoteException e) { 548 throw new RuntimeException("Package manager has died", e); 549 } 550 551 throw new NameNotFoundException(className.toString()); 552 } 553 554 @Override 555 public List<InstrumentationInfo> queryInstrumentation( 556 String targetPackage, int flags) { 557 try { 558 return mPM.queryInstrumentation(targetPackage, flags); 559 } catch (RemoteException e) { 560 throw new RuntimeException("Package manager has died", e); 561 } 562 } 563 564 @Override public Drawable getDrawable(String packageName, int resid, 565 ApplicationInfo appInfo) { 566 ResourceName name = new ResourceName(packageName, resid); 567 Drawable dr = getCachedIcon(name); 568 if (dr != null) { 569 return dr; 570 } 571 if (appInfo == null) { 572 try { 573 appInfo = getApplicationInfo(packageName, 0); 574 } catch (NameNotFoundException e) { 575 return null; 576 } 577 } 578 try { 579 Resources r = getResourcesForApplication(appInfo); 580 dr = r.getDrawable(resid); 581 if (false) { 582 RuntimeException e = new RuntimeException("here"); 583 e.fillInStackTrace(); 584 Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid) 585 + " from package " + packageName 586 + ": app scale=" + r.getCompatibilityInfo().applicationScale 587 + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale, 588 e); 589 } 590 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x" 591 + Integer.toHexString(resid) + " from " + r 592 + ": " + dr); 593 putCachedIcon(name, dr); 594 return dr; 595 } catch (NameNotFoundException e) { 596 Log.w("PackageManager", "Failure retrieving resources for" 597 + appInfo.packageName); 598 } catch (Resources.NotFoundException e) { 599 Log.w("PackageManager", "Failure retrieving resources for" 600 + appInfo.packageName + ": " + e.getMessage()); 601 } catch (RuntimeException e) { 602 // If an exception was thrown, fall through to return 603 // default icon. 604 Log.w("PackageManager", "Failure retrieving icon 0x" 605 + Integer.toHexString(resid) + " in package " 606 + packageName, e); 607 } 608 return null; 609 } 610 611 @Override public Drawable getActivityIcon(ComponentName activityName) 612 throws NameNotFoundException { 613 return getActivityInfo(activityName, 0).loadIcon(this); 614 } 615 616 @Override public Drawable getActivityIcon(Intent intent) 617 throws NameNotFoundException { 618 if (intent.getComponent() != null) { 619 return getActivityIcon(intent.getComponent()); 620 } 621 622 ResolveInfo info = resolveActivity( 623 intent, PackageManager.MATCH_DEFAULT_ONLY); 624 if (info != null) { 625 return info.activityInfo.loadIcon(this); 626 } 627 628 throw new NameNotFoundException(intent.toUri(0)); 629 } 630 631 @Override public Drawable getDefaultActivityIcon() { 632 return Resources.getSystem().getDrawable( 633 com.android.internal.R.drawable.sym_def_app_icon); 634 } 635 636 @Override public Drawable getApplicationIcon(ApplicationInfo info) { 637 return info.loadIcon(this); 638 } 639 640 @Override public Drawable getApplicationIcon(String packageName) 641 throws NameNotFoundException { 642 return getApplicationIcon(getApplicationInfo(packageName, 0)); 643 } 644 645 @Override 646 public Drawable getActivityLogo(ComponentName activityName) 647 throws NameNotFoundException { 648 return getActivityInfo(activityName, 0).loadLogo(this); 649 } 650 651 @Override 652 public Drawable getActivityLogo(Intent intent) 653 throws NameNotFoundException { 654 if (intent.getComponent() != null) { 655 return getActivityLogo(intent.getComponent()); 656 } 657 658 ResolveInfo info = resolveActivity( 659 intent, PackageManager.MATCH_DEFAULT_ONLY); 660 if (info != null) { 661 return info.activityInfo.loadLogo(this); 662 } 663 664 throw new NameNotFoundException(intent.toUri(0)); 665 } 666 667 @Override 668 public Drawable getApplicationLogo(ApplicationInfo info) { 669 return info.loadLogo(this); 670 } 671 672 @Override 673 public Drawable getApplicationLogo(String packageName) 674 throws NameNotFoundException { 675 return getApplicationLogo(getApplicationInfo(packageName, 0)); 676 } 677 678 @Override public Resources getResourcesForActivity( 679 ComponentName activityName) throws NameNotFoundException { 680 return getResourcesForApplication( 681 getActivityInfo(activityName, 0).applicationInfo); 682 } 683 684 @Override public Resources getResourcesForApplication( 685 ApplicationInfo app) throws NameNotFoundException { 686 if (app.packageName.equals("system")) { 687 return mContext.mMainThread.getSystemContext().getResources(); 688 } 689 Resources r = mContext.mMainThread.getTopLevelResources( 690 app.uid == Process.myUid() ? app.sourceDir 691 : app.publicSourceDir, mContext.mPackageInfo); 692 if (r != null) { 693 return r; 694 } 695 throw new NameNotFoundException("Unable to open " + app.publicSourceDir); 696 } 697 698 @Override public Resources getResourcesForApplication( 699 String appPackageName) throws NameNotFoundException { 700 return getResourcesForApplication( 701 getApplicationInfo(appPackageName, 0)); 702 } 703 704 int mCachedSafeMode = -1; 705 @Override public boolean isSafeMode() { 706 try { 707 if (mCachedSafeMode < 0) { 708 mCachedSafeMode = mPM.isSafeMode() ? 1 : 0; 709 } 710 return mCachedSafeMode != 0; 711 } catch (RemoteException e) { 712 throw new RuntimeException("Package manager has died", e); 713 } 714 } 715 716 static void configurationChanged() { 717 synchronized (sSync) { 718 sIconCache.clear(); 719 sStringCache.clear(); 720 } 721 } 722 723 ApplicationPackageManager(ContextImpl context, 724 IPackageManager pm) { 725 mContext = context; 726 mPM = pm; 727 } 728 729 private Drawable getCachedIcon(ResourceName name) { 730 synchronized (sSync) { 731 WeakReference<Drawable.ConstantState> wr = sIconCache.get(name); 732 if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for " 733 + name + ": " + wr); 734 if (wr != null) { // we have the activity 735 Drawable.ConstantState state = wr.get(); 736 if (state != null) { 737 if (DEBUG_ICONS) { 738 Log.v(TAG, "Get cached drawable state for " + name + ": " + state); 739 } 740 // Note: It's okay here to not use the newDrawable(Resources) variant 741 // of the API. The ConstantState comes from a drawable that was 742 // originally created by passing the proper app Resources instance 743 // which means the state should already contain the proper 744 // resources specific information (like density.) See 745 // BitmapDrawable.BitmapState for instance. 746 return state.newDrawable(); 747 } 748 // our entry has been purged 749 sIconCache.remove(name); 750 } 751 } 752 return null; 753 } 754 755 private void putCachedIcon(ResourceName name, Drawable dr) { 756 synchronized (sSync) { 757 sIconCache.put(name, new WeakReference<Drawable.ConstantState>(dr.getConstantState())); 758 if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable state for " + name + ": " + dr); 759 } 760 } 761 762 static void handlePackageBroadcast(int cmd, String[] pkgList, boolean hasPkgInfo) { 763 boolean immediateGc = false; 764 if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) { 765 immediateGc = true; 766 } 767 if (pkgList != null && (pkgList.length > 0)) { 768 boolean needCleanup = false; 769 for (String ssp : pkgList) { 770 synchronized (sSync) { 771 if (sIconCache.size() > 0) { 772 Iterator<ResourceName> it = sIconCache.keySet().iterator(); 773 while (it.hasNext()) { 774 ResourceName nm = it.next(); 775 if (nm.packageName.equals(ssp)) { 776 //Log.i(TAG, "Removing cached drawable for " + nm); 777 it.remove(); 778 needCleanup = true; 779 } 780 } 781 } 782 if (sStringCache.size() > 0) { 783 Iterator<ResourceName> it = sStringCache.keySet().iterator(); 784 while (it.hasNext()) { 785 ResourceName nm = it.next(); 786 if (nm.packageName.equals(ssp)) { 787 //Log.i(TAG, "Removing cached string for " + nm); 788 it.remove(); 789 needCleanup = true; 790 } 791 } 792 } 793 } 794 } 795 if (needCleanup || hasPkgInfo) { 796 if (immediateGc) { 797 // Schedule an immediate gc. 798 Runtime.getRuntime().gc(); 799 } else { 800 ActivityThread.currentActivityThread().scheduleGcIdler(); 801 } 802 } 803 } 804 } 805 806 private static final class ResourceName { 807 final String packageName; 808 final int iconId; 809 810 ResourceName(String _packageName, int _iconId) { 811 packageName = _packageName; 812 iconId = _iconId; 813 } 814 815 ResourceName(ApplicationInfo aInfo, int _iconId) { 816 this(aInfo.packageName, _iconId); 817 } 818 819 ResourceName(ComponentInfo cInfo, int _iconId) { 820 this(cInfo.applicationInfo.packageName, _iconId); 821 } 822 823 ResourceName(ResolveInfo rInfo, int _iconId) { 824 this(rInfo.activityInfo.applicationInfo.packageName, _iconId); 825 } 826 827 @Override 828 public boolean equals(Object o) { 829 if (this == o) return true; 830 if (o == null || getClass() != o.getClass()) return false; 831 832 ResourceName that = (ResourceName) o; 833 834 if (iconId != that.iconId) return false; 835 return !(packageName != null ? 836 !packageName.equals(that.packageName) : that.packageName != null); 837 838 } 839 840 @Override 841 public int hashCode() { 842 int result; 843 result = packageName.hashCode(); 844 result = 31 * result + iconId; 845 return result; 846 } 847 848 @Override 849 public String toString() { 850 return "{ResourceName " + packageName + " / " + iconId + "}"; 851 } 852 } 853 854 private CharSequence getCachedString(ResourceName name) { 855 synchronized (sSync) { 856 WeakReference<CharSequence> wr = sStringCache.get(name); 857 if (wr != null) { // we have the activity 858 CharSequence cs = wr.get(); 859 if (cs != null) { 860 return cs; 861 } 862 // our entry has been purged 863 sStringCache.remove(name); 864 } 865 } 866 return null; 867 } 868 869 private void putCachedString(ResourceName name, CharSequence cs) { 870 synchronized (sSync) { 871 sStringCache.put(name, new WeakReference<CharSequence>(cs)); 872 } 873 } 874 875 @Override 876 public CharSequence getText(String packageName, int resid, 877 ApplicationInfo appInfo) { 878 ResourceName name = new ResourceName(packageName, resid); 879 CharSequence text = getCachedString(name); 880 if (text != null) { 881 return text; 882 } 883 if (appInfo == null) { 884 try { 885 appInfo = getApplicationInfo(packageName, 0); 886 } catch (NameNotFoundException e) { 887 return null; 888 } 889 } 890 try { 891 Resources r = getResourcesForApplication(appInfo); 892 text = r.getText(resid); 893 putCachedString(name, text); 894 return text; 895 } catch (NameNotFoundException e) { 896 Log.w("PackageManager", "Failure retrieving resources for" 897 + appInfo.packageName); 898 } catch (RuntimeException e) { 899 // If an exception was thrown, fall through to return 900 // default icon. 901 Log.w("PackageManager", "Failure retrieving text 0x" 902 + Integer.toHexString(resid) + " in package " 903 + packageName, e); 904 } 905 return null; 906 } 907 908 @Override 909 public XmlResourceParser getXml(String packageName, int resid, 910 ApplicationInfo appInfo) { 911 if (appInfo == null) { 912 try { 913 appInfo = getApplicationInfo(packageName, 0); 914 } catch (NameNotFoundException e) { 915 return null; 916 } 917 } 918 try { 919 Resources r = getResourcesForApplication(appInfo); 920 return r.getXml(resid); 921 } catch (RuntimeException e) { 922 // If an exception was thrown, fall through to return 923 // default icon. 924 Log.w("PackageManager", "Failure retrieving xml 0x" 925 + Integer.toHexString(resid) + " in package " 926 + packageName, e); 927 } catch (NameNotFoundException e) { 928 Log.w("PackageManager", "Failure retrieving resources for " 929 + appInfo.packageName); 930 } 931 return null; 932 } 933 934 @Override 935 public CharSequence getApplicationLabel(ApplicationInfo info) { 936 return info.loadLabel(this); 937 } 938 939 @Override 940 public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags, 941 String installerPackageName) { 942 try { 943 mPM.installPackage(packageURI, observer, flags, installerPackageName); 944 } catch (RemoteException e) { 945 // Should never happen! 946 } 947 } 948 949 @Override 950 public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer, 951 int flags, String installerPackageName, Uri verificationURI, 952 ManifestDigest manifestDigest) { 953 try { 954 mPM.installPackageWithVerification(packageURI, observer, flags, installerPackageName, 955 verificationURI, manifestDigest); 956 } catch (RemoteException e) { 957 // Should never happen! 958 } 959 } 960 961 @Override 962 public void verifyPendingInstall(int id, int response) { 963 try { 964 mPM.verifyPendingInstall(id, response); 965 } catch (RemoteException e) { 966 // Should never happen! 967 } 968 } 969 970 @Override 971 public void setInstallerPackageName(String targetPackage, 972 String installerPackageName) { 973 try { 974 mPM.setInstallerPackageName(targetPackage, installerPackageName); 975 } catch (RemoteException e) { 976 // Should never happen! 977 } 978 } 979 980 @Override 981 public void movePackage(String packageName, IPackageMoveObserver observer, int flags) { 982 try { 983 mPM.movePackage(packageName, observer, flags); 984 } catch (RemoteException e) { 985 // Should never happen! 986 } 987 } 988 989 @Override 990 public String getInstallerPackageName(String packageName) { 991 try { 992 return mPM.getInstallerPackageName(packageName); 993 } catch (RemoteException e) { 994 // Should never happen! 995 } 996 return null; 997 } 998 999 @Override 1000 public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) { 1001 try { 1002 mPM.deletePackage(packageName, observer, flags); 1003 } catch (RemoteException e) { 1004 // Should never happen! 1005 } 1006 } 1007 @Override 1008 public void clearApplicationUserData(String packageName, 1009 IPackageDataObserver observer) { 1010 try { 1011 mPM.clearApplicationUserData(packageName, observer); 1012 } catch (RemoteException e) { 1013 // Should never happen! 1014 } 1015 } 1016 @Override 1017 public void deleteApplicationCacheFiles(String packageName, 1018 IPackageDataObserver observer) { 1019 try { 1020 mPM.deleteApplicationCacheFiles(packageName, observer); 1021 } catch (RemoteException e) { 1022 // Should never happen! 1023 } 1024 } 1025 @Override 1026 public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) { 1027 try { 1028 mPM.freeStorageAndNotify(idealStorageSize, observer); 1029 } catch (RemoteException e) { 1030 // Should never happen! 1031 } 1032 } 1033 1034 @Override 1035 public void freeStorage(long freeStorageSize, IntentSender pi) { 1036 try { 1037 mPM.freeStorage(freeStorageSize, pi); 1038 } catch (RemoteException e) { 1039 // Should never happen! 1040 } 1041 } 1042 1043 @Override 1044 public void getPackageSizeInfo(String packageName, 1045 IPackageStatsObserver observer) { 1046 try { 1047 mPM.getPackageSizeInfo(packageName, observer); 1048 } catch (RemoteException e) { 1049 // Should never happen! 1050 } 1051 } 1052 @Override 1053 public void addPackageToPreferred(String packageName) { 1054 try { 1055 mPM.addPackageToPreferred(packageName); 1056 } catch (RemoteException e) { 1057 // Should never happen! 1058 } 1059 } 1060 1061 @Override 1062 public void removePackageFromPreferred(String packageName) { 1063 try { 1064 mPM.removePackageFromPreferred(packageName); 1065 } catch (RemoteException e) { 1066 // Should never happen! 1067 } 1068 } 1069 1070 @Override 1071 public List<PackageInfo> getPreferredPackages(int flags) { 1072 try { 1073 return mPM.getPreferredPackages(flags); 1074 } catch (RemoteException e) { 1075 // Should never happen! 1076 } 1077 return new ArrayList<PackageInfo>(); 1078 } 1079 1080 @Override 1081 public void addPreferredActivity(IntentFilter filter, 1082 int match, ComponentName[] set, ComponentName activity) { 1083 try { 1084 mPM.addPreferredActivity(filter, match, set, activity); 1085 } catch (RemoteException e) { 1086 // Should never happen! 1087 } 1088 } 1089 1090 @Override 1091 public void replacePreferredActivity(IntentFilter filter, 1092 int match, ComponentName[] set, ComponentName activity) { 1093 try { 1094 mPM.replacePreferredActivity(filter, match, set, activity); 1095 } catch (RemoteException e) { 1096 // Should never happen! 1097 } 1098 } 1099 1100 @Override 1101 public void clearPackagePreferredActivities(String packageName) { 1102 try { 1103 mPM.clearPackagePreferredActivities(packageName); 1104 } catch (RemoteException e) { 1105 // Should never happen! 1106 } 1107 } 1108 1109 @Override 1110 public int getPreferredActivities(List<IntentFilter> outFilters, 1111 List<ComponentName> outActivities, String packageName) { 1112 try { 1113 return mPM.getPreferredActivities(outFilters, outActivities, packageName); 1114 } catch (RemoteException e) { 1115 // Should never happen! 1116 } 1117 return 0; 1118 } 1119 1120 @Override 1121 public void setComponentEnabledSetting(ComponentName componentName, 1122 int newState, int flags) { 1123 try { 1124 mPM.setComponentEnabledSetting(componentName, newState, flags); 1125 } catch (RemoteException e) { 1126 // Should never happen! 1127 } 1128 } 1129 1130 @Override 1131 public int getComponentEnabledSetting(ComponentName componentName) { 1132 try { 1133 return mPM.getComponentEnabledSetting(componentName); 1134 } catch (RemoteException e) { 1135 // Should never happen! 1136 } 1137 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 1138 } 1139 1140 @Override 1141 public void setApplicationEnabledSetting(String packageName, 1142 int newState, int flags) { 1143 try { 1144 mPM.setApplicationEnabledSetting(packageName, newState, flags); 1145 } catch (RemoteException e) { 1146 // Should never happen! 1147 } 1148 } 1149 1150 @Override 1151 public int getApplicationEnabledSetting(String packageName) { 1152 try { 1153 return mPM.getApplicationEnabledSetting(packageName); 1154 } catch (RemoteException e) { 1155 // Should never happen! 1156 } 1157 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 1158 } 1159 1160 // Multi-user support 1161 1162 /** 1163 * @hide 1164 */ 1165 @Override 1166 public UserInfo createUser(String name, int flags) { 1167 try { 1168 return mPM.createUser(name, flags); 1169 } catch (RemoteException e) { 1170 // Should never happen! 1171 } 1172 return null; 1173 } 1174 1175 /** 1176 * @hide 1177 */ 1178 @Override 1179 public List<UserInfo> getUsers() { 1180 try { 1181 return mPM.getUsers(); 1182 } catch (RemoteException re) { 1183 ArrayList<UserInfo> users = new ArrayList<UserInfo>(); 1184 UserInfo primary = new UserInfo(0, "Root!", UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY); 1185 users.add(primary); 1186 return users; 1187 } 1188 } 1189 1190 /** 1191 * @hide 1192 */ 1193 @Override 1194 public boolean removeUser(int id) { 1195 try { 1196 return mPM.removeUser(id); 1197 } catch (RemoteException e) { 1198 return false; 1199 } 1200 } 1201 1202 /** 1203 * @hide 1204 */ 1205 @Override 1206 public void updateUserName(int id, String name) { 1207 // TODO: 1208 } 1209 1210 /** 1211 * @hide 1212 */ 1213 @Override 1214 public void updateUserFlags(int id, int flags) { 1215 // TODO: 1216 } 1217 1218 /** 1219 * @hide 1220 */ 1221 @Override 1222 public VerifierDeviceIdentity getVerifierDeviceIdentity() { 1223 try { 1224 return mPM.getVerifierDeviceIdentity(); 1225 } catch (RemoteException e) { 1226 // Should never happen! 1227 } 1228 return null; 1229 } 1230 1231 private final ContextImpl mContext; 1232 private final IPackageManager mPM; 1233 1234 private static final Object sSync = new Object(); 1235 private static HashMap<ResourceName, WeakReference<Drawable.ConstantState>> sIconCache 1236 = new HashMap<ResourceName, WeakReference<Drawable.ConstantState>>(); 1237 private static HashMap<ResourceName, WeakReference<CharSequence>> sStringCache 1238 = new HashMap<ResourceName, WeakReference<CharSequence>>(); 1239} 1240