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