Merge "Do not lock when calling startActivityFromRecents" into sc-v2-dev am: a752da8c80

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15921002

Change-Id: Ib68ea3032db81b704d299c0c40b6bf9e12532dfe
This commit is contained in:
Riddle Hsu
2021-09-28 09:48:19 +00:00
committed by Automerger Merge Worker
4 changed files with 123 additions and 84 deletions

View File

@@ -1732,10 +1732,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(bOptions); final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(bOptions);
final long origId = Binder.clearCallingIdentity(); final long origId = Binder.clearCallingIdentity();
try { try {
synchronized (mGlobalLock) {
return mTaskSupervisor.startActivityFromRecents(callingPid, callingUid, taskId, return mTaskSupervisor.startActivityFromRecents(callingPid, callingUid, taskId,
safeOptions); safeOptions);
}
} finally { } finally {
Binder.restoreCallingIdentity(origId); Binder.restoreCallingIdentity(origId);
} }

View File

@@ -2474,30 +2474,39 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
} }
} }
/**
* Start the given task from the recent tasks. Do not hold WM global lock when calling this
* method to avoid potential deadlock or permission deny by UriGrantsManager when resolving
* activity (see {@link ActivityStarter.Request#resolveActivity} and
* {@link com.android.server.am.ContentProviderHelper#checkContentProviderUriPermission}).
*
* @return The result code of starter.
*/
int startActivityFromRecents(int callingPid, int callingUid, int taskId, int startActivityFromRecents(int callingPid, int callingUid, int taskId,
SafeActivityOptions options) { SafeActivityOptions options) {
Task task = null; final Task task;
final int taskCallingUid;
final String callingPackage; final String callingPackage;
final String callingFeatureId; final String callingFeatureId;
final Intent intent; final Intent intent;
final int userId; final int userId;
int activityType = ACTIVITY_TYPE_UNDEFINED;
int windowingMode = WINDOWING_MODE_UNDEFINED;
final ActivityOptions activityOptions = options != null final ActivityOptions activityOptions = options != null
? options.getOptions(this) ? options.getOptions(this)
: null; : null;
boolean moveHomeTaskForward = true; boolean moveHomeTaskForward = true;
synchronized (mService.mGlobalLock) {
int activityType = ACTIVITY_TYPE_UNDEFINED;
if (activityOptions != null) { if (activityOptions != null) {
activityType = activityOptions.getLaunchActivityType(); activityType = activityOptions.getLaunchActivityType();
windowingMode = activityOptions.getLaunchWindowingMode(); final int windowingMode = activityOptions.getLaunchWindowingMode();
if (activityOptions.freezeRecentTasksReordering() if (activityOptions.freezeRecentTasksReordering()
&& mRecentTasks.isCallerRecents(callingUid)) { && mRecentTasks.isCallerRecents(callingUid)) {
mRecentTasks.setFreezeTaskListReordering(); mRecentTasks.setFreezeTaskListReordering();
} }
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
|| activityOptions.getLaunchRootTask() != null) { || activityOptions.getLaunchRootTask() != null) {
// Don't move home activity forward if we are launching into primary split or there // Don't move home activity forward if we are launching into primary split or
// is a launch root set. // there is a launch root set.
moveHomeTaskForward = false; moveHomeTaskForward = false;
} }
} }
@@ -2506,6 +2515,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
+ taskId + " can't be launch in the home/recents root task."); + taskId + " can't be launch in the home/recents root task.");
} }
boolean shouldStartActivity = false;
mService.deferWindowLayout(); mService.deferWindowLayout();
try { try {
task = mRootWindowContainer.anyTaskForId(taskId, task = mRootWindowContainer.anyTaskForId(taskId,
@@ -2517,16 +2527,17 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
} }
if (moveHomeTaskForward) { if (moveHomeTaskForward) {
// We always want to return to the home activity instead of the recents activity // We always want to return to the home activity instead of the recents
// from whatever is started from the recents activity, so move the home root task // activity from whatever is started from the recents activity, so move
// forward. // the home root task forward.
// TODO (b/115289124): Multi-display supports for recents. // TODO (b/115289124): Multi-display supports for recents.
mRootWindowContainer.getDefaultTaskDisplayArea().moveHomeRootTaskToFront( mRootWindowContainer.getDefaultTaskDisplayArea().moveHomeRootTaskToFront(
"startActivityFromRecents"); "startActivityFromRecents");
} }
// If the user must confirm credentials (e.g. when first launching a work app and the // If the user must confirm credentials (e.g. when first launching a work
// Work Challenge is present) let startActivityInPackage handle the intercepting. // app and the Work Challenge is present) let startActivityInPackage handle
// the intercepting.
if (!mService.mAmInternal.shouldConfirmCredentials(task.mUserId) if (!mService.mAmInternal.shouldConfirmCredentials(task.mUserId)
&& task.getRootActivity() != null) { && task.getRootActivity() != null) {
final ActivityRecord targetActivity = task.getTopNonFinishingActivity(); final ActivityRecord targetActivity = task.getTopNonFinishingActivity();
@@ -2536,16 +2547,16 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
final LaunchingState launchingState = final LaunchingState launchingState =
mActivityMetricsLogger.notifyActivityLaunching(task.intent); mActivityMetricsLogger.notifyActivityLaunching(task.intent);
try { try {
mService.moveTaskToFrontLocked(null /* appThread */, null /* callingPackage */, mService.moveTaskToFrontLocked(null /* appThread */,
task.mTaskId, 0, options); null /* callingPackage */, task.mTaskId, 0, options);
// Apply options to prevent pendingOptions be taken when scheduling activity // Apply options to prevent pendingOptions be taken when scheduling
// lifecycle transaction to make sure the override pending app transition will // activity lifecycle transaction to make sure the override pending app
// be applied immediately. // transition will be applied immediately.
targetActivity.applyOptionsAnimation(); targetActivity.applyOptionsAnimation();
} finally { } finally {
mActivityMetricsLogger.notifyActivityLaunched(launchingState, mActivityMetricsLogger.notifyActivityLaunched(launchingState,
START_TASK_TO_FRONT, false /* newActivityCreated */, targetActivity, START_TASK_TO_FRONT, false /* newActivityCreated */,
activityOptions); targetActivity, activityOptions);
} }
mService.getActivityStartController().postStartActivityProcessingForLastStarter( mService.getActivityStartController().postStartActivityProcessingForLastStarter(
@@ -2555,23 +2566,36 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
// As it doesn't go to ActivityStarter.executeRequest() path, we need to resume // As it doesn't go to ActivityStarter.executeRequest() path, we need to resume
// app switching here also. // app switching here also.
mService.resumeAppSwitches(); mService.resumeAppSwitches();
return ActivityManager.START_TASK_TO_FRONT; return ActivityManager.START_TASK_TO_FRONT;
} }
// The task is empty or needs to show the confirmation for credential.
shouldStartActivity = true;
} finally {
if (!shouldStartActivity) {
mService.continueWindowLayout();
}
}
taskCallingUid = task.mCallingUid;
callingPackage = task.mCallingPackage; callingPackage = task.mCallingPackage;
callingFeatureId = task.mCallingFeatureId; callingFeatureId = task.mCallingFeatureId;
intent = task.intent; intent = task.intent;
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY); intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
userId = task.mUserId; userId = task.mUserId;
return mService.getActivityStartController().startActivityInPackage(task.mCallingUid, }
// ActivityStarter will acquire the lock where the places need, so execute the request
// outside of the lock.
try {
return mService.getActivityStartController().startActivityInPackage(taskCallingUid,
callingPid, callingUid, callingPackage, callingFeatureId, intent, null, null, callingPid, callingUid, callingPackage, callingFeatureId, intent, null, null,
null, 0, 0, options, userId, task, "startActivityFromRecents", null, 0, 0, options, userId, task, "startActivityFromRecents",
false /* validateIncomingUser */, null /* originatingPendingIntent */, false /* validateIncomingUser */, null /* originatingPendingIntent */,
false /* allowBackgroundActivityStart */); false /* allowBackgroundActivityStart */);
} finally { } finally {
synchronized (mService.mGlobalLock) {
mService.continueWindowLayout(); mService.continueWindowLayout();
} }
} }
}
/** /**
* Internal container to store a match qualifier alongside a WaitResult. * Internal container to store a match qualifier alongside a WaitResult.

View File

@@ -35,10 +35,10 @@ import android.os.UserHandle;
*/ */
class AppTaskImpl extends IAppTask.Stub { class AppTaskImpl extends IAppTask.Stub {
private static final String TAG = "AppTaskImpl"; private static final String TAG = "AppTaskImpl";
private ActivityTaskManagerService mService; private final ActivityTaskManagerService mService;
private int mTaskId; private final int mTaskId;
private int mCallingUid; private final int mCallingUid;
public AppTaskImpl(ActivityTaskManagerService service, int taskId, int callingUid) { public AppTaskImpl(ActivityTaskManagerService service, int taskId, int callingUid) {
mService = service; mService = service;
@@ -113,9 +113,9 @@ class AppTaskImpl extends IAppTask.Stub {
return; return;
} }
} }
mService.mTaskSupervisor.startActivityFromRecents(callingPid,
callingUid, mTaskId, null);
} }
mService.mTaskSupervisor.startActivityFromRecents(callingPid, callingUid, mTaskId,
null /* options */);
} finally { } finally {
Binder.restoreCallingIdentity(origId); Binder.restoreCallingIdentity(origId);
} }

