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 static android.app.ActivityOptions.KEY_SPLASH_SCREEN_THEME; 20 import static android.app.PendingIntent.FLAG_IMMUTABLE; 21 import static android.app.PendingIntent.FLAG_MUTABLE; 22 import static android.app.PendingIntent.FLAG_UPDATE_CURRENT; 23 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; 24 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT; 25 import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION; 26 import static android.content.pm.LauncherApps.FLAG_CACHE_BUBBLE_SHORTCUTS; 27 import static android.content.pm.LauncherApps.FLAG_CACHE_NOTIFICATION_SHORTCUTS; 28 import static android.content.pm.LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS; 29 30 import android.annotation.AppIdInt; 31 import android.annotation.NonNull; 32 import android.annotation.Nullable; 33 import android.annotation.UserIdInt; 34 import android.app.ActivityManager; 35 import android.app.ActivityManagerInternal; 36 import android.app.ActivityOptions; 37 import android.app.AppGlobals; 38 import android.app.IApplicationThread; 39 import android.app.PendingIntent; 40 import android.app.admin.DevicePolicyManager; 41 import android.app.usage.UsageStatsManagerInternal; 42 import android.content.ActivityNotFoundException; 43 import android.content.BroadcastReceiver; 44 import android.content.ComponentName; 45 import android.content.Context; 46 import android.content.Intent; 47 import android.content.IntentFilter; 48 import android.content.IntentSender; 49 import android.content.LocusId; 50 import android.content.pm.ActivityInfo; 51 import android.content.pm.ApplicationInfo; 52 import android.content.pm.ILauncherApps; 53 import android.content.pm.IOnAppsChangedListener; 54 import android.content.pm.IPackageInstallerCallback; 55 import android.content.pm.IPackageManager; 56 import android.content.pm.IShortcutChangeCallback; 57 import android.content.pm.IncrementalStatesInfo; 58 import android.content.pm.LauncherActivityInfoInternal; 59 import android.content.pm.LauncherApps; 60 import android.content.pm.LauncherApps.ShortcutQuery; 61 import android.content.pm.PackageInfo; 62 import android.content.pm.PackageInstaller.SessionInfo; 63 import android.content.pm.PackageManager; 64 import android.content.pm.PackageManagerInternal; 65 import android.content.pm.ParceledListSlice; 66 import android.content.pm.ResolveInfo; 67 import android.content.pm.ShortcutInfo; 68 import android.content.pm.ShortcutQueryWrapper; 69 import android.content.pm.ShortcutServiceInternal; 70 import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener; 71 import android.content.pm.UserInfo; 72 import android.graphics.Rect; 73 import android.net.Uri; 74 import android.os.Binder; 75 import android.os.Bundle; 76 import android.os.Handler; 77 import android.os.IInterface; 78 import android.os.ParcelFileDescriptor; 79 import android.os.Process; 80 import android.os.RemoteCallbackList; 81 import android.os.RemoteException; 82 import android.os.ServiceManager; 83 import android.os.UserHandle; 84 import android.os.UserManager; 85 import android.provider.Settings; 86 import android.util.Log; 87 import android.util.Pair; 88 import android.util.Slog; 89 90 import com.android.internal.annotations.GuardedBy; 91 import com.android.internal.annotations.VisibleForTesting; 92 import com.android.internal.content.PackageMonitor; 93 import com.android.internal.infra.AndroidFuture; 94 import com.android.internal.os.BackgroundThread; 95 import com.android.internal.util.ArrayUtils; 96 import com.android.internal.util.CollectionUtils; 97 import com.android.internal.util.Preconditions; 98 import com.android.server.LocalServices; 99 import com.android.server.SystemService; 100 import com.android.server.pm.parsing.pkg.AndroidPackage; 101 import com.android.server.wm.ActivityTaskManagerInternal; 102 103 import java.util.ArrayList; 104 import java.util.Arrays; 105 import java.util.Collections; 106 import java.util.HashSet; 107 import java.util.List; 108 import java.util.Objects; 109 import java.util.concurrent.ExecutionException; 110 111 /** 112 * Service that manages requests and callbacks for launchers that support 113 * managed profiles. 114 */ 115 public class LauncherAppsService extends SystemService { 116 117 private final LauncherAppsImpl mLauncherAppsImpl; 118 LauncherAppsService(Context context)119 public LauncherAppsService(Context context) { 120 super(context); 121 mLauncherAppsImpl = new LauncherAppsImpl(context); 122 } 123 124 @Override onStart()125 public void onStart() { 126 publishBinderService(Context.LAUNCHER_APPS_SERVICE, mLauncherAppsImpl); 127 mLauncherAppsImpl.registerLoadingProgressForIncrementalApps(); 128 LocalServices.addService(LauncherAppsServiceInternal.class, mLauncherAppsImpl.mInternal); 129 } 130 131 static class BroadcastCookie { 132 public final UserHandle user; 133 public final String packageName; 134 public final int callingUid; 135 public final int callingPid; 136 BroadcastCookie(UserHandle userHandle, String packageName, int callingPid, int callingUid)137 BroadcastCookie(UserHandle userHandle, String packageName, int callingPid, int callingUid) { 138 this.user = userHandle; 139 this.packageName = packageName; 140 this.callingUid = callingUid; 141 this.callingPid = callingPid; 142 } 143 } 144 145 /** 146 * Local system service interface. 147 * @hide Only for use within system server 148 */ 149 public abstract static class LauncherAppsServiceInternal { 150 /** Same as startShortcut except supports forwarding of caller uid/pid. */ startShortcut(int callerUid, int callerPid, String callingPackage, String packageName, String featureId, String shortcutId, Rect sourceBounds, Bundle startActivityOptions, int targetUserId)151 public abstract boolean startShortcut(int callerUid, int callerPid, String callingPackage, 152 String packageName, String featureId, String shortcutId, Rect sourceBounds, 153 Bundle startActivityOptions, int targetUserId); 154 } 155 156 @VisibleForTesting 157 static class LauncherAppsImpl extends ILauncherApps.Stub { 158 private static final boolean DEBUG = false; 159 private static final String TAG = "LauncherAppsService"; 160 161 private final Context mContext; 162 private final UserManager mUm; 163 private final IPackageManager mIPM; 164 private final UserManagerInternal mUserManagerInternal; 165 private final UsageStatsManagerInternal mUsageStatsManagerInternal; 166 private final ActivityManagerInternal mActivityManagerInternal; 167 private final ActivityTaskManagerInternal mActivityTaskManagerInternal; 168 private final ShortcutServiceInternal mShortcutServiceInternal; 169 private final PackageManagerInternal mPackageManagerInternal; 170 private final PackageCallbackList<IOnAppsChangedListener> mListeners 171 = new PackageCallbackList<IOnAppsChangedListener>(); 172 private final DevicePolicyManager mDpm; 173 174 private final PackageRemovedListener mPackageRemovedListener = 175 new PackageRemovedListener(); 176 private final MyPackageMonitor mPackageMonitor = new MyPackageMonitor(); 177 178 @GuardedBy("mListeners") 179 private boolean mIsWatchingPackageBroadcasts = false; 180 181 private final ShortcutChangeHandler mShortcutChangeHandler; 182 183 private final Handler mCallbackHandler; 184 185 private PackageInstallerService mPackageInstallerService; 186 187 final LauncherAppsServiceInternal mInternal; 188 LauncherAppsImpl(Context context)189 public LauncherAppsImpl(Context context) { 190 mContext = context; 191 mIPM = AppGlobals.getPackageManager(); 192 mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 193 mUserManagerInternal = Objects.requireNonNull( 194 LocalServices.getService(UserManagerInternal.class)); 195 mUsageStatsManagerInternal = Objects.requireNonNull( 196 LocalServices.getService(UsageStatsManagerInternal.class)); 197 mActivityManagerInternal = Objects.requireNonNull( 198 LocalServices.getService(ActivityManagerInternal.class)); 199 mActivityTaskManagerInternal = Objects.requireNonNull( 200 LocalServices.getService(ActivityTaskManagerInternal.class)); 201 mShortcutServiceInternal = Objects.requireNonNull( 202 LocalServices.getService(ShortcutServiceInternal.class)); 203 mPackageManagerInternal = Objects.requireNonNull( 204 LocalServices.getService(PackageManagerInternal.class)); 205 mShortcutServiceInternal.addListener(mPackageMonitor); 206 mShortcutChangeHandler = new ShortcutChangeHandler(mUserManagerInternal); 207 mShortcutServiceInternal.addShortcutChangeCallback(mShortcutChangeHandler); 208 mCallbackHandler = BackgroundThread.getHandler(); 209 mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 210 mInternal = new LocalService(); 211 } 212 213 @VisibleForTesting injectBinderCallingUid()214 int injectBinderCallingUid() { 215 return getCallingUid(); 216 } 217 218 @VisibleForTesting injectBinderCallingPid()219 int injectBinderCallingPid() { 220 return getCallingPid(); 221 } 222 injectCallingUserId()223 final int injectCallingUserId() { 224 return UserHandle.getUserId(injectBinderCallingUid()); 225 } 226 227 @VisibleForTesting injectClearCallingIdentity()228 long injectClearCallingIdentity() { 229 return Binder.clearCallingIdentity(); 230 } 231 232 // Injection point. 233 @VisibleForTesting injectRestoreCallingIdentity(long token)234 void injectRestoreCallingIdentity(long token) { 235 Binder.restoreCallingIdentity(token); 236 } 237 getCallingUserId()238 private int getCallingUserId() { 239 return UserHandle.getUserId(injectBinderCallingUid()); 240 } 241 242 /* 243 * @see android.content.pm.ILauncherApps#addOnAppsChangedListener 244 */ 245 @Override addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener)246 public void addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener) 247 throws RemoteException { 248 verifyCallingPackage(callingPackage); 249 synchronized (mListeners) { 250 if (DEBUG) { 251 Log.d(TAG, "Adding listener from " + Binder.getCallingUserHandle()); 252 } 253 if (mListeners.getRegisteredCallbackCount() == 0) { 254 if (DEBUG) { 255 Log.d(TAG, "Starting package monitoring"); 256 } 257 startWatchingPackageBroadcasts(); 258 } 259 mListeners.unregister(listener); 260 mListeners.register(listener, new BroadcastCookie(UserHandle.of(getCallingUserId()), 261 callingPackage, injectBinderCallingPid(), injectBinderCallingUid())); 262 } 263 } 264 265 /* 266 * @see android.content.pm.ILauncherApps#removeOnAppsChangedListener 267 */ 268 @Override removeOnAppsChangedListener(IOnAppsChangedListener listener)269 public void removeOnAppsChangedListener(IOnAppsChangedListener listener) 270 throws RemoteException { 271 synchronized (mListeners) { 272 if (DEBUG) { 273 Log.d(TAG, "Removing listener from " + Binder.getCallingUserHandle()); 274 } 275 mListeners.unregister(listener); 276 if (mListeners.getRegisteredCallbackCount() == 0) { 277 stopWatchingPackageBroadcasts(); 278 } 279 } 280 } 281 282 /** 283 * @see android.content.pm.ILauncherApps#registerPackageInstallerCallback 284 */ 285 @Override registerPackageInstallerCallback(String callingPackage, IPackageInstallerCallback callback)286 public void registerPackageInstallerCallback(String callingPackage, 287 IPackageInstallerCallback callback) { 288 verifyCallingPackage(callingPackage); 289 UserHandle callingIdUserHandle = new UserHandle(getCallingUserId()); 290 getPackageInstallerService().registerCallback(callback, eventUserId -> 291 isEnabledProfileOf(callingIdUserHandle, 292 new UserHandle(eventUserId), "shouldReceiveEvent")); 293 } 294 295 @Override getAllSessions(String callingPackage)296 public ParceledListSlice<SessionInfo> getAllSessions(String callingPackage) { 297 verifyCallingPackage(callingPackage); 298 List<SessionInfo> sessionInfos = new ArrayList<>(); 299 int[] userIds = mUm.getEnabledProfileIds(getCallingUserId()); 300 final int callingUid = Binder.getCallingUid(); 301 final long token = Binder.clearCallingIdentity(); 302 try { 303 for (int userId : userIds) { 304 sessionInfos.addAll(getPackageInstallerService().getAllSessions(userId) 305 .getList()); 306 } 307 } finally { 308 Binder.restoreCallingIdentity(token); 309 } 310 sessionInfos.removeIf(info -> shouldFilterSession(callingUid, info)); 311 return new ParceledListSlice<>(sessionInfos); 312 } 313 shouldFilterSession(int uid, SessionInfo session)314 private boolean shouldFilterSession(int uid, SessionInfo session) { 315 if (session == null) { 316 return false; 317 } 318 return uid != session.getInstallerUid() 319 && !mPackageManagerInternal.canQueryPackage(uid, session.getAppPackageName()); 320 } 321 getPackageInstallerService()322 private PackageInstallerService getPackageInstallerService() { 323 if (mPackageInstallerService == null) { 324 try { 325 mPackageInstallerService = ((PackageInstallerService) ((IPackageManager) 326 ServiceManager.getService("package")).getPackageInstaller()); 327 } catch (RemoteException e) { 328 Slog.wtf(TAG, "Error gettig IPackageInstaller", e); 329 } 330 } 331 return mPackageInstallerService; 332 } 333 334 /** 335 * Register a receiver to watch for package broadcasts 336 */ startWatchingPackageBroadcasts()337 private void startWatchingPackageBroadcasts() { 338 if (!mIsWatchingPackageBroadcasts) { 339 final IntentFilter filter = new IntentFilter(); 340 filter.addAction(Intent.ACTION_PACKAGE_REMOVED_INTERNAL); 341 filter.addDataScheme("package"); 342 mContext.registerReceiverAsUser(mPackageRemovedListener, UserHandle.ALL, filter, 343 /* broadcastPermission= */ null, mCallbackHandler); 344 mPackageMonitor.register(mContext, UserHandle.ALL, true, mCallbackHandler); 345 mIsWatchingPackageBroadcasts = true; 346 } 347 } 348 349 /** 350 * Unregister package broadcast receiver 351 */ stopWatchingPackageBroadcasts()352 private void stopWatchingPackageBroadcasts() { 353 if (DEBUG) { 354 Log.d(TAG, "Stopped watching for packages"); 355 } 356 if (mIsWatchingPackageBroadcasts) { 357 mContext.unregisterReceiver(mPackageRemovedListener); 358 mPackageMonitor.unregister(); 359 mIsWatchingPackageBroadcasts = false; 360 } 361 } 362 checkCallbackCount()363 void checkCallbackCount() { 364 synchronized (mListeners) { 365 if (DEBUG) { 366 Log.d(TAG, "Callback count = " + mListeners.getRegisteredCallbackCount()); 367 } 368 if (mListeners.getRegisteredCallbackCount() == 0) { 369 stopWatchingPackageBroadcasts(); 370 } 371 } 372 } 373 374 /** 375 * Checks if the calling user is in the same group as {@code targetUser}, and allowed 376 * to access it. 377 * 378 * @return TRUE if the calling user can access {@code targetUserId}. FALSE if not *but 379 * they're still in the same profile group*. 380 * 381 * @throws SecurityException if the calling user and {@code targetUser} are not in the same 382 * group. 383 */ canAccessProfile(int targetUserId, String message)384 private boolean canAccessProfile(int targetUserId, String message) { 385 return canAccessProfile(injectBinderCallingUid(), injectCallingUserId(), 386 injectBinderCallingPid(), targetUserId, message); 387 } 388 canAccessProfile(int callingUid, int callingUserId, int callingPid, int targetUserId, String message)389 private boolean canAccessProfile(int callingUid, int callingUserId, int callingPid, 390 int targetUserId, String message) { 391 392 if (targetUserId == callingUserId) return true; 393 if (injectHasInteractAcrossUsersFullPermission(callingPid, callingUid)) { 394 return true; 395 } 396 397 long ident = injectClearCallingIdentity(); 398 try { 399 final UserInfo callingUserInfo = mUm.getUserInfo(callingUserId); 400 if (callingUserInfo != null && callingUserInfo.isProfile()) { 401 Slog.w(TAG, message + " for another profile " 402 + targetUserId + " from " + callingUserId + " not allowed"); 403 return false; 404 } 405 } finally { 406 injectRestoreCallingIdentity(ident); 407 } 408 409 return mUserManagerInternal.isProfileAccessible(callingUserId, targetUserId, 410 message, true); 411 } 412 verifyCallingPackage(String callingPackage)413 private void verifyCallingPackage(String callingPackage) { 414 verifyCallingPackage(callingPackage, injectBinderCallingUid()); 415 } 416 417 @VisibleForTesting // We override it in unit tests verifyCallingPackage(String callingPackage, int callerUid)418 void verifyCallingPackage(String callingPackage, int callerUid) { 419 int packageUid = -1; 420 try { 421 packageUid = mIPM.getPackageUid(callingPackage, 422 PackageManager.MATCH_DIRECT_BOOT_AWARE 423 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE 424 | PackageManager.MATCH_UNINSTALLED_PACKAGES, 425 UserHandle.getUserId(callerUid)); 426 } catch (RemoteException ignore) { 427 } 428 if (packageUid < 0) { 429 Log.e(TAG, "Package not found: " + callingPackage); 430 } 431 if (packageUid != callerUid) { 432 throw new SecurityException("Calling package name mismatch"); 433 } 434 } 435 getHiddenAppActivityInfo(String packageName, int callingUid, UserHandle user)436 private LauncherActivityInfoInternal getHiddenAppActivityInfo(String packageName, 437 int callingUid, UserHandle user) { 438 Intent intent = new Intent(); 439 intent.setComponent(new ComponentName(packageName, 440 PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME)); 441 final List<LauncherActivityInfoInternal> apps = queryIntentLauncherActivities(intent, 442 callingUid, user); 443 if (apps.size() > 0) { 444 return apps.get(0); 445 } 446 return null; 447 } 448 449 @Override shouldHideFromSuggestions(String packageName, UserHandle user)450 public boolean shouldHideFromSuggestions(String packageName, UserHandle user) { 451 final int userId = user.getIdentifier(); 452 if (!canAccessProfile(userId, "cannot get shouldHideFromSuggestions")) { 453 return false; 454 } 455 if (mPackageManagerInternal.filterAppAccess( 456 packageName, Binder.getCallingUid(), userId)) { 457 return false; 458 } 459 final int flags = mPackageManagerInternal.getDistractingPackageRestrictions( 460 packageName, userId); 461 return (flags & PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS) != 0; 462 } 463 464 @Override getLauncherActivities( String callingPackage, String packageName, UserHandle user)465 public ParceledListSlice<LauncherActivityInfoInternal> getLauncherActivities( 466 String callingPackage, String packageName, UserHandle user) throws RemoteException { 467 ParceledListSlice<LauncherActivityInfoInternal> launcherActivities = 468 queryActivitiesForUser(callingPackage, 469 new Intent(Intent.ACTION_MAIN) 470 .addCategory(Intent.CATEGORY_LAUNCHER) 471 .setPackage(packageName), 472 user); 473 if (Settings.Global.getInt(mContext.getContentResolver(), 474 Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED, 1) == 0) { 475 return launcherActivities; 476 } 477 if (launcherActivities == null) { 478 // Cannot access profile, so we don't even return any hidden apps. 479 return null; 480 } 481 482 final int callingUid = injectBinderCallingUid(); 483 final long ident = injectClearCallingIdentity(); 484 try { 485 if (mUm.getUserInfo(user.getIdentifier()).isManagedProfile()) { 486 // Managed profile should not show hidden apps 487 return launcherActivities; 488 } 489 if (mDpm.getDeviceOwnerComponentOnAnyUser() != null) { 490 // Device owner devices should not show hidden apps 491 return launcherActivities; 492 } 493 494 final ArrayList<LauncherActivityInfoInternal> result = new ArrayList<>( 495 launcherActivities.getList()); 496 if (packageName != null) { 497 // If this hidden app should not be shown, return the original list. 498 // Otherwise, inject hidden activity that forwards user to app details page. 499 if (result.size() > 0) { 500 return launcherActivities; 501 } 502 final ApplicationInfo appInfo = mPackageManagerInternal.getApplicationInfo( 503 packageName, /* flags= */ 0, callingUid, user.getIdentifier()); 504 if (shouldShowSyntheticActivity(user, appInfo)) { 505 LauncherActivityInfoInternal info = getHiddenAppActivityInfo(packageName, 506 callingUid, user); 507 if (info != null) { 508 result.add(info); 509 } 510 } 511 return new ParceledListSlice<>(result); 512 } 513 final HashSet<String> visiblePackages = new HashSet<>(); 514 for (LauncherActivityInfoInternal info : result) { 515 visiblePackages.add(info.getActivityInfo().packageName); 516 } 517 final List<ApplicationInfo> installedPackages = 518 mPackageManagerInternal.getInstalledApplications(/* flags= */ 0, 519 user.getIdentifier(), callingUid); 520 for (ApplicationInfo applicationInfo : installedPackages) { 521 if (!visiblePackages.contains(applicationInfo.packageName)) { 522 if (!shouldShowSyntheticActivity(user, applicationInfo)) { 523 continue; 524 } 525 LauncherActivityInfoInternal info = getHiddenAppActivityInfo( 526 applicationInfo.packageName, callingUid, user); 527 if (info != null) { 528 result.add(info); 529 } 530 } 531 } 532 return new ParceledListSlice<>(result); 533 } finally { 534 injectRestoreCallingIdentity(ident); 535 } 536 } 537 shouldShowSyntheticActivity(UserHandle user, ApplicationInfo appInfo)538 private boolean shouldShowSyntheticActivity(UserHandle user, ApplicationInfo appInfo) { 539 if (appInfo == null || appInfo.isSystemApp() || appInfo.isUpdatedSystemApp()) { 540 return false; 541 } 542 if (isManagedProfileAdmin(user, appInfo.packageName)) { 543 return false; 544 } 545 final AndroidPackage pkg = mPackageManagerInternal.getPackage(appInfo.packageName); 546 if (pkg == null) { 547 // Should not happen, but we shouldn't be failing if it does 548 return false; 549 } 550 // If app does not have any default enabled launcher activity or any permissions, 551 // the app can legitimately have no icon so we do not show the synthetic activity. 552 return requestsPermissions(pkg) && hasDefaultEnableLauncherActivity( 553 appInfo.packageName); 554 } 555 requestsPermissions(@onNull AndroidPackage pkg)556 private boolean requestsPermissions(@NonNull AndroidPackage pkg) { 557 return !ArrayUtils.isEmpty(pkg.getRequestedPermissions()); 558 } 559 hasDefaultEnableLauncherActivity(@onNull String packageName)560 private boolean hasDefaultEnableLauncherActivity(@NonNull String packageName) { 561 final Intent matchIntent = new Intent(Intent.ACTION_MAIN); 562 matchIntent.addCategory(Intent.CATEGORY_LAUNCHER); 563 matchIntent.setPackage(packageName); 564 final List<ResolveInfo> infoList = mPackageManagerInternal.queryIntentActivities( 565 matchIntent, matchIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 566 PackageManager.MATCH_DISABLED_COMPONENTS, Binder.getCallingUid(), 567 getCallingUserId()); 568 final int size = infoList.size(); 569 for (int i = 0; i < size; i++) { 570 if (infoList.get(i).activityInfo.enabled) { 571 return true; 572 } 573 } 574 return false; 575 } 576 isManagedProfileAdmin(UserHandle user, String packageName)577 private boolean isManagedProfileAdmin(UserHandle user, String packageName) { 578 final List<UserInfo> userInfoList = mUm.getProfiles(user.getIdentifier()); 579 for (int i = 0; i < userInfoList.size(); i++) { 580 UserInfo userInfo = userInfoList.get(i); 581 if (!userInfo.isManagedProfile()) { 582 continue; 583 } 584 ComponentName componentName = mDpm.getProfileOwnerAsUser(userInfo.getUserHandle()); 585 if (componentName == null) { 586 continue; 587 } 588 if (componentName.getPackageName().equals(packageName)) { 589 return true; 590 } 591 } 592 return false; 593 } 594 595 @Override resolveLauncherActivityInternal( String callingPackage, ComponentName component, UserHandle user)596 public LauncherActivityInfoInternal resolveLauncherActivityInternal( 597 String callingPackage, ComponentName component, UserHandle user) 598 throws RemoteException { 599 if (!canAccessProfile(user.getIdentifier(), "Cannot resolve activity")) { 600 return null; 601 } 602 603 final int callingUid = injectBinderCallingUid(); 604 final long ident = Binder.clearCallingIdentity(); 605 try { 606 final ActivityInfo activityInfo = mPackageManagerInternal.getActivityInfo(component, 607 PackageManager.MATCH_DIRECT_BOOT_AWARE 608 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 609 callingUid, user.getIdentifier()); 610 if (activityInfo == null) { 611 return null; 612 } 613 if (component == null || component.getPackageName() == null) { 614 // should not happen 615 return null; 616 } 617 final IncrementalStatesInfo incrementalStatesInfo = 618 mPackageManagerInternal.getIncrementalStatesInfo(component.getPackageName(), 619 callingUid, user.getIdentifier()); 620 if (incrementalStatesInfo == null) { 621 // package does not exist; should not happen 622 return null; 623 } 624 return new LauncherActivityInfoInternal(activityInfo, incrementalStatesInfo); 625 } finally { 626 Binder.restoreCallingIdentity(ident); 627 } 628 } 629 630 @Override getShortcutConfigActivities( String callingPackage, String packageName, UserHandle user)631 public ParceledListSlice getShortcutConfigActivities( 632 String callingPackage, String packageName, UserHandle user) 633 throws RemoteException { 634 return queryActivitiesForUser(callingPackage, 635 new Intent(Intent.ACTION_CREATE_SHORTCUT).setPackage(packageName), user); 636 } 637 queryActivitiesForUser( String callingPackage, Intent intent, UserHandle user)638 private ParceledListSlice<LauncherActivityInfoInternal> queryActivitiesForUser( 639 String callingPackage, Intent intent, UserHandle user) { 640 if (!canAccessProfile(user.getIdentifier(), "Cannot retrieve activities")) { 641 return null; 642 } 643 final int callingUid = injectBinderCallingUid(); 644 long ident = injectClearCallingIdentity(); 645 try { 646 return new ParceledListSlice<>(queryIntentLauncherActivities(intent, callingUid, 647 user)); 648 } finally { 649 injectRestoreCallingIdentity(ident); 650 } 651 } 652 queryIntentLauncherActivities( Intent intent, int callingUid, UserHandle user)653 private List<LauncherActivityInfoInternal> queryIntentLauncherActivities( 654 Intent intent, int callingUid, UserHandle user) { 655 final List<ResolveInfo> apps = mPackageManagerInternal.queryIntentActivities(intent, 656 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 657 PackageManager.MATCH_DIRECT_BOOT_AWARE 658 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 659 callingUid, user.getIdentifier()); 660 final int numResolveInfos = apps.size(); 661 List<LauncherActivityInfoInternal> results = new ArrayList<>(); 662 for (int i = 0; i < numResolveInfos; i++) { 663 final ResolveInfo ri = apps.get(i); 664 final String packageName = ri.activityInfo.packageName; 665 if (packageName == null) { 666 // should not happen 667 continue; 668 } 669 final IncrementalStatesInfo incrementalStatesInfo = 670 mPackageManagerInternal.getIncrementalStatesInfo(packageName, callingUid, 671 user.getIdentifier()); 672 if (incrementalStatesInfo == null) { 673 // package doesn't exist any more; should not happen 674 continue; 675 } 676 results.add(new LauncherActivityInfoInternal(ri.activityInfo, 677 incrementalStatesInfo)); 678 } 679 return results; 680 } 681 682 @Override getShortcutConfigActivityIntent(String callingPackage, ComponentName component, UserHandle user)683 public IntentSender getShortcutConfigActivityIntent(String callingPackage, 684 ComponentName component, UserHandle user) throws RemoteException { 685 ensureShortcutPermission(callingPackage); 686 if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) { 687 return null; 688 } 689 Objects.requireNonNull(component); 690 691 // All right, create the sender. 692 final int callingUid = injectBinderCallingUid(); 693 final long identity = Binder.clearCallingIdentity(); 694 try { 695 Intent packageIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT) 696 .setPackage(component.getPackageName()); 697 List<ResolveInfo> apps = 698 mPackageManagerInternal.queryIntentActivities(packageIntent, 699 packageIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 700 PackageManager.MATCH_DIRECT_BOOT_AWARE 701 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 702 callingUid, user.getIdentifier()); 703 // ensure that the component is present in the list 704 if (!apps.stream().anyMatch( 705 ri -> component.getClassName().equals(ri.activityInfo.name))) { 706 return null; 707 } 708 709 Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT).setComponent(component); 710 final PendingIntent pi = PendingIntent.getActivityAsUser( 711 mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT 712 | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT, 713 null, user); 714 return pi == null ? null : pi.getIntentSender(); 715 } finally { 716 Binder.restoreCallingIdentity(identity); 717 } 718 } 719 720 /** 721 * Returns the intents for a specific shortcut. 722 */ 723 @Nullable 724 @Override getShortcutIntent(@onNull final String callingPackage, @NonNull final String packageName, @NonNull final String shortcutId, @Nullable final Bundle opts, @NonNull final UserHandle user)725 public PendingIntent getShortcutIntent(@NonNull final String callingPackage, 726 @NonNull final String packageName, @NonNull final String shortcutId, 727 @Nullable final Bundle opts, @NonNull final UserHandle user) 728 throws RemoteException { 729 Objects.requireNonNull(callingPackage); 730 Objects.requireNonNull(packageName); 731 Objects.requireNonNull(shortcutId); 732 Objects.requireNonNull(user); 733 734 ensureShortcutPermission(callingPackage); 735 if (!canAccessProfile(user.getIdentifier(), "Cannot get shortcuts")) { 736 return null; 737 } 738 739 final AndroidFuture<Intent[]> ret = new AndroidFuture<>(); 740 Intent[] intents; 741 mShortcutServiceInternal.createShortcutIntentsAsync(getCallingUserId(), 742 callingPackage, packageName, shortcutId, user.getIdentifier(), 743 injectBinderCallingPid(), injectBinderCallingUid(), ret); 744 try { 745 intents = ret.get(); 746 } catch (InterruptedException | ExecutionException e) { 747 return null; 748 } 749 if (intents == null || intents.length == 0) { 750 return null; 751 } 752 final long ident = Binder.clearCallingIdentity(); 753 try { 754 return injectCreatePendingIntent(0 /* requestCode */, intents, 755 FLAG_IMMUTABLE | FLAG_UPDATE_CURRENT, opts, packageName, 756 mPackageManagerInternal.getPackageUid( 757 packageName, PackageManager.MATCH_DIRECT_BOOT_AUTO, 758 user.getIdentifier())); 759 } finally { 760 Binder.restoreCallingIdentity(ident); 761 } 762 } 763 764 @Override isPackageEnabled(String callingPackage, String packageName, UserHandle user)765 public boolean isPackageEnabled(String callingPackage, String packageName, UserHandle user) 766 throws RemoteException { 767 if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) { 768 return false; 769 } 770 771 final int callingUid = injectBinderCallingUid(); 772 final long ident = Binder.clearCallingIdentity(); 773 try { 774 final PackageInfo info = mPackageManagerInternal.getPackageInfo(packageName, 775 PackageManager.MATCH_DIRECT_BOOT_AWARE 776 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 777 callingUid, user.getIdentifier()); 778 return info != null && info.applicationInfo.enabled; 779 } finally { 780 Binder.restoreCallingIdentity(ident); 781 } 782 } 783 784 @Override getSuspendedPackageLauncherExtras(String packageName, UserHandle user)785 public Bundle getSuspendedPackageLauncherExtras(String packageName, 786 UserHandle user) { 787 final int callingUid = injectBinderCallingUid(); 788 final int userId = user.getIdentifier(); 789 if (!canAccessProfile(userId, "Cannot get launcher extras")) { 790 return null; 791 } 792 if (mPackageManagerInternal.filterAppAccess(packageName, callingUid, userId)) { 793 return null; 794 } 795 return mPackageManagerInternal.getSuspendedPackageLauncherExtras(packageName, userId); 796 } 797 798 @Override getApplicationInfo( String callingPackage, String packageName, int flags, UserHandle user)799 public ApplicationInfo getApplicationInfo( 800 String callingPackage, String packageName, int flags, UserHandle user) 801 throws RemoteException { 802 if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) { 803 return null; 804 } 805 806 final int callingUid = injectBinderCallingUid(); 807 final long ident = Binder.clearCallingIdentity(); 808 try { 809 final ApplicationInfo info = mPackageManagerInternal.getApplicationInfo(packageName, 810 flags, callingUid, user.getIdentifier()); 811 return info; 812 } finally { 813 Binder.restoreCallingIdentity(ident); 814 } 815 } 816 817 @Override getAppUsageLimit(String callingPackage, String packageName, UserHandle user)818 public LauncherApps.AppUsageLimit getAppUsageLimit(String callingPackage, 819 String packageName, UserHandle user) { 820 verifyCallingPackage(callingPackage); 821 if (!canAccessProfile(user.getIdentifier(), "Cannot access usage limit")) { 822 return null; 823 } 824 if (!mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid())) { 825 throw new SecurityException("Caller is not the recents app"); 826 } 827 828 final UsageStatsManagerInternal.AppUsageLimitData data = 829 mUsageStatsManagerInternal.getAppUsageLimit(packageName, user); 830 if (data == null) { 831 return null; 832 } 833 return new LauncherApps.AppUsageLimit( 834 data.getTotalUsageLimit(), data.getUsageRemaining()); 835 } 836 ensureShortcutPermission(@onNull String callingPackage)837 private void ensureShortcutPermission(@NonNull String callingPackage) { 838 ensureShortcutPermission(injectBinderCallingUid(), injectBinderCallingPid(), 839 callingPackage); 840 } 841 ensureShortcutPermission(int callerUid, int callerPid, @NonNull String callingPackage)842 private void ensureShortcutPermission(int callerUid, int callerPid, 843 @NonNull String callingPackage) { 844 verifyCallingPackage(callingPackage, callerUid); 845 if (!mShortcutServiceInternal.hasShortcutHostPermission(UserHandle.getUserId(callerUid), 846 callingPackage, callerPid, callerUid)) { 847 throw new SecurityException("Caller can't access shortcut information"); 848 } 849 } 850 ensureStrictAccessShortcutsPermission(@onNull String callingPackage)851 private void ensureStrictAccessShortcutsPermission(@NonNull String callingPackage) { 852 verifyCallingPackage(callingPackage); 853 if (!injectHasAccessShortcutsPermission(injectBinderCallingPid(), 854 injectBinderCallingUid())) { 855 throw new SecurityException("Caller can't access shortcut information"); 856 } 857 } 858 859 /** 860 * Returns true if the caller has the "ACCESS_SHORTCUTS" permission. 861 */ 862 @VisibleForTesting injectHasAccessShortcutsPermission(int callingPid, int callingUid)863 boolean injectHasAccessShortcutsPermission(int callingPid, int callingUid) { 864 return mContext.checkPermission(android.Manifest.permission.ACCESS_SHORTCUTS, 865 callingPid, callingUid) == PackageManager.PERMISSION_GRANTED; 866 } 867 868 /** 869 * Returns true if the caller has the "INTERACT_ACROSS_USERS_FULL" permission. 870 */ 871 @VisibleForTesting injectHasInteractAcrossUsersFullPermission(int callingPid, int callingUid)872 boolean injectHasInteractAcrossUsersFullPermission(int callingPid, int callingUid) { 873 return mContext.checkPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, 874 callingPid, callingUid) == PackageManager.PERMISSION_GRANTED; 875 } 876 877 @VisibleForTesting injectCreatePendingIntent(int requestCode, @NonNull Intent[] intents, int flags, Bundle options, String ownerPackage, int ownerUserId)878 PendingIntent injectCreatePendingIntent(int requestCode, @NonNull Intent[] intents, 879 int flags, Bundle options, String ownerPackage, int ownerUserId) { 880 return mActivityManagerInternal.getPendingIntentActivityAsApp(requestCode, intents, 881 flags, null /* options */, ownerPackage, ownerUserId); 882 } 883 884 @Override getShortcuts(@onNull final String callingPackage, @NonNull final ShortcutQueryWrapper query, @NonNull final UserHandle targetUser)885 public ParceledListSlice getShortcuts(@NonNull final String callingPackage, 886 @NonNull final ShortcutQueryWrapper query, @NonNull final UserHandle targetUser) { 887 ensureShortcutPermission(callingPackage); 888 if (!canAccessProfile(targetUser.getIdentifier(), "Cannot get shortcuts")) { 889 return new ParceledListSlice<>(Collections.EMPTY_LIST); 890 } 891 892 final long changedSince = query.getChangedSince(); 893 final String packageName = query.getPackage(); 894 final List<String> shortcutIds = query.getShortcutIds(); 895 final List<LocusId> locusIds = query.getLocusIds(); 896 final ComponentName componentName = query.getActivity(); 897 final int flags = query.getQueryFlags(); 898 if (shortcutIds != null && packageName == null) { 899 throw new IllegalArgumentException( 900 "To query by shortcut ID, package name must also be set"); 901 } 902 if (locusIds != null && packageName == null) { 903 throw new IllegalArgumentException( 904 "To query by locus ID, package name must also be set"); 905 } 906 if ((query.getQueryFlags() & ShortcutQuery.FLAG_GET_PERSONS_DATA) != 0) { 907 ensureStrictAccessShortcutsPermission(callingPackage); 908 } 909 910 // TODO(b/29399275): Eclipse compiler requires explicit List<ShortcutInfo> cast below. 911 return new ParceledListSlice<>((List<ShortcutInfo>) 912 mShortcutServiceInternal.getShortcuts(getCallingUserId(), 913 callingPackage, changedSince, packageName, shortcutIds, locusIds, 914 componentName, flags, targetUser.getIdentifier(), 915 injectBinderCallingPid(), injectBinderCallingUid())); 916 } 917 918 @Override getShortcutsAsync(@onNull final String callingPackage, @NonNull final ShortcutQueryWrapper query, @NonNull final UserHandle targetUser, @NonNull final AndroidFuture<List<ShortcutInfo>> cb)919 public void getShortcutsAsync(@NonNull final String callingPackage, 920 @NonNull final ShortcutQueryWrapper query, @NonNull final UserHandle targetUser, 921 @NonNull final AndroidFuture<List<ShortcutInfo>> cb) { 922 ensureShortcutPermission(callingPackage); 923 if (!canAccessProfile(targetUser.getIdentifier(), "Cannot get shortcuts")) { 924 cb.complete(Collections.EMPTY_LIST); 925 return; 926 } 927 928 final long changedSince = query.getChangedSince(); 929 final String packageName = query.getPackage(); 930 final List<String> shortcutIds = query.getShortcutIds(); 931 final List<LocusId> locusIds = query.getLocusIds(); 932 final ComponentName componentName = query.getActivity(); 933 final int flags = query.getQueryFlags(); 934 if (shortcutIds != null && packageName == null) { 935 throw new IllegalArgumentException( 936 "To query by shortcut ID, package name must also be set"); 937 } 938 if (locusIds != null && packageName == null) { 939 throw new IllegalArgumentException( 940 "To query by locus ID, package name must also be set"); 941 } 942 if ((query.getQueryFlags() & ShortcutQuery.FLAG_GET_PERSONS_DATA) != 0) { 943 ensureStrictAccessShortcutsPermission(callingPackage); 944 } 945 946 mShortcutServiceInternal.getShortcutsAsync(getCallingUserId(), 947 callingPackage, changedSince, packageName, shortcutIds, locusIds, 948 componentName, flags, targetUser.getIdentifier(), 949 injectBinderCallingPid(), injectBinderCallingUid(), cb); 950 } 951 952 @Override registerShortcutChangeCallback(@onNull final String callingPackage, @NonNull final ShortcutQueryWrapper query, @NonNull final IShortcutChangeCallback callback)953 public void registerShortcutChangeCallback(@NonNull final String callingPackage, 954 @NonNull final ShortcutQueryWrapper query, 955 @NonNull final IShortcutChangeCallback callback) { 956 957 ensureShortcutPermission(callingPackage); 958 959 if (query.getShortcutIds() != null && query.getPackage() == null) { 960 throw new IllegalArgumentException( 961 "To query by shortcut ID, package name must also be set"); 962 } 963 if (query.getLocusIds() != null && query.getPackage() == null) { 964 throw new IllegalArgumentException( 965 "To query by locus ID, package name must also be set"); 966 } 967 968 UserHandle user = UserHandle.of(injectCallingUserId()); 969 if (injectHasInteractAcrossUsersFullPermission(injectBinderCallingPid(), 970 injectBinderCallingUid())) { 971 user = null; 972 } 973 974 mShortcutChangeHandler.addShortcutChangeCallback(callback, query, user); 975 } 976 977 @Override unregisterShortcutChangeCallback(String callingPackage, IShortcutChangeCallback callback)978 public void unregisterShortcutChangeCallback(String callingPackage, 979 IShortcutChangeCallback callback) { 980 ensureShortcutPermission(callingPackage); 981 982 mShortcutChangeHandler.removeShortcutChangeCallback(callback); 983 } 984 985 @Override pinShortcuts(String callingPackage, String packageName, List<String> ids, UserHandle targetUser)986 public void pinShortcuts(String callingPackage, String packageName, List<String> ids, 987 UserHandle targetUser) { 988 ensureShortcutPermission(callingPackage); 989 if (!canAccessProfile(targetUser.getIdentifier(), "Cannot pin shortcuts")) { 990 return; 991 } 992 993 mShortcutServiceInternal.pinShortcuts(getCallingUserId(), 994 callingPackage, packageName, ids, targetUser.getIdentifier()); 995 } 996 997 @Override cacheShortcuts(String callingPackage, String packageName, List<String> ids, UserHandle targetUser, int cacheFlags)998 public void cacheShortcuts(String callingPackage, String packageName, List<String> ids, 999 UserHandle targetUser, int cacheFlags) { 1000 ensureStrictAccessShortcutsPermission(callingPackage); 1001 if (!canAccessProfile(targetUser.getIdentifier(), "Cannot cache shortcuts")) { 1002 return; 1003 } 1004 1005 mShortcutServiceInternal.cacheShortcuts( 1006 getCallingUserId(), callingPackage, packageName, ids, 1007 targetUser.getIdentifier(), toShortcutsCacheFlags(cacheFlags)); 1008 } 1009 1010 @Override uncacheShortcuts(String callingPackage, String packageName, List<String> ids, UserHandle targetUser, int cacheFlags)1011 public void uncacheShortcuts(String callingPackage, String packageName, List<String> ids, 1012 UserHandle targetUser, int cacheFlags) { 1013 ensureStrictAccessShortcutsPermission(callingPackage); 1014 if (!canAccessProfile(targetUser.getIdentifier(), "Cannot uncache shortcuts")) { 1015 return; 1016 } 1017 1018 mShortcutServiceInternal.uncacheShortcuts( 1019 getCallingUserId(), callingPackage, packageName, ids, 1020 targetUser.getIdentifier(), toShortcutsCacheFlags(cacheFlags)); 1021 } 1022 1023 @Override getShortcutIconResId(String callingPackage, String packageName, String id, int targetUserId)1024 public int getShortcutIconResId(String callingPackage, String packageName, String id, 1025 int targetUserId) { 1026 ensureShortcutPermission(callingPackage); 1027 if (!canAccessProfile(targetUserId, "Cannot access shortcuts")) { 1028 return 0; 1029 } 1030 1031 return mShortcutServiceInternal.getShortcutIconResId(getCallingUserId(), 1032 callingPackage, packageName, id, targetUserId); 1033 } 1034 1035 @Override getShortcutIconFd(String callingPackage, String packageName, String id, int targetUserId)1036 public ParcelFileDescriptor getShortcutIconFd(String callingPackage, 1037 String packageName, String id, int targetUserId) { 1038 ensureShortcutPermission(callingPackage); 1039 if (!canAccessProfile(targetUserId, "Cannot access shortcuts")) { 1040 return null; 1041 } 1042 1043 final AndroidFuture<ParcelFileDescriptor> ret = new AndroidFuture<>(); 1044 mShortcutServiceInternal.getShortcutIconFdAsync(getCallingUserId(), 1045 callingPackage, packageName, id, targetUserId, ret); 1046 try { 1047 return ret.get(); 1048 } catch (InterruptedException | ExecutionException e) { 1049 throw new RuntimeException(e); 1050 } 1051 } 1052 1053 @Override getShortcutIconUri(String callingPackage, String packageName, String shortcutId, int userId)1054 public String getShortcutIconUri(String callingPackage, String packageName, 1055 String shortcutId, int userId) { 1056 ensureShortcutPermission(callingPackage); 1057 if (!canAccessProfile(userId, "Cannot access shortcuts")) { 1058 return null; 1059 } 1060 1061 final AndroidFuture<String> ret = new AndroidFuture<>(); 1062 mShortcutServiceInternal.getShortcutIconUriAsync(getCallingUserId(), callingPackage, 1063 packageName, shortcutId, userId, ret); 1064 try { 1065 return ret.get(); 1066 } catch (InterruptedException | ExecutionException e) { 1067 throw new RuntimeException(e); 1068 } 1069 } 1070 1071 @Override hasShortcutHostPermission(String callingPackage)1072 public boolean hasShortcutHostPermission(String callingPackage) { 1073 verifyCallingPackage(callingPackage); 1074 return mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(), 1075 callingPackage, injectBinderCallingPid(), injectBinderCallingUid()); 1076 } 1077 1078 @Override startShortcut(String callingPackage, String packageName, String featureId, String shortcutId, Rect sourceBounds, Bundle startActivityOptions, int targetUserId)1079 public boolean startShortcut(String callingPackage, String packageName, String featureId, 1080 String shortcutId, Rect sourceBounds, Bundle startActivityOptions, 1081 int targetUserId) { 1082 return startShortcutInner(injectBinderCallingUid(), injectBinderCallingPid(), 1083 injectCallingUserId(), callingPackage, packageName, featureId, shortcutId, 1084 sourceBounds, startActivityOptions, targetUserId); 1085 } 1086 startShortcutInner(int callerUid, int callerPid, int callingUserId, String callingPackage, String packageName, String featureId, String shortcutId, Rect sourceBounds, Bundle startActivityOptions, int targetUserId)1087 private boolean startShortcutInner(int callerUid, int callerPid, int callingUserId, 1088 String callingPackage, String packageName, String featureId, String shortcutId, 1089 Rect sourceBounds, Bundle startActivityOptions, int targetUserId) { 1090 verifyCallingPackage(callingPackage, callerUid); 1091 if (!canAccessProfile(targetUserId, "Cannot start activity")) { 1092 return false; 1093 } 1094 1095 // Even without the permission, pinned shortcuts are always launchable. 1096 if (!mShortcutServiceInternal.isPinnedByCaller(callingUserId, 1097 callingPackage, packageName, shortcutId, targetUserId)) { 1098 ensureShortcutPermission(callerUid, callerPid, callingPackage); 1099 } 1100 1101 final AndroidFuture<Intent[]> ret = new AndroidFuture<>(); 1102 Intent[] intents; 1103 mShortcutServiceInternal.createShortcutIntentsAsync(getCallingUserId(), callingPackage, 1104 packageName, shortcutId, targetUserId, 1105 injectBinderCallingPid(), injectBinderCallingUid(), ret); 1106 try { 1107 intents = ret.get(); 1108 } catch (InterruptedException | ExecutionException e) { 1109 return false; 1110 } 1111 if (intents == null || intents.length == 0) { 1112 return false; 1113 } 1114 // Note the target activity doesn't have to be exported. 1115 1116 // Flag for bubble 1117 ActivityOptions options = ActivityOptions.fromBundle(startActivityOptions); 1118 if (options != null) { 1119 if (options.isApplyActivityFlagsForBubbles()) { 1120 // Flag for bubble to make behaviour match documentLaunchMode=always. 1121 intents[0].addFlags(FLAG_ACTIVITY_NEW_DOCUMENT); 1122 intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); 1123 } 1124 if (options.isApplyMultipleTaskFlagForShortcut()) { 1125 intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); 1126 } 1127 if (options.isApplyNoUserActionFlagForShortcut()) { 1128 intents[0].addFlags(FLAG_ACTIVITY_NO_USER_ACTION); 1129 } 1130 } 1131 intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1132 intents[0].setSourceBounds(sourceBounds); 1133 1134 // Replace theme for splash screen 1135 final String splashScreenThemeResName = 1136 mShortcutServiceInternal.getShortcutStartingThemeResName(callingUserId, 1137 callingPackage, packageName, shortcutId, targetUserId); 1138 if (splashScreenThemeResName != null && !splashScreenThemeResName.isEmpty()) { 1139 if (startActivityOptions == null) { 1140 startActivityOptions = new Bundle(); 1141 } 1142 startActivityOptions.putString(KEY_SPLASH_SCREEN_THEME, splashScreenThemeResName); 1143 } 1144 return startShortcutIntentsAsPublisher( 1145 intents, packageName, featureId, startActivityOptions, targetUserId); 1146 } 1147 startShortcutIntentsAsPublisher(@onNull Intent[] intents, @NonNull String publisherPackage, @Nullable String publishedFeatureId, Bundle startActivityOptions, int userId)1148 private boolean startShortcutIntentsAsPublisher(@NonNull Intent[] intents, 1149 @NonNull String publisherPackage, @Nullable String publishedFeatureId, 1150 Bundle startActivityOptions, int userId) { 1151 final int code; 1152 try { 1153 code = mActivityTaskManagerInternal.startActivitiesAsPackage(publisherPackage, 1154 publishedFeatureId, userId, intents, startActivityOptions); 1155 if (ActivityManager.isStartResultSuccessful(code)) { 1156 return true; // Success 1157 } else { 1158 Log.e(TAG, "Couldn't start activity, code=" + code); 1159 } 1160 return false; 1161 } catch (SecurityException e) { 1162 if (DEBUG) { 1163 Slog.d(TAG, "SecurityException while launching intent", e); 1164 } 1165 return false; 1166 } 1167 } 1168 1169 @Override isActivityEnabled( String callingPackage, ComponentName component, UserHandle user)1170 public boolean isActivityEnabled( 1171 String callingPackage, ComponentName component, UserHandle user) 1172 throws RemoteException { 1173 if (!canAccessProfile(user.getIdentifier(), "Cannot check component")) { 1174 return false; 1175 } 1176 1177 final int callingUid = injectBinderCallingUid(); 1178 final int state = mPackageManagerInternal.getComponentEnabledSetting(component, 1179 callingUid, user.getIdentifier()); 1180 switch (state) { 1181 case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT: 1182 break; // Need to check the manifest's enabled state. 1183 case PackageManager.COMPONENT_ENABLED_STATE_ENABLED: 1184 return true; 1185 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED: 1186 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER: 1187 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED: 1188 return false; 1189 } 1190 1191 final long ident = Binder.clearCallingIdentity(); 1192 try { 1193 final ActivityInfo info = mPackageManagerInternal.getActivityInfo(component, 1194 PackageManager.MATCH_DIRECT_BOOT_AWARE 1195 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 1196 callingUid, user.getIdentifier()); 1197 // Note we don't check "exported" because if the caller has the same UID as the 1198 // callee's UID, it can still be launched. 1199 // (If an app doesn't export a front door activity and causes issues with the 1200 // launcher, that's just the app's bug.) 1201 return info != null && info.isEnabled(); 1202 } finally { 1203 Binder.restoreCallingIdentity(ident); 1204 } 1205 } 1206 1207 @Override startSessionDetailsActivityAsUser(IApplicationThread caller, String callingPackage, String callingFeatureId, SessionInfo sessionInfo, Rect sourceBounds, Bundle opts, UserHandle userHandle)1208 public void startSessionDetailsActivityAsUser(IApplicationThread caller, 1209 String callingPackage, String callingFeatureId, SessionInfo sessionInfo, 1210 Rect sourceBounds, Bundle opts, UserHandle userHandle) throws RemoteException { 1211 int userId = userHandle.getIdentifier(); 1212 if (!canAccessProfile(userId, "Cannot start details activity")) { 1213 return; 1214 } 1215 1216 Intent i = new Intent(Intent.ACTION_VIEW) 1217 .setData(new Uri.Builder() 1218 .scheme("market") 1219 .authority("details") 1220 .appendQueryParameter("id", sessionInfo.appPackageName) 1221 .build()) 1222 .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app") 1223 .authority(callingPackage).build()); 1224 i.setSourceBounds(sourceBounds); 1225 1226 mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage, 1227 callingFeatureId, i, /* resultTo= */ null, Intent.FLAG_ACTIVITY_NEW_TASK, opts, 1228 userId); 1229 } 1230 1231 @Override getActivityLaunchIntent(String callingPackage, ComponentName component, UserHandle user)1232 public PendingIntent getActivityLaunchIntent(String callingPackage, ComponentName component, 1233 UserHandle user) { 1234 ensureShortcutPermission(callingPackage); 1235 if (!canAccessProfile(user.getIdentifier(), "Cannot start activity")) { 1236 throw new ActivityNotFoundException("Activity could not be found"); 1237 } 1238 1239 final Intent launchIntent = getMainActivityLaunchIntent(component, user); 1240 if (launchIntent == null) { 1241 throw new SecurityException("Attempt to launch activity without " 1242 + " category Intent.CATEGORY_LAUNCHER " + component); 1243 } 1244 1245 final long ident = Binder.clearCallingIdentity(); 1246 try { 1247 // If we reach here, we've verified that the caller has access to the profile and 1248 // is launching an exported activity with CATEGORY_LAUNCHER so we can clear the 1249 // calling identity to mirror the startActivityAsUser() call which does not validate 1250 // the calling user 1251 return PendingIntent.getActivityAsUser(mContext, 0 /* requestCode */, launchIntent, 1252 FLAG_MUTABLE, null /* opts */, user); 1253 } finally { 1254 Binder.restoreCallingIdentity(ident); 1255 } 1256 } 1257 1258 @Override startActivityAsUser(IApplicationThread caller, String callingPackage, String callingFeatureId, ComponentName component, Rect sourceBounds, Bundle opts, UserHandle user)1259 public void startActivityAsUser(IApplicationThread caller, String callingPackage, 1260 String callingFeatureId, ComponentName component, Rect sourceBounds, 1261 Bundle opts, UserHandle user) throws RemoteException { 1262 if (!canAccessProfile(user.getIdentifier(), "Cannot start activity")) { 1263 return; 1264 } 1265 1266 Intent launchIntent = getMainActivityLaunchIntent(component, user); 1267 if (launchIntent == null) { 1268 throw new SecurityException("Attempt to launch activity without " 1269 + " category Intent.CATEGORY_LAUNCHER " + component); 1270 } 1271 launchIntent.setSourceBounds(sourceBounds); 1272 1273 mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage, 1274 callingFeatureId, launchIntent, /* resultTo= */ null, 1275 Intent.FLAG_ACTIVITY_NEW_TASK, opts, user.getIdentifier()); 1276 } 1277 1278 /** 1279 * Returns the main activity launch intent for the given component package. 1280 */ getMainActivityLaunchIntent(ComponentName component, UserHandle user)1281 private Intent getMainActivityLaunchIntent(ComponentName component, UserHandle user) { 1282 Intent launchIntent = new Intent(Intent.ACTION_MAIN); 1283 launchIntent.addCategory(Intent.CATEGORY_LAUNCHER); 1284 launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1285 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 1286 launchIntent.setPackage(component.getPackageName()); 1287 1288 boolean canLaunch = false; 1289 1290 final int callingUid = injectBinderCallingUid(); 1291 final long ident = Binder.clearCallingIdentity(); 1292 try { 1293 // Check that the component actually has Intent.CATEGORY_LAUCNCHER 1294 // as calling startActivityAsUser ignores the category and just 1295 // resolves based on the component if present. 1296 final List<ResolveInfo> apps = mPackageManagerInternal.queryIntentActivities( 1297 launchIntent, 1298 launchIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 1299 PackageManager.MATCH_DIRECT_BOOT_AWARE 1300 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 1301 callingUid, user.getIdentifier()); 1302 final int size = apps.size(); 1303 for (int i = 0; i < size; ++i) { 1304 ActivityInfo activityInfo = apps.get(i).activityInfo; 1305 if (activityInfo.packageName.equals(component.getPackageName()) && 1306 activityInfo.name.equals(component.getClassName())) { 1307 if (!activityInfo.exported) { 1308 throw new SecurityException("Cannot launch non-exported components " 1309 + component); 1310 } 1311 1312 // Found an activity with category launcher that matches 1313 // this component so ok to launch. 1314 launchIntent.setPackage(null); 1315 launchIntent.setComponent(component); 1316 canLaunch = true; 1317 break; 1318 } 1319 } 1320 if (!canLaunch) { 1321 return null; 1322 } 1323 } finally { 1324 Binder.restoreCallingIdentity(ident); 1325 } 1326 return launchIntent; 1327 } 1328 1329 @Override showAppDetailsAsUser(IApplicationThread caller, String callingPackage, String callingFeatureId, ComponentName component, Rect sourceBounds, Bundle opts, UserHandle user)1330 public void showAppDetailsAsUser(IApplicationThread caller, 1331 String callingPackage, String callingFeatureId, ComponentName component, 1332 Rect sourceBounds, Bundle opts, UserHandle user) throws RemoteException { 1333 if (!canAccessProfile(user.getIdentifier(), "Cannot show app details")) { 1334 return; 1335 } 1336 1337 final Intent intent; 1338 final long ident = Binder.clearCallingIdentity(); 1339 try { 1340 String packageName = component.getPackageName(); 1341 int uId = -1; 1342 try { 1343 uId = mContext.getPackageManager().getApplicationInfo( 1344 packageName, PackageManager.MATCH_ANY_USER).uid; 1345 } catch (PackageManager.NameNotFoundException e) { 1346 Log.d(TAG, "package not found: " + e); 1347 } 1348 intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, 1349 Uri.fromParts("package", packageName, null)); 1350 intent.putExtra("uId", uId); 1351 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 1352 intent.setSourceBounds(sourceBounds); 1353 } finally { 1354 Binder.restoreCallingIdentity(ident); 1355 } 1356 mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage, 1357 callingFeatureId, intent, /* resultTo= */ null, Intent.FLAG_ACTIVITY_NEW_TASK, 1358 opts, user.getIdentifier()); 1359 } 1360 1361 /** Checks if user is a profile of or same as listeningUser. 1362 * and the user is enabled. */ isEnabledProfileOf(UserHandle listeningUser, UserHandle user, String debugMsg)1363 private boolean isEnabledProfileOf(UserHandle listeningUser, UserHandle user, 1364 String debugMsg) { 1365 return mUserManagerInternal.isProfileAccessible(listeningUser.getIdentifier(), 1366 user.getIdentifier(), debugMsg, false); 1367 } 1368 1369 /** Returns whether or not the result to the listener should be filtered. */ isPackageVisibleToListener(String packageName, BroadcastCookie cookie)1370 private boolean isPackageVisibleToListener(String packageName, BroadcastCookie cookie) { 1371 return !mPackageManagerInternal.filterAppAccess(packageName, cookie.callingUid, 1372 cookie.user.getIdentifier()); 1373 } 1374 1375 /** Returns whether or not the given appId is in allow list */ isCallingAppIdAllowed(int[] appIdAllowList, @AppIdInt int appId)1376 private static boolean isCallingAppIdAllowed(int[] appIdAllowList, @AppIdInt int appId) { 1377 if (appIdAllowList == null || appId < Process.FIRST_APPLICATION_UID) { 1378 return true; 1379 } 1380 return Arrays.binarySearch(appIdAllowList, appId) > -1; 1381 } 1382 getFilteredPackageNames(String[] packageNames, BroadcastCookie cookie)1383 private String[] getFilteredPackageNames(String[] packageNames, BroadcastCookie cookie) { 1384 final List<String> filteredPackageNames = new ArrayList<>(); 1385 for (String packageName : packageNames) { 1386 if (!isPackageVisibleToListener(packageName, cookie)) { 1387 continue; 1388 } 1389 filteredPackageNames.add(packageName); 1390 } 1391 return filteredPackageNames.toArray(new String[filteredPackageNames.size()]); 1392 } 1393 toShortcutsCacheFlags(int cacheFlags)1394 private int toShortcutsCacheFlags(int cacheFlags) { 1395 int ret = 0; 1396 if (cacheFlags == FLAG_CACHE_NOTIFICATION_SHORTCUTS) { 1397 ret = ShortcutInfo.FLAG_CACHED_NOTIFICATIONS; 1398 } else if (cacheFlags == FLAG_CACHE_BUBBLE_SHORTCUTS) { 1399 ret = ShortcutInfo.FLAG_CACHED_BUBBLES; 1400 } else if (cacheFlags == FLAG_CACHE_PEOPLE_TILE_SHORTCUTS) { 1401 ret = ShortcutInfo.FLAG_CACHED_PEOPLE_TILE; 1402 } 1403 Preconditions.checkArgumentPositive(ret, "Invalid cache owner"); 1404 1405 return ret; 1406 } 1407 1408 @VisibleForTesting postToPackageMonitorHandler(Runnable r)1409 void postToPackageMonitorHandler(Runnable r) { 1410 mCallbackHandler.post(r); 1411 } 1412 1413 /** 1414 * Check all installed apps and if a package is installed via Incremental and not fully 1415 * loaded, register loading progress listener. 1416 */ registerLoadingProgressForIncrementalApps()1417 void registerLoadingProgressForIncrementalApps() { 1418 final List<UserHandle> users = mUm.getUserProfiles(); 1419 if (users == null) { 1420 return; 1421 } 1422 for (UserHandle user : users) { 1423 mPackageManagerInternal.forEachInstalledPackage(pkg -> { 1424 final String packageName = pkg.getPackageName(); 1425 if (mPackageManagerInternal.getIncrementalStatesInfo(packageName, 1426 Process.myUid(), user.getIdentifier()).isLoading()) { 1427 mPackageManagerInternal.registerInstalledLoadingProgressCallback( 1428 packageName, new PackageLoadingProgressCallback(packageName, user), 1429 user.getIdentifier()); 1430 } 1431 }, user.getIdentifier()); 1432 } 1433 } 1434 1435 public static class ShortcutChangeHandler implements LauncherApps.ShortcutChangeCallback { 1436 private final UserManagerInternal mUserManagerInternal; 1437 ShortcutChangeHandler(UserManagerInternal userManager)1438 ShortcutChangeHandler(UserManagerInternal userManager) { 1439 mUserManagerInternal = userManager; 1440 } 1441 1442 private final RemoteCallbackList<IShortcutChangeCallback> mCallbacks = 1443 new RemoteCallbackList<>(); 1444 addShortcutChangeCallback(IShortcutChangeCallback callback, ShortcutQueryWrapper query, UserHandle user)1445 public synchronized void addShortcutChangeCallback(IShortcutChangeCallback callback, 1446 ShortcutQueryWrapper query, UserHandle user) { 1447 mCallbacks.unregister(callback); 1448 mCallbacks.register(callback, new Pair<>(query, user)); 1449 } 1450 removeShortcutChangeCallback( IShortcutChangeCallback callback)1451 public synchronized void removeShortcutChangeCallback( 1452 IShortcutChangeCallback callback) { 1453 mCallbacks.unregister(callback); 1454 } 1455 1456 @Override onShortcutsAddedOrUpdated(String packageName, List<ShortcutInfo> shortcuts, UserHandle user)1457 public void onShortcutsAddedOrUpdated(String packageName, List<ShortcutInfo> shortcuts, 1458 UserHandle user) { 1459 onShortcutEvent(packageName, shortcuts, user, false); 1460 } 1461 1462 @Override onShortcutsRemoved(String packageName, List<ShortcutInfo> shortcuts, UserHandle user)1463 public void onShortcutsRemoved(String packageName, List<ShortcutInfo> shortcuts, 1464 UserHandle user) { 1465 onShortcutEvent(packageName, shortcuts, user, true); 1466 } 1467 onShortcutEvent(String packageName, List<ShortcutInfo> shortcuts, UserHandle user, boolean shortcutsRemoved)1468 private void onShortcutEvent(String packageName, 1469 List<ShortcutInfo> shortcuts, UserHandle user, boolean shortcutsRemoved) { 1470 int count = mCallbacks.beginBroadcast(); 1471 1472 for (int i = 0; i < count; i++) { 1473 final IShortcutChangeCallback callback = mCallbacks.getBroadcastItem(i); 1474 final Pair<ShortcutQueryWrapper, UserHandle> cookie = 1475 (Pair<ShortcutQueryWrapper, UserHandle>) 1476 mCallbacks.getBroadcastCookie(i); 1477 1478 final UserHandle callbackUser = cookie.second; 1479 if (callbackUser != null && !hasUserAccess(callbackUser, user)) { 1480 // Callback owner does not have access to the shortcuts' user. 1481 continue; 1482 } 1483 1484 // Filter the list by query, if any matches exists, send via callback. 1485 List<ShortcutInfo> matchedList = filterShortcutsByQuery(packageName, shortcuts, 1486 cookie.first, shortcutsRemoved); 1487 if (!CollectionUtils.isEmpty(matchedList)) { 1488 try { 1489 if (shortcutsRemoved) { 1490 callback.onShortcutsRemoved(packageName, matchedList, user); 1491 } else { 1492 callback.onShortcutsAddedOrUpdated(packageName, matchedList, user); 1493 } 1494 } catch (RemoteException e) { 1495 // The RemoteCallbackList will take care of removing the dead object. 1496 } 1497 } 1498 } 1499 1500 mCallbacks.finishBroadcast(); 1501 } 1502 filterShortcutsByQuery(String packageName, List<ShortcutInfo> shortcuts, ShortcutQueryWrapper query, boolean shortcutsRemoved)1503 public static List<ShortcutInfo> filterShortcutsByQuery(String packageName, 1504 List<ShortcutInfo> shortcuts, ShortcutQueryWrapper query, 1505 boolean shortcutsRemoved) { 1506 final long changedSince = query.getChangedSince(); 1507 final String queryPackage = query.getPackage(); 1508 final List<String> shortcutIds = query.getShortcutIds(); 1509 final List<LocusId> locusIds = query.getLocusIds(); 1510 final ComponentName activity = query.getActivity(); 1511 final int flags = query.getQueryFlags(); 1512 1513 if (queryPackage != null && !queryPackage.equals(packageName)) { 1514 return null; 1515 } 1516 1517 List<ShortcutInfo> matches = new ArrayList<>(); 1518 1519 final boolean matchDynamic = (flags & ShortcutQuery.FLAG_MATCH_DYNAMIC) != 0; 1520 final boolean matchPinned = (flags & ShortcutQuery.FLAG_MATCH_PINNED) != 0; 1521 final boolean matchManifest = (flags & ShortcutQuery.FLAG_MATCH_MANIFEST) != 0; 1522 final boolean matchCached = (flags & ShortcutQuery.FLAG_MATCH_CACHED) != 0; 1523 final int shortcutFlags = (matchDynamic ? ShortcutInfo.FLAG_DYNAMIC : 0) 1524 | (matchPinned ? ShortcutInfo.FLAG_PINNED : 0) 1525 | (matchManifest ? ShortcutInfo.FLAG_MANIFEST : 0) 1526 | (matchCached ? ShortcutInfo.FLAG_CACHED_ALL : 0); 1527 1528 for (int i = 0; i < shortcuts.size(); i++) { 1529 final ShortcutInfo si = shortcuts.get(i); 1530 1531 if (activity != null && !activity.equals(si.getActivity())) { 1532 continue; 1533 } 1534 if (changedSince != 0 && changedSince > si.getLastChangedTimestamp()) { 1535 continue; 1536 } 1537 if (shortcutIds != null && !shortcutIds.contains(si.getId())) { 1538 continue; 1539 } 1540 if (locusIds != null && !locusIds.contains(si.getLocusId())) { 1541 continue; 1542 } 1543 if (shortcutsRemoved || (shortcutFlags & si.getFlags()) != 0) { 1544 matches.add(si); 1545 } 1546 } 1547 1548 return matches; 1549 } 1550 hasUserAccess(UserHandle callbackUser, UserHandle shortcutUser)1551 private boolean hasUserAccess(UserHandle callbackUser, UserHandle shortcutUser) { 1552 final int callbackUserId = callbackUser.getIdentifier(); 1553 final int shortcutUserId = shortcutUser.getIdentifier(); 1554 1555 if (shortcutUser == callbackUser) return true; 1556 return mUserManagerInternal.isProfileAccessible(callbackUserId, shortcutUserId, 1557 null, false); 1558 } 1559 } 1560 1561 private class PackageRemovedListener extends BroadcastReceiver { 1562 1563 @Override onReceive(Context context, Intent intent)1564 public void onReceive(Context context, Intent intent) { 1565 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 1566 UserHandle.USER_NULL); 1567 if (userId == UserHandle.USER_NULL) { 1568 Slog.w(TAG, "Intent broadcast does not contain user handle: " + intent); 1569 return; 1570 } 1571 final String action = intent.getAction(); 1572 // Handle onPackageRemoved. 1573 if (Intent.ACTION_PACKAGE_REMOVED_INTERNAL.equals(action)) { 1574 final String packageName = getPackageName(intent); 1575 final int[] appIdAllowList = 1576 intent.getIntArrayExtra(Intent.EXTRA_VISIBILITY_ALLOW_LIST); 1577 // If {@link #EXTRA_REPLACING} is true, that will be onPackageChanged case. 1578 if (packageName != null && !intent.getBooleanExtra( 1579 Intent.EXTRA_REPLACING, /* defaultValue= */ false)) { 1580 final UserHandle user = new UserHandle(userId); 1581 final int n = mListeners.beginBroadcast(); 1582 try { 1583 for (int i = 0; i < n; i++) { 1584 final IOnAppsChangedListener listener = 1585 mListeners.getBroadcastItem(i); 1586 final BroadcastCookie cookie = 1587 (BroadcastCookie) mListeners.getBroadcastCookie(i); 1588 if (!isEnabledProfileOf(cookie.user, user, "onPackageRemoved")) { 1589 continue; 1590 } 1591 if (!isCallingAppIdAllowed(appIdAllowList, UserHandle.getAppId( 1592 cookie.callingUid))) { 1593 continue; 1594 } 1595 try { 1596 listener.onPackageRemoved(user, packageName); 1597 } catch (RemoteException re) { 1598 Slog.d(TAG, "Callback failed ", re); 1599 } 1600 } 1601 } finally { 1602 mListeners.finishBroadcast(); 1603 } 1604 } 1605 } 1606 } 1607 getPackageName(Intent intent)1608 private String getPackageName(Intent intent) { 1609 final Uri uri = intent.getData(); 1610 final String pkg = uri != null ? uri.getSchemeSpecificPart() : null; 1611 return pkg; 1612 } 1613 } 1614 1615 private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener { 1616 1617 // TODO Simplify with lambdas. 1618 1619 @Override onPackageAdded(String packageName, int uid)1620 public void onPackageAdded(String packageName, int uid) { 1621 UserHandle user = new UserHandle(getChangingUserId()); 1622 final int n = mListeners.beginBroadcast(); 1623 try { 1624 for (int i = 0; i < n; i++) { 1625 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 1626 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 1627 if (!isEnabledProfileOf(cookie.user, user, "onPackageAdded")) { 1628 continue; 1629 } 1630 if (!isPackageVisibleToListener(packageName, cookie)) { 1631 continue; 1632 } 1633 try { 1634 listener.onPackageAdded(user, packageName); 1635 } catch (RemoteException re) { 1636 Slog.d(TAG, "Callback failed ", re); 1637 } 1638 } 1639 } finally { 1640 mListeners.finishBroadcast(); 1641 } 1642 super.onPackageAdded(packageName, uid); 1643 mPackageManagerInternal.registerInstalledLoadingProgressCallback(packageName, 1644 new PackageLoadingProgressCallback(packageName, user), 1645 user.getIdentifier()); 1646 } 1647 1648 @Override onPackageModified(String packageName)1649 public void onPackageModified(String packageName) { 1650 onPackageChanged(packageName); 1651 super.onPackageModified(packageName); 1652 } 1653 onPackageChanged(String packageName)1654 private void onPackageChanged(String packageName) { 1655 UserHandle user = new UserHandle(getChangingUserId()); 1656 final int n = mListeners.beginBroadcast(); 1657 try { 1658 for (int i = 0; i < n; i++) { 1659 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 1660 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 1661 if (!isEnabledProfileOf(cookie.user, user, "onPackageModified")) { 1662 continue; 1663 } 1664 if (!isPackageVisibleToListener(packageName, cookie)) { 1665 continue; 1666 } 1667 try { 1668 listener.onPackageChanged(user, packageName); 1669 } catch (RemoteException re) { 1670 Slog.d(TAG, "Callback failed ", re); 1671 } 1672 } 1673 } finally { 1674 mListeners.finishBroadcast(); 1675 } 1676 } 1677 1678 @Override onPackagesAvailable(String[] packages)1679 public void onPackagesAvailable(String[] packages) { 1680 UserHandle user = new UserHandle(getChangingUserId()); 1681 final int n = mListeners.beginBroadcast(); 1682 try { 1683 for (int i = 0; i < n; i++) { 1684 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 1685 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 1686 if (!isEnabledProfileOf(cookie.user, user, "onPackagesAvailable")) { 1687 continue; 1688 } 1689 final String[] filteredPackages = getFilteredPackageNames(packages, cookie); 1690 // If all packages are filtered, skip notifying listener. 1691 if (ArrayUtils.isEmpty(filteredPackages)) { 1692 continue; 1693 } 1694 try { 1695 listener.onPackagesAvailable(user, filteredPackages, isReplacing()); 1696 } catch (RemoteException re) { 1697 Slog.d(TAG, "Callback failed ", re); 1698 } 1699 } 1700 } finally { 1701 mListeners.finishBroadcast(); 1702 } 1703 1704 super.onPackagesAvailable(packages); 1705 } 1706 1707 @Override onPackagesUnavailable(String[] packages)1708 public void onPackagesUnavailable(String[] packages) { 1709 UserHandle user = new UserHandle(getChangingUserId()); 1710 final int n = mListeners.beginBroadcast(); 1711 try { 1712 for (int i = 0; i < n; i++) { 1713 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 1714 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 1715 if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnavailable")) { 1716 continue; 1717 } 1718 final String[] filteredPackages = getFilteredPackageNames(packages, cookie); 1719 // If all packages are filtered, skip notifying listener. 1720 if (ArrayUtils.isEmpty(filteredPackages)) { 1721 continue; 1722 } 1723 try { 1724 listener.onPackagesUnavailable(user, filteredPackages, isReplacing()); 1725 } catch (RemoteException re) { 1726 Slog.d(TAG, "Callback failed ", re); 1727 } 1728 } 1729 } finally { 1730 mListeners.finishBroadcast(); 1731 } 1732 1733 super.onPackagesUnavailable(packages); 1734 } 1735 1736 @Override onPackagesSuspended(String[] packages)1737 public void onPackagesSuspended(String[] packages) { 1738 UserHandle user = new UserHandle(getChangingUserId()); 1739 final ArrayList<Pair<String, Bundle>> packagesWithExtras = new ArrayList<>(); 1740 final ArrayList<String> packagesWithoutExtras = new ArrayList<>(); 1741 for (String pkg : packages) { 1742 final Bundle launcherExtras = 1743 mPackageManagerInternal.getSuspendedPackageLauncherExtras(pkg, 1744 user.getIdentifier()); 1745 if (launcherExtras != null) { 1746 packagesWithExtras.add(new Pair<>(pkg, launcherExtras)); 1747 } else { 1748 packagesWithoutExtras.add(pkg); 1749 } 1750 } 1751 final String[] packagesNullExtras = packagesWithoutExtras.toArray( 1752 new String[packagesWithoutExtras.size()]); 1753 final int n = mListeners.beginBroadcast(); 1754 try { 1755 for (int i = 0; i < n; i++) { 1756 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 1757 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 1758 if (!isEnabledProfileOf(cookie.user, user, "onPackagesSuspended")) { 1759 continue; 1760 } 1761 final String[] filteredPackagesWithoutExtras = 1762 getFilteredPackageNames(packagesNullExtras, cookie); 1763 try { 1764 if (!ArrayUtils.isEmpty(filteredPackagesWithoutExtras)) { 1765 listener.onPackagesSuspended(user, filteredPackagesWithoutExtras, 1766 /* launcherExtras= */ null); 1767 } 1768 for (int idx = 0; idx < packagesWithExtras.size(); idx++) { 1769 Pair<String, Bundle> packageExtraPair = packagesWithExtras.get(idx); 1770 if (!isPackageVisibleToListener(packageExtraPair.first, cookie)) { 1771 continue; 1772 } 1773 listener.onPackagesSuspended(user, 1774 new String[]{packageExtraPair.first}, 1775 packageExtraPair.second); 1776 } 1777 } catch (RemoteException re) { 1778 Slog.d(TAG, "Callback failed ", re); 1779 } 1780 } 1781 } finally { 1782 mListeners.finishBroadcast(); 1783 } 1784 } 1785 1786 @Override onPackagesUnsuspended(String[] packages)1787 public void onPackagesUnsuspended(String[] packages) { 1788 UserHandle user = new UserHandle(getChangingUserId()); 1789 final int n = mListeners.beginBroadcast(); 1790 try { 1791 for (int i = 0; i < n; i++) { 1792 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 1793 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 1794 if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnsuspended")) { 1795 continue; 1796 } 1797 final String[] filteredPackages = getFilteredPackageNames(packages, cookie); 1798 // If all packages are filtered, skip notifying listener. 1799 if (ArrayUtils.isEmpty(filteredPackages)) { 1800 continue; 1801 } 1802 try { 1803 listener.onPackagesUnsuspended(user, filteredPackages); 1804 } catch (RemoteException re) { 1805 Slog.d(TAG, "Callback failed ", re); 1806 } 1807 } 1808 } finally { 1809 mListeners.finishBroadcast(); 1810 } 1811 1812 super.onPackagesUnsuspended(packages); 1813 } 1814 1815 @Override onShortcutChanged(@onNull String packageName, @UserIdInt int userId)1816 public void onShortcutChanged(@NonNull String packageName, 1817 @UserIdInt int userId) { 1818 postToPackageMonitorHandler(() -> onShortcutChangedInner(packageName, userId)); 1819 } 1820 onShortcutChangedInner(@onNull String packageName, @UserIdInt int userId)1821 private void onShortcutChangedInner(@NonNull String packageName, 1822 @UserIdInt int userId) { 1823 final int n = mListeners.beginBroadcast(); 1824 try { 1825 final UserHandle user = UserHandle.of(userId); 1826 1827 for (int i = 0; i < n; i++) { 1828 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 1829 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 1830 if (!isEnabledProfileOf(cookie.user, user, "onShortcutChanged")) { 1831 continue; 1832 } 1833 if (!isPackageVisibleToListener(packageName, cookie)) { 1834 continue; 1835 } 1836 final int launcherUserId = cookie.user.getIdentifier(); 1837 1838 // Make sure the caller has the permission. 1839 if (!mShortcutServiceInternal.hasShortcutHostPermission( 1840 launcherUserId, cookie.packageName, 1841 cookie.callingPid, cookie.callingUid)) { 1842 continue; 1843 } 1844 // Each launcher has a different set of pinned shortcuts, so we need to do a 1845 // query in here. 1846 // (As of now, only one launcher has the permission at a time, so it's bit 1847 // moot, but we may change the permission model eventually.) 1848 final List<ShortcutInfo> list = 1849 mShortcutServiceInternal.getShortcuts(launcherUserId, 1850 cookie.packageName, 1851 /* changedSince= */ 0, packageName, /* shortcutIds=*/ null, 1852 /* locusIds=*/ null, /* component= */ null, 1853 ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY 1854 | ShortcutQuery.FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED 1855 , userId, cookie.callingPid, cookie.callingUid); 1856 try { 1857 listener.onShortcutChanged(user, packageName, 1858 new ParceledListSlice<>(list)); 1859 } catch (RemoteException re) { 1860 Slog.d(TAG, "Callback failed ", re); 1861 } 1862 1863 } 1864 } catch (RuntimeException e) { 1865 // When the user is locked we get IllegalState, so just catch all. 1866 Log.w(TAG, e.getMessage(), e); 1867 } finally { 1868 mListeners.finishBroadcast(); 1869 } 1870 } 1871 1872 @Override onPackageStateChanged(String packageName, int uid)1873 public void onPackageStateChanged(String packageName, int uid) { 1874 onPackageChanged(packageName); 1875 super.onPackageStateChanged(packageName, uid); 1876 } 1877 } 1878 1879 class PackageCallbackList<T extends IInterface> extends RemoteCallbackList<T> { 1880 @Override onCallbackDied(T callback, Object cookie)1881 public void onCallbackDied(T callback, Object cookie) { 1882 checkCallbackCount(); 1883 } 1884 } 1885 1886 class PackageLoadingProgressCallback extends 1887 PackageManagerInternal.InstalledLoadingProgressCallback { 1888 private String mPackageName; 1889 private UserHandle mUser; 1890 PackageLoadingProgressCallback(String packageName, UserHandle user)1891 PackageLoadingProgressCallback(String packageName, UserHandle user) { 1892 super(mCallbackHandler); 1893 mPackageName = packageName; 1894 mUser = user; 1895 } 1896 1897 @Override onLoadingProgressChanged(float progress)1898 public void onLoadingProgressChanged(float progress) { 1899 final int n = mListeners.beginBroadcast(); 1900 try { 1901 for (int i = 0; i < n; i++) { 1902 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 1903 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 1904 if (!isEnabledProfileOf(cookie.user, mUser, "onLoadingProgressChanged")) { 1905 continue; 1906 } 1907 if (!isPackageVisibleToListener(mPackageName, cookie)) { 1908 continue; 1909 } 1910 try { 1911 listener.onPackageLoadingProgressChanged(mUser, mPackageName, progress); 1912 } catch (RemoteException re) { 1913 Slog.d(TAG, "Callback failed ", re); 1914 } 1915 } 1916 } finally { 1917 mListeners.finishBroadcast(); 1918 } 1919 } 1920 } 1921 1922 final class LocalService extends LauncherAppsServiceInternal { 1923 @Override startShortcut(int callerUid, int callerPid, String callingPackage, String packageName, String featureId, String shortcutId, Rect sourceBounds, Bundle startActivityOptions, int targetUserId)1924 public boolean startShortcut(int callerUid, int callerPid, String callingPackage, 1925 String packageName, String featureId, String shortcutId, Rect sourceBounds, 1926 Bundle startActivityOptions, int targetUserId) { 1927 return LauncherAppsImpl.this.startShortcutInner(callerUid, callerPid, 1928 UserHandle.getUserId(callerUid), callingPackage, packageName, featureId, 1929 shortcutId, sourceBounds, startActivityOptions, targetUserId); 1930 } 1931 } 1932 } 1933 } 1934