Fix potential deadlock in transactions
It was possible to hit a deadlock scenario when using the waitAsyncStart utility. Since that was using the main handler for unlocked work, if the transaction was applied from the main handler thread, it would deadlock (this happens when transactions are queued-up on syncengine). This adds a check and will run the uncommon queued launches on anim-thread (which is 1 higher priority). This also has the waitAsyncStart function actually return the result so that we can properly observe the effects of a PendingIntent Bug: 271317661 Bug: 267738124 Test: System still runs and tests pass. Change-Id: If99668b71cafe016b1ab2aad501c53d246e2877d
This commit is contained in:
@@ -74,7 +74,9 @@ import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Parcel;
|
||||
import android.os.RemoteException;
|
||||
import android.util.AndroidRuntimeException;
|
||||
@@ -998,11 +1000,14 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
||||
activityOptions.setCallerDisplayId(DEFAULT_DISPLAY);
|
||||
}
|
||||
final Bundle options = activityOptions != null ? activityOptions.toBundle() : null;
|
||||
waitAsyncStart(() -> mService.mAmInternal.sendIntentSender(
|
||||
int res = waitAsyncStart(() -> mService.mAmInternal.sendIntentSender(
|
||||
hop.getPendingIntent().getTarget(),
|
||||
hop.getPendingIntent().getWhitelistToken(), 0 /* code */,
|
||||
hop.getActivityIntent(), resolvedType, null /* finishReceiver */,
|
||||
null /* requiredPermission */, options));
|
||||
if (ActivityManager.isStartResultSuccessful(res)) {
|
||||
effects |= TRANSACT_EFFECTS_LIFECYCLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HIERARCHY_OP_TYPE_START_SHORTCUT: {
|
||||
@@ -1353,9 +1358,16 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
||||
* Post and wait for the result of the activity start to prevent potential deadlock against
|
||||
* {@link WindowManagerGlobalLock}.
|
||||
*/
|
||||
private void waitAsyncStart(IntSupplier startActivity) {
|
||||
private int waitAsyncStart(IntSupplier startActivity) {
|
||||
final Integer[] starterResult = {null};
|
||||
mService.mH.post(() -> {
|
||||
final Handler handler = (Looper.myLooper() == mService.mH.getLooper())
|
||||
// uncommon case where a queued transaction is trying to start an activity. We can't
|
||||
// post to our own thread and wait (otherwise we deadlock), so use anim thread
|
||||
// instead (which is 1 higher priority).
|
||||
? mService.mWindowManager.mAnimationHandler
|
||||
// Otherwise just put it on main handler
|
||||
: mService.mH;
|
||||
handler.post(() -> {
|
||||
try {
|
||||
starterResult[0] = startActivity.getAsInt();
|
||||
} catch (Throwable t) {
|
||||
@@ -1372,6 +1384,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
return starterResult[0];
|
||||
}
|
||||
|
||||
private int sanitizeAndApplyHierarchyOp(WindowContainer container,
|
||||
|
||||
Reference in New Issue
Block a user