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