Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c8ecacc0 authored by Evan Rosky's avatar Evan Rosky
Browse files

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
parent f362c2d7
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -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,