Shortcuts let the launcher start activities on work profile, so we can't apply
the usual cross-user startActivity check.
LauncherApps already checks the calling user and the target user relationship,
so let's just skip the handleIncomingUser check.
Bug:
72659387
Test: atest CtsShortcutManagerTestCases
Test: atest ${ANDROID_BUILD_TOP}/cts/hostsidetests/shortcuts/hostside/src/android/content/pm/cts/shortcuthost/ShortcutManagerMultiuserTest.java
Change-Id: I3b6179af0c9d5e54ed8fd57c9c830f7a6ecec9da
/**
* Start activity {@code intents} as if {@code packageName} on user {@code userId} did it.
*
+ * - DO NOT call it with the calling UID cleared.
+ * - All the necessary caller permission checks must be done at callsites.
+ *
* @return error codes used by {@link IActivityManager#startActivity} and its siblings.
*/
public abstract int startActivitiesAsPackage(String packageName,
}
synchronized (ActivityManagerService.this) {
- return mActivityStartController.startActivitiesInPackage(packageUid, packageName,
+ return mActivityStartController.startActivitiesInPackage(
+ packageUid, packageName,
intents, resolvedTypes, null /* resultTo */,
- SafeActivityOptions.fromBundle(bOptions), userId);
+ SafeActivityOptions.fromBundle(bOptions), userId,
+ false /* validateIncomingUser */);
}
}
.execute();
}
+ /**
+ * Start intents as a package.
+ *
+ * @param uid make a call as if this UID did.
+ * @param callingPackage make a call as if this package did.
+ * @param intents intents to start.
+ * @param userId start the intents on this user.
+ * @param validateIncomingUser set true to skip checking {@code userId} with the calling UID.
+ */
final int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents,
- String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId) {
+ String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId,
+ boolean validateIncomingUser) {
final String reason = "startActivityInPackage";
- userId = mService.mUserController.handleIncomingUser(Binder.getCallingPid(),
- Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, reason, null);
+ if (validateIncomingUser) {
+ userId = mService.mUserController.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, reason, null);
+ } else {
+ mService.mUserController.ensureNotSpecialUser(userId);
+ }
// TODO: Switch to user app stacks here.
return startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo, options,
userId, reason);
allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
res = owner.getActivityStartController().startActivitiesInPackage(
uid, key.packageName, allIntents, allResolvedTypes,
- resultTo, mergedOptions, userId);
+ resultTo, mergedOptions, userId,
+ true /* validateIncomingUser */);
} else {
res = owner.getActivityStartController().startActivityInPackage(uid,
callingPid, callingUid, key.packageName, finalIntent,
}
}
}
- if (!allowAll && targetUserId < 0) {
- throw new IllegalArgumentException(
- "Call does not support special user #" + targetUserId);
+ if (!allowAll) {
+ ensureNotSpecialUser(targetUserId);
}
// Check shell permission
if (callingUid == Process.SHELL_UID && targetUserId >= UserHandle.USER_SYSTEM) {
? getCurrentUserId(): userId;
}
+ void ensureNotSpecialUser(int userId) {
+ if (userId >= 0) {
+ return;
+ }
+ throw new IllegalArgumentException("Call does not support special user #" + userId);
+ }
+
void registerUserSwitchObserver(IUserSwitchObserver observer, String name) {
Preconditions.checkNotNull(name, "Observer name cannot be null");
if (mInjector.checkCallingPermission(INTERACT_ACROSS_USERS_FULL)