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

Commit 6f0b217d authored by Jerry Chang's avatar Jerry Chang Committed by Automerger Merge Worker
Browse files

Merge "Prevent potential deadlock when sending pending intent in WCT" into tm-dev am: ec8b28e5

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17214344

Change-Id: I873af9e14b8b0f41d6c79e1fe05b1f48375d5584
parents a7feff3b ec8b28e5
Loading
Loading
Loading
Loading
+34 −26
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.IntSupplier;

/**
 * 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);
                final SafeActivityOptions safeOptions =
                        SafeActivityOptions.fromBundle(launchOpts, caller.mPid, caller.mUid);
                final Integer[] starterResult = {null};
                // startActivityFromRecents should not be called in lock.
                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) {
                    }
                }
                waitAsyncStart(() -> mService.mTaskSupervisor.startActivityFromRecents(
                        caller.mPid, caller.mUid, taskId, safeOptions));
                break;
            }
            case HIERARCHY_OP_TYPE_PENDING_INTENT: {
@@ -838,22 +821,22 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                        mService.mContext.getContentResolver())
                        : null;

                Bundle options = null;
                ActivityOptions activityOptions = null;
                if (hop.getPendingIntent().isActivity()) {
                    // 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
                    // display where it was on since it has higher preference.
                    ActivityOptions activityOptions = hop.getLaunchOptions() != null
                    activityOptions = hop.getLaunchOptions() != null
                            ? new ActivityOptions(hop.getLaunchOptions())
                            : ActivityOptions.makeBasic();
                    activityOptions.setCallerDisplayId(DEFAULT_DISPLAY);
                    options = activityOptions.toBundle();
                }

                mService.mAmInternal.sendIntentSender(hop.getPendingIntent().getTarget(),
                final Bundle options = activityOptions != null ? activityOptions.toBundle() : null;
                waitAsyncStart(() -> mService.mAmInternal.sendIntentSender(
                        hop.getPendingIntent().getTarget(),
                        hop.getPendingIntent().getWhitelistToken(), 0 /* code */,
                        hop.getActivityIntent(), resolvedType, null /* finishReceiver */,
                        null /* requiredPermission */, options);
                        null /* requiredPermission */, options));
                break;
            }
            case HIERARCHY_OP_TYPE_START_SHORTCUT: {
@@ -914,6 +897,31 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
        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,
            WindowContainerTransaction.HierarchyOp hop) {
        final Task task = container.asTask();