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