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