View File

@@ -318,7 +318,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
* @param caller Info about the calling process. * @param caller Info about the calling process.
*/ */
private void applyTransaction(@NonNull WindowContainerTransaction t, int syncId, private void applyTransaction(@NonNull WindowContainerTransaction t, int syncId,
@Nullable Transition transition, @Nullable CallerInfo caller) { @Nullable Transition transition, @NonNull CallerInfo caller) {
int effects = 0; int effects = 0;
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Apply window transaction, syncId=%d", syncId); ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Apply window transaction, syncId=%d", syncId);
mService.deferWindowLayout(); mService.deferWindowLayout();
@@ -540,7 +540,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
private int applyHierarchyOp(WindowContainerTransaction.HierarchyOp hop, int effects, private int applyHierarchyOp(WindowContainerTransaction.HierarchyOp hop, int effects,
int syncId, @Nullable Transition transition, boolean isInLockTaskMode, int syncId, @Nullable Transition transition, boolean isInLockTaskMode,
@Nullable CallerInfo caller, @Nullable IBinder errorCallbackToken, @NonNull CallerInfo caller, @Nullable IBinder errorCallbackToken,
@Nullable ITaskFragmentOrganizer organizer) { @Nullable ITaskFragmentOrganizer organizer) {
final int type = hop.getType(); final int type = hop.getType();
switch (type) { switch (type) {
@@ -628,11 +628,28 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
final int taskId = launchOpts.getInt( final int taskId = launchOpts.getInt(
WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID); WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID);
launchOpts.remove(WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID); launchOpts.remove(WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID);
final SafeActivityOptions safeOptions = caller != null final SafeActivityOptions safeOptions =
? SafeActivityOptions.fromBundle(launchOpts, caller.mPid, caller.mUid) SafeActivityOptions.fromBundle(launchOpts, caller.mPid, caller.mUid);
: SafeActivityOptions.fromBundle(launchOpts); final Integer[] starterResult = { null };
mService.mTaskSupervisor.startActivityFromRecents(caller.mPid, caller.mUid, // startActivityFromRecents should not be called in lock.
taskId, safeOptions); mService.mH.post(() -> {
try {
starterResult[0] = mService.mTaskSupervisor.startActivityFromRecents(
caller.mPid, caller.mUid, taskId, safeOptions);
} catch (Throwable t) {
starterResult[0] = ActivityManager.START_CANCELED;
Slog.w(TAG, t);
}
synchronized (mGlobalLock) {
mGlobalLock.notifyAll();
}
});
while (starterResult[0] == null) {
try {
mGlobalLock.wait();
} catch (InterruptedException ignored) {
}
}
break; break;
case HIERARCHY_OP_TYPE_PENDING_INTENT: case HIERARCHY_OP_TYPE_PENDING_INTENT:
String resolvedType = hop.getActivityIntent() != null String resolvedType = hop.getActivityIntent() != null