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