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