Merge "Prevent potential deadlock when sending pending intent in WCT" into tm-dev
This commit is contained in:
@@ -94,6 +94,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.IntSupplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server side implementation for the interface for organizing windows
|
* Server side implementation for the interface for organizing windows
|
||||||
@@ -810,26 +811,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
|||||||
launchOpts.remove(WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID);
|
launchOpts.remove(WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID);
|
||||||
final SafeActivityOptions safeOptions =
|
final SafeActivityOptions safeOptions =
|
||||||
SafeActivityOptions.fromBundle(launchOpts, caller.mPid, caller.mUid);
|
SafeActivityOptions.fromBundle(launchOpts, caller.mPid, caller.mUid);
|
||||||
final Integer[] starterResult = {null};
|
waitAsyncStart(() -> mService.mTaskSupervisor.startActivityFromRecents(
|
||||||
// startActivityFromRecents should not be called in lock.
|
caller.mPid, caller.mUid, 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: {
|
||||||
@@ -838,22 +821,22 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
|||||||
mService.mContext.getContentResolver())
|
mService.mContext.getContentResolver())
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
Bundle options = null;
|
ActivityOptions activityOptions = null;
|
||||||
if (hop.getPendingIntent().isActivity()) {
|
if (hop.getPendingIntent().isActivity()) {
|
||||||
// Set the context display id as preferred for this activity launches, so that
|
// Set the context display id as preferred for this activity launches, so that
|
||||||
// it can land on caller's display. Or just brought the task to front at the
|
// it can land on caller's display. Or just brought the task to front at the
|
||||||
// display where it was on since it has higher preference.
|
// display where it was on since it has higher preference.
|
||||||
ActivityOptions activityOptions = hop.getLaunchOptions() != null
|
activityOptions = hop.getLaunchOptions() != null
|
||||||
? new ActivityOptions(hop.getLaunchOptions())
|
? new ActivityOptions(hop.getLaunchOptions())
|
||||||
: ActivityOptions.makeBasic();
|
: ActivityOptions.makeBasic();
|
||||||
activityOptions.setCallerDisplayId(DEFAULT_DISPLAY);
|
activityOptions.setCallerDisplayId(DEFAULT_DISPLAY);
|
||||||
options = activityOptions.toBundle();
|
|
||||||
}
|
}
|
||||||
|
final Bundle options = activityOptions != null ? activityOptions.toBundle() : null;
|
||||||
mService.mAmInternal.sendIntentSender(hop.getPendingIntent().getTarget(),
|
waitAsyncStart(() -> mService.mAmInternal.sendIntentSender(
|
||||||
|
hop.getPendingIntent().getTarget(),
|
||||||
hop.getPendingIntent().getWhitelistToken(), 0 /* code */,
|
hop.getPendingIntent().getWhitelistToken(), 0 /* code */,
|
||||||
hop.getActivityIntent(), resolvedType, null /* finishReceiver */,
|
hop.getActivityIntent(), resolvedType, null /* finishReceiver */,
|
||||||
null /* requiredPermission */, options);
|
null /* requiredPermission */, options));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HIERARCHY_OP_TYPE_START_SHORTCUT: {
|
case HIERARCHY_OP_TYPE_START_SHORTCUT: {
|
||||||
@@ -914,6 +897,31 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
|||||||
return effects;
|
return effects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post and wait for the result of the activity start to prevent potential deadlock against
|
||||||
|
* {@link WindowManagerGlobalLock}.
|
||||||
|
*/
|
||||||
|
private void waitAsyncStart(IntSupplier startActivity) {
|
||||||
|
final Integer[] starterResult = {null};
|
||||||
|
mService.mH.post(() -> {
|
||||||
|
try {
|
||||||
|
starterResult[0] = startActivity.getAsInt();
|
||||||
|
} 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) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int sanitizeAndApplyHierarchyOp(WindowContainer container,
|
private int sanitizeAndApplyHierarchyOp(WindowContainer container,
|
||||||
WindowContainerTransaction.HierarchyOp hop) {
|
WindowContainerTransaction.HierarchyOp hop) {
|
||||||
final Task task = container.asTask();
|
final Task task = container.asTask();
|
||||||
|
|||||||
Reference in New Issue
Block a user