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