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