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