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