ApplicationPackageManager.java revision 0aaa0d931716e9f57a1d84d795fab2df75092756
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());
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> 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 dr = wr.get();
736                if (dr != null) {
737                    if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
738                                           + name + ": " + dr);
739                    return dr;
740                }
741                // our entry has been purged
742                sIconCache.remove(name);
743            }
744        }
745        return null;
746    }
747
748    private void putCachedIcon(ResourceName name, Drawable dr) {
749        synchronized (sSync) {
750            sIconCache.put(name, new WeakReference<Drawable>(dr));
751            if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
752                                   + name + ": " + dr);
753        }
754    }
755
756    static final void handlePackageBroadcast(int cmd, String[] pkgList,
757                                             boolean hasPkgInfo) {
758        boolean immediateGc = false;
759        if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
760            immediateGc = true;
761        }
762        if (pkgList != null && (pkgList.length > 0)) {
763            boolean needCleanup = false;
764            for (String ssp : pkgList) {
765                synchronized (sSync) {
766                    if (sIconCache.size() > 0) {
767                        Iterator<ResourceName> it = sIconCache.keySet().iterator();
768                        while (it.hasNext()) {
769                            ResourceName nm = it.next();
770                            if (nm.packageName.equals(ssp)) {
771                                //Log.i(TAG, "Removing cached drawable for " + nm);
772                                it.remove();
773                                needCleanup = true;
774                            }
775                        }
776                    }
777                    if (sStringCache.size() > 0) {
778                        Iterator<ResourceName> it = sStringCache.keySet().iterator();
779                        while (it.hasNext()) {
780                            ResourceName nm = it.next();
781                            if (nm.packageName.equals(ssp)) {
782                                //Log.i(TAG, "Removing cached string for " + nm);
783                                it.remove();
784                                needCleanup = true;
785                            }
786                        }
787                    }
788                }
789            }
790            if (needCleanup || hasPkgInfo) {
791                if (immediateGc) {
792                    // Schedule an immediate gc.
793                    Runtime.getRuntime().gc();
794                } else {
795                    ActivityThread.currentActivityThread().scheduleGcIdler();
796                }
797            }
798        }
799    }
800
801    private static final class ResourceName {
802        final String packageName;
803        final int iconId;
804
805        ResourceName(String _packageName, int _iconId) {
806            packageName = _packageName;
807            iconId = _iconId;
808        }
809
810        ResourceName(ApplicationInfo aInfo, int _iconId) {
811            this(aInfo.packageName, _iconId);
812        }
813
814        ResourceName(ComponentInfo cInfo, int _iconId) {
815            this(cInfo.applicationInfo.packageName, _iconId);
816        }
817
818        ResourceName(ResolveInfo rInfo, int _iconId) {
819            this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
820        }
821
822        @Override
823        public boolean equals(Object o) {
824            if (this == o) return true;
825            if (o == null || getClass() != o.getClass()) return false;
826
827            ResourceName that = (ResourceName) o;
828
829            if (iconId != that.iconId) return false;
830            return !(packageName != null ?
831                     !packageName.equals(that.packageName) : that.packageName != null);
832
833        }
834
835        @Override
836        public int hashCode() {
837            int result;
838            result = packageName.hashCode();
839            result = 31 * result + iconId;
840            return result;
841        }
842
843        @Override
844        public String toString() {
845            return "{ResourceName " + packageName + " / " + iconId + "}";
846        }
847    }
848
849    private CharSequence getCachedString(ResourceName name) {
850        synchronized (sSync) {
851            WeakReference<CharSequence> wr = sStringCache.get(name);
852            if (wr != null) {   // we have the activity
853                CharSequence cs = wr.get();
854                if (cs != null) {
855                    return cs;
856                }
857                // our entry has been purged
858                sStringCache.remove(name);
859            }
860        }
861        return null;
862    }
863
864    private void putCachedString(ResourceName name, CharSequence cs) {
865        synchronized (sSync) {
866            sStringCache.put(name, new WeakReference<CharSequence>(cs));
867        }
868    }
869
870    @Override
871    public CharSequence getText(String packageName, int resid,
872                                ApplicationInfo appInfo) {
873        ResourceName name = new ResourceName(packageName, resid);
874        CharSequence text = getCachedString(name);
875        if (text != null) {
876            return text;
877        }
878        if (appInfo == null) {
879            try {
880                appInfo = getApplicationInfo(packageName, 0);
881            } catch (NameNotFoundException e) {
882                return null;
883            }
884        }
885        try {
886            Resources r = getResourcesForApplication(appInfo);
887            text = r.getText(resid);
888            putCachedString(name, text);
889            return text;
890        } catch (NameNotFoundException e) {
891            Log.w("PackageManager", "Failure retrieving resources for"
892                  + appInfo.packageName);
893        } catch (RuntimeException e) {
894            // If an exception was thrown, fall through to return
895            // default icon.
896            Log.w("PackageManager", "Failure retrieving text 0x"
897                  + Integer.toHexString(resid) + " in package "
898                  + packageName, e);
899        }
900        return null;
901    }
902
903    @Override
904    public XmlResourceParser getXml(String packageName, int resid,
905                                    ApplicationInfo appInfo) {
906        if (appInfo == null) {
907            try {
908                appInfo = getApplicationInfo(packageName, 0);
909            } catch (NameNotFoundException e) {
910                return null;
911            }
912        }
913        try {
914            Resources r = getResourcesForApplication(appInfo);
915            return r.getXml(resid);
916        } catch (RuntimeException e) {
917            // If an exception was thrown, fall through to return
918            // default icon.
919            Log.w("PackageManager", "Failure retrieving xml 0x"
920                  + Integer.toHexString(resid) + " in package "
921                  + packageName, e);
922        } catch (NameNotFoundException e) {
923            Log.w("PackageManager", "Failure retrieving resources for "
924                  + appInfo.packageName);
925        }
926        return null;
927    }
928
929    @Override
930    public CharSequence getApplicationLabel(ApplicationInfo info) {
931        return info.loadLabel(this);
932    }
933
934    @Override
935    public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
936                               String installerPackageName) {
937        try {
938            mPM.installPackage(packageURI, observer, flags, installerPackageName);
939        } catch (RemoteException e) {
940            // Should never happen!
941        }
942    }
943
944    @Override
945    public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
946            int flags, String installerPackageName, Uri verificationURI,
947            ManifestDigest manifestDigest) {
948        try {
949            mPM.installPackageWithVerification(packageURI, observer, flags, installerPackageName,
950                    verificationURI, manifestDigest);
951        } catch (RemoteException e) {
952            // Should never happen!
953        }
954    }
955
956    @Override
957    public void verifyPendingInstall(int id, boolean verified, String failureMessage) {
958        try {
959            mPM.verifyPendingInstall(id, verified, failureMessage);
960        } catch (RemoteException e) {
961            // Should never happen!
962        }
963    }
964
965    @Override
966    public void setInstallerPackageName(String targetPackage,
967            String installerPackageName) {
968        try {
969            mPM.setInstallerPackageName(targetPackage, installerPackageName);
970        } catch (RemoteException e) {
971            // Should never happen!
972        }
973    }
974
975    @Override
976    public void movePackage(String packageName, IPackageMoveObserver observer, int flags) {
977        try {
978            mPM.movePackage(packageName, observer, flags);
979        } catch (RemoteException e) {
980            // Should never happen!
981        }
982    }
983
984    @Override
985    public String getInstallerPackageName(String packageName) {
986        try {
987            return mPM.getInstallerPackageName(packageName);
988        } catch (RemoteException e) {
989            // Should never happen!
990        }
991        return null;
992    }
993
994    @Override
995    public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
996        try {
997            mPM.deletePackage(packageName, observer, flags);
998        } catch (RemoteException e) {
999            // Should never happen!
1000        }
1001    }
1002    @Override
1003    public void clearApplicationUserData(String packageName,
1004                                         IPackageDataObserver observer) {
1005        try {
1006            mPM.clearApplicationUserData(packageName, observer);
1007        } catch (RemoteException e) {
1008            // Should never happen!
1009        }
1010    }
1011    @Override
1012    public void deleteApplicationCacheFiles(String packageName,
1013                                            IPackageDataObserver observer) {
1014        try {
1015            mPM.deleteApplicationCacheFiles(packageName, observer);
1016        } catch (RemoteException e) {
1017            // Should never happen!
1018        }
1019    }
1020    @Override
1021    public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
1022        try {
1023            mPM.freeStorageAndNotify(idealStorageSize, observer);
1024        } catch (RemoteException e) {
1025            // Should never happen!
1026        }
1027    }
1028
1029    @Override
1030    public void freeStorage(long freeStorageSize, IntentSender pi) {
1031        try {
1032            mPM.freeStorage(freeStorageSize, pi);
1033        } catch (RemoteException e) {
1034            // Should never happen!
1035        }
1036    }
1037
1038    @Override
1039    public void getPackageSizeInfo(String packageName,
1040                                   IPackageStatsObserver observer) {
1041        try {
1042            mPM.getPackageSizeInfo(packageName, observer);
1043        } catch (RemoteException e) {
1044            // Should never happen!
1045        }
1046    }
1047    @Override
1048    public void addPackageToPreferred(String packageName) {
1049        try {
1050            mPM.addPackageToPreferred(packageName);
1051        } catch (RemoteException e) {
1052            // Should never happen!
1053        }
1054    }
1055
1056    @Override
1057    public void removePackageFromPreferred(String packageName) {
1058        try {
1059            mPM.removePackageFromPreferred(packageName);
1060        } catch (RemoteException e) {
1061            // Should never happen!
1062        }
1063    }
1064
1065    @Override
1066    public List<PackageInfo> getPreferredPackages(int flags) {
1067        try {
1068            return mPM.getPreferredPackages(flags);
1069        } catch (RemoteException e) {
1070            // Should never happen!
1071        }
1072        return new ArrayList<PackageInfo>();
1073    }
1074
1075    @Override
1076    public void addPreferredActivity(IntentFilter filter,
1077                                     int match, ComponentName[] set, ComponentName activity) {
1078        try {
1079            mPM.addPreferredActivity(filter, match, set, activity);
1080        } catch (RemoteException e) {
1081            // Should never happen!
1082        }
1083    }
1084
1085    @Override
1086    public void replacePreferredActivity(IntentFilter filter,
1087                                         int match, ComponentName[] set, ComponentName activity) {
1088        try {
1089            mPM.replacePreferredActivity(filter, match, set, activity);
1090        } catch (RemoteException e) {
1091            // Should never happen!
1092        }
1093    }
1094
1095    @Override
1096    public void clearPackagePreferredActivities(String packageName) {
1097        try {
1098            mPM.clearPackagePreferredActivities(packageName);
1099        } catch (RemoteException e) {
1100            // Should never happen!
1101        }
1102    }
1103
1104    @Override
1105    public int getPreferredActivities(List<IntentFilter> outFilters,
1106                                      List<ComponentName> outActivities, String packageName) {
1107        try {
1108            return mPM.getPreferredActivities(outFilters, outActivities, packageName);
1109        } catch (RemoteException e) {
1110            // Should never happen!
1111        }
1112        return 0;
1113    }
1114
1115    @Override
1116    public void setComponentEnabledSetting(ComponentName componentName,
1117                                           int newState, int flags) {
1118        try {
1119            mPM.setComponentEnabledSetting(componentName, newState, flags);
1120        } catch (RemoteException e) {
1121            // Should never happen!
1122        }
1123    }
1124
1125    @Override
1126    public int getComponentEnabledSetting(ComponentName componentName) {
1127        try {
1128            return mPM.getComponentEnabledSetting(componentName);
1129        } catch (RemoteException e) {
1130            // Should never happen!
1131        }
1132        return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
1133    }
1134
1135    @Override
1136    public void setApplicationEnabledSetting(String packageName,
1137                                             int newState, int flags) {
1138        try {
1139            mPM.setApplicationEnabledSetting(packageName, newState, flags);
1140        } catch (RemoteException e) {
1141            // Should never happen!
1142        }
1143    }
1144
1145    @Override
1146    public int getApplicationEnabledSetting(String packageName) {
1147        try {
1148            return mPM.getApplicationEnabledSetting(packageName);
1149        } catch (RemoteException e) {
1150            // Should never happen!
1151        }
1152        return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
1153    }
1154
1155    // Multi-user support
1156
1157    /**
1158     * @hide
1159     */
1160    @Override
1161    public UserInfo createUser(String name, int flags) {
1162        try {
1163            return mPM.createUser(name, flags);
1164        } catch (RemoteException e) {
1165            // Should never happen!
1166        }
1167        return null;
1168    }
1169
1170    /**
1171     * @hide
1172     */
1173    @Override
1174    public List<UserInfo> getUsers() {
1175        // TODO:
1176        // Dummy code, always returns just the primary user
1177        ArrayList<UserInfo> users = new ArrayList<UserInfo>();
1178        UserInfo primary = new UserInfo(0, "Root!",
1179                UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
1180        users.add(primary);
1181        return users;
1182    }
1183
1184    /**
1185     * @hide
1186     */
1187    @Override
1188    public boolean removeUser(int id) {
1189        try {
1190            return mPM.removeUser(id);
1191        } catch (RemoteException e) {
1192            return false;
1193        }
1194    }
1195
1196    /**
1197     * @hide
1198     */
1199    @Override
1200    public void updateUserName(int id, String name) {
1201        // TODO:
1202    }
1203
1204    /**
1205     * @hide
1206     */
1207    @Override
1208    public void updateUserFlags(int id, int flags) {
1209        // TODO:
1210    }
1211
1212    /**
1213     * @hide
1214     */
1215    @Override
1216    public VerifierDeviceIdentity getVerifierDeviceIdentity() {
1217        try {
1218            return mPM.getVerifierDeviceIdentity();
1219        } catch (RemoteException e) {
1220            // Should never happen!
1221        }
1222        return null;
1223    }
1224
1225    private final ContextImpl mContext;
1226    private final IPackageManager mPM;
1227
1228    private static final Object sSync = new Object();
1229    private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
1230            = new HashMap<ResourceName, WeakReference<Drawable> >();
1231    private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
1232            = new HashMap<ResourceName, WeakReference<CharSequence> >();
1233}
1234