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