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