ApplicationPackageManager.java revision f1b7f20bb839c96e8254ccb65398135f10fd45d9
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            return mPM.queryContentProviders(processName, uid, flags);
781        } catch (RemoteException e) {
782            throw new RuntimeException("Package manager has died", e);
783        }
784    }
785
786    @Override
787    public InstrumentationInfo getInstrumentationInfo(
788        ComponentName className, int flags)
789            throws NameNotFoundException {
790        try {
791            InstrumentationInfo ii = mPM.getInstrumentationInfo(
792                className, flags);
793            if (ii != null) {
794                return ii;
795            }
796        } catch (RemoteException e) {
797            throw new RuntimeException("Package manager has died", e);
798        }
799
800        throw new NameNotFoundException(className.toString());
801    }
802
803    @Override
804    public List<InstrumentationInfo> queryInstrumentation(
805        String targetPackage, int flags) {
806        try {
807            return mPM.queryInstrumentation(targetPackage, flags);
808        } catch (RemoteException e) {
809            throw new RuntimeException("Package manager has died", e);
810        }
811    }
812
813    @Nullable
814    @Override
815    public Drawable getDrawable(String packageName, @DrawableRes int resId,
816            @Nullable ApplicationInfo appInfo) {
817        final ResourceName name = new ResourceName(packageName, resId);
818        final Drawable cachedIcon = getCachedIcon(name);
819        if (cachedIcon != null) {
820            return cachedIcon;
821        }
822
823        if (appInfo == null) {
824            try {
825                appInfo = getApplicationInfo(packageName, sDefaultFlags);
826            } catch (NameNotFoundException e) {
827                return null;
828            }
829        }
830
831        if (resId != 0) {
832            try {
833                final Resources r = getResourcesForApplication(appInfo);
834                final Drawable dr = r.getDrawable(resId, null);
835                if (dr != null) {
836                    putCachedIcon(name, dr);
837                }
838
839                if (false) {
840                    RuntimeException e = new RuntimeException("here");
841                    e.fillInStackTrace();
842                    Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resId)
843                                    + " from package " + packageName
844                                    + ": app scale=" + r.getCompatibilityInfo().applicationScale
845                                    + ", caller scale=" + mContext.getResources()
846                                    .getCompatibilityInfo().applicationScale,
847                            e);
848                }
849                if (DEBUG_ICONS) {
850                    Log.v(TAG, "Getting drawable 0x"
851                            + Integer.toHexString(resId) + " from " + r
852                            + ": " + dr);
853                }
854                return dr;
855            } catch (NameNotFoundException e) {
856                Log.w("PackageManager", "Failure retrieving resources for "
857                        + appInfo.packageName);
858            } catch (Resources.NotFoundException e) {
859                Log.w("PackageManager", "Failure retrieving resources for "
860                        + appInfo.packageName + ": " + e.getMessage());
861            } catch (Exception e) {
862                // If an exception was thrown, fall through to return
863                // default icon.
864                Log.w("PackageManager", "Failure retrieving icon 0x"
865                        + Integer.toHexString(resId) + " in package "
866                        + packageName, e);
867            }
868        }
869
870        return null;
871    }
872
873    @Override public Drawable getActivityIcon(ComponentName activityName)
874            throws NameNotFoundException {
875        return getActivityInfo(activityName, sDefaultFlags).loadIcon(this);
876    }
877
878    @Override public Drawable getActivityIcon(Intent intent)
879            throws NameNotFoundException {
880        if (intent.getComponent() != null) {
881            return getActivityIcon(intent.getComponent());
882        }
883
884        ResolveInfo info = resolveActivity(
885            intent, PackageManager.MATCH_DEFAULT_ONLY);
886        if (info != null) {
887            return info.activityInfo.loadIcon(this);
888        }
889
890        throw new NameNotFoundException(intent.toUri(0));
891    }
892
893    @Override public Drawable getDefaultActivityIcon() {
894        return Resources.getSystem().getDrawable(
895            com.android.internal.R.drawable.sym_def_app_icon);
896    }
897
898    @Override public Drawable getApplicationIcon(ApplicationInfo info) {
899        return info.loadIcon(this);
900    }
901
902    @Override public Drawable getApplicationIcon(String packageName)
903            throws NameNotFoundException {
904        return getApplicationIcon(getApplicationInfo(packageName, sDefaultFlags));
905    }
906
907    @Override
908    public Drawable getActivityBanner(ComponentName activityName)
909            throws NameNotFoundException {
910        return getActivityInfo(activityName, sDefaultFlags).loadBanner(this);
911    }
912
913    @Override
914    public Drawable getActivityBanner(Intent intent)
915            throws NameNotFoundException {
916        if (intent.getComponent() != null) {
917            return getActivityBanner(intent.getComponent());
918        }
919
920        ResolveInfo info = resolveActivity(
921                intent, PackageManager.MATCH_DEFAULT_ONLY);
922        if (info != null) {
923            return info.activityInfo.loadBanner(this);
924        }
925
926        throw new NameNotFoundException(intent.toUri(0));
927    }
928
929    @Override
930    public Drawable getApplicationBanner(ApplicationInfo info) {
931        return info.loadBanner(this);
932    }
933
934    @Override
935    public Drawable getApplicationBanner(String packageName)
936            throws NameNotFoundException {
937        return getApplicationBanner(getApplicationInfo(packageName, sDefaultFlags));
938    }
939
940    @Override
941    public Drawable getActivityLogo(ComponentName activityName)
942            throws NameNotFoundException {
943        return getActivityInfo(activityName, sDefaultFlags).loadLogo(this);
944    }
945
946    @Override
947    public Drawable getActivityLogo(Intent intent)
948            throws NameNotFoundException {
949        if (intent.getComponent() != null) {
950            return getActivityLogo(intent.getComponent());
951        }
952
953        ResolveInfo info = resolveActivity(
954            intent, PackageManager.MATCH_DEFAULT_ONLY);
955        if (info != null) {
956            return info.activityInfo.loadLogo(this);
957        }
958
959        throw new NameNotFoundException(intent.toUri(0));
960    }
961
962    @Override
963    public Drawable getApplicationLogo(ApplicationInfo info) {
964        return info.loadLogo(this);
965    }
966
967    @Override
968    public Drawable getApplicationLogo(String packageName)
969            throws NameNotFoundException {
970        return getApplicationLogo(getApplicationInfo(packageName, sDefaultFlags));
971    }
972
973    @Override
974    public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
975        final int badgeResId = getBadgeResIdForUser(user.getIdentifier());
976        if (badgeResId == 0) {
977            return icon;
978        }
979        Drawable badgeIcon = getDrawable("system", badgeResId, null);
980        return getBadgedDrawable(icon, badgeIcon, null, true);
981    }
982
983    @Override
984    public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user,
985            Rect badgeLocation, int badgeDensity) {
986        Drawable badgeDrawable = getUserBadgeForDensity(user, badgeDensity);
987        if (badgeDrawable == null) {
988            return drawable;
989        }
990        return getBadgedDrawable(drawable, badgeDrawable, badgeLocation, true);
991    }
992
993    @Override
994    public Drawable getUserBadgeForDensity(UserHandle user, int density) {
995        UserInfo userInfo = getUserIfProfile(user.getIdentifier());
996        if (userInfo != null && userInfo.isManagedProfile()) {
997            if (density <= 0) {
998                density = mContext.getResources().getDisplayMetrics().densityDpi;
999            }
1000            return Resources.getSystem().getDrawableForDensity(
1001                    com.android.internal.R.drawable.ic_corp_badge, density);
1002        }
1003        return null;
1004    }
1005
1006    @Override
1007    public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
1008        UserInfo userInfo = getUserIfProfile(user.getIdentifier());
1009        if (userInfo != null && userInfo.isManagedProfile()) {
1010            return Resources.getSystem().getString(
1011                    com.android.internal.R.string.managed_profile_label_badge, label);
1012        }
1013        return label;
1014    }
1015
1016    @Override
1017    public Resources getResourcesForActivity(ComponentName activityName)
1018            throws NameNotFoundException {
1019        return getResourcesForApplication(
1020            getActivityInfo(activityName, sDefaultFlags).applicationInfo);
1021    }
1022
1023    @Override
1024    public Resources getResourcesForApplication(@NonNull ApplicationInfo app)
1025            throws NameNotFoundException {
1026        if (app.packageName.equals("system")) {
1027            return mContext.mMainThread.getSystemContext().getResources();
1028        }
1029        final boolean sameUid = (app.uid == Process.myUid());
1030        final Resources r = mContext.mMainThread.getTopLevelResources(
1031                sameUid ? app.sourceDir : app.publicSourceDir,
1032                sameUid ? app.splitSourceDirs : app.splitPublicSourceDirs,
1033                app.resourceDirs, app.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
1034                null, mContext.mPackageInfo);
1035        if (r != null) {
1036            return r;
1037        }
1038        throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
1039    }
1040
1041    @Override
1042    public Resources getResourcesForApplication(String appPackageName)
1043            throws NameNotFoundException {
1044        return getResourcesForApplication(
1045            getApplicationInfo(appPackageName, sDefaultFlags));
1046    }
1047
1048    /** @hide */
1049    @Override
1050    public Resources getResourcesForApplicationAsUser(String appPackageName, int userId)
1051            throws NameNotFoundException {
1052        if (userId < 0) {
1053            throw new IllegalArgumentException(
1054                    "Call does not support special user #" + userId);
1055        }
1056        if ("system".equals(appPackageName)) {
1057            return mContext.mMainThread.getSystemContext().getResources();
1058        }
1059        try {
1060            ApplicationInfo ai = mPM.getApplicationInfo(appPackageName, sDefaultFlags, userId);
1061            if (ai != null) {
1062                return getResourcesForApplication(ai);
1063            }
1064        } catch (RemoteException e) {
1065            throw new RuntimeException("Package manager has died", e);
1066        }
1067        throw new NameNotFoundException("Package " + appPackageName + " doesn't exist");
1068    }
1069
1070    int mCachedSafeMode = -1;
1071    @Override public boolean isSafeMode() {
1072        try {
1073            if (mCachedSafeMode < 0) {
1074                mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
1075            }
1076            return mCachedSafeMode != 0;
1077        } catch (RemoteException e) {
1078            throw new RuntimeException("Package manager has died", e);
1079        }
1080    }
1081
1082    @Override
1083    public void addOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
1084        synchronized (mPermissionListeners) {
1085            if (mPermissionListeners.get(listener) != null) {
1086                return;
1087            }
1088            OnPermissionsChangeListenerDelegate delegate =
1089                    new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper());
1090            try {
1091                mPM.addOnPermissionsChangeListener(delegate);
1092                mPermissionListeners.put(listener, delegate);
1093            } catch (RemoteException e) {
1094                throw new RuntimeException("Package manager has died", e);
1095            }
1096        }
1097    }
1098
1099    @Override
1100    public void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
1101        synchronized (mPermissionListeners) {
1102            IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener);
1103            if (delegate != null) {
1104                try {
1105                    mPM.removeOnPermissionsChangeListener(delegate);
1106                    mPermissionListeners.remove(listener);
1107                } catch (RemoteException e) {
1108                    throw new RuntimeException("Package manager has died", e);
1109                }
1110            }
1111        }
1112    }
1113
1114    static void configurationChanged() {
1115        synchronized (sSync) {
1116            sIconCache.clear();
1117            sStringCache.clear();
1118        }
1119    }
1120
1121    ApplicationPackageManager(ContextImpl context,
1122                              IPackageManager pm) {
1123        mContext = context;
1124        mPM = pm;
1125    }
1126
1127    @Nullable
1128    private Drawable getCachedIcon(@NonNull ResourceName name) {
1129        synchronized (sSync) {
1130            final WeakReference<Drawable.ConstantState> wr = sIconCache.get(name);
1131            if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
1132                                   + name + ": " + wr);
1133            if (wr != null) {   // we have the activity
1134                final Drawable.ConstantState state = wr.get();
1135                if (state != null) {
1136                    if (DEBUG_ICONS) {
1137                        Log.v(TAG, "Get cached drawable state for " + name + ": " + state);
1138                    }
1139                    // Note: It's okay here to not use the newDrawable(Resources) variant
1140                    //       of the API. The ConstantState comes from a drawable that was
1141                    //       originally created by passing the proper app Resources instance
1142                    //       which means the state should already contain the proper
1143                    //       resources specific information (like density.) See
1144                    //       BitmapDrawable.BitmapState for instance.
1145                    return state.newDrawable();
1146                }
1147                // our entry has been purged
1148                sIconCache.remove(name);
1149            }
1150        }
1151        return null;
1152    }
1153
1154    private void putCachedIcon(@NonNull ResourceName name, @NonNull Drawable dr) {
1155        synchronized (sSync) {
1156            sIconCache.put(name, new WeakReference<>(dr.getConstantState()));
1157            if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable state for " + name + ": " + dr);
1158        }
1159    }
1160
1161    static void handlePackageBroadcast(int cmd, String[] pkgList, boolean hasPkgInfo) {
1162        boolean immediateGc = false;
1163        if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
1164            immediateGc = true;
1165        }
1166        if (pkgList != null && (pkgList.length > 0)) {
1167            boolean needCleanup = false;
1168            for (String ssp : pkgList) {
1169                synchronized (sSync) {
1170                    for (int i=sIconCache.size()-1; i>=0; i--) {
1171                        ResourceName nm = sIconCache.keyAt(i);
1172                        if (nm.packageName.equals(ssp)) {
1173                            //Log.i(TAG, "Removing cached drawable for " + nm);
1174                            sIconCache.removeAt(i);
1175                            needCleanup = true;
1176                        }
1177                    }
1178                    for (int i=sStringCache.size()-1; i>=0; i--) {
1179                        ResourceName nm = sStringCache.keyAt(i);
1180                        if (nm.packageName.equals(ssp)) {
1181                            //Log.i(TAG, "Removing cached string for " + nm);
1182                            sStringCache.removeAt(i);
1183                            needCleanup = true;
1184                        }
1185                    }
1186                }
1187            }
1188            if (needCleanup || hasPkgInfo) {
1189                if (immediateGc) {
1190                    // Schedule an immediate gc.
1191                    Runtime.getRuntime().gc();
1192                } else {
1193                    ActivityThread.currentActivityThread().scheduleGcIdler();
1194                }
1195            }
1196        }
1197    }
1198
1199    private static final class ResourceName {
1200        final String packageName;
1201        final int iconId;
1202
1203        ResourceName(String _packageName, int _iconId) {
1204            packageName = _packageName;
1205            iconId = _iconId;
1206        }
1207
1208        ResourceName(ApplicationInfo aInfo, int _iconId) {
1209            this(aInfo.packageName, _iconId);
1210        }
1211
1212        ResourceName(ComponentInfo cInfo, int _iconId) {
1213            this(cInfo.applicationInfo.packageName, _iconId);
1214        }
1215
1216        ResourceName(ResolveInfo rInfo, int _iconId) {
1217            this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
1218        }
1219
1220        @Override
1221        public boolean equals(Object o) {
1222            if (this == o) return true;
1223            if (o == null || getClass() != o.getClass()) return false;
1224
1225            ResourceName that = (ResourceName) o;
1226
1227            if (iconId != that.iconId) return false;
1228            return !(packageName != null ?
1229                     !packageName.equals(that.packageName) : that.packageName != null);
1230
1231        }
1232
1233        @Override
1234        public int hashCode() {
1235            int result;
1236            result = packageName.hashCode();
1237            result = 31 * result + iconId;
1238            return result;
1239        }
1240
1241        @Override
1242        public String toString() {
1243            return "{ResourceName " + packageName + " / " + iconId + "}";
1244        }
1245    }
1246
1247    private CharSequence getCachedString(ResourceName name) {
1248        synchronized (sSync) {
1249            WeakReference<CharSequence> wr = sStringCache.get(name);
1250            if (wr != null) {   // we have the activity
1251                CharSequence cs = wr.get();
1252                if (cs != null) {
1253                    return cs;
1254                }
1255                // our entry has been purged
1256                sStringCache.remove(name);
1257            }
1258        }
1259        return null;
1260    }
1261
1262    private void putCachedString(ResourceName name, CharSequence cs) {
1263        synchronized (sSync) {
1264            sStringCache.put(name, new WeakReference<CharSequence>(cs));
1265        }
1266    }
1267
1268    @Override
1269    public CharSequence getText(String packageName, @StringRes int resid,
1270                                ApplicationInfo appInfo) {
1271        ResourceName name = new ResourceName(packageName, resid);
1272        CharSequence text = getCachedString(name);
1273        if (text != null) {
1274            return text;
1275        }
1276        if (appInfo == null) {
1277            try {
1278                appInfo = getApplicationInfo(packageName, sDefaultFlags);
1279            } catch (NameNotFoundException e) {
1280                return null;
1281            }
1282        }
1283        try {
1284            Resources r = getResourcesForApplication(appInfo);
1285            text = r.getText(resid);
1286            putCachedString(name, text);
1287            return text;
1288        } catch (NameNotFoundException e) {
1289            Log.w("PackageManager", "Failure retrieving resources for "
1290                  + appInfo.packageName);
1291        } catch (RuntimeException e) {
1292            // If an exception was thrown, fall through to return
1293            // default icon.
1294            Log.w("PackageManager", "Failure retrieving text 0x"
1295                  + Integer.toHexString(resid) + " in package "
1296                  + packageName, e);
1297        }
1298        return null;
1299    }
1300
1301    @Override
1302    public XmlResourceParser getXml(String packageName, @XmlRes int resid,
1303                                    ApplicationInfo appInfo) {
1304        if (appInfo == null) {
1305            try {
1306                appInfo = getApplicationInfo(packageName, sDefaultFlags);
1307            } catch (NameNotFoundException e) {
1308                return null;
1309            }
1310        }
1311        try {
1312            Resources r = getResourcesForApplication(appInfo);
1313            return r.getXml(resid);
1314        } catch (RuntimeException e) {
1315            // If an exception was thrown, fall through to return
1316            // default icon.
1317            Log.w("PackageManager", "Failure retrieving xml 0x"
1318                  + Integer.toHexString(resid) + " in package "
1319                  + packageName, e);
1320        } catch (NameNotFoundException e) {
1321            Log.w("PackageManager", "Failure retrieving resources for "
1322                  + appInfo.packageName);
1323        }
1324        return null;
1325    }
1326
1327    @Override
1328    public CharSequence getApplicationLabel(ApplicationInfo info) {
1329        return info.loadLabel(this);
1330    }
1331
1332    @Override
1333    public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
1334                               String installerPackageName) {
1335        final VerificationParams verificationParams = new VerificationParams(null, null,
1336                null, VerificationParams.NO_UID, null);
1337        installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
1338                installerPackageName, verificationParams, null);
1339    }
1340
1341    @Override
1342    public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
1343            int flags, String installerPackageName, Uri verificationURI,
1344            ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
1345        final VerificationParams verificationParams = new VerificationParams(verificationURI, null,
1346                null, VerificationParams.NO_UID, manifestDigest);
1347        installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
1348                installerPackageName, verificationParams, encryptionParams);
1349    }
1350
1351    @Override
1352    public void installPackageWithVerificationAndEncryption(Uri packageURI,
1353            IPackageInstallObserver observer, int flags, String installerPackageName,
1354            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
1355        installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
1356                installerPackageName, verificationParams, encryptionParams);
1357    }
1358
1359    @Override
1360    public void installPackage(Uri packageURI, PackageInstallObserver observer,
1361            int flags, String installerPackageName) {
1362        final VerificationParams verificationParams = new VerificationParams(null, null,
1363                null, VerificationParams.NO_UID, null);
1364        installCommon(packageURI, observer, flags, installerPackageName, verificationParams, null);
1365    }
1366
1367    @Override
1368    public void installPackageWithVerification(Uri packageURI,
1369            PackageInstallObserver observer, int flags, String installerPackageName,
1370            Uri verificationURI, ManifestDigest manifestDigest,
1371            ContainerEncryptionParams encryptionParams) {
1372        final VerificationParams verificationParams = new VerificationParams(verificationURI, null,
1373                null, VerificationParams.NO_UID, manifestDigest);
1374        installCommon(packageURI, observer, flags, installerPackageName, verificationParams,
1375                encryptionParams);
1376    }
1377
1378    @Override
1379    public void installPackageWithVerificationAndEncryption(Uri packageURI,
1380            PackageInstallObserver observer, int flags, String installerPackageName,
1381            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
1382        installCommon(packageURI, observer, flags, installerPackageName, verificationParams,
1383                encryptionParams);
1384    }
1385
1386    private void installCommon(Uri packageURI,
1387            PackageInstallObserver observer, int flags, String installerPackageName,
1388            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
1389        if (!"file".equals(packageURI.getScheme())) {
1390            throw new UnsupportedOperationException("Only file:// URIs are supported");
1391        }
1392        if (encryptionParams != null) {
1393            throw new UnsupportedOperationException("ContainerEncryptionParams not supported");
1394        }
1395
1396        final String originPath = packageURI.getPath();
1397        try {
1398            mPM.installPackage(originPath, observer.getBinder(), flags, installerPackageName,
1399                    verificationParams, null);
1400        } catch (RemoteException ignored) {
1401        }
1402    }
1403
1404    @Override
1405    public int installExistingPackage(String packageName)
1406            throws NameNotFoundException {
1407        try {
1408            int res = mPM.installExistingPackageAsUser(packageName, UserHandle.myUserId());
1409            if (res == INSTALL_FAILED_INVALID_URI) {
1410                throw new NameNotFoundException("Package " + packageName + " doesn't exist");
1411            }
1412            return res;
1413        } catch (RemoteException e) {
1414            // Should never happen!
1415            throw new NameNotFoundException("Package " + packageName + " doesn't exist");
1416        }
1417    }
1418
1419    @Override
1420    public void verifyPendingInstall(int id, int response) {
1421        try {
1422            mPM.verifyPendingInstall(id, response);
1423        } catch (RemoteException e) {
1424            // Should never happen!
1425        }
1426    }
1427
1428    @Override
1429    public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
1430            long millisecondsToDelay) {
1431        try {
1432            mPM.extendVerificationTimeout(id, verificationCodeAtTimeout, millisecondsToDelay);
1433        } catch (RemoteException e) {
1434            // Should never happen!
1435        }
1436    }
1437
1438    @Override
1439    public void verifyIntentFilter(int id, int verificationCode, List<String> outFailedDomains) {
1440        try {
1441            mPM.verifyIntentFilter(id, verificationCode, outFailedDomains);
1442        } catch (RemoteException e) {
1443            // Should never happen!
1444        }
1445    }
1446
1447    @Override
1448    public int getIntentVerificationStatus(String packageName, int userId) {
1449        try {
1450            return mPM.getIntentVerificationStatus(packageName, userId);
1451        } catch (RemoteException e) {
1452            // Should never happen!
1453            return PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
1454        }
1455    }
1456
1457    @Override
1458    public boolean updateIntentVerificationStatus(String packageName, int status, int userId) {
1459        try {
1460            return mPM.updateIntentVerificationStatus(packageName, status, userId);
1461        } catch (RemoteException e) {
1462            // Should never happen!
1463            return false;
1464        }
1465    }
1466
1467    @Override
1468    public List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
1469        try {
1470            return mPM.getIntentFilterVerifications(packageName);
1471        } catch (RemoteException e) {
1472            // Should never happen!
1473            return null;
1474        }
1475    }
1476
1477    @Override
1478    public List<IntentFilter> getAllIntentFilters(String packageName) {
1479        try {
1480            return mPM.getAllIntentFilters(packageName);
1481        } catch (RemoteException e) {
1482            // Should never happen!
1483            return null;
1484        }
1485    }
1486
1487    @Override
1488    public String getDefaultBrowserPackageName(int userId) {
1489        try {
1490            return mPM.getDefaultBrowserPackageName(userId);
1491        } catch (RemoteException e) {
1492            // Should never happen!
1493            return null;
1494        }
1495    }
1496
1497    @Override
1498    public boolean setDefaultBrowserPackageName(String packageName, int userId) {
1499        try {
1500            return mPM.setDefaultBrowserPackageName(packageName, userId);
1501        } catch (RemoteException e) {
1502            // Should never happen!
1503            return false;
1504        }
1505    }
1506
1507    @Override
1508    public void setInstallerPackageName(String targetPackage,
1509            String installerPackageName) {
1510        try {
1511            mPM.setInstallerPackageName(targetPackage, installerPackageName);
1512        } catch (RemoteException e) {
1513            // Should never happen!
1514        }
1515    }
1516
1517    @Override
1518    public String getInstallerPackageName(String packageName) {
1519        try {
1520            return mPM.getInstallerPackageName(packageName);
1521        } catch (RemoteException e) {
1522            // Should never happen!
1523        }
1524        return null;
1525    }
1526
1527    @Override
1528    public int getMoveStatus(int moveId) {
1529        try {
1530            return mPM.getMoveStatus(moveId);
1531        } catch (RemoteException e) {
1532            throw e.rethrowAsRuntimeException();
1533        }
1534    }
1535
1536    @Override
1537    public void registerMoveCallback(MoveCallback callback, Handler handler) {
1538        synchronized (mDelegates) {
1539            final MoveCallbackDelegate delegate = new MoveCallbackDelegate(callback,
1540                    handler.getLooper());
1541            try {
1542                mPM.registerMoveCallback(delegate);
1543            } catch (RemoteException e) {
1544                throw e.rethrowAsRuntimeException();
1545            }
1546            mDelegates.add(delegate);
1547        }
1548    }
1549
1550    @Override
1551    public void unregisterMoveCallback(MoveCallback callback) {
1552        synchronized (mDelegates) {
1553            for (Iterator<MoveCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
1554                final MoveCallbackDelegate delegate = i.next();
1555                if (delegate.mCallback == callback) {
1556                    try {
1557                        mPM.unregisterMoveCallback(delegate);
1558                    } catch (RemoteException e) {
1559                        throw e.rethrowAsRuntimeException();
1560                    }
1561                    i.remove();
1562                }
1563            }
1564        }
1565    }
1566
1567    @Override
1568    public int movePackage(String packageName, VolumeInfo vol) {
1569        try {
1570            final String volumeUuid;
1571            if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) {
1572                volumeUuid = StorageManager.UUID_PRIVATE_INTERNAL;
1573            } else if (vol.isPrimaryPhysical()) {
1574                volumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL;
1575            } else {
1576                volumeUuid = Preconditions.checkNotNull(vol.fsUuid);
1577            }
1578
1579            return mPM.movePackage(packageName, volumeUuid);
1580        } catch (RemoteException e) {
1581            throw e.rethrowAsRuntimeException();
1582        }
1583    }
1584
1585    @Override
1586    public @Nullable VolumeInfo getPackageCurrentVolume(ApplicationInfo app) {
1587        final StorageManager storage = mContext.getSystemService(StorageManager.class);
1588        if (app.isInternal()) {
1589            return storage.findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL);
1590        } else if (app.isExternalAsec()) {
1591            return storage.getPrimaryPhysicalVolume();
1592        } else {
1593            return storage.findVolumeByUuid(app.volumeUuid);
1594        }
1595    }
1596
1597    @Override
1598    public @NonNull List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app) {
1599        final StorageManager storage = mContext.getSystemService(StorageManager.class);
1600        final VolumeInfo currentVol = getPackageCurrentVolume(app);
1601        final List<VolumeInfo> vols = storage.getVolumes();
1602        final List<VolumeInfo> candidates = new ArrayList<>();
1603        for (VolumeInfo vol : vols) {
1604            if (Objects.equals(vol, currentVol) || isPackageCandidateVolume(app, vol)) {
1605                candidates.add(vol);
1606            }
1607        }
1608        return candidates;
1609    }
1610
1611    private static boolean isPackageCandidateVolume(ApplicationInfo app, VolumeInfo vol) {
1612        // Private internal is always an option
1613        if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.getId())) {
1614            return true;
1615        }
1616
1617        // System apps and apps demanding internal storage can't be moved
1618        // anywhere else
1619        if (app.isSystemApp()
1620                || app.installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
1621            return false;
1622        }
1623
1624        // Gotta be able to write there
1625        if (!vol.isMountedWritable()) {
1626            return false;
1627        }
1628
1629        // Moving into an ASEC on public primary is only option internal
1630        if (vol.isPrimaryPhysical()) {
1631            return app.isInternal();
1632        }
1633
1634        // Otherwise we can move to any private volume
1635        return (vol.getType() == VolumeInfo.TYPE_PRIVATE);
1636    }
1637
1638    @Override
1639    public int movePrimaryStorage(VolumeInfo vol) {
1640        try {
1641            final String volumeUuid;
1642            if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.id)) {
1643                volumeUuid = StorageManager.UUID_PRIVATE_INTERNAL;
1644            } else if (vol.isPrimaryPhysical()) {
1645                volumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL;
1646            } else {
1647                volumeUuid = Preconditions.checkNotNull(vol.fsUuid);
1648            }
1649
1650            return mPM.movePrimaryStorage(volumeUuid);
1651        } catch (RemoteException e) {
1652            throw e.rethrowAsRuntimeException();
1653        }
1654    }
1655
1656    @Override
1657    public @Nullable VolumeInfo getPrimaryStorageCurrentVolume() {
1658        final StorageManager storage = mContext.getSystemService(StorageManager.class);
1659        final String volumeUuid = storage.getPrimaryStorageUuid();
1660        return storage.findVolumeByQualifiedUuid(volumeUuid);
1661    }
1662
1663    @Override
1664    public @NonNull List<VolumeInfo> getPrimaryStorageCandidateVolumes() {
1665        final StorageManager storage = mContext.getSystemService(StorageManager.class);
1666        final VolumeInfo currentVol = getPrimaryStorageCurrentVolume();
1667        final List<VolumeInfo> vols = storage.getVolumes();
1668        final List<VolumeInfo> candidates = new ArrayList<>();
1669        if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL,
1670                storage.getPrimaryStorageUuid()) && currentVol != null) {
1671            // TODO: support moving primary physical to emulated volume
1672            candidates.add(currentVol);
1673        } else {
1674            for (VolumeInfo vol : vols) {
1675                if (Objects.equals(vol, currentVol) || isPrimaryStorageCandidateVolume(vol)) {
1676                    candidates.add(vol);
1677                }
1678            }
1679        }
1680        return candidates;
1681    }
1682
1683    private static boolean isPrimaryStorageCandidateVolume(VolumeInfo vol) {
1684        // Private internal is always an option
1685        if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.getId())) {
1686            return true;
1687        }
1688
1689        // Gotta be able to write there
1690        if (!vol.isMountedWritable()) {
1691            return false;
1692        }
1693
1694        // We can move to any private volume
1695        return (vol.getType() == VolumeInfo.TYPE_PRIVATE);
1696    }
1697
1698    @Override
1699    public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
1700        try {
1701            mPM.deletePackageAsUser(packageName, observer, UserHandle.myUserId(), flags);
1702        } catch (RemoteException e) {
1703            // Should never happen!
1704        }
1705    }
1706
1707    @Override
1708    public void clearApplicationUserData(String packageName,
1709                                         IPackageDataObserver observer) {
1710        try {
1711            mPM.clearApplicationUserData(packageName, observer, mContext.getUserId());
1712        } catch (RemoteException e) {
1713            // Should never happen!
1714        }
1715    }
1716    @Override
1717    public void deleteApplicationCacheFiles(String packageName,
1718                                            IPackageDataObserver observer) {
1719        try {
1720            mPM.deleteApplicationCacheFiles(packageName, observer);
1721        } catch (RemoteException e) {
1722            // Should never happen!
1723        }
1724    }
1725
1726    @Override
1727    public void freeStorageAndNotify(String volumeUuid, long idealStorageSize,
1728            IPackageDataObserver observer) {
1729        try {
1730            mPM.freeStorageAndNotify(volumeUuid, idealStorageSize, observer);
1731        } catch (RemoteException e) {
1732            // Should never happen!
1733        }
1734    }
1735
1736    @Override
1737    public void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi) {
1738        try {
1739            mPM.freeStorage(volumeUuid, freeStorageSize, pi);
1740        } catch (RemoteException e) {
1741            // Should never happen!
1742        }
1743    }
1744
1745    @Override
1746    public void getPackageSizeInfo(String packageName, int userHandle,
1747            IPackageStatsObserver observer) {
1748        try {
1749            mPM.getPackageSizeInfo(packageName, userHandle, observer);
1750        } catch (RemoteException e) {
1751            // Should never happen!
1752        }
1753    }
1754    @Override
1755    public void addPackageToPreferred(String packageName) {
1756        try {
1757            mPM.addPackageToPreferred(packageName);
1758        } catch (RemoteException e) {
1759            // Should never happen!
1760        }
1761    }
1762
1763    @Override
1764    public void removePackageFromPreferred(String packageName) {
1765        try {
1766            mPM.removePackageFromPreferred(packageName);
1767        } catch (RemoteException e) {
1768            // Should never happen!
1769        }
1770    }
1771
1772    @Override
1773    public List<PackageInfo> getPreferredPackages(int flags) {
1774        try {
1775            return mPM.getPreferredPackages(flags);
1776        } catch (RemoteException e) {
1777            // Should never happen!
1778        }
1779        return new ArrayList<PackageInfo>();
1780    }
1781
1782    @Override
1783    public void addPreferredActivity(IntentFilter filter,
1784                                     int match, ComponentName[] set, ComponentName activity) {
1785        try {
1786            mPM.addPreferredActivity(filter, match, set, activity, mContext.getUserId());
1787        } catch (RemoteException e) {
1788            // Should never happen!
1789        }
1790    }
1791
1792    @Override
1793    public void addPreferredActivity(IntentFilter filter, int match,
1794            ComponentName[] set, ComponentName activity, int userId) {
1795        try {
1796            mPM.addPreferredActivity(filter, match, set, activity, userId);
1797        } catch (RemoteException e) {
1798            // Should never happen!
1799        }
1800    }
1801
1802    @Override
1803    public void replacePreferredActivity(IntentFilter filter,
1804                                         int match, ComponentName[] set, ComponentName activity) {
1805        try {
1806            mPM.replacePreferredActivity(filter, match, set, activity, UserHandle.myUserId());
1807        } catch (RemoteException e) {
1808            // Should never happen!
1809        }
1810    }
1811
1812    @Override
1813    public void replacePreferredActivityAsUser(IntentFilter filter,
1814                                         int match, ComponentName[] set, ComponentName activity,
1815                                         int userId) {
1816        try {
1817            mPM.replacePreferredActivity(filter, match, set, activity, userId);
1818        } catch (RemoteException e) {
1819            // Should never happen!
1820        }
1821    }
1822
1823    @Override
1824    public void clearPackagePreferredActivities(String packageName) {
1825        try {
1826            mPM.clearPackagePreferredActivities(packageName);
1827        } catch (RemoteException e) {
1828            // Should never happen!
1829        }
1830    }
1831
1832    @Override
1833    public int getPreferredActivities(List<IntentFilter> outFilters,
1834                                      List<ComponentName> outActivities, String packageName) {
1835        try {
1836            return mPM.getPreferredActivities(outFilters, outActivities, packageName);
1837        } catch (RemoteException e) {
1838            // Should never happen!
1839        }
1840        return 0;
1841    }
1842
1843    @Override
1844    public ComponentName getHomeActivities(List<ResolveInfo> outActivities) {
1845        try {
1846            return mPM.getHomeActivities(outActivities);
1847        } catch (RemoteException e) {
1848            // Should never happen!
1849        }
1850        return null;
1851    }
1852
1853    @Override
1854    public void setComponentEnabledSetting(ComponentName componentName,
1855                                           int newState, int flags) {
1856        try {
1857            mPM.setComponentEnabledSetting(componentName, newState, flags, mContext.getUserId());
1858        } catch (RemoteException e) {
1859            // Should never happen!
1860        }
1861    }
1862
1863    @Override
1864    public int getComponentEnabledSetting(ComponentName componentName) {
1865        try {
1866            return mPM.getComponentEnabledSetting(componentName, mContext.getUserId());
1867        } catch (RemoteException e) {
1868            // Should never happen!
1869        }
1870        return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
1871    }
1872
1873    @Override
1874    public void setApplicationEnabledSetting(String packageName,
1875                                             int newState, int flags) {
1876        try {
1877            mPM.setApplicationEnabledSetting(packageName, newState, flags,
1878                    mContext.getUserId(), mContext.getOpPackageName());
1879        } catch (RemoteException e) {
1880            // Should never happen!
1881        }
1882    }
1883
1884    @Override
1885    public int getApplicationEnabledSetting(String packageName) {
1886        try {
1887            return mPM.getApplicationEnabledSetting(packageName, mContext.getUserId());
1888        } catch (RemoteException e) {
1889            // Should never happen!
1890        }
1891        return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
1892    }
1893
1894    @Override
1895    public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
1896            UserHandle user) {
1897        try {
1898            return mPM.setApplicationHiddenSettingAsUser(packageName, hidden,
1899                    user.getIdentifier());
1900        } catch (RemoteException re) {
1901            // Should never happen!
1902        }
1903        return false;
1904    }
1905
1906    @Override
1907    public boolean getApplicationHiddenSettingAsUser(String packageName, UserHandle user) {
1908        try {
1909            return mPM.getApplicationHiddenSettingAsUser(packageName, user.getIdentifier());
1910        } catch (RemoteException re) {
1911            // Should never happen!
1912        }
1913        return false;
1914    }
1915
1916    /** @hide */
1917    @Override
1918    public KeySet getKeySetByAlias(String packageName, String alias) {
1919        Preconditions.checkNotNull(packageName);
1920        Preconditions.checkNotNull(alias);
1921        KeySet ks;
1922        try {
1923            ks = mPM.getKeySetByAlias(packageName, alias);
1924        } catch (RemoteException e) {
1925            return null;
1926        }
1927        return ks;
1928    }
1929
1930    /** @hide */
1931    @Override
1932    public KeySet getSigningKeySet(String packageName) {
1933        Preconditions.checkNotNull(packageName);
1934        KeySet ks;
1935        try {
1936            ks = mPM.getSigningKeySet(packageName);
1937        } catch (RemoteException e) {
1938            return null;
1939        }
1940        return ks;
1941    }
1942
1943    /** @hide */
1944    @Override
1945    public boolean isSignedBy(String packageName, KeySet ks) {
1946        Preconditions.checkNotNull(packageName);
1947        Preconditions.checkNotNull(ks);
1948        try {
1949            return mPM.isPackageSignedByKeySet(packageName, ks);
1950        } catch (RemoteException e) {
1951            return false;
1952        }
1953    }
1954
1955    /** @hide */
1956    @Override
1957    public boolean isSignedByExactly(String packageName, KeySet ks) {
1958        Preconditions.checkNotNull(packageName);
1959        Preconditions.checkNotNull(ks);
1960        try {
1961            return mPM.isPackageSignedByKeySetExactly(packageName, ks);
1962        } catch (RemoteException e) {
1963            return false;
1964        }
1965    }
1966
1967    /**
1968     * @hide
1969     */
1970    @Override
1971    public VerifierDeviceIdentity getVerifierDeviceIdentity() {
1972        try {
1973            return mPM.getVerifierDeviceIdentity();
1974        } catch (RemoteException e) {
1975            // Should never happen!
1976        }
1977        return null;
1978    }
1979
1980    /**
1981     * @hide
1982     */
1983    @Override
1984    public boolean isUpgrade() {
1985        try {
1986            return mPM.isUpgrade();
1987        } catch (RemoteException e) {
1988            return false;
1989        }
1990    }
1991
1992    @Override
1993    public PackageInstaller getPackageInstaller() {
1994        synchronized (mLock) {
1995            if (mInstaller == null) {
1996                try {
1997                    mInstaller = new PackageInstaller(mContext, this, mPM.getPackageInstaller(),
1998                            mContext.getPackageName(), mContext.getUserId());
1999                } catch (RemoteException e) {
2000                    throw e.rethrowAsRuntimeException();
2001                }
2002            }
2003            return mInstaller;
2004        }
2005    }
2006
2007    @Override
2008    public boolean isPackageAvailable(String packageName) {
2009        try {
2010            return mPM.isPackageAvailable(packageName, mContext.getUserId());
2011        } catch (RemoteException e) {
2012            throw e.rethrowAsRuntimeException();
2013        }
2014    }
2015
2016    /**
2017     * @hide
2018     */
2019    @Override
2020    public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId,
2021            int flags) {
2022        try {
2023            mPM.addCrossProfileIntentFilter(filter, mContext.getOpPackageName(),
2024                    sourceUserId, targetUserId, flags);
2025        } catch (RemoteException e) {
2026            // Should never happen!
2027        }
2028    }
2029
2030    /**
2031     * @hide
2032     */
2033    @Override
2034    public void clearCrossProfileIntentFilters(int sourceUserId) {
2035        try {
2036            mPM.clearCrossProfileIntentFilters(sourceUserId, mContext.getOpPackageName());
2037        } catch (RemoteException e) {
2038            // Should never happen!
2039        }
2040    }
2041
2042    /**
2043     * @hide
2044     */
2045    public Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
2046        Drawable dr = loadUnbadgedItemIcon(itemInfo, appInfo);
2047        if (itemInfo.showUserIcon != UserHandle.USER_NULL) {
2048            return dr;
2049        }
2050        return getUserBadgedIcon(dr, new UserHandle(mContext.getUserId()));
2051    }
2052
2053    /**
2054     * @hide
2055     */
2056    public Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
2057        if (itemInfo.showUserIcon != UserHandle.USER_NULL) {
2058            Bitmap bitmap = getUserManager().getUserIcon(itemInfo.showUserIcon);
2059            if (bitmap == null) {
2060                return UserIcons.getDefaultUserIcon(itemInfo.showUserIcon, /* light= */ false);
2061            }
2062            return new BitmapDrawable(bitmap);
2063        }
2064        Drawable dr = null;
2065        if (itemInfo.packageName != null) {
2066            dr = getDrawable(itemInfo.packageName, itemInfo.icon, appInfo);
2067        }
2068        if (dr == null) {
2069            dr = itemInfo.loadDefaultIcon(this);
2070        }
2071        return dr;
2072    }
2073
2074    private Drawable getBadgedDrawable(Drawable drawable, Drawable badgeDrawable,
2075            Rect badgeLocation, boolean tryBadgeInPlace) {
2076        final int badgedWidth = drawable.getIntrinsicWidth();
2077        final int badgedHeight = drawable.getIntrinsicHeight();
2078        final boolean canBadgeInPlace = tryBadgeInPlace
2079                && (drawable instanceof BitmapDrawable)
2080                && ((BitmapDrawable) drawable).getBitmap().isMutable();
2081
2082        final Bitmap bitmap;
2083        if (canBadgeInPlace) {
2084            bitmap = ((BitmapDrawable) drawable).getBitmap();
2085        } else {
2086            bitmap = Bitmap.createBitmap(badgedWidth, badgedHeight, Bitmap.Config.ARGB_8888);
2087        }
2088        Canvas canvas = new Canvas(bitmap);
2089
2090        if (!canBadgeInPlace) {
2091            drawable.setBounds(0, 0, badgedWidth, badgedHeight);
2092            drawable.draw(canvas);
2093        }
2094
2095        if (badgeLocation != null) {
2096            if (badgeLocation.left < 0 || badgeLocation.top < 0
2097                    || badgeLocation.width() > badgedWidth || badgeLocation.height() > badgedHeight) {
2098                throw new IllegalArgumentException("Badge location " + badgeLocation
2099                        + " not in badged drawable bounds "
2100                        + new Rect(0, 0, badgedWidth, badgedHeight));
2101            }
2102            badgeDrawable.setBounds(0, 0, badgeLocation.width(), badgeLocation.height());
2103
2104            canvas.save();
2105            canvas.translate(badgeLocation.left, badgeLocation.top);
2106            badgeDrawable.draw(canvas);
2107            canvas.restore();
2108        } else {
2109            badgeDrawable.setBounds(0, 0, badgedWidth, badgedHeight);
2110            badgeDrawable.draw(canvas);
2111        }
2112
2113        if (!canBadgeInPlace) {
2114            BitmapDrawable mergedDrawable = new BitmapDrawable(mContext.getResources(), bitmap);
2115
2116            if (drawable instanceof BitmapDrawable) {
2117                BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
2118                mergedDrawable.setTargetDensity(bitmapDrawable.getBitmap().getDensity());
2119            }
2120
2121            return mergedDrawable;
2122        }
2123
2124        return drawable;
2125    }
2126
2127    private int getBadgeResIdForUser(int userHandle) {
2128        // Return the framework-provided badge.
2129        UserInfo userInfo = getUserIfProfile(userHandle);
2130        if (userInfo != null && userInfo.isManagedProfile()) {
2131            return com.android.internal.R.drawable.ic_corp_icon_badge;
2132        }
2133        return 0;
2134    }
2135
2136    private UserInfo getUserIfProfile(int userHandle) {
2137        List<UserInfo> userProfiles = getUserManager().getProfiles(UserHandle.myUserId());
2138        for (UserInfo user : userProfiles) {
2139            if (user.id == userHandle) {
2140                return user;
2141            }
2142        }
2143        return null;
2144    }
2145
2146    /** {@hide} */
2147    private static class MoveCallbackDelegate extends IPackageMoveObserver.Stub implements
2148            Handler.Callback {
2149        private static final int MSG_CREATED = 1;
2150        private static final int MSG_STATUS_CHANGED = 2;
2151
2152        final MoveCallback mCallback;
2153        final Handler mHandler;
2154
2155        public MoveCallbackDelegate(MoveCallback callback, Looper looper) {
2156            mCallback = callback;
2157            mHandler = new Handler(looper, this);
2158        }
2159
2160        @Override
2161        public boolean handleMessage(Message msg) {
2162            switch (msg.what) {
2163                case MSG_CREATED: {
2164                    final SomeArgs args = (SomeArgs) msg.obj;
2165                    mCallback.onCreated(args.argi1, (Bundle) args.arg2);
2166                    args.recycle();
2167                    return true;
2168                }
2169                case MSG_STATUS_CHANGED: {
2170                    final SomeArgs args = (SomeArgs) msg.obj;
2171                    mCallback.onStatusChanged(args.argi1, args.argi2, (long) args.arg3);
2172                    args.recycle();
2173                    return true;
2174                }
2175            }
2176            return false;
2177        }
2178
2179        @Override
2180        public void onCreated(int moveId, Bundle extras) {
2181            final SomeArgs args = SomeArgs.obtain();
2182            args.argi1 = moveId;
2183            args.arg2 = extras;
2184            mHandler.obtainMessage(MSG_CREATED, args).sendToTarget();
2185        }
2186
2187        @Override
2188        public void onStatusChanged(int moveId, int status, long estMillis) {
2189            final SomeArgs args = SomeArgs.obtain();
2190            args.argi1 = moveId;
2191            args.argi2 = status;
2192            args.arg3 = estMillis;
2193            mHandler.obtainMessage(MSG_STATUS_CHANGED, args).sendToTarget();
2194        }
2195    }
2196
2197    private final ContextImpl mContext;
2198    private final IPackageManager mPM;
2199
2200    private static final Object sSync = new Object();
2201    private static ArrayMap<ResourceName, WeakReference<Drawable.ConstantState>> sIconCache
2202            = new ArrayMap<ResourceName, WeakReference<Drawable.ConstantState>>();
2203    private static ArrayMap<ResourceName, WeakReference<CharSequence>> sStringCache
2204            = new ArrayMap<ResourceName, WeakReference<CharSequence>>();
2205
2206    private final Map<OnPermissionsChangedListener, IOnPermissionsChangeListener>
2207            mPermissionListeners = new ArrayMap<>();
2208
2209    public class OnPermissionsChangeListenerDelegate extends IOnPermissionsChangeListener.Stub
2210            implements Handler.Callback{
2211        private static final int MSG_PERMISSIONS_CHANGED = 1;
2212
2213        private final OnPermissionsChangedListener mListener;
2214        private final Handler mHandler;
2215
2216
2217        public OnPermissionsChangeListenerDelegate(OnPermissionsChangedListener listener,
2218                Looper looper) {
2219            mListener = listener;
2220            mHandler = new Handler(looper, this);
2221        }
2222
2223        @Override
2224        public void onPermissionsChanged(int uid) {
2225            mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
2226        }
2227
2228        @Override
2229        public boolean handleMessage(Message msg) {
2230            switch (msg.what) {
2231                case MSG_PERMISSIONS_CHANGED: {
2232                    final int uid = msg.arg1;
2233                    mListener.onPermissionsChanged(uid);
2234                    return true;
2235                }
2236            }
2237            return false;
2238        }
2239    }
2240}
2241