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