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