ApplicationPackageManager.java revision 50a05454795c93ac483f5cb6819e74cb17be1b5b
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.annotation.DrawableRes;
20import android.annotation.NonNull;
21import android.annotation.Nullable;
22import android.annotation.StringRes;
23import android.annotation.XmlRes;
24import android.content.ComponentName;
25import android.content.ContentResolver;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.content.IntentSender;
29import android.content.pm.ActivityInfo;
30import android.content.pm.ApplicationInfo;
31import android.content.pm.ComponentInfo;
32import android.content.pm.ContainerEncryptionParams;
33import android.content.pm.FeatureInfo;
34import android.content.pm.IPackageDataObserver;
35import android.content.pm.IPackageDeleteObserver;
36import android.content.pm.IPackageInstallObserver;
37import android.content.pm.IPackageManager;
38import android.content.pm.IPackageMoveObserver;
39import android.content.pm.IPackageStatsObserver;
40import android.content.pm.InstrumentationInfo;
41import android.content.pm.IntentFilterVerificationInfo;
42import android.content.pm.KeySet;
43import android.content.pm.ManifestDigest;
44import android.content.pm.PackageInfo;
45import android.content.pm.PackageInstaller;
46import android.content.pm.PackageItemInfo;
47import android.content.pm.PackageManager;
48import android.content.pm.ParceledListSlice;
49import android.content.pm.PermissionGroupInfo;
50import android.content.pm.PermissionInfo;
51import android.content.pm.ProviderInfo;
52import android.content.pm.ResolveInfo;
53import android.content.pm.ServiceInfo;
54import android.content.pm.UserInfo;
55import android.content.pm.VerificationParams;
56import android.content.pm.VerifierDeviceIdentity;
57import android.content.res.Resources;
58import android.content.res.XmlResourceParser;
59import android.graphics.Bitmap;
60import android.graphics.Canvas;
61import android.graphics.Rect;
62import android.graphics.drawable.BitmapDrawable;
63import android.graphics.drawable.Drawable;
64import android.net.Uri;
65import android.os.Bundle;
66import android.os.Handler;
67import android.os.Looper;
68import android.os.Message;
69import android.os.Process;
70import android.os.RemoteException;
71import android.os.SystemProperties;
72import android.os.UserHandle;
73import android.os.UserManager;
74import android.os.storage.StorageManager;
75import android.os.storage.VolumeInfo;
76import android.util.ArrayMap;
77import android.util.Log;
78import android.view.Display;
79
80import dalvik.system.VMRuntime;
81
82import com.android.internal.annotations.GuardedBy;
83import com.android.internal.os.SomeArgs;
84import com.android.internal.util.Preconditions;
85import com.android.internal.util.UserIcons;
86
87import java.lang.ref.WeakReference;
88import java.util.ArrayList;
89import java.util.Iterator;
90import java.util.List;
91import java.util.Objects;
92
93/*package*/
94final class ApplicationPackageManager extends PackageManager {
95    private static final String TAG = "ApplicationPackageManager";
96    private final static boolean DEBUG_ICONS = false;
97
98    // Default flags to use with PackageManager when no flags are given.
99    private final static int sDefaultFlags = PackageManager.GET_SHARED_LIBRARY_FILES;
100
101    private final Object mLock = new Object();
102
103    @GuardedBy("mLock")
104    private UserManager mUserManager;
105    @GuardedBy("mLock")
106    private PackageInstaller mInstaller;
107
108    @GuardedBy("mDelegates")
109    private final ArrayList<MoveCallbackDelegate> mDelegates = new ArrayList<>();
110
111    UserManager getUserManager() {
112        synchronized (mLock) {
113            if (mUserManager == null) {
114                mUserManager = UserManager.get(mContext);
115            }
116            return mUserManager;
117        }
118    }
119
120    @Override
121    public PackageInfo getPackageInfo(String packageName, int flags)
122            throws NameNotFoundException {
123        try {
124            PackageInfo pi = mPM.getPackageInfo(packageName, flags, mContext.getUserId());
125            if (pi != null) {
126                return pi;
127            }
128        } catch (RemoteException e) {
129            throw new RuntimeException("Package manager has died", e);
130        }
131
132        throw new NameNotFoundException(packageName);
133    }
134
135    @Override
136    public String[] currentToCanonicalPackageNames(String[] names) {
137        try {
138            return mPM.currentToCanonicalPackageNames(names);
139        } catch (RemoteException e) {
140            throw new RuntimeException("Package manager has died", e);
141        }
142    }
143
144    @Override
145    public String[] canonicalToCurrentPackageNames(String[] names) {
146        try {
147            return mPM.canonicalToCurrentPackageNames(names);
148        } catch (RemoteException e) {
149            throw new RuntimeException("Package manager has died", e);
150        }
151    }
152
153    @Override
154    public Intent getLaunchIntentForPackage(String packageName) {
155        // First see if the package has an INFO activity; the existence of
156        // such an activity is implied to be the desired front-door for the
157        // overall package (such as if it has multiple launcher entries).
158        Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
159        intentToResolve.addCategory(Intent.CATEGORY_INFO);
160        intentToResolve.setPackage(packageName);
161        List<ResolveInfo> ris = queryIntentActivities(intentToResolve, 0);
162
163        // Otherwise, try to find a main launcher activity.
164        if (ris == null || ris.size() <= 0) {
165            // reuse the intent instance
166            intentToResolve.removeCategory(Intent.CATEGORY_INFO);
167            intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
168            intentToResolve.setPackage(packageName);
169            ris = queryIntentActivities(intentToResolve, 0);
170        }
171        if (ris == null || ris.size() <= 0) {
172            return null;
173        }
174        Intent intent = new Intent(intentToResolve);
175        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
176        intent.setClassName(ris.get(0).activityInfo.packageName,
177                ris.get(0).activityInfo.name);
178        return intent;
179    }
180
181    @Override
182    public Intent getLeanbackLaunchIntentForPackage(String packageName) {
183        // Try to find a main leanback_launcher activity.
184        Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
185        intentToResolve.addCategory(Intent.CATEGORY_LEANBACK_LAUNCHER);
186        intentToResolve.setPackage(packageName);
187        List<ResolveInfo> ris = queryIntentActivities(intentToResolve, 0);
188
189        if (ris == null || ris.size() <= 0) {
190            return null;
191        }
192        Intent intent = new Intent(intentToResolve);
193        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
194        intent.setClassName(ris.get(0).activityInfo.packageName,
195                ris.get(0).activityInfo.name);
196        return intent;
197    }
198
199    @Override
200    public int[] getPackageGids(String packageName)
201            throws NameNotFoundException {
202        try {
203            int[] gids = mPM.getPackageGids(packageName, mContext.getUserId());
204            if (gids != null) {
205                return gids;
206            }
207        } catch (RemoteException e) {
208            throw new RuntimeException("Package manager has died", e);
209        }
210
211        throw new NameNotFoundException(packageName);
212    }
213
214    @Override
215    public int getPackageUid(String packageName, int userHandle)
216            throws NameNotFoundException {
217        try {
218            int uid = mPM.getPackageUid(packageName, userHandle);
219            if (uid >= 0) {
220                return uid;
221            }
222        } catch (RemoteException e) {
223            throw new RuntimeException("Package manager has died", e);
224        }
225
226        throw new NameNotFoundException(packageName);
227    }
228
229    @Override
230    public PermissionInfo getPermissionInfo(String name, int flags)
231            throws NameNotFoundException {
232        try {
233            PermissionInfo pi = mPM.getPermissionInfo(name, flags);
234            if (pi != null) {
235                return pi;
236            }
237        } catch (RemoteException e) {
238            throw new RuntimeException("Package manager has died", e);
239        }
240
241        throw new NameNotFoundException(name);
242    }
243
244    @Override
245    public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
246            throws NameNotFoundException {
247        try {
248            List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags);
249            if (pi != null) {
250                return pi;
251            }
252        } catch (RemoteException e) {
253            throw new RuntimeException("Package manager has died", e);
254        }
255
256        throw new NameNotFoundException(group);
257    }
258
259    @Override
260    public PermissionGroupInfo getPermissionGroupInfo(String name,
261                                                      int flags) throws NameNotFoundException {
262        try {
263            PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags);
264            if (pgi != null) {
265                return pgi;
266            }
267        } catch (RemoteException e) {
268            throw new RuntimeException("Package manager has died", e);
269        }
270
271        throw new NameNotFoundException(name);
272    }
273
274    @Override
275    public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
276        try {
277            return mPM.getAllPermissionGroups(flags);
278        } catch (RemoteException e) {
279            throw new RuntimeException("Package manager has died", e);
280        }
281    }
282
283    @Override
284    public ApplicationInfo getApplicationInfo(String packageName, int flags)
285            throws NameNotFoundException {
286        try {
287            ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags, mContext.getUserId());
288            if (ai != null) {
289                // This is a temporary hack. Callers must use
290                // createPackageContext(packageName).getApplicationInfo() to
291                // get the right paths.
292                maybeAdjustApplicationInfo(ai);
293                return ai;
294            }
295        } catch (RemoteException e) {
296            throw new RuntimeException("Package manager has died", e);
297        }
298
299        throw new NameNotFoundException(packageName);
300    }
301
302    private static void maybeAdjustApplicationInfo(ApplicationInfo info) {
303        // If we're dealing with a multi-arch application that has both
304        // 32 and 64 bit shared libraries, we might need to choose the secondary
305        // depending on what the current runtime's instruction set is.
306        if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) {
307            final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
308
309            // Get the instruction set that the libraries of secondary Abi is supported.
310            // In presence of a native bridge this might be different than the one secondary Abi used.
311            String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
312            final String secondaryDexCodeIsa = SystemProperties.get("ro.dalvik.vm.isa." + secondaryIsa);
313            secondaryIsa = secondaryDexCodeIsa.isEmpty() ? secondaryIsa : secondaryDexCodeIsa;
314
315            // If the runtimeIsa is the same as the primary isa, then we do nothing.
316            // Everything will be set up correctly because info.nativeLibraryDir will
317            // correspond to the right ISA.
318            if (runtimeIsa.equals(secondaryIsa)) {
319                info.nativeLibraryDir = info.secondaryNativeLibraryDir;
320            }
321        }
322    }
323
324
325    @Override
326    public ActivityInfo getActivityInfo(ComponentName className, int flags)
327            throws NameNotFoundException {
328        try {
329            ActivityInfo ai = mPM.getActivityInfo(className, flags, mContext.getUserId());
330            if (ai != null) {
331                return ai;
332            }
333        } catch (RemoteException e) {
334            throw new RuntimeException("Package manager has died", e);
335        }
336
337        throw new NameNotFoundException(className.toString());
338    }
339
340    @Override
341    public ActivityInfo getReceiverInfo(ComponentName className, int flags)
342            throws NameNotFoundException {
343        try {
344            ActivityInfo ai = mPM.getReceiverInfo(className, flags, mContext.getUserId());
345            if (ai != null) {
346                return ai;
347            }
348        } catch (RemoteException e) {
349            throw new RuntimeException("Package manager has died", e);
350        }
351
352        throw new NameNotFoundException(className.toString());
353    }
354
355    @Override
356    public ServiceInfo getServiceInfo(ComponentName className, int flags)
357            throws NameNotFoundException {
358        try {
359            ServiceInfo si = mPM.getServiceInfo(className, flags, mContext.getUserId());
360            if (si != null) {
361                return si;
362            }
363        } catch (RemoteException e) {
364            throw new RuntimeException("Package manager has died", e);
365        }
366
367        throw new NameNotFoundException(className.toString());
368    }
369
370    @Override
371    public ProviderInfo getProviderInfo(ComponentName className, int flags)
372            throws NameNotFoundException {
373        try {
374            ProviderInfo pi = mPM.getProviderInfo(className, flags, mContext.getUserId());
375            if (pi != null) {
376                return pi;
377            }
378        } catch (RemoteException e) {
379            throw new RuntimeException("Package manager has died", e);
380        }
381
382        throw new NameNotFoundException(className.toString());
383    }
384
385    @Override
386    public String[] getSystemSharedLibraryNames() {
387        try {
388            return mPM.getSystemSharedLibraryNames();
389        } catch (RemoteException e) {
390            throw new RuntimeException("Package manager has died", e);
391        }
392    }
393
394    @Override
395    public FeatureInfo[] getSystemAvailableFeatures() {
396        try {
397            return mPM.getSystemAvailableFeatures();
398        } catch (RemoteException e) {
399            throw new RuntimeException("Package manager has died", e);
400        }
401    }
402
403    @Override
404    public boolean hasSystemFeature(String name) {
405        try {
406            return mPM.hasSystemFeature(name);
407        } catch (RemoteException e) {
408            throw new RuntimeException("Package manager has died", e);
409        }
410    }
411
412    @Override
413    public int checkPermission(String permName, String pkgName) {
414        try {
415            return mPM.checkPermission(permName, pkgName, mContext.getUserId());
416        } catch (RemoteException e) {
417            throw new RuntimeException("Package manager has died", e);
418        }
419    }
420
421    @Override
422    public boolean addPermission(PermissionInfo info) {
423        try {
424            return mPM.addPermission(info);
425        } catch (RemoteException e) {
426            throw new RuntimeException("Package manager has died", e);
427        }
428    }
429
430    @Override
431    public boolean addPermissionAsync(PermissionInfo info) {
432        try {
433            return mPM.addPermissionAsync(info);
434        } catch (RemoteException e) {
435            throw new RuntimeException("Package manager has died", e);
436        }
437    }
438
439    @Override
440    public void removePermission(String name) {
441        try {
442            mPM.removePermission(name);
443        } catch (RemoteException e) {
444            throw new RuntimeException("Package manager has died", e);
445        }
446    }
447
448    @Override
449    public void grantPermission(String packageName, String permissionName, UserHandle user) {
450        try {
451            mPM.grantPermission(packageName, permissionName, user.getIdentifier());
452        } catch (RemoteException e) {
453            throw new RuntimeException("Package manager has died", e);
454        }
455    }
456
457    @Override
458    public void revokePermission(String packageName, String permissionName, UserHandle user) {
459        try {
460            mPM.revokePermission(packageName, permissionName, user.getIdentifier());
461        } catch (RemoteException e) {
462            throw new RuntimeException("Package manager has died", e);
463        }
464    }
465
466    @Override
467    public int checkSignatures(String pkg1, String pkg2) {
468        try {
469            return mPM.checkSignatures(pkg1, pkg2);
470        } catch (RemoteException e) {
471            throw new RuntimeException("Package manager has died", e);
472        }
473    }
474
475    @Override
476    public int checkSignatures(int uid1, int uid2) {
477        try {
478            return mPM.checkUidSignatures(uid1, uid2);
479        } catch (RemoteException e) {
480            throw new RuntimeException("Package manager has died", e);
481        }
482    }
483
484    @Override
485    public String[] getPackagesForUid(int uid) {
486        try {
487            return mPM.getPackagesForUid(uid);
488        } catch (RemoteException e) {
489            throw new RuntimeException("Package manager has died", e);
490        }
491    }
492
493    @Override
494    public String getNameForUid(int uid) {
495        try {
496            return mPM.getNameForUid(uid);
497        } catch (RemoteException e) {
498            throw new RuntimeException("Package manager has died", e);
499        }
500    }
501
502    @Override
503    public int getUidForSharedUser(String sharedUserName)
504            throws NameNotFoundException {
505        try {
506            int uid = mPM.getUidForSharedUser(sharedUserName);
507            if(uid != -1) {
508                return uid;
509            }
510        } catch (RemoteException e) {
511            throw new RuntimeException("Package manager has died", e);
512        }
513        throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
514    }
515
516    @SuppressWarnings("unchecked")
517    @Override
518    public List<PackageInfo> getInstalledPackages(int flags) {
519        return getInstalledPackages(flags, mContext.getUserId());
520    }
521
522    /** @hide */
523    @Override
524    public List<PackageInfo> getInstalledPackages(int flags, int userId) {
525        try {
526            ParceledListSlice<PackageInfo> slice = mPM.getInstalledPackages(flags, userId);
527            return slice.getList();
528        } catch (RemoteException e) {
529            throw new RuntimeException("Package manager has died", e);
530        }
531    }
532
533    @SuppressWarnings("unchecked")
534    @Override
535    public List<PackageInfo> getPackagesHoldingPermissions(
536            String[] permissions, int flags) {
537        final int userId = mContext.getUserId();
538        try {
539            ParceledListSlice<PackageInfo> slice = mPM.getPackagesHoldingPermissions(
540                    permissions, flags, userId);
541            return slice.getList();
542        } catch (RemoteException e) {
543            throw new RuntimeException("Package manager has died", e);
544        }
545    }
546
547    @SuppressWarnings("unchecked")
548    @Override
549    public List<ApplicationInfo> getInstalledApplications(int flags) {
550        final int userId = mContext.getUserId();
551        try {
552            ParceledListSlice<ApplicationInfo> slice = mPM.getInstalledApplications(flags, userId);
553            return slice.getList();
554        } catch (RemoteException e) {
555            throw new RuntimeException("Package manager has died", e);
556        }
557    }
558
559    @Override
560    public ResolveInfo resolveActivity(Intent intent, int flags) {
561        return resolveActivityAsUser(intent, flags, mContext.getUserId());
562    }
563
564    @Override
565    public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {
566        try {
567            return mPM.resolveIntent(
568                intent,
569                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
570                flags,
571                userId);
572        } catch (RemoteException e) {
573            throw new RuntimeException("Package manager has died", e);
574        }
575    }
576
577    @Override
578    public List<ResolveInfo> queryIntentActivities(Intent intent,
579                                                   int flags) {
580        return queryIntentActivitiesAsUser(intent, flags, mContext.getUserId());
581    }
582
583    /** @hide Same as above but for a specific user */
584    @Override
585    public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
586                                                   int flags, int userId) {
587        try {
588            return mPM.queryIntentActivities(
589                intent,
590                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
591                flags,
592                userId);
593        } catch (RemoteException e) {
594            throw new RuntimeException("Package manager has died", e);
595        }
596    }
597
598    @Override
599    public List<ResolveInfo> queryIntentActivityOptions(
600        ComponentName caller, Intent[] specifics, Intent intent,
601        int flags) {
602        final ContentResolver resolver = mContext.getContentResolver();
603
604        String[] specificTypes = null;
605        if (specifics != null) {
606            final int N = specifics.length;
607            for (int i=0; i<N; i++) {
608                Intent sp = specifics[i];
609                if (sp != null) {
610                    String t = sp.resolveTypeIfNeeded(resolver);
611                    if (t != null) {
612                        if (specificTypes == null) {
613                            specificTypes = new String[N];
614                        }
615                        specificTypes[i] = t;
616                    }
617                }
618            }
619        }
620
621        try {
622            return mPM.queryIntentActivityOptions(caller, specifics,
623                                                  specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
624                                                  flags, mContext.getUserId());
625        } catch (RemoteException e) {
626            throw new RuntimeException("Package manager has died", e);
627        }
628    }
629
630    /**
631     * @hide
632     */
633    @Override
634    public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags, int userId) {
635        try {
636            return mPM.queryIntentReceivers(
637                intent,
638                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
639                flags,
640                userId);
641        } catch (RemoteException e) {
642            throw new RuntimeException("Package manager has died", e);
643        }
644    }
645
646    @Override
647    public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
648        return queryBroadcastReceivers(intent, flags, mContext.getUserId());
649    }
650
651    @Override
652    public ResolveInfo resolveService(Intent intent, int flags) {
653        try {
654            return mPM.resolveService(
655                intent,
656                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
657                flags,
658                mContext.getUserId());
659        } catch (RemoteException e) {
660            throw new RuntimeException("Package manager has died", e);
661        }
662    }
663
664    @Override
665    public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
666        try {
667            return mPM.queryIntentServices(
668                intent,
669                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
670                flags,
671                userId);
672        } catch (RemoteException e) {
673            throw new RuntimeException("Package manager has died", e);
674        }
675    }
676
677    @Override
678    public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
679        return queryIntentServicesAsUser(intent, flags, mContext.getUserId());
680    }
681
682    @Override
683    public List<ResolveInfo> queryIntentContentProvidersAsUser(
684            Intent intent, int flags, int userId) {
685        try {
686            return mPM.queryIntentContentProviders(intent,
687                    intent.resolveTypeIfNeeded(mContext.getContentResolver()), flags, userId);
688        } catch (RemoteException e) {
689            throw new RuntimeException("Package manager has died", e);
690        }
691    }
692
693    @Override
694    public List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) {
695        return queryIntentContentProvidersAsUser(intent, flags, mContext.getUserId());
696    }
697
698    @Override
699    public ProviderInfo resolveContentProvider(String name, int flags) {
700        return resolveContentProviderAsUser(name, flags, mContext.getUserId());
701    }
702
703    /** @hide **/
704    @Override
705    public ProviderInfo resolveContentProviderAsUser(String name, int flags, int userId) {
706        try {
707            return mPM.resolveContentProvider(name, flags, userId);
708        } catch (RemoteException e) {
709            throw new RuntimeException("Package manager has died", e);
710        }
711    }
712
713    @Override
714    public List<ProviderInfo> queryContentProviders(String processName,
715                                                    int uid, int flags) {
716        try {
717            return mPM.queryContentProviders(processName, uid, flags);
718        } catch (RemoteException e) {
719            throw new RuntimeException("Package manager has died", e);
720        }
721    }
722
723    @Override
724    public InstrumentationInfo getInstrumentationInfo(
725        ComponentName className, int flags)
726            throws NameNotFoundException {
727        try {
728            InstrumentationInfo ii = mPM.getInstrumentationInfo(
729                className, flags);
730            if (ii != null) {
731                return ii;
732            }
733        } catch (RemoteException e) {
734            throw new RuntimeException("Package manager has died", e);
735        }
736
737        throw new NameNotFoundException(className.toString());
738    }
739
740    @Override
741    public List<InstrumentationInfo> queryInstrumentation(
742        String targetPackage, int flags) {
743        try {
744            return mPM.queryInstrumentation(targetPackage, flags);
745        } catch (RemoteException e) {
746            throw new RuntimeException("Package manager has died", e);
747        }
748    }
749
750    @Nullable
751    @Override
752    public Drawable getDrawable(String packageName, @DrawableRes int resId,
753            @Nullable ApplicationInfo appInfo) {
754        final ResourceName name = new ResourceName(packageName, resId);
755        final Drawable cachedIcon = getCachedIcon(name);
756        if (cachedIcon != null) {
757            return cachedIcon;
758        }
759
760        if (appInfo == null) {
761            try {
762                appInfo = getApplicationInfo(packageName, sDefaultFlags);
763            } catch (NameNotFoundException e) {
764                return null;
765            }
766        }
767
768        if (resId != 0) {
769            try {
770                final Resources r = getResourcesForApplication(appInfo);
771                final Drawable dr = r.getDrawable(resId, null);
772                if (dr != null) {
773                    putCachedIcon(name, dr);
774                }
775
776                if (false) {
777                    RuntimeException e = new RuntimeException("here");
778                    e.fillInStackTrace();
779                    Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resId)
780                                    + " from package " + packageName
781                                    + ": app scale=" + r.getCompatibilityInfo().applicationScale
782                                    + ", caller scale=" + mContext.getResources()
783                                    .getCompatibilityInfo().applicationScale,
784                            e);
785                }
786                if (DEBUG_ICONS) {
787                    Log.v(TAG, "Getting drawable 0x"
788                            + Integer.toHexString(resId) + " from " + r
789                            + ": " + dr);
790                }
791                return dr;
792            } catch (NameNotFoundException e) {
793                Log.w("PackageManager", "Failure retrieving resources for "
794                        + appInfo.packageName);
795            } catch (Resources.NotFoundException e) {
796                Log.w("PackageManager", "Failure retrieving resources for "
797                        + appInfo.packageName + ": " + e.getMessage());
798            } catch (Exception e) {
799                // If an exception was thrown, fall through to return
800                // default icon.
801                Log.w("PackageManager", "Failure retrieving icon 0x"
802                        + Integer.toHexString(resId) + " in package "
803                        + packageName, e);
804            }
805        }
806
807        return null;
808    }
809
810    @Override public Drawable getActivityIcon(ComponentName activityName)
811            throws NameNotFoundException {
812        return getActivityInfo(activityName, sDefaultFlags).loadIcon(this);
813    }
814
815    @Override public Drawable getActivityIcon(Intent intent)
816            throws NameNotFoundException {
817        if (intent.getComponent() != null) {
818            return getActivityIcon(intent.getComponent());
819        }
820
821        ResolveInfo info = resolveActivity(
822            intent, PackageManager.MATCH_DEFAULT_ONLY);
823        if (info != null) {
824            return info.activityInfo.loadIcon(this);
825        }
826
827        throw new NameNotFoundException(intent.toUri(0));
828    }
829
830    @Override public Drawable getDefaultActivityIcon() {
831        return Resources.getSystem().getDrawable(
832            com.android.internal.R.drawable.sym_def_app_icon);
833    }
834
835    @Override public Drawable getApplicationIcon(ApplicationInfo info) {
836        return info.loadIcon(this);
837    }
838
839    @Override public Drawable getApplicationIcon(String packageName)
840            throws NameNotFoundException {
841        return getApplicationIcon(getApplicationInfo(packageName, sDefaultFlags));
842    }
843
844    @Override
845    public Drawable getActivityBanner(ComponentName activityName)
846            throws NameNotFoundException {
847        return getActivityInfo(activityName, sDefaultFlags).loadBanner(this);
848    }
849
850    @Override
851    public Drawable getActivityBanner(Intent intent)
852            throws NameNotFoundException {
853        if (intent.getComponent() != null) {
854            return getActivityBanner(intent.getComponent());
855        }
856
857        ResolveInfo info = resolveActivity(
858                intent, PackageManager.MATCH_DEFAULT_ONLY);
859        if (info != null) {
860            return info.activityInfo.loadBanner(this);
861        }
862
863        throw new NameNotFoundException(intent.toUri(0));
864    }
865
866    @Override
867    public Drawable getApplicationBanner(ApplicationInfo info) {
868        return info.loadBanner(this);
869    }
870
871    @Override
872    public Drawable getApplicationBanner(String packageName)
873            throws NameNotFoundException {
874        return getApplicationBanner(getApplicationInfo(packageName, sDefaultFlags));
875    }
876
877    @Override
878    public Drawable getActivityLogo(ComponentName activityName)
879            throws NameNotFoundException {
880        return getActivityInfo(activityName, sDefaultFlags).loadLogo(this);
881    }
882
883    @Override
884    public Drawable getActivityLogo(Intent intent)
885            throws NameNotFoundException {
886        if (intent.getComponent() != null) {
887            return getActivityLogo(intent.getComponent());
888        }
889
890        ResolveInfo info = resolveActivity(
891            intent, PackageManager.MATCH_DEFAULT_ONLY);
892        if (info != null) {
893            return info.activityInfo.loadLogo(this);
894        }
895
896        throw new NameNotFoundException(intent.toUri(0));
897    }
898
899    @Override
900    public Drawable getApplicationLogo(ApplicationInfo info) {
901        return info.loadLogo(this);
902    }
903
904    @Override
905    public Drawable getApplicationLogo(String packageName)
906            throws NameNotFoundException {
907        return getApplicationLogo(getApplicationInfo(packageName, sDefaultFlags));
908    }
909
910    @Override
911    public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
912        final int badgeResId = getBadgeResIdForUser(user.getIdentifier());
913        if (badgeResId == 0) {
914            return icon;
915        }
916        Drawable badgeIcon = getDrawable("system", badgeResId, null);
917        return getBadgedDrawable(icon, badgeIcon, null, true);
918    }
919
920    @Override
921    public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user,
922            Rect badgeLocation, int badgeDensity) {
923        Drawable badgeDrawable = getUserBadgeForDensity(user, badgeDensity);
924        if (badgeDrawable == null) {
925            return drawable;
926        }
927        return getBadgedDrawable(drawable, badgeDrawable, badgeLocation, true);
928    }
929
930    @Override
931    public Drawable getUserBadgeForDensity(UserHandle user, int density) {
932        UserInfo userInfo = getUserIfProfile(user.getIdentifier());
933        if (userInfo != null && userInfo.isManagedProfile()) {
934            if (density <= 0) {
935                density = mContext.getResources().getDisplayMetrics().densityDpi;
936            }
937            return Resources.getSystem().getDrawableForDensity(
938                    com.android.internal.R.drawable.ic_corp_badge, density);
939        }
940        return null;
941    }
942
943    @Override
944    public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
945        UserInfo userInfo = getUserIfProfile(user.getIdentifier());
946        if (userInfo != null && userInfo.isManagedProfile()) {
947            return Resources.getSystem().getString(
948                    com.android.internal.R.string.managed_profile_label_badge, label);
949        }
950        return label;
951    }
952
953    @Override
954    public Resources getResourcesForActivity(ComponentName activityName)
955            throws NameNotFoundException {
956        return getResourcesForApplication(
957            getActivityInfo(activityName, sDefaultFlags).applicationInfo);
958    }
959
960    @Override
961    public Resources getResourcesForApplication(@NonNull ApplicationInfo app)
962            throws NameNotFoundException {
963        if (app.packageName.equals("system")) {
964            return mContext.mMainThread.getSystemContext().getResources();
965        }
966        final boolean sameUid = (app.uid == Process.myUid());
967        final Resources r = mContext.mMainThread.getTopLevelResources(
968                sameUid ? app.sourceDir : app.publicSourceDir,
969                sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs,
970                app.resourceDirs, app.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
971                null, mContext.mPackageInfo);
972        if (r != null) {
973            return r;
974        }
975        throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
976    }
977
978    @Override
979    public Resources getResourcesForApplication(String appPackageName)
980            throws NameNotFoundException {
981        return getResourcesForApplication(
982            getApplicationInfo(appPackageName, sDefaultFlags));
983    }
984
985    /** @hide */
986    @Override
987    public Resources getResourcesForApplicationAsUser(String appPackageName, int userId)
988            throws NameNotFoundException {
989        if (userId < 0) {
990            throw new IllegalArgumentException(
991                    "Call does not support special user #" + userId);
992        }
993        if ("system".equals(appPackageName)) {
994            return mContext.mMainThread.getSystemContext().getResources();
995        }
996        try {
997            ApplicationInfo ai = mPM.getApplicationInfo(appPackageName, sDefaultFlags, userId);
998            if (ai != null) {
999                return getResourcesForApplication(ai);
1000            }
1001        } catch (RemoteException e) {
1002            throw new RuntimeException("Package manager has died", e);
1003        }
1004        throw new NameNotFoundException("Package " + appPackageName + " doesn't exist");
1005    }
1006
1007    int mCachedSafeMode = -1;
1008    @Override public boolean isSafeMode() {
1009        try {
1010            if (mCachedSafeMode < 0) {
1011                mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
1012            }
1013            return mCachedSafeMode != 0;
1014        } catch (RemoteException e) {
1015            throw new RuntimeException("Package manager has died", e);
1016        }
1017    }
1018
1019    static void configurationChanged() {
1020        synchronized (sSync) {
1021            sIconCache.clear();
1022            sStringCache.clear();
1023        }
1024    }
1025
1026    ApplicationPackageManager(ContextImpl context,
1027                              IPackageManager pm) {
1028        mContext = context;
1029        mPM = pm;
1030    }
1031
1032    @Nullable
1033    private Drawable getCachedIcon(@NonNull ResourceName name) {
1034        synchronized (sSync) {
1035            final WeakReference<Drawable.ConstantState> wr = sIconCache.get(name);
1036            if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
1037                                   + name + ": " + wr);
1038            if (wr != null) {   // we have the activity
1039                final Drawable.ConstantState state = wr.get();
1040                if (state != null) {
1041                    if (DEBUG_ICONS) {
1042                        Log.v(TAG, "Get cached drawable state for " + name + ": " + state);
1043                    }
1044                    // Note: It's okay here to not use the newDrawable(Resources) variant
1045                    //       of the API. The ConstantState comes from a drawable that was
1046                    //       originally created by passing the proper app Resources instance
1047                    //       which means the state should already contain the proper
1048                    //       resources specific information (like density.) See
1049                    //       BitmapDrawable.BitmapState for instance.
1050                    return state.newDrawable();
1051                }
1052                // our entry has been purged
1053                sIconCache.remove(name);
1054            }
1055        }
1056        return null;
1057    }
1058
1059    private void putCachedIcon(@NonNull ResourceName name, @NonNull Drawable dr) {
1060        synchronized (sSync) {
1061            sIconCache.put(name, new WeakReference<>(dr.getConstantState()));
1062            if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable state for " + name + ": " + dr);
1063        }
1064    }
1065
1066    static void handlePackageBroadcast(int cmd, String[] pkgList, boolean hasPkgInfo) {
1067        boolean immediateGc = false;
1068        if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
1069            immediateGc = true;
1070        }
1071        if (pkgList != null && (pkgList.length > 0)) {
1072            boolean needCleanup = false;
1073            for (String ssp : pkgList) {
1074                synchronized (sSync) {
1075                    for (int i=sIconCache.size()-1; i>=0; i--) {
1076                        ResourceName nm = sIconCache.keyAt(i);
1077                        if (nm.packageName.equals(ssp)) {
1078                            //Log.i(TAG, "Removing cached drawable for " + nm);
1079                            sIconCache.removeAt(i);
1080                            needCleanup = true;
1081                        }
1082                    }
1083                    for (int i=sStringCache.size()-1; i>=0; i--) {
1084                        ResourceName nm = sStringCache.keyAt(i);
1085                        if (nm.packageName.equals(ssp)) {
1086                            //Log.i(TAG, "Removing cached string for " + nm);
1087                            sStringCache.removeAt(i);
1088                            needCleanup = true;
1089                        }
1090                    }
1091                }
1092            }
1093            if (needCleanup || hasPkgInfo) {
1094                if (immediateGc) {
1095                    // Schedule an immediate gc.
1096                    Runtime.getRuntime().gc();
1097                } else {
1098                    ActivityThread.currentActivityThread().scheduleGcIdler();
1099                }
1100            }
1101        }
1102    }
1103
1104    private static final class ResourceName {
1105        final String packageName;
1106        final int iconId;
1107
1108        ResourceName(String _packageName, int _iconId) {
1109            packageName = _packageName;
1110            iconId = _iconId;
1111        }
1112
1113        ResourceName(ApplicationInfo aInfo, int _iconId) {
1114            this(aInfo.packageName, _iconId);
1115        }
1116
1117        ResourceName(ComponentInfo cInfo, int _iconId) {
1118            this(cInfo.applicationInfo.packageName, _iconId);
1119        }
1120
1121        ResourceName(ResolveInfo rInfo, int _iconId) {
1122            this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
1123        }
1124
1125        @Override
1126        public boolean equals(Object o) {
1127            if (this == o) return true;
1128            if (o == null || getClass() != o.getClass()) return false;
1129
1130            ResourceName that = (ResourceName) o;
1131
1132            if (iconId != that.iconId) return false;
1133            return !(packageName != null ?
1134                     !packageName.equals(that.packageName) : that.packageName != null);
1135
1136        }
1137
1138        @Override
1139        public int hashCode() {
1140            int result;
1141            result = packageName.hashCode();
1142            result = 31 * result + iconId;
1143            return result;
1144        }
1145
1146        @Override
1147        public String toString() {
1148            return "{ResourceName " + packageName + " / " + iconId + "}";
1149        }
1150    }
1151
1152    private CharSequence getCachedString(ResourceName name) {
1153        synchronized (sSync) {
1154            WeakReference<CharSequence> wr = sStringCache.get(name);
1155            if (wr != null) {   // we have the activity
1156                CharSequence cs = wr.get();
1157                if (cs != null) {
1158                    return cs;
1159                }
1160                // our entry has been purged
1161                sStringCache.remove(name);
1162            }
1163        }
1164        return null;
1165    }
1166
1167    private void putCachedString(ResourceName name, CharSequence cs) {
1168        synchronized (sSync) {
1169            sStringCache.put(name, new WeakReference<CharSequence>(cs));
1170        }
1171    }
1172
1173    @Override
1174    public CharSequence getText(String packageName, @StringRes int resid,
1175                                ApplicationInfo appInfo) {
1176        ResourceName name = new ResourceName(packageName, resid);
1177        CharSequence text = getCachedString(name);
1178        if (text != null) {
1179            return text;
1180        }
1181        if (appInfo == null) {
1182            try {
1183                appInfo = getApplicationInfo(packageName, sDefaultFlags);
1184            } catch (NameNotFoundException e) {
1185                return null;
1186            }
1187        }
1188        try {
1189            Resources r = getResourcesForApplication(appInfo);
1190            text = r.getText(resid);
1191            putCachedString(name, text);
1192            return text;
1193        } catch (NameNotFoundException e) {
1194            Log.w("PackageManager", "Failure retrieving resources for "
1195                  + appInfo.packageName);
1196        } catch (RuntimeException e) {
1197            // If an exception was thrown, fall through to return
1198            // default icon.
1199            Log.w("PackageManager", "Failure retrieving text 0x"
1200                  + Integer.toHexString(resid) + " in package "
1201                  + packageName, e);
1202        }
1203        return null;
1204    }
1205
1206    @Override
1207    public XmlResourceParser getXml(String packageName, @XmlRes int resid,
1208                                    ApplicationInfo appInfo) {
1209        if (appInfo == null) {
1210            try {
1211                appInfo = getApplicationInfo(packageName, sDefaultFlags);
1212            } catch (NameNotFoundException e) {
1213                return null;
1214            }
1215        }
1216        try {
1217            Resources r = getResourcesForApplication(appInfo);
1218            return r.getXml(resid);
1219        } catch (RuntimeException e) {
1220            // If an exception was thrown, fall through to return
1221            // default icon.
1222            Log.w("PackageManager", "Failure retrieving xml 0x"
1223                  + Integer.toHexString(resid) + " in package "
1224                  + packageName, e);
1225        } catch (NameNotFoundException e) {
1226            Log.w("PackageManager", "Failure retrieving resources for "
1227                  + appInfo.packageName);
1228        }
1229        return null;
1230    }
1231
1232    @Override
1233    public CharSequence getApplicationLabel(ApplicationInfo info) {
1234        return info.loadLabel(this);
1235    }
1236
1237    @Override
1238    public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
1239                               String installerPackageName) {
1240        final VerificationParams verificationParams = new VerificationParams(null, null,
1241                null, VerificationParams.NO_UID, null);
1242        installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
1243                installerPackageName, verificationParams, null);
1244    }
1245
1246    @Override
1247    public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
1248            int flags, String installerPackageName, Uri verificationURI,
1249            ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
1250        final VerificationParams verificationParams = new VerificationParams(verificationURI, null,
1251                null, VerificationParams.NO_UID, manifestDigest);
1252        installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
1253                installerPackageName, verificationParams, encryptionParams);
1254    }
1255
1256    @Override
1257    public void installPackageWithVerificationAndEncryption(Uri packageURI,
1258            IPackageInstallObserver observer, int flags, String installerPackageName,
1259            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
1260        installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
1261                installerPackageName, verificationParams, encryptionParams);
1262    }
1263
1264    @Override
1265    public void installPackage(Uri packageURI, PackageInstallObserver observer,
1266            int flags, String installerPackageName) {
1267        final VerificationParams verificationParams = new VerificationParams(null, null,
1268                null, VerificationParams.NO_UID, null);
1269        installCommon(packageURI, observer, flags, installerPackageName, verificationParams, null);
1270    }
1271
1272    @Override
1273    public void installPackageWithVerification(Uri packageURI,
1274            PackageInstallObserver observer, int flags, String installerPackageName,
1275            Uri verificationURI, ManifestDigest manifestDigest,
1276            ContainerEncryptionParams encryptionParams) {
1277        final VerificationParams verificationParams = new VerificationParams(verificationURI, null,
1278                null, VerificationParams.NO_UID, manifestDigest);
1279        installCommon(packageURI, observer, flags, installerPackageName, verificationParams,
1280                encryptionParams);
1281    }
1282
1283    @Override
1284    public void installPackageWithVerificationAndEncryption(Uri packageURI,
1285            PackageInstallObserver observer, int flags, String installerPackageName,
1286            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
1287        installCommon(packageURI, observer, flags, installerPackageName, verificationParams,
1288                encryptionParams);
1289    }
1290
1291    private void installCommon(Uri packageURI,
1292            PackageInstallObserver observer, int flags, String installerPackageName,
1293            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
1294        if (!"file".equals(packageURI.getScheme())) {
1295            throw new UnsupportedOperationException("Only file:// URIs are supported");
1296        }
1297        if (encryptionParams != null) {
1298            throw new UnsupportedOperationException("ContainerEncryptionParams not supported");
1299        }
1300
1301        final String originPath = packageURI.getPath();
1302        try {
1303            mPM.installPackage(originPath, observer.getBinder(), flags, installerPackageName,
1304                    verificationParams, null);
1305        } catch (RemoteException ignored) {
1306        }
1307    }
1308
1309    @Override
1310    public int installExistingPackage(String packageName)
1311            throws NameNotFoundException {
1312        try {
1313            int res = mPM.installExistingPackageAsUser(packageName, UserHandle.myUserId());
1314            if (res == INSTALL_FAILED_INVALID_URI) {
1315                throw new NameNotFoundException("Package " + packageName + " doesn't exist");
1316            }
1317            return res;
1318        } catch (RemoteException e) {
1319            // Should never happen!
1320            throw new NameNotFoundException("Package " + packageName + " doesn't exist");
1321        }
1322    }
1323
1324    @Override
1325    public void verifyPendingInstall(int id, int response) {
1326        try {
1327            mPM.verifyPendingInstall(id, response);
1328        } catch (RemoteException e) {
1329            // Should never happen!
1330        }
1331    }
1332
1333    @Override
1334    public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
1335            long millisecondsToDelay) {
1336        try {
1337            mPM.extendVerificationTimeout(id, verificationCodeAtTimeout, millisecondsToDelay);
1338        } catch (RemoteException e) {
1339            // Should never happen!
1340        }
1341    }
1342
1343    @Override
1344    public void verifyIntentFilter(int id, int verificationCode, List<String> outFailedDomains) {
1345        try {
1346            mPM.verifyIntentFilter(id, verificationCode, outFailedDomains);
1347        } catch (RemoteException e) {
1348            // Should never happen!
1349        }
1350    }
1351
1352    @Override
1353    public int getIntentVerificationStatus(String packageName, int userId) {
1354        try {
1355            return mPM.getIntentVerificationStatus(packageName, userId);
1356        } catch (RemoteException e) {
1357            // Should never happen!
1358            return PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
1359        }
1360    }
1361
1362    @Override
1363    public boolean updateIntentVerificationStatus(String packageName, int status, int userId) {
1364        try {
1365            return mPM.updateIntentVerificationStatus(packageName, status, userId);
1366        } catch (RemoteException e) {
1367            // Should never happen!
1368            return false;
1369        }
1370    }
1371
1372    @Override
1373    public List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
1374        try {
1375            return mPM.getIntentFilterVerifications(packageName);
1376        } catch (RemoteException e) {
1377            // Should never happen!
1378            return null;
1379        }
1380    }
1381
1382    @Override
1383    public List<IntentFilter> getAllIntentFilters(String packageName) {
1384        try {
1385            return mPM.getAllIntentFilters(packageName);
1386        } catch (RemoteException e) {
1387            // Should never happen!
1388            return null;
1389        }
1390    }
1391
1392    @Override
1393    public String getDefaultBrowserPackageName(int userId) {
1394        try {
1395            return mPM.getDefaultBrowserPackageName(userId);
1396        } catch (RemoteException e) {
1397            // Should never happen!
1398            return null;
1399        }
1400    }
1401
1402    @Override
1403    public boolean setDefaultBrowserPackageName(String packageName, int userId) {
1404        try {
1405            return mPM.setDefaultBrowserPackageName(packageName, userId);
1406        } catch (RemoteException e) {
1407            // Should never happen!
1408            return false;
1409        }
1410    }
1411
1412    @Override
1413    public void setInstallerPackageName(String targetPackage,
1414            String installerPackageName) {
1415        try {
1416            mPM.setInstallerPackageName(targetPackage, installerPackageName);
1417        } catch (RemoteException e) {
1418            // Should never happen!
1419        }
1420    }
1421
1422    @Override
1423    public String getInstallerPackageName(String packageName) {
1424        try {
1425            return mPM.getInstallerPackageName(packageName);
1426        } catch (RemoteException e) {
1427            // Should never happen!
1428        }
1429        return null;
1430    }
1431
1432    @Override
1433    public int getMoveStatus(int moveId) {
1434        try {
1435            return mPM.getMoveStatus(moveId);
1436        } catch (RemoteException e) {
1437            throw e.rethrowAsRuntimeException();
1438        }
1439    }
1440
1441    @Override
1442    public void registerMoveCallback(MoveCallback callback, Handler handler) {
1443        synchronized (mDelegates) {
1444            final MoveCallbackDelegate delegate = new MoveCallbackDelegate(callback,
1445                    handler.getLooper());
1446            try {
1447                mPM.registerMoveCallback(delegate);
1448            } catch (RemoteException e) {
1449                throw e.rethrowAsRuntimeException();
1450            }
1451            mDelegates.add(delegate);
1452        }
1453    }
1454
1455    @Override
1456    public void unregisterMoveCallback(MoveCallback callback) {
1457        synchronized (mDelegates) {
1458            for (Iterator<MoveCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
1459                final MoveCallbackDelegate delegate = i.next();
1460                if (delegate.mCallback == callback) {
1461                    try {
1462                        mPM.unregisterMoveCallback(delegate);
1463                    } catch (RemoteException e) {
1464                        throw e.rethrowAsRuntimeException();
1465                    }
1466                    i.remove();
1467                }
1468            }
1469        }
1470    }
1471
1472    @Override
1473    public int movePackage(String packageName, VolumeInfo vol) {
1474        try {
1475            final String volumeUuid;
1476            if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) {
1477                volumeUuid = StorageManager.UUID_PRIVATE_INTERNAL;
1478            } else if (vol.isPrimaryPhysical()) {
1479                volumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL;
1480            } else {
1481                volumeUuid = Preconditions.checkNotNull(vol.fsUuid);
1482            }
1483
1484            return mPM.movePackage(packageName, volumeUuid);
1485        } catch (RemoteException e) {
1486            throw e.rethrowAsRuntimeException();
1487        }
1488    }
1489
1490    @Override
1491    public @Nullable VolumeInfo getPackageCurrentVolume(ApplicationInfo app) {
1492        final StorageManager storage = mContext.getSystemService(StorageManager.class);
1493        if (app.isInternal()) {
1494            return storage.findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL);
1495        } else if (app.isExternalAsec()) {
1496            return storage.getPrimaryPhysicalVolume();
1497        } else {
1498            return storage.findVolumeByUuid(app.volumeUuid);
1499        }
1500    }
1501
1502    @Override
1503    public @NonNull List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app) {
1504        final StorageManager storage = mContext.getSystemService(StorageManager.class);
1505        final VolumeInfo currentVol = getPackageCurrentVolume(app);
1506        final List<VolumeInfo> vols = storage.getVolumes();
1507        final List<VolumeInfo> candidates = new ArrayList<>();
1508        for (VolumeInfo vol : vols) {
1509            if (Objects.equals(vol, currentVol) || isPackageCandidateVolume(app, vol)) {
1510                candidates.add(vol);
1511            }
1512        }
1513        return candidates;
1514    }
1515
1516    private static boolean isPackageCandidateVolume(ApplicationInfo app, VolumeInfo vol) {
1517        // Private internal is always an option
1518        if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.getId())) {
1519            return true;
1520        }
1521
1522        // System apps and apps demanding internal storage can't be moved
1523        // anywhere else
1524        if (app.isSystemApp()
1525                || app.installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
1526            return false;
1527        }
1528
1529        // Gotta be able to write there
1530        if (!vol.isMountedWritable()) {
1531            return false;
1532        }
1533
1534        // Moving into an ASEC on public primary is only option internal
1535        if (vol.isPrimaryPhysical()) {
1536            return app.isInternal();
1537        }
1538
1539        // Otherwise we can move to any private volume
1540        return (vol.getType() == VolumeInfo.TYPE_PRIVATE);
1541    }
1542
1543    @Override
1544    public int movePrimaryStorage(VolumeInfo vol) {
1545        try {
1546            final String volumeUuid;
1547            if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) {
1548                volumeUuid = StorageManager.UUID_PRIVATE_INTERNAL;
1549            } else if (vol.isPrimaryPhysical()) {
1550                volumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL;
1551            } else {
1552                volumeUuid = Preconditions.checkNotNull(vol.fsUuid);
1553            }
1554
1555            return mPM.movePrimaryStorage(volumeUuid);
1556        } catch (RemoteException e) {
1557            throw e.rethrowAsRuntimeException();
1558        }
1559    }
1560
1561    @Override
1562    public @Nullable VolumeInfo getPrimaryStorageCurrentVolume() {
1563        final StorageManager storage = mContext.getSystemService(StorageManager.class);
1564        final String volumeUuid = storage.getPrimaryStorageUuid();
1565        return storage.findVolumeByQualifiedUuid(volumeUuid);
1566    }
1567
1568    @Override
1569    public @NonNull List<VolumeInfo> getPrimaryStorageCandidateVolumes() {
1570        final StorageManager storage = mContext.getSystemService(StorageManager.class);
1571        final VolumeInfo currentVol = getPrimaryStorageCurrentVolume();
1572        final List<VolumeInfo> vols = storage.getVolumes();
1573        final List<VolumeInfo> candidates = new ArrayList<>();
1574        for (VolumeInfo vol : vols) {
1575            if (Objects.equals(vol, currentVol) || isPrimaryStorageCandidateVolume(vol)) {
1576                candidates.add(vol);
1577            }
1578        }
1579        return candidates;
1580    }
1581
1582    private static boolean isPrimaryStorageCandidateVolume(VolumeInfo vol) {
1583        // Private internal is always an option
1584        if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.getId())) {
1585            return true;
1586        }
1587
1588        // Gotta be able to write there
1589        if (!vol.isMountedWritable()) {
1590            return false;
1591        }
1592
1593        // We can move to public volumes on legacy devices
1594        if ((vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.getDisk().isDefaultPrimary()) {
1595            return true;
1596        }
1597
1598        // Otherwise we can move to any private volume
1599        return (vol.getType() == VolumeInfo.TYPE_PRIVATE);
1600    }
1601
1602    @Override
1603    public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
1604        try {
1605            mPM.deletePackageAsUser(packageName, observer, UserHandle.myUserId(), flags);
1606        } catch (RemoteException e) {
1607            // Should never happen!
1608        }
1609    }
1610
1611    @Override
1612    public void clearApplicationUserData(String packageName,
1613                                         IPackageDataObserver observer) {
1614        try {
1615            mPM.clearApplicationUserData(packageName, observer, mContext.getUserId());
1616        } catch (RemoteException e) {
1617            // Should never happen!
1618        }
1619    }
1620    @Override
1621    public void deleteApplicationCacheFiles(String packageName,
1622                                            IPackageDataObserver observer) {
1623        try {
1624            mPM.deleteApplicationCacheFiles(packageName, observer);
1625        } catch (RemoteException e) {
1626            // Should never happen!
1627        }
1628    }
1629
1630    @Override
1631    public void freeStorageAndNotify(String volumeUuid, long idealStorageSize,
1632            IPackageDataObserver observer) {
1633        try {
1634            mPM.freeStorageAndNotify(volumeUuid, idealStorageSize, observer);
1635        } catch (RemoteException e) {
1636            // Should never happen!
1637        }
1638    }
1639
1640    @Override
1641    public void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi) {
1642        try {
1643            mPM.freeStorage(volumeUuid, freeStorageSize, pi);
1644        } catch (RemoteException e) {
1645            // Should never happen!
1646        }
1647    }
1648
1649    @Override
1650    public void getPackageSizeInfo(String packageName, int userHandle,
1651            IPackageStatsObserver observer) {
1652        try {
1653            mPM.getPackageSizeInfo(packageName, userHandle, observer);
1654        } catch (RemoteException e) {
1655            // Should never happen!
1656        }
1657    }
1658    @Override
1659    public void addPackageToPreferred(String packageName) {
1660        try {
1661            mPM.addPackageToPreferred(packageName);
1662        } catch (RemoteException e) {
1663            // Should never happen!
1664        }
1665    }
1666
1667    @Override
1668    public void removePackageFromPreferred(String packageName) {
1669        try {
1670            mPM.removePackageFromPreferred(packageName);
1671        } catch (RemoteException e) {
1672            // Should never happen!
1673        }
1674    }
1675
1676    @Override
1677    public List<PackageInfo> getPreferredPackages(int flags) {
1678        try {
1679            return mPM.getPreferredPackages(flags);
1680        } catch (RemoteException e) {
1681            // Should never happen!
1682        }
1683        return new ArrayList<PackageInfo>();
1684    }
1685
1686    @Override
1687    public void addPreferredActivity(IntentFilter filter,
1688                                     int match, ComponentName[] set, ComponentName activity) {
1689        try {
1690            mPM.addPreferredActivity(filter, match, set, activity, mContext.getUserId());
1691        } catch (RemoteException e) {
1692            // Should never happen!
1693        }
1694    }
1695
1696    @Override
1697    public void addPreferredActivity(IntentFilter filter, int match,
1698            ComponentName[] set, ComponentName activity, int userId) {
1699        try {
1700            mPM.addPreferredActivity(filter, match, set, activity, userId);
1701        } catch (RemoteException e) {
1702            // Should never happen!
1703        }
1704    }
1705
1706    @Override
1707    public void replacePreferredActivity(IntentFilter filter,
1708                                         int match, ComponentName[] set, ComponentName activity) {
1709        try {
1710            mPM.replacePreferredActivity(filter, match, set, activity, UserHandle.myUserId());
1711        } catch (RemoteException e) {
1712            // Should never happen!
1713        }
1714    }
1715
1716    @Override
1717    public void replacePreferredActivityAsUser(IntentFilter filter,
1718                                         int match, ComponentName[] set, ComponentName activity,
1719                                         int userId) {
1720        try {
1721            mPM.replacePreferredActivity(filter, match, set, activity, userId);
1722        } catch (RemoteException e) {
1723            // Should never happen!
1724        }
1725    }
1726
1727    @Override
1728    public void clearPackagePreferredActivities(String packageName) {
1729        try {
1730            mPM.clearPackagePreferredActivities(packageName);
1731        } catch (RemoteException e) {
1732            // Should never happen!
1733        }
1734    }
1735
1736    @Override
1737    public int getPreferredActivities(List<IntentFilter> outFilters,
1738                                      List<ComponentName> outActivities, String packageName) {
1739        try {
1740            return mPM.getPreferredActivities(outFilters, outActivities, packageName);
1741        } catch (RemoteException e) {
1742            // Should never happen!
1743        }
1744        return 0;
1745    }
1746
1747    @Override
1748    public ComponentName getHomeActivities(List<ResolveInfo> outActivities) {
1749        try {
1750            return mPM.getHomeActivities(outActivities);
1751        } catch (RemoteException e) {
1752            // Should never happen!
1753        }
1754        return null;
1755    }
1756
1757    @Override
1758    public void setComponentEnabledSetting(ComponentName componentName,
1759                                           int newState, int flags) {
1760        try {
1761            mPM.setComponentEnabledSetting(componentName, newState, flags, mContext.getUserId());
1762        } catch (RemoteException e) {
1763            // Should never happen!
1764        }
1765    }
1766
1767    @Override
1768    public int getComponentEnabledSetting(ComponentName componentName) {
1769        try {
1770            return mPM.getComponentEnabledSetting(componentName, mContext.getUserId());
1771        } catch (RemoteException e) {
1772            // Should never happen!
1773        }
1774        return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
1775    }
1776
1777    @Override
1778    public void setApplicationEnabledSetting(String packageName,
1779                                             int newState, int flags) {
1780        try {
1781            mPM.setApplicationEnabledSetting(packageName, newState, flags,
1782                    mContext.getUserId(), mContext.getOpPackageName());
1783        } catch (RemoteException e) {
1784            // Should never happen!
1785        }
1786    }
1787
1788    @Override
1789    public int getApplicationEnabledSetting(String packageName) {
1790        try {
1791            return mPM.getApplicationEnabledSetting(packageName, mContext.getUserId());
1792        } catch (RemoteException e) {
1793            // Should never happen!
1794        }
1795        return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
1796    }
1797
1798    @Override
1799    public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
1800            UserHandle user) {
1801        try {
1802            return mPM.setApplicationHiddenSettingAsUser(packageName, hidden,
1803                    user.getIdentifier());
1804        } catch (RemoteException re) {
1805            // Should never happen!
1806        }
1807        return false;
1808    }
1809
1810    @Override
1811    public boolean getApplicationHiddenSettingAsUser(String packageName, UserHandle user) {
1812        try {
1813            return mPM.getApplicationHiddenSettingAsUser(packageName, user.getIdentifier());
1814        } catch (RemoteException re) {
1815            // Should never happen!
1816        }
1817        return false;
1818    }
1819
1820    /** @hide */
1821    @Override
1822    public KeySet getKeySetByAlias(String packageName, String alias) {
1823        Preconditions.checkNotNull(packageName);
1824        Preconditions.checkNotNull(alias);
1825        KeySet ks;
1826        try {
1827            ks = mPM.getKeySetByAlias(packageName, alias);
1828        } catch (RemoteException e) {
1829            return null;
1830        }
1831        return ks;
1832    }
1833
1834    /** @hide */
1835    @Override
1836    public KeySet getSigningKeySet(String packageName) {
1837        Preconditions.checkNotNull(packageName);
1838        KeySet ks;
1839        try {
1840            ks = mPM.getSigningKeySet(packageName);
1841        } catch (RemoteException e) {
1842            return null;
1843        }
1844        return ks;
1845    }
1846
1847    /** @hide */
1848    @Override
1849    public boolean isSignedBy(String packageName, KeySet ks) {
1850        Preconditions.checkNotNull(packageName);
1851        Preconditions.checkNotNull(ks);
1852        try {
1853            return mPM.isPackageSignedByKeySet(packageName, ks);
1854        } catch (RemoteException e) {
1855            return false;
1856        }
1857    }
1858
1859    /** @hide */
1860    @Override
1861    public boolean isSignedByExactly(String packageName, KeySet ks) {
1862        Preconditions.checkNotNull(packageName);
1863        Preconditions.checkNotNull(ks);
1864        try {
1865            return mPM.isPackageSignedByKeySetExactly(packageName, ks);
1866        } catch (RemoteException e) {
1867            return false;
1868        }
1869    }
1870
1871    /**
1872     * @hide
1873     */
1874    @Override
1875    public VerifierDeviceIdentity getVerifierDeviceIdentity() {
1876        try {
1877            return mPM.getVerifierDeviceIdentity();
1878        } catch (RemoteException e) {
1879            // Should never happen!
1880        }
1881        return null;
1882    }
1883
1884    /**
1885     * @hide
1886     */
1887    @Override
1888    public boolean isUpgrade() {
1889        try {
1890            return mPM.isUpgrade();
1891        } catch (RemoteException e) {
1892            return false;
1893        }
1894    }
1895
1896    @Override
1897    public PackageInstaller getPackageInstaller() {
1898        synchronized (mLock) {
1899            if (mInstaller == null) {
1900                try {
1901                    mInstaller = new PackageInstaller(mContext, this, mPM.getPackageInstaller(),
1902                            mContext.getPackageName(), mContext.getUserId());
1903                } catch (RemoteException e) {
1904                    throw e.rethrowAsRuntimeException();
1905                }
1906            }
1907            return mInstaller;
1908        }
1909    }
1910
1911    @Override
1912    public boolean isPackageAvailable(String packageName) {
1913        try {
1914            return mPM.isPackageAvailable(packageName, mContext.getUserId());
1915        } catch (RemoteException e) {
1916            throw e.rethrowAsRuntimeException();
1917        }
1918    }
1919
1920    /**
1921     * @hide
1922     */
1923    @Override
1924    public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId,
1925            int flags) {
1926        try {
1927            mPM.addCrossProfileIntentFilter(filter, mContext.getOpPackageName(),
1928                    sourceUserId, targetUserId, flags);
1929        } catch (RemoteException e) {
1930            // Should never happen!
1931        }
1932    }
1933
1934    /**
1935     * @hide
1936     */
1937    @Override
1938    public void clearCrossProfileIntentFilters(int sourceUserId) {
1939        try {
1940            mPM.clearCrossProfileIntentFilters(sourceUserId, mContext.getOpPackageName());
1941        } catch (RemoteException e) {
1942            // Should never happen!
1943        }
1944    }
1945
1946    /**
1947     * @hide
1948     */
1949    public Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
1950        Drawable dr = loadUnbadgedItemIcon(itemInfo, appInfo);
1951        if (itemInfo.showUserIcon != UserHandle.USER_NULL) {
1952            return dr;
1953        }
1954        return getUserBadgedIcon(dr, new UserHandle(mContext.getUserId()));
1955    }
1956
1957    /**
1958     * @hide
1959     */
1960    public Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
1961        if (itemInfo.showUserIcon != UserHandle.USER_NULL) {
1962            Bitmap bitmap = getUserManager().getUserIcon(itemInfo.showUserIcon);
1963            if (bitmap == null) {
1964                return UserIcons.getDefaultUserIcon(itemInfo.showUserIcon, /* light= */ false);
1965            }
1966            return new BitmapDrawable(bitmap);
1967        }
1968        Drawable dr = null;
1969        if (itemInfo.packageName != null) {
1970            dr = getDrawable(itemInfo.packageName, itemInfo.icon, appInfo);
1971        }
1972        if (dr == null) {
1973            dr = itemInfo.loadDefaultIcon(this);
1974        }
1975        return dr;
1976    }
1977
1978    private Drawable getBadgedDrawable(Drawable drawable, Drawable badgeDrawable,
1979            Rect badgeLocation, boolean tryBadgeInPlace) {
1980        final int badgedWidth = drawable.getIntrinsicWidth();
1981        final int badgedHeight = drawable.getIntrinsicHeight();
1982        final boolean canBadgeInPlace = tryBadgeInPlace
1983                && (drawable instanceof BitmapDrawable)
1984                && ((BitmapDrawable) drawable).getBitmap().isMutable();
1985
1986        final Bitmap bitmap;
1987        if (canBadgeInPlace) {
1988            bitmap = ((BitmapDrawable) drawable).getBitmap();
1989        } else {
1990            bitmap = Bitmap.createBitmap(badgedWidth, badgedHeight, Bitmap.Config.ARGB_8888);
1991        }
1992        Canvas canvas = new Canvas(bitmap);
1993
1994        if (!canBadgeInPlace) {
1995            drawable.setBounds(0, 0, badgedWidth, badgedHeight);
1996            drawable.draw(canvas);
1997        }
1998
1999        if (badgeLocation != null) {
2000            if (badgeLocation.left < 0 || badgeLocation.top < 0
2001                    || badgeLocation.width() > badgedWidth || badgeLocation.height() > badgedHeight) {
2002                throw new IllegalArgumentException("Badge location " + badgeLocation
2003                        + " not in badged drawable bounds "
2004                        + new Rect(0, 0, badgedWidth, badgedHeight));
2005            }
2006            badgeDrawable.setBounds(0, 0, badgeLocation.width(), badgeLocation.height());
2007
2008            canvas.save();
2009            canvas.translate(badgeLocation.left, badgeLocation.top);
2010            badgeDrawable.draw(canvas);
2011            canvas.restore();
2012        } else {
2013            badgeDrawable.setBounds(0, 0, badgedWidth, badgedHeight);
2014            badgeDrawable.draw(canvas);
2015        }
2016
2017        if (!canBadgeInPlace) {
2018            BitmapDrawable mergedDrawable = new BitmapDrawable(mContext.getResources(), bitmap);
2019
2020            if (drawable instanceof BitmapDrawable) {
2021                BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
2022                mergedDrawable.setTargetDensity(bitmapDrawable.getBitmap().getDensity());
2023            }
2024
2025            return mergedDrawable;
2026        }
2027
2028        return drawable;
2029    }
2030
2031    private int getBadgeResIdForUser(int userHandle) {
2032        // Return the framework-provided badge.
2033        UserInfo userInfo = getUserIfProfile(userHandle);
2034        if (userInfo != null && userInfo.isManagedProfile()) {
2035            return com.android.internal.R.drawable.ic_corp_icon_badge;
2036        }
2037        return 0;
2038    }
2039
2040    private UserInfo getUserIfProfile(int userHandle) {
2041        List<UserInfo> userProfiles = getUserManager().getProfiles(UserHandle.myUserId());
2042        for (UserInfo user : userProfiles) {
2043            if (user.id == userHandle) {
2044                return user;
2045            }
2046        }
2047        return null;
2048    }
2049
2050    /** {@hide} */
2051    private static class MoveCallbackDelegate extends IPackageMoveObserver.Stub implements
2052            Handler.Callback {
2053        private static final int MSG_CREATED = 1;
2054        private static final int MSG_STATUS_CHANGED = 2;
2055
2056        final MoveCallback mCallback;
2057        final Handler mHandler;
2058
2059        public MoveCallbackDelegate(MoveCallback callback, Looper looper) {
2060            mCallback = callback;
2061            mHandler = new Handler(looper, this);
2062        }
2063
2064        @Override
2065        public boolean handleMessage(Message msg) {
2066            switch (msg.what) {
2067                case MSG_CREATED: {
2068                    final SomeArgs args = (SomeArgs) msg.obj;
2069                    mCallback.onCreated(args.argi1, (Bundle) args.arg2);
2070                    args.recycle();
2071                    return true;
2072                }
2073                case MSG_STATUS_CHANGED: {
2074                    final SomeArgs args = (SomeArgs) msg.obj;
2075                    mCallback.onStatusChanged(args.argi1, args.argi2, (long) args.arg3);
2076                    args.recycle();
2077                    return true;
2078                }
2079            }
2080            return false;
2081        }
2082
2083        @Override
2084        public void onCreated(int moveId, Bundle extras) {
2085            final SomeArgs args = SomeArgs.obtain();
2086            args.argi1 = moveId;
2087            args.arg2 = extras;
2088            mHandler.obtainMessage(MSG_CREATED, args).sendToTarget();
2089        }
2090
2091        @Override
2092        public void onStatusChanged(int moveId, int status, long estMillis) {
2093            final SomeArgs args = SomeArgs.obtain();
2094            args.argi1 = moveId;
2095            args.argi2 = status;
2096            args.arg3 = estMillis;
2097            mHandler.obtainMessage(MSG_STATUS_CHANGED, args).sendToTarget();
2098        }
2099    }
2100
2101    private final ContextImpl mContext;
2102    private final IPackageManager mPM;
2103
2104    private static final Object sSync = new Object();
2105    private static ArrayMap<ResourceName, WeakReference<Drawable.ConstantState>> sIconCache
2106            = new ArrayMap<ResourceName, WeakReference<Drawable.ConstantState>>();
2107    private static ArrayMap<ResourceName, WeakReference<CharSequence>> sStringCache
2108            = new ArrayMap<ResourceName, WeakReference<CharSequence>>();
2109}
2110