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