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