Merge "Do not lock when calling startActivityFromRecents" into sc-v2-dev
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2474,102 +2474,126 @@ 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;
|
||||||
if (activityOptions != null) {
|
synchronized (mService.mGlobalLock) {
|
||||||
activityType = activityOptions.getLaunchActivityType();
|
int activityType = ACTIVITY_TYPE_UNDEFINED;
|
||||||
windowingMode = activityOptions.getLaunchWindowingMode();
|
if (activityOptions != null) {
|
||||||
if (activityOptions.freezeRecentTasksReordering()
|
activityType = activityOptions.getLaunchActivityType();
|
||||||
&& mRecentTasks.isCallerRecents(callingUid)) {
|
final int windowingMode = activityOptions.getLaunchWindowingMode();
|
||||||
mRecentTasks.setFreezeTaskListReordering();
|
if (activityOptions.freezeRecentTasksReordering()
|
||||||
|
&& mRecentTasks.isCallerRecents(callingUid)) {
|
||||||
|
mRecentTasks.setFreezeTaskListReordering();
|
||||||
|
}
|
||||||
|
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
|
||||||
|
|| activityOptions.getLaunchRootTask() != null) {
|
||||||
|
// Don't move home activity forward if we are launching into primary split or
|
||||||
|
// there is a launch root set.
|
||||||
|
moveHomeTaskForward = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
|
if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) {
|
||||||
|| activityOptions.getLaunchRootTask() != null) {
|
throw new IllegalArgumentException("startActivityFromRecents: Task "
|
||||||
// Don't move home activity forward if we are launching into primary split or there
|
+ taskId + " can't be launch in the home/recents root task.");
|
||||||
// is a launch root set.
|
|
||||||
moveHomeTaskForward = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) {
|
|
||||||
throw new IllegalArgumentException("startActivityFromRecents: Task "
|
|
||||||
+ taskId + " can't be launch in the home/recents root task.");
|
|
||||||
}
|
|
||||||
|
|
||||||
mService.deferWindowLayout();
|
|
||||||
try {
|
|
||||||
task = mRootWindowContainer.anyTaskForId(taskId,
|
|
||||||
MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE, activityOptions, ON_TOP);
|
|
||||||
if (task == null) {
|
|
||||||
mWindowManager.executeAppTransition();
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"startActivityFromRecents: Task " + taskId + " not found.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moveHomeTaskForward) {
|
boolean shouldStartActivity = false;
|
||||||
// We always want to return to the home activity instead of the recents activity
|
mService.deferWindowLayout();
|
||||||
// from whatever is started from the recents activity, so move the home root task
|
try {
|
||||||
// forward.
|
task = mRootWindowContainer.anyTaskForId(taskId,
|
||||||
// TODO (b/115289124): Multi-display supports for recents.
|
MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE, activityOptions, ON_TOP);
|
||||||
mRootWindowContainer.getDefaultTaskDisplayArea().moveHomeRootTaskToFront(
|
if (task == null) {
|
||||||
"startActivityFromRecents");
|
mWindowManager.executeAppTransition();
|
||||||
}
|
throw new IllegalArgumentException(
|
||||||
|
"startActivityFromRecents: Task " + taskId + " not found.");
|
||||||
// If the user must confirm credentials (e.g. when first launching a work app and the
|
|
||||||
// Work Challenge is present) let startActivityInPackage handle the intercepting.
|
|
||||||
if (!mService.mAmInternal.shouldConfirmCredentials(task.mUserId)
|
|
||||||
&& task.getRootActivity() != null) {
|
|
||||||
final ActivityRecord targetActivity = task.getTopNonFinishingActivity();
|
|
||||||
|
|
||||||
mRootWindowContainer.startPowerModeLaunchIfNeeded(
|
|
||||||
true /* forceSend */, targetActivity);
|
|
||||||
final LaunchingState launchingState =
|
|
||||||
mActivityMetricsLogger.notifyActivityLaunching(task.intent);
|
|
||||||
try {
|
|
||||||
mService.moveTaskToFrontLocked(null /* appThread */, null /* callingPackage */,
|
|
||||||
task.mTaskId, 0, options);
|
|
||||||
// Apply options to prevent pendingOptions be taken when scheduling activity
|
|
||||||
// lifecycle transaction to make sure the override pending app transition will
|
|
||||||
// be applied immediately.
|
|
||||||
targetActivity.applyOptionsAnimation();
|
|
||||||
} finally {
|
|
||||||
mActivityMetricsLogger.notifyActivityLaunched(launchingState,
|
|
||||||
START_TASK_TO_FRONT, false /* newActivityCreated */, targetActivity,
|
|
||||||
activityOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mService.getActivityStartController().postStartActivityProcessingForLastStarter(
|
if (moveHomeTaskForward) {
|
||||||
task.getTopNonFinishingActivity(), ActivityManager.START_TASK_TO_FRONT,
|
// We always want to return to the home activity instead of the recents
|
||||||
task.getRootTask());
|
// activity from whatever is started from the recents activity, so move
|
||||||
|
// the home root task forward.
|
||||||
|
// TODO (b/115289124): Multi-display supports for recents.
|
||||||
|
mRootWindowContainer.getDefaultTaskDisplayArea().moveHomeRootTaskToFront(
|
||||||
|
"startActivityFromRecents");
|
||||||
|
}
|
||||||
|
|
||||||
// As it doesn't go to ActivityStarter.executeRequest() path, we need to resume
|
// If the user must confirm credentials (e.g. when first launching a work
|
||||||
// app switching here also.
|
// app and the Work Challenge is present) let startActivityInPackage handle
|
||||||
mService.resumeAppSwitches();
|
// the intercepting.
|
||||||
|
if (!mService.mAmInternal.shouldConfirmCredentials(task.mUserId)
|
||||||
|
&& task.getRootActivity() != null) {
|
||||||
|
final ActivityRecord targetActivity = task.getTopNonFinishingActivity();
|
||||||
|
|
||||||
return ActivityManager.START_TASK_TO_FRONT;
|
mRootWindowContainer.startPowerModeLaunchIfNeeded(
|
||||||
|
true /* forceSend */, targetActivity);
|
||||||
|
final LaunchingState launchingState =
|
||||||
|
mActivityMetricsLogger.notifyActivityLaunching(task.intent);
|
||||||
|
try {
|
||||||
|
mService.moveTaskToFrontLocked(null /* appThread */,
|
||||||
|
null /* callingPackage */, task.mTaskId, 0, options);
|
||||||
|
// Apply options to prevent pendingOptions be taken when scheduling
|
||||||
|
// activity lifecycle transaction to make sure the override pending app
|
||||||
|
// transition will be applied immediately.
|
||||||
|
targetActivity.applyOptionsAnimation();
|
||||||
|
} finally {
|
||||||
|
mActivityMetricsLogger.notifyActivityLaunched(launchingState,
|
||||||
|
START_TASK_TO_FRONT, false /* newActivityCreated */,
|
||||||
|
targetActivity, activityOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
mService.getActivityStartController().postStartActivityProcessingForLastStarter(
|
||||||
|
task.getTopNonFinishingActivity(), ActivityManager.START_TASK_TO_FRONT,
|
||||||
|
task.getRootTask());
|
||||||
|
|
||||||
|
// As it doesn't go to ActivityStarter.executeRequest() path, we need to resume
|
||||||
|
// app switching here also.
|
||||||
|
mService.resumeAppSwitches();
|
||||||
|
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 {
|
||||||
mService.continueWindowLayout();
|
synchronized (mService.mGlobalLock) {
|
||||||
|
mService.continueWindowLayout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user