From c8ecacc046492399b13719578c8f39b1b67e08b7 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Wed, 1 Mar 2023 18:35:04 -0800 Subject: [PATCH] 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 --- .../server/wm/WindowOrganizerController.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 8e22821820a1f..b9cb59a17a2ef 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -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,