ApplicationPackageManager.java revision 4b2e934928a2eb65927bd39197198c28c49efb94
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.PermissionGroupInfo;
38import android.content.pm.PermissionInfo;
39import android.content.pm.ProviderInfo;
40import android.content.pm.ResolveInfo;
41import android.content.pm.ServiceInfo;
42import android.content.pm.UserInfo;
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        List<ResolveInfo> ris = queryIntentActivities(intentToResolve, 0);
105
106        // Otherwise, try to find a main launcher activity.
107        if (ris == null || ris.size() <= 0) {
108            // reuse the intent instance
109            intentToResolve.removeCategory(Intent.CATEGORY_INFO);
110            intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
111            intentToResolve.setPackage(packageName);
112            ris = queryIntentActivities(intentToResolve, 0);
113        }
114        if (ris == null || ris.size() <= 0) {
115            return null;
116        }
117        Intent intent = new Intent(intentToResolve);
118        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
119        intent.setClassName(ris.get(0).activityInfo.packageName,
120                ris.get(0).activityInfo.name);
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 (Resources.NotFoundException e) {
574            Log.w("PackageManager", "Failure retrieving resources for"
575                  + appInfo.packageName + ": " + e.getMessage());
576        } catch (RuntimeException e) {
577            // If an exception was thrown, fall through to return
578            // default icon.
579            Log.w("PackageManager", "Failure retrieving icon 0x"
580                  + Integer.toHexString(resid) + " in package "
581                  + packageName, e);
582        }
583        return null;
584    }
585
586    @Override public Drawable getActivityIcon(ComponentName activityName)
587            throws NameNotFoundException {
588        return getActivityInfo(activityName, 0).loadIcon(this);
589    }
590
591    @Override public Drawable getActivityIcon(Intent intent)
592            throws NameNotFoundException {
593        if (intent.getComponent() != null) {
594            return getActivityIcon(intent.getComponent());
595        }
596
597        ResolveInfo info = resolveActivity(
598            intent, PackageManager.MATCH_DEFAULT_ONLY);
599        if (info != null) {
600            return info.activityInfo.loadIcon(this);
601        }
602
603        throw new NameNotFoundException(intent.toURI());
604    }
605
606    @Override public Drawable getDefaultActivityIcon() {
607        return Resources.getSystem().getDrawable(
608            com.android.internal.R.drawable.sym_def_app_icon);
609    }
610
611    @Override public Drawable getApplicationIcon(ApplicationInfo info) {
612        return info.loadIcon(this);
613    }
614
615    @Override public Drawable getApplicationIcon(String packageName)
616            throws NameNotFoundException {
617        return getApplicationIcon(getApplicationInfo(packageName, 0));
618    }
619
620    @Override
621    public Drawable getActivityLogo(ComponentName activityName)
622            throws NameNotFoundException {
623        return getActivityInfo(activityName, 0).loadLogo(this);
624    }
625
626    @Override
627    public Drawable getActivityLogo(Intent intent)
628            throws NameNotFoundException {
629        if (intent.getComponent() != null) {
630            return getActivityLogo(intent.getComponent());
631        }
632
633        ResolveInfo info = resolveActivity(
634            intent, PackageManager.MATCH_DEFAULT_ONLY);
635        if (info != null) {
636            return info.activityInfo.loadLogo(this);
637        }
638
639        throw new NameNotFoundException(intent.toUri(0));
640    }
641
642    @Override
643    public Drawable getApplicationLogo(ApplicationInfo info) {
644        return info.loadLogo(this);
645    }
646
647    @Override
648    public Drawable getApplicationLogo(String packageName)
649            throws NameNotFoundException {
650        return getApplicationLogo(getApplicationInfo(packageName, 0));
651    }
652
653    @Override public Resources getResourcesForActivity(
654        ComponentName activityName) throws NameNotFoundException {
655        return getResourcesForApplication(
656            getActivityInfo(activityName, 0).applicationInfo);
657    }
658
659    @Override public Resources getResourcesForApplication(
660        ApplicationInfo app) throws NameNotFoundException {
661        if (app.packageName.equals("system")) {
662            return mContext.mMainThread.getSystemContext().getResources();
663        }
664        Resources r = mContext.mMainThread.getTopLevelResources(
665            app.uid == Process.myUid() ? app.sourceDir
666            : app.publicSourceDir, mContext.mPackageInfo);
667        if (r != null) {
668            return r;
669        }
670        throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
671    }
672
673    @Override public Resources getResourcesForApplication(
674        String appPackageName) throws NameNotFoundException {
675        return getResourcesForApplication(
676            getApplicationInfo(appPackageName, 0));
677    }
678
679    int mCachedSafeMode = -1;
680    @Override public boolean isSafeMode() {
681        try {
682            if (mCachedSafeMode < 0) {
683                mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
684            }
685            return mCachedSafeMode != 0;
686        } catch (RemoteException e) {
687            throw new RuntimeException("Package manager has died", e);
688        }
689    }
690
691    static void configurationChanged() {
692        synchronized (sSync) {
693            sIconCache.clear();
694            sStringCache.clear();
695        }
696    }
697
698    ApplicationPackageManager(ContextImpl context,
699                              IPackageManager pm) {
700        mContext = context;
701        mPM = pm;
702    }
703
704    private Drawable getCachedIcon(ResourceName name) {
705        synchronized (sSync) {
706            WeakReference<Drawable> wr = sIconCache.get(name);
707            if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
708                                   + name + ": " + wr);
709            if (wr != null) {   // we have the activity
710                Drawable dr = wr.get();
711                if (dr != null) {
712                    if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
713                                           + name + ": " + dr);
714                    return dr;
715                }
716                // our entry has been purged
717                sIconCache.remove(name);
718            }
719        }
720        return null;
721    }
722
723    private void putCachedIcon(ResourceName name, Drawable dr) {
724        synchronized (sSync) {
725            sIconCache.put(name, new WeakReference<Drawable>(dr));
726            if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
727                                   + name + ": " + dr);
728        }
729    }
730
731    static final void handlePackageBroadcast(int cmd, String[] pkgList,
732                                             boolean hasPkgInfo) {
733        boolean immediateGc = false;
734        if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
735            immediateGc = true;
736        }
737        if (pkgList != null && (pkgList.length > 0)) {
738            boolean needCleanup = false;
739            for (String ssp : pkgList) {
740                synchronized (sSync) {
741                    if (sIconCache.size() > 0) {
742                        Iterator<ResourceName> it = sIconCache.keySet().iterator();
743                        while (it.hasNext()) {
744                            ResourceName nm = it.next();
745                            if (nm.packageName.equals(ssp)) {
746                                //Log.i(TAG, "Removing cached drawable for " + nm);
747                                it.remove();
748                                needCleanup = true;
749                            }
750                        }
751                    }
752                    if (sStringCache.size() > 0) {
753                        Iterator<ResourceName> it = sStringCache.keySet().iterator();
754                        while (it.hasNext()) {
755                            ResourceName nm = it.next();
756                            if (nm.packageName.equals(ssp)) {
757                                //Log.i(TAG, "Removing cached string for " + nm);
758                                it.remove();
759                                needCleanup = true;
760                            }
761                        }
762                    }
763                }
764            }
765            if (needCleanup || hasPkgInfo) {
766                if (immediateGc) {
767                    // Schedule an immediate gc.
768                    Runtime.getRuntime().gc();
769                } else {
770                    ActivityThread.currentActivityThread().scheduleGcIdler();
771                }
772            }
773        }
774    }
775
776    private static final class ResourceName {
777        final String packageName;
778        final int iconId;
779
780        ResourceName(String _packageName, int _iconId) {
781            packageName = _packageName;
782            iconId = _iconId;
783        }
784
785        ResourceName(ApplicationInfo aInfo, int _iconId) {
786            this(aInfo.packageName, _iconId);
787        }
788
789        ResourceName(ComponentInfo cInfo, int _iconId) {
790            this(cInfo.applicationInfo.packageName, _iconId);
791        }
792
793        ResourceName(ResolveInfo rInfo, int _iconId) {
794            this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
795        }
796
797        @Override
798        public boolean equals(Object o) {
799            if (this == o) return true;
800            if (o == null || getClass() != o.getClass()) return false;
801
802            ResourceName that = (ResourceName) o;
803
804            if (iconId != that.iconId) return false;
805            return !(packageName != null ?
806                     !packageName.equals(that.packageName) : that.packageName != null);
807
808        }
809
810        @Override
811        public int hashCode() {
812            int result;
813            result = packageName.hashCode();
814            result = 31 * result + iconId;
815            return result;
816        }
817
818        @Override
819        public String toString() {
820            return "{ResourceName " + packageName + " / " + iconId + "}";
821        }
822    }
823
824    private CharSequence getCachedString(ResourceName name) {
825        synchronized (sSync) {
826            WeakReference<CharSequence> wr = sStringCache.get(name);
827            if (wr != null) {   // we have the activity
828                CharSequence cs = wr.get();
829                if (cs != null) {
830                    return cs;
831                }
832                // our entry has been purged
833                sStringCache.remove(name);
834            }
835        }
836        return null;
837    }
838
839    private void putCachedString(ResourceName name, CharSequence cs) {
840        synchronized (sSync) {
841            sStringCache.put(name, new WeakReference<CharSequence>(cs));
842        }
843    }
844
845    @Override
846    public CharSequence getText(String packageName, int resid,
847                                ApplicationInfo appInfo) {
848        ResourceName name = new ResourceName(packageName, resid);
849        CharSequence text = getCachedString(name);
850        if (text != null) {
851            return text;
852        }
853        if (appInfo == null) {
854            try {
855                appInfo = getApplicationInfo(packageName, 0);
856            } catch (NameNotFoundException e) {
857                return null;
858            }
859        }
860        try {
861            Resources r = getResourcesForApplication(appInfo);
862            text = r.getText(resid);
863            putCachedString(name, text);
864            return text;
865        } catch (NameNotFoundException e) {
866            Log.w("PackageManager", "Failure retrieving resources for"
867                  + appInfo.packageName);
868        } catch (RuntimeException e) {
869            // If an exception was thrown, fall through to return
870            // default icon.
871            Log.w("PackageManager", "Failure retrieving text 0x"
872                  + Integer.toHexString(resid) + " in package "
873                  + packageName, e);
874        }
875        return null;
876    }
877
878    @Override
879    public XmlResourceParser getXml(String packageName, int resid,
880                                    ApplicationInfo appInfo) {
881        if (appInfo == null) {
882            try {
883                appInfo = getApplicationInfo(packageName, 0);
884            } catch (NameNotFoundException e) {
885                return null;
886            }
887        }
888        try {
889            Resources r = getResourcesForApplication(appInfo);
890            return r.getXml(resid);
891        } catch (RuntimeException e) {
892            // If an exception was thrown, fall through to return
893            // default icon.
894            Log.w("PackageManager", "Failure retrieving xml 0x"
895                  + Integer.toHexString(resid) + " in package "
896                  + packageName, e);
897        } catch (NameNotFoundException e) {
898            Log.w("PackageManager", "Failure retrieving resources for "
899                  + appInfo.packageName);
900        }
901        return null;
902    }
903
904    @Override
905    public CharSequence getApplicationLabel(ApplicationInfo info) {
906        return info.loadLabel(this);
907    }
908
909    @Override
910    public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
911                               String installerPackageName) {
912        try {
913            mPM.installPackage(packageURI, observer, flags, installerPackageName);
914        } catch (RemoteException e) {
915            // Should never happen!
916        }
917    }
918
919    @Override
920    public void setInstallerPackageName(String targetPackage,
921            String installerPackageName) {
922        try {
923            mPM.setInstallerPackageName(targetPackage, installerPackageName);
924        } catch (RemoteException e) {
925            // Should never happen!
926        }
927    }
928
929    @Override
930    public void movePackage(String packageName, IPackageMoveObserver observer, int flags) {
931        try {
932            mPM.movePackage(packageName, observer, flags);
933        } catch (RemoteException e) {
934            // Should never happen!
935        }
936    }
937
938    @Override
939    public String getInstallerPackageName(String packageName) {
940        try {
941            return mPM.getInstallerPackageName(packageName);
942        } catch (RemoteException e) {
943            // Should never happen!
944        }
945        return null;
946    }
947
948    @Override
949    public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
950        try {
951            mPM.deletePackage(packageName, observer, flags);
952        } catch (RemoteException e) {
953            // Should never happen!
954        }
955    }
956    @Override
957    public void clearApplicationUserData(String packageName,
958                                         IPackageDataObserver observer) {
959        try {
960            mPM.clearApplicationUserData(packageName, observer);
961        } catch (RemoteException e) {
962            // Should never happen!
963        }
964    }
965    @Override
966    public void deleteApplicationCacheFiles(String packageName,
967                                            IPackageDataObserver observer) {
968        try {
969            mPM.deleteApplicationCacheFiles(packageName, observer);
970        } catch (RemoteException e) {
971            // Should never happen!
972        }
973    }
974    @Override
975    public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
976        try {
977            mPM.freeStorageAndNotify(idealStorageSize, observer);
978        } catch (RemoteException e) {
979            // Should never happen!
980        }
981    }
982
983    @Override
984    public void freeStorage(long freeStorageSize, IntentSender pi) {
985        try {
986            mPM.freeStorage(freeStorageSize, pi);
987        } catch (RemoteException e) {
988            // Should never happen!
989        }
990    }
991
992    @Override
993    public void getPackageSizeInfo(String packageName,
994                                   IPackageStatsObserver observer) {
995        try {
996            mPM.getPackageSizeInfo(packageName, observer);
997        } catch (RemoteException e) {
998            // Should never happen!
999        }
1000    }
1001    @Override
1002    public void addPackageToPreferred(String packageName) {
1003        try {
1004            mPM.addPackageToPreferred(packageName);
1005        } catch (RemoteException e) {
1006            // Should never happen!
1007        }
1008    }
1009
1010    @Override
1011    public void removePackageFromPreferred(String packageName) {
1012        try {
1013            mPM.removePackageFromPreferred(packageName);
1014        } catch (RemoteException e) {
1015            // Should never happen!
1016        }
1017    }
1018
1019    @Override
1020    public List<PackageInfo> getPreferredPackages(int flags) {
1021        try {
1022            return mPM.getPreferredPackages(flags);
1023        } catch (RemoteException e) {
1024            // Should never happen!
1025        }
1026        return new ArrayList<PackageInfo>();
1027    }
1028
1029    @Override
1030    public void addPreferredActivity(IntentFilter filter,
1031                                     int match, ComponentName[] set, ComponentName activity) {
1032        try {
1033            mPM.addPreferredActivity(filter, match, set, activity);
1034        } catch (RemoteException e) {
1035            // Should never happen!
1036        }
1037    }
1038
1039    @Override
1040    public void replacePreferredActivity(IntentFilter filter,
1041                                         int match, ComponentName[] set, ComponentName activity) {
1042        try {
1043            mPM.replacePreferredActivity(filter, match, set, activity);
1044        } catch (RemoteException e) {
1045            // Should never happen!
1046        }
1047    }
1048
1049    @Override
1050    public void clearPackagePreferredActivities(String packageName) {
1051        try {
1052            mPM.clearPackagePreferredActivities(packageName);
1053        } catch (RemoteException e) {
1054            // Should never happen!
1055        }
1056    }
1057
1058    @Override
1059    public int getPreferredActivities(List<IntentFilter> outFilters,
1060                                      List<ComponentName> outActivities, String packageName) {
1061        try {
1062            return mPM.getPreferredActivities(outFilters, outActivities, packageName);
1063        } catch (RemoteException e) {
1064            // Should never happen!
1065        }
1066        return 0;
1067    }
1068
1069    @Override
1070    public void setComponentEnabledSetting(ComponentName componentName,
1071                                           int newState, int flags) {
1072        try {
1073            mPM.setComponentEnabledSetting(componentName, newState, flags);
1074        } catch (RemoteException e) {
1075            // Should never happen!
1076        }
1077    }
1078
1079    @Override
1080    public int getComponentEnabledSetting(ComponentName componentName) {
1081        try {
1082            return mPM.getComponentEnabledSetting(componentName);
1083        } catch (RemoteException e) {
1084            // Should never happen!
1085        }
1086        return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
1087    }
1088
1089    @Override
1090    public void setApplicationEnabledSetting(String packageName,
1091                                             int newState, int flags) {
1092        try {
1093            mPM.setApplicationEnabledSetting(packageName, newState, flags);
1094        } catch (RemoteException e) {
1095            // Should never happen!
1096        }
1097    }
1098
1099    @Override
1100    public int getApplicationEnabledSetting(String packageName) {
1101        try {
1102            return mPM.getApplicationEnabledSetting(packageName);
1103        } catch (RemoteException e) {
1104            // Should never happen!
1105        }
1106        return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
1107    }
1108
1109    // Multi-user support
1110
1111    /**
1112     * @hide
1113     */
1114    @Override
1115    public UserInfo createUser(String name, int flags) {
1116        // TODO
1117        return null;
1118    }
1119
1120    /**
1121     * @hide
1122     */
1123    @Override
1124    public List<UserInfo> getUsers() {
1125        // TODO:
1126        // Dummy code, always returns just the primary user
1127        ArrayList<UserInfo> users = new ArrayList<UserInfo>();
1128        UserInfo primary = new UserInfo(0, "Root!",
1129                UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
1130        users.add(primary);
1131        return users;
1132    }
1133
1134    /**
1135     * @hide
1136     */
1137    @Override
1138    public boolean removeUser(int id) {
1139        // TODO:
1140        return false;
1141    }
1142
1143    /**
1144     * @hide
1145     */
1146    @Override
1147    public void updateUserName(int id, String name) {
1148        // TODO:
1149    }
1150
1151    /**
1152     * @hide
1153     */
1154    @Override
1155    public void updateUserFlags(int id, int flags) {
1156        // TODO:
1157    }
1158
1159    private final ContextImpl mContext;
1160    private final IPackageManager mPM;
1161
1162    private static final Object sSync = new Object();
1163    private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
1164            = new HashMap<ResourceName, WeakReference<Drawable> >();
1165    private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
1166            = new HashMap<ResourceName, WeakReference<CharSequence> >();
1167}
1168