Home | History | Annotate | Download | only in pm
      1 /*
      2  * Copyright (C) 2014 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 
     17 package com.android.server.pm;
     18 
     19 import android.annotation.NonNull;
     20 import android.annotation.UserIdInt;
     21 import android.app.ActivityManager;
     22 import android.app.ActivityManagerInternal;
     23 import android.app.AppGlobals;
     24 import android.app.IApplicationThread;
     25 import android.app.PendingIntent;
     26 import android.content.ComponentName;
     27 import android.content.Context;
     28 import android.content.Intent;
     29 import android.content.IntentSender;
     30 import android.content.pm.ActivityInfo;
     31 import android.content.pm.ApplicationInfo;
     32 import android.content.pm.ILauncherApps;
     33 import android.content.pm.IOnAppsChangedListener;
     34 import android.content.pm.LauncherApps.ShortcutQuery;
     35 import android.content.pm.PackageInfo;
     36 import android.content.pm.PackageManager;
     37 import android.content.pm.PackageManagerInternal;
     38 import android.content.pm.ParceledListSlice;
     39 import android.content.pm.ResolveInfo;
     40 import android.content.pm.ShortcutInfo;
     41 import android.content.pm.ShortcutServiceInternal;
     42 import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
     43 import android.content.pm.UserInfo;
     44 import android.graphics.Rect;
     45 import android.net.Uri;
     46 import android.os.Binder;
     47 import android.os.Bundle;
     48 import android.os.Handler;
     49 import android.os.IInterface;
     50 import android.os.ParcelFileDescriptor;
     51 import android.os.RemoteCallbackList;
     52 import android.os.RemoteException;
     53 import android.os.UserHandle;
     54 import android.os.UserManager;
     55 import android.os.UserManagerInternal;
     56 import android.provider.Settings;
     57 import android.util.Log;
     58 import android.util.Slog;
     59 
     60 import com.android.internal.annotations.VisibleForTesting;
     61 import com.android.internal.content.PackageMonitor;
     62 import com.android.internal.os.BackgroundThread;
     63 import com.android.internal.util.Preconditions;
     64 import com.android.server.LocalServices;
     65 import com.android.server.SystemService;
     66 
     67 import java.util.Collections;
     68 import java.util.List;
     69 
     70 /**
     71  * Service that manages requests and callbacks for launchers that support
     72  * managed profiles.
     73  */
     74 public class LauncherAppsService extends SystemService {
     75 
     76     private final LauncherAppsImpl mLauncherAppsImpl;
     77 
     78     public LauncherAppsService(Context context) {
     79         super(context);
     80         mLauncherAppsImpl = new LauncherAppsImpl(context);
     81     }
     82 
     83     @Override
     84     public void onStart() {
     85         publishBinderService(Context.LAUNCHER_APPS_SERVICE, mLauncherAppsImpl);
     86     }
     87 
     88     static class BroadcastCookie {
     89         public final UserHandle user;
     90         public final String packageName;
     91         public final int callingUid;
     92         public final int callingPid;
     93 
     94         BroadcastCookie(UserHandle userHandle, String packageName, int callingPid, int callingUid) {
     95             this.user = userHandle;
     96             this.packageName = packageName;
     97             this.callingUid = callingUid;
     98             this.callingPid = callingPid;
     99         }
    100     }
    101 
    102     @VisibleForTesting
    103     static class LauncherAppsImpl extends ILauncherApps.Stub {
    104         private static final boolean DEBUG = false;
    105         private static final String TAG = "LauncherAppsService";
    106         private final Context mContext;
    107         private final UserManager mUm;
    108         private final UserManagerInternal mUserManagerInternal;
    109         private final ActivityManagerInternal mActivityManagerInternal;
    110         private final ShortcutServiceInternal mShortcutServiceInternal;
    111         private final PackageCallbackList<IOnAppsChangedListener> mListeners
    112                 = new PackageCallbackList<IOnAppsChangedListener>();
    113 
    114         private final MyPackageMonitor mPackageMonitor = new MyPackageMonitor();
    115 
    116         private final Handler mCallbackHandler;
    117 
    118         public LauncherAppsImpl(Context context) {
    119             mContext = context;
    120             mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
    121             mUserManagerInternal = Preconditions.checkNotNull(
    122                     LocalServices.getService(UserManagerInternal.class));
    123             mActivityManagerInternal = Preconditions.checkNotNull(
    124                     LocalServices.getService(ActivityManagerInternal.class));
    125             mShortcutServiceInternal = Preconditions.checkNotNull(
    126                     LocalServices.getService(ShortcutServiceInternal.class));
    127             mShortcutServiceInternal.addListener(mPackageMonitor);
    128             mCallbackHandler = BackgroundThread.getHandler();
    129         }
    130 
    131         @VisibleForTesting
    132         int injectBinderCallingUid() {
    133             return getCallingUid();
    134         }
    135 
    136         @VisibleForTesting
    137         int injectBinderCallingPid() {
    138             return getCallingPid();
    139         }
    140 
    141         final int injectCallingUserId() {
    142             return UserHandle.getUserId(injectBinderCallingUid());
    143         }
    144 
    145         @VisibleForTesting
    146         long injectClearCallingIdentity() {
    147             return Binder.clearCallingIdentity();
    148         }
    149 
    150         // Injection point.
    151         @VisibleForTesting
    152         void injectRestoreCallingIdentity(long token) {
    153             Binder.restoreCallingIdentity(token);
    154         }
    155 
    156         private int getCallingUserId() {
    157             return UserHandle.getUserId(injectBinderCallingUid());
    158         }
    159 
    160         /*
    161          * @see android.content.pm.ILauncherApps#addOnAppsChangedListener(
    162          *          android.content.pm.IOnAppsChangedListener)
    163          */
    164         @Override
    165         public void addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener)
    166                 throws RemoteException {
    167             verifyCallingPackage(callingPackage);
    168             synchronized (mListeners) {
    169                 if (DEBUG) {
    170                     Log.d(TAG, "Adding listener from " + Binder.getCallingUserHandle());
    171                 }
    172                 if (mListeners.getRegisteredCallbackCount() == 0) {
    173                     if (DEBUG) {
    174                         Log.d(TAG, "Starting package monitoring");
    175                     }
    176                     startWatchingPackageBroadcasts();
    177                 }
    178                 mListeners.unregister(listener);
    179                 mListeners.register(listener, new BroadcastCookie(UserHandle.of(getCallingUserId()),
    180                         callingPackage, injectBinderCallingPid(), injectBinderCallingUid()));
    181             }
    182         }
    183 
    184         /*
    185          * @see android.content.pm.ILauncherApps#removeOnAppsChangedListener(
    186          *          android.content.pm.IOnAppsChangedListener)
    187          */
    188         @Override
    189         public void removeOnAppsChangedListener(IOnAppsChangedListener listener)
    190                 throws RemoteException {
    191             synchronized (mListeners) {
    192                 if (DEBUG) {
    193                     Log.d(TAG, "Removing listener from " + Binder.getCallingUserHandle());
    194                 }
    195                 mListeners.unregister(listener);
    196                 if (mListeners.getRegisteredCallbackCount() == 0) {
    197                     stopWatchingPackageBroadcasts();
    198                 }
    199             }
    200         }
    201 
    202         /**
    203          * Register a receiver to watch for package broadcasts
    204          */
    205         private void startWatchingPackageBroadcasts() {
    206             mPackageMonitor.register(mContext, UserHandle.ALL, true, mCallbackHandler);
    207         }
    208 
    209         /**
    210          * Unregister package broadcast receiver
    211          */
    212         private void stopWatchingPackageBroadcasts() {
    213             if (DEBUG) {
    214                 Log.d(TAG, "Stopped watching for packages");
    215             }
    216             mPackageMonitor.unregister();
    217         }
    218 
    219         void checkCallbackCount() {
    220             synchronized (mListeners) {
    221                 if (DEBUG) {
    222                     Log.d(TAG, "Callback count = " + mListeners.getRegisteredCallbackCount());
    223                 }
    224                 if (mListeners.getRegisteredCallbackCount() == 0) {
    225                     stopWatchingPackageBroadcasts();
    226                 }
    227             }
    228         }
    229 
    230         /**
    231          * Checks if the calling user is in the same group as {@code targetUser}, and allowed
    232          * to access it.
    233          *
    234          * @return TRUE if the calling user can access {@code targetUserId}.  FALSE if not *but
    235          * they're still in the same profile group*.
    236          *
    237          * @throws SecurityException if the calling user and {@code targetUser} are not in the same
    238          * group.
    239          */
    240         private boolean canAccessProfile(int targetUserId, String message) {
    241             final int callingUserId = injectCallingUserId();
    242 
    243             if (targetUserId == callingUserId) return true;
    244 
    245             long ident = injectClearCallingIdentity();
    246             try {
    247                 final UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
    248                 if (callingUserInfo != null && callingUserInfo.isManagedProfile()) {
    249                     Slog.w(TAG, message + " for another profile "
    250                             + targetUserId + " from " + callingUserId + " not allowed");
    251                     return false;
    252                 }
    253             } finally {
    254                 injectRestoreCallingIdentity(ident);
    255             }
    256 
    257             return mUserManagerInternal.isProfileAccessible(injectCallingUserId(), targetUserId,
    258                     message, true);
    259         }
    260 
    261         @VisibleForTesting // We override it in unit tests
    262         void verifyCallingPackage(String callingPackage) {
    263             int packageUid = -1;
    264             try {
    265                 packageUid = AppGlobals.getPackageManager().getPackageUid(callingPackage,
    266                         PackageManager.MATCH_DIRECT_BOOT_AWARE
    267                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
    268                                 | PackageManager.MATCH_UNINSTALLED_PACKAGES,
    269                         UserHandle.getUserId(getCallingUid()));
    270             } catch (RemoteException ignore) {
    271             }
    272             if (packageUid < 0) {
    273                 Log.e(TAG, "Package not found: " + callingPackage);
    274             }
    275             if (packageUid != injectBinderCallingUid()) {
    276                 throw new SecurityException("Calling package name mismatch");
    277             }
    278         }
    279 
    280         @Override
    281         public ParceledListSlice<ResolveInfo> getLauncherActivities(String callingPackage,
    282                 String packageName, UserHandle user)
    283                 throws RemoteException {
    284             return queryActivitiesForUser(callingPackage,
    285                     new Intent(Intent.ACTION_MAIN)
    286                             .addCategory(Intent.CATEGORY_LAUNCHER)
    287                             .setPackage(packageName),
    288                     user);
    289         }
    290 
    291         @Override
    292         public ActivityInfo resolveActivity(
    293                 String callingPackage, ComponentName component, UserHandle user)
    294                 throws RemoteException {
    295             if (!canAccessProfile(user.getIdentifier(), "Cannot resolve activity")) {
    296                 return null;
    297             }
    298 
    299             final int callingUid = injectBinderCallingUid();
    300             long ident = Binder.clearCallingIdentity();
    301             try {
    302                 final PackageManagerInternal pmInt =
    303                         LocalServices.getService(PackageManagerInternal.class);
    304                 return pmInt.getActivityInfo(component,
    305                         PackageManager.MATCH_DIRECT_BOOT_AWARE
    306                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
    307                         callingUid, user.getIdentifier());
    308             } finally {
    309                 Binder.restoreCallingIdentity(ident);
    310             }
    311         }
    312 
    313         @Override
    314         public ParceledListSlice getShortcutConfigActivities(
    315                 String callingPackage, String packageName, UserHandle user)
    316                 throws RemoteException {
    317             return queryActivitiesForUser(callingPackage,
    318                     new Intent(Intent.ACTION_CREATE_SHORTCUT).setPackage(packageName), user);
    319         }
    320 
    321         private ParceledListSlice<ResolveInfo> queryActivitiesForUser(String callingPackage,
    322                 Intent intent, UserHandle user) {
    323             if (!canAccessProfile(user.getIdentifier(), "Cannot retrieve activities")) {
    324                 return null;
    325             }
    326 
    327             final int callingUid = injectBinderCallingUid();
    328             long ident = injectClearCallingIdentity();
    329             try {
    330                 final PackageManagerInternal pmInt =
    331                         LocalServices.getService(PackageManagerInternal.class);
    332                 List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
    333                         PackageManager.MATCH_DIRECT_BOOT_AWARE
    334                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
    335                         callingUid, user.getIdentifier());
    336                 return new ParceledListSlice<>(apps);
    337             } finally {
    338                 injectRestoreCallingIdentity(ident);
    339             }
    340         }
    341 
    342         @Override
    343         public IntentSender getShortcutConfigActivityIntent(String callingPackage,
    344                 ComponentName component, UserHandle user) throws RemoteException {
    345             ensureShortcutPermission(callingPackage);
    346             if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
    347                 return null;
    348             }
    349             Preconditions.checkNotNull(component);
    350 
    351             // All right, create the sender.
    352             Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT).setComponent(component);
    353             final long identity = Binder.clearCallingIdentity();
    354             try {
    355                 final PendingIntent pi = PendingIntent.getActivityAsUser(
    356                         mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT
    357                                 | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT,
    358                         null, user);
    359                 return pi == null ? null : pi.getIntentSender();
    360             } finally {
    361                 Binder.restoreCallingIdentity(identity);
    362             }
    363         }
    364 
    365         @Override
    366         public boolean isPackageEnabled(String callingPackage, String packageName, UserHandle user)
    367                 throws RemoteException {
    368             if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
    369                 return false;
    370             }
    371 
    372             final int callingUid = injectBinderCallingUid();
    373             long ident = Binder.clearCallingIdentity();
    374             try {
    375                 final PackageManagerInternal pmInt =
    376                         LocalServices.getService(PackageManagerInternal.class);
    377                 PackageInfo info = pmInt.getPackageInfo(packageName,
    378                         PackageManager.MATCH_DIRECT_BOOT_AWARE
    379                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
    380                         callingUid, user.getIdentifier());
    381                 return info != null && info.applicationInfo.enabled;
    382             } finally {
    383                 Binder.restoreCallingIdentity(ident);
    384             }
    385         }
    386 
    387         @Override
    388         public Bundle getSuspendedPackageLauncherExtras(String packageName,
    389                 UserHandle user) {
    390             if (!canAccessProfile(user.getIdentifier(), "Cannot get launcher extras")) {
    391                 return null;
    392             }
    393             final PackageManagerInternal pmi =
    394                     LocalServices.getService(PackageManagerInternal.class);
    395             return pmi.getSuspendedPackageLauncherExtras(packageName, user.getIdentifier());
    396         }
    397 
    398         @Override
    399         public ApplicationInfo getApplicationInfo(
    400                 String callingPackage, String packageName, int flags, UserHandle user)
    401                 throws RemoteException {
    402             if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
    403                 return null;
    404             }
    405 
    406             final int callingUid = injectBinderCallingUid();
    407             long ident = Binder.clearCallingIdentity();
    408             try {
    409                 final PackageManagerInternal pmInt =
    410                         LocalServices.getService(PackageManagerInternal.class);
    411                 ApplicationInfo info = pmInt.getApplicationInfo(packageName, flags,
    412                         callingUid, user.getIdentifier());
    413                 return info;
    414             } finally {
    415                 Binder.restoreCallingIdentity(ident);
    416             }
    417         }
    418 
    419         private void ensureShortcutPermission(@NonNull String callingPackage) {
    420             verifyCallingPackage(callingPackage);
    421             if (!mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
    422                     callingPackage, injectBinderCallingPid(), injectBinderCallingUid())) {
    423                 throw new SecurityException("Caller can't access shortcut information");
    424             }
    425         }
    426 
    427         @Override
    428         public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
    429                 String packageName, List shortcutIds, ComponentName componentName, int flags,
    430                 UserHandle targetUser) {
    431             ensureShortcutPermission(callingPackage);
    432             if (!canAccessProfile(targetUser.getIdentifier(), "Cannot get shortcuts")) {
    433                 return new ParceledListSlice<>(Collections.EMPTY_LIST);
    434             }
    435             if (shortcutIds != null && packageName == null) {
    436                 throw new IllegalArgumentException(
    437                         "To query by shortcut ID, package name must also be set");
    438             }
    439 
    440             // TODO(b/29399275): Eclipse compiler requires explicit List<ShortcutInfo> cast below.
    441             return new ParceledListSlice<>((List<ShortcutInfo>)
    442                     mShortcutServiceInternal.getShortcuts(getCallingUserId(),
    443                             callingPackage, changedSince, packageName, shortcutIds,
    444                             componentName, flags, targetUser.getIdentifier(),
    445                             injectBinderCallingPid(), injectBinderCallingUid()));
    446         }
    447 
    448         @Override
    449         public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
    450                 UserHandle targetUser) {
    451             ensureShortcutPermission(callingPackage);
    452             if (!canAccessProfile(targetUser.getIdentifier(), "Cannot pin shortcuts")) {
    453                 return;
    454             }
    455 
    456             mShortcutServiceInternal.pinShortcuts(getCallingUserId(),
    457                     callingPackage, packageName, ids, targetUser.getIdentifier());
    458         }
    459 
    460         @Override
    461         public int getShortcutIconResId(String callingPackage, String packageName, String id,
    462                 int targetUserId) {
    463             ensureShortcutPermission(callingPackage);
    464             if (!canAccessProfile(targetUserId, "Cannot access shortcuts")) {
    465                 return 0;
    466             }
    467 
    468             return mShortcutServiceInternal.getShortcutIconResId(getCallingUserId(),
    469                     callingPackage, packageName, id, targetUserId);
    470         }
    471 
    472         @Override
    473         public ParcelFileDescriptor getShortcutIconFd(String callingPackage,
    474                 String packageName, String id, int targetUserId) {
    475             ensureShortcutPermission(callingPackage);
    476             if (!canAccessProfile(targetUserId, "Cannot access shortcuts")) {
    477                 return null;
    478             }
    479 
    480             return mShortcutServiceInternal.getShortcutIconFd(getCallingUserId(),
    481                     callingPackage, packageName, id, targetUserId);
    482         }
    483 
    484         @Override
    485         public boolean hasShortcutHostPermission(String callingPackage) {
    486             verifyCallingPackage(callingPackage);
    487             return mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
    488                     callingPackage, injectBinderCallingPid(), injectBinderCallingUid());
    489         }
    490 
    491         @Override
    492         public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
    493                 Rect sourceBounds, Bundle startActivityOptions, int targetUserId) {
    494             verifyCallingPackage(callingPackage);
    495             if (!canAccessProfile(targetUserId, "Cannot start activity")) {
    496                 return false;
    497             }
    498 
    499             // Even without the permission, pinned shortcuts are always launchable.
    500             if (!mShortcutServiceInternal.isPinnedByCaller(getCallingUserId(),
    501                     callingPackage, packageName, shortcutId, targetUserId)) {
    502                 ensureShortcutPermission(callingPackage);
    503             }
    504 
    505             final Intent[] intents = mShortcutServiceInternal.createShortcutIntents(
    506                     getCallingUserId(), callingPackage, packageName, shortcutId, targetUserId,
    507                     injectBinderCallingPid(), injectBinderCallingUid());
    508             if (intents == null || intents.length == 0) {
    509                 return false;
    510             }
    511             // Note the target activity doesn't have to be exported.
    512 
    513             intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    514             intents[0].setSourceBounds(sourceBounds);
    515 
    516             return startShortcutIntentsAsPublisher(
    517                     intents, packageName, startActivityOptions, targetUserId);
    518         }
    519 
    520         private boolean startShortcutIntentsAsPublisher(@NonNull Intent[] intents,
    521                 @NonNull String publisherPackage, Bundle startActivityOptions, int userId) {
    522             final int code;
    523             try {
    524                 code = mActivityManagerInternal.startActivitiesAsPackage(publisherPackage,
    525                         userId, intents, startActivityOptions);
    526                 if (ActivityManager.isStartResultSuccessful(code)) {
    527                     return true; // Success
    528                 } else {
    529                     Log.e(TAG, "Couldn't start activity, code=" + code);
    530                 }
    531                 return false;
    532             } catch (SecurityException e) {
    533                 if (DEBUG) {
    534                     Slog.d(TAG, "SecurityException while launching intent", e);
    535                 }
    536                 return false;
    537             }
    538         }
    539 
    540         @Override
    541         public boolean isActivityEnabled(
    542                 String callingPackage, ComponentName component, UserHandle user)
    543                 throws RemoteException {
    544             if (!canAccessProfile(user.getIdentifier(), "Cannot check component")) {
    545                 return false;
    546             }
    547 
    548             final int callingUid = injectBinderCallingUid();
    549             long ident = Binder.clearCallingIdentity();
    550             try {
    551                 final PackageManagerInternal pmInt =
    552                         LocalServices.getService(PackageManagerInternal.class);
    553                 ActivityInfo info = pmInt.getActivityInfo(component,
    554                         PackageManager.MATCH_DIRECT_BOOT_AWARE
    555                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
    556                         callingUid, user.getIdentifier());
    557                 return info != null;
    558             } finally {
    559                 Binder.restoreCallingIdentity(ident);
    560             }
    561         }
    562 
    563         @Override
    564         public void startActivityAsUser(IApplicationThread caller, String callingPackage,
    565                 ComponentName component, Rect sourceBounds,
    566                 Bundle opts, UserHandle user) throws RemoteException {
    567             if (!canAccessProfile(user.getIdentifier(), "Cannot start activity")) {
    568                 return;
    569             }
    570 
    571             Intent launchIntent = new Intent(Intent.ACTION_MAIN);
    572             launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    573             launchIntent.setSourceBounds(sourceBounds);
    574             launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
    575                     | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
    576             launchIntent.setPackage(component.getPackageName());
    577 
    578             boolean canLaunch = false;
    579 
    580             final int callingUid = injectBinderCallingUid();
    581             long ident = Binder.clearCallingIdentity();
    582             try {
    583                 final PackageManagerInternal pmInt =
    584                         LocalServices.getService(PackageManagerInternal.class);
    585                 ActivityInfo info = pmInt.getActivityInfo(component,
    586                         PackageManager.MATCH_DIRECT_BOOT_AWARE
    587                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
    588                         callingUid, user.getIdentifier());
    589                 if (!info.exported) {
    590                     throw new SecurityException("Cannot launch non-exported components "
    591                             + component);
    592                 }
    593 
    594                 // Check that the component actually has Intent.CATEGORY_LAUCNCHER
    595                 // as calling startActivityAsUser ignores the category and just
    596                 // resolves based on the component if present.
    597                 List<ResolveInfo> apps = pmInt.queryIntentActivities(launchIntent,
    598                         PackageManager.MATCH_DIRECT_BOOT_AWARE
    599                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
    600                         callingUid, user.getIdentifier());
    601                 final int size = apps.size();
    602                 for (int i = 0; i < size; ++i) {
    603                     ActivityInfo activityInfo = apps.get(i).activityInfo;
    604                     if (activityInfo.packageName.equals(component.getPackageName()) &&
    605                             activityInfo.name.equals(component.getClassName())) {
    606                         // Found an activity with category launcher that matches
    607                         // this component so ok to launch.
    608                         launchIntent.setPackage(null);
    609                         launchIntent.setComponent(component);
    610                         canLaunch = true;
    611                         break;
    612                     }
    613                 }
    614                 if (!canLaunch) {
    615                     throw new SecurityException("Attempt to launch activity without "
    616                             + " category Intent.CATEGORY_LAUNCHER " + component);
    617                 }
    618             } finally {
    619                 Binder.restoreCallingIdentity(ident);
    620             }
    621             mActivityManagerInternal.startActivityAsUser(caller, callingPackage,
    622                     launchIntent, opts, user.getIdentifier());
    623         }
    624 
    625         @Override
    626         public void showAppDetailsAsUser(IApplicationThread caller,
    627                 String callingPackage, ComponentName component,
    628                 Rect sourceBounds, Bundle opts, UserHandle user) throws RemoteException {
    629             if (!canAccessProfile(user.getIdentifier(), "Cannot show app details")) {
    630                 return;
    631             }
    632 
    633             final Intent intent;
    634             long ident = Binder.clearCallingIdentity();
    635             try {
    636                 String packageName = component.getPackageName();
    637                 intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
    638                         Uri.fromParts("package", packageName, null));
    639                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    640                 intent.setSourceBounds(sourceBounds);
    641             } finally {
    642                 Binder.restoreCallingIdentity(ident);
    643             }
    644             mActivityManagerInternal.startActivityAsUser(caller, callingPackage,
    645                     intent, opts, user.getIdentifier());
    646         }
    647 
    648         /** Checks if user is a profile of or same as listeningUser.
    649          * and the user is enabled. */
    650         private boolean isEnabledProfileOf(UserHandle listeningUser, UserHandle user,
    651                 String debugMsg) {
    652             return mUserManagerInternal.isProfileAccessible(listeningUser.getIdentifier(),
    653                     user.getIdentifier(), debugMsg, false);
    654         }
    655 
    656         @VisibleForTesting
    657         void postToPackageMonitorHandler(Runnable r) {
    658             mCallbackHandler.post(r);
    659         }
    660 
    661         private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener {
    662 
    663             // TODO Simplify with lambdas.
    664 
    665             @Override
    666             public void onPackageAdded(String packageName, int uid) {
    667                 UserHandle user = new UserHandle(getChangingUserId());
    668                 final int n = mListeners.beginBroadcast();
    669                 try {
    670                     for (int i = 0; i < n; i++) {
    671                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
    672                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
    673                         if (!isEnabledProfileOf(cookie.user, user, "onPackageAdded")) continue;
    674                         try {
    675                             listener.onPackageAdded(user, packageName);
    676                         } catch (RemoteException re) {
    677                             Slog.d(TAG, "Callback failed ", re);
    678                         }
    679                     }
    680                 } finally {
    681                     mListeners.finishBroadcast();
    682                 }
    683 
    684                 super.onPackageAdded(packageName, uid);
    685             }
    686 
    687             @Override
    688             public void onPackageRemoved(String packageName, int uid) {
    689                 UserHandle user = new UserHandle(getChangingUserId());
    690                 final int n = mListeners.beginBroadcast();
    691                 try {
    692                     for (int i = 0; i < n; i++) {
    693                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
    694                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
    695                         if (!isEnabledProfileOf(cookie.user, user, "onPackageRemoved")) continue;
    696                         try {
    697                             listener.onPackageRemoved(user, packageName);
    698                         } catch (RemoteException re) {
    699                             Slog.d(TAG, "Callback failed ", re);
    700                         }
    701                     }
    702                 } finally {
    703                     mListeners.finishBroadcast();
    704                 }
    705 
    706                 super.onPackageRemoved(packageName, uid);
    707             }
    708 
    709             @Override
    710             public void onPackageModified(String packageName) {
    711                 UserHandle user = new UserHandle(getChangingUserId());
    712                 final int n = mListeners.beginBroadcast();
    713                 try {
    714                     for (int i = 0; i < n; i++) {
    715                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
    716                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
    717                         if (!isEnabledProfileOf(cookie.user, user, "onPackageModified")) continue;
    718                         try {
    719                             listener.onPackageChanged(user, packageName);
    720                         } catch (RemoteException re) {
    721                             Slog.d(TAG, "Callback failed ", re);
    722                         }
    723                     }
    724                 } finally {
    725                     mListeners.finishBroadcast();
    726                 }
    727 
    728                 super.onPackageModified(packageName);
    729             }
    730 
    731             @Override
    732             public void onPackagesAvailable(String[] packages) {
    733                 UserHandle user = new UserHandle(getChangingUserId());
    734                 final int n = mListeners.beginBroadcast();
    735                 try {
    736                     for (int i = 0; i < n; i++) {
    737                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
    738                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
    739                         if (!isEnabledProfileOf(cookie.user, user, "onPackagesAvailable")) continue;
    740                         try {
    741                             listener.onPackagesAvailable(user, packages, isReplacing());
    742                         } catch (RemoteException re) {
    743                             Slog.d(TAG, "Callback failed ", re);
    744                         }
    745                     }
    746                 } finally {
    747                     mListeners.finishBroadcast();
    748                 }
    749 
    750                 super.onPackagesAvailable(packages);
    751             }
    752 
    753             @Override
    754             public void onPackagesUnavailable(String[] packages) {
    755                 UserHandle user = new UserHandle(getChangingUserId());
    756                 final int n = mListeners.beginBroadcast();
    757                 try {
    758                     for (int i = 0; i < n; i++) {
    759                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
    760                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
    761                         if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnavailable")) continue;
    762                         try {
    763                             listener.onPackagesUnavailable(user, packages, isReplacing());
    764                         } catch (RemoteException re) {
    765                             Slog.d(TAG, "Callback failed ", re);
    766                         }
    767                     }
    768                 } finally {
    769                     mListeners.finishBroadcast();
    770                 }
    771 
    772                 super.onPackagesUnavailable(packages);
    773             }
    774 
    775             @Override
    776             public void onPackagesSuspended(String[] packages, Bundle launcherExtras) {
    777                 UserHandle user = new UserHandle(getChangingUserId());
    778                 final int n = mListeners.beginBroadcast();
    779                 try {
    780                     for (int i = 0; i < n; i++) {
    781                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
    782                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
    783                         if (!isEnabledProfileOf(cookie.user, user, "onPackagesSuspended")) continue;
    784                         try {
    785                             listener.onPackagesSuspended(user, packages, launcherExtras);
    786                         } catch (RemoteException re) {
    787                             Slog.d(TAG, "Callback failed ", re);
    788                         }
    789                     }
    790                 } finally {
    791                     mListeners.finishBroadcast();
    792                 }
    793 
    794                 super.onPackagesSuspended(packages, launcherExtras);
    795             }
    796 
    797             @Override
    798             public void onPackagesUnsuspended(String[] packages) {
    799                 UserHandle user = new UserHandle(getChangingUserId());
    800                 final int n = mListeners.beginBroadcast();
    801                 try {
    802                     for (int i = 0; i < n; i++) {
    803                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
    804                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
    805                         if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnsuspended")) continue;
    806                         try {
    807                             listener.onPackagesUnsuspended(user, packages);
    808                         } catch (RemoteException re) {
    809                             Slog.d(TAG, "Callback failed ", re);
    810                         }
    811                     }
    812                 } finally {
    813                     mListeners.finishBroadcast();
    814                 }
    815 
    816                 super.onPackagesUnsuspended(packages);
    817             }
    818 
    819             @Override
    820             public void onShortcutChanged(@NonNull String packageName,
    821                     @UserIdInt int userId) {
    822                 postToPackageMonitorHandler(() -> onShortcutChangedInner(packageName, userId));
    823             }
    824 
    825             private void onShortcutChangedInner(@NonNull String packageName,
    826                     @UserIdInt int userId) {
    827                 final int n = mListeners.beginBroadcast();
    828                 try {
    829                     final UserHandle user = UserHandle.of(userId);
    830 
    831                     for (int i = 0; i < n; i++) {
    832                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
    833                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
    834                         if (!isEnabledProfileOf(cookie.user, user, "onShortcutChanged")) continue;
    835 
    836                         final int launcherUserId = cookie.user.getIdentifier();
    837 
    838                         // Make sure the caller has the permission.
    839                         if (!mShortcutServiceInternal.hasShortcutHostPermission(
    840                                 launcherUserId, cookie.packageName,
    841                                 cookie.callingPid, cookie.callingUid)) {
    842                             continue;
    843                         }
    844                         // Each launcher has a different set of pinned shortcuts, so we need to do a
    845                         // query in here.
    846                         // (As of now, only one launcher has the permission at a time, so it's bit
    847                         // moot, but we may change the permission model eventually.)
    848                         final List<ShortcutInfo> list =
    849                                 mShortcutServiceInternal.getShortcuts(launcherUserId,
    850                                         cookie.packageName,
    851                                         /* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
    852                                         /* component= */ null,
    853                                         ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
    854                                         | ShortcutQuery.FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED
    855                                         , userId, cookie.callingPid, cookie.callingUid);
    856                         try {
    857                             listener.onShortcutChanged(user, packageName,
    858                                     new ParceledListSlice<>(list));
    859                         } catch (RemoteException re) {
    860                             Slog.d(TAG, "Callback failed ", re);
    861                         }
    862                     }
    863                 } catch (RuntimeException e) {
    864                     // When the user is locked we get IllegalState, so just catch all.
    865                     Log.w(TAG, e.getMessage(), e);
    866                 } finally {
    867                     mListeners.finishBroadcast();
    868                 }
    869             }
    870         }
    871 
    872         class PackageCallbackList<T extends IInterface> extends RemoteCallbackList<T> {
    873             @Override
    874             public void onCallbackDied(T callback, Object cookie) {
    875                 checkCallbackCount();
    876             }
    877         }
    878     }
    879 }
    880