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