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

Commit 9c904ba8 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Revert^2 "Verify hierarchy change for cross-UID ActivityEmbedding""...

Merge "Revert^2 "Verify hierarchy change for cross-UID ActivityEmbedding"" into tm-dev am: 9a068ad6

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

Change-Id: Ief642fd027a5d4cb17fa581b5597a6bd064b1741
parents fabe13ed 9a068ad6
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -524,7 +524,16 @@ class TaskFragment extends WindowContainer<WindowContainer> {
                || isAllowedToEmbedActivityInTrustedMode(a);
    }

    /**
     * Checks if the organized task fragment is allowed to embed activity in untrusted mode.
     */
    boolean isAllowedToEmbedActivityInUntrustedMode(@NonNull ActivityRecord a) {
        final WindowContainer parent = getParent();
        if (parent == null || !parent.getBounds().contains(getBounds())) {
            // Without full trust between the host and the embedded activity, we don't allow
            // TaskFragment to have bounds outside of the parent bounds.
            return false;
        }
        return (a.info.flags & FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING)
                == FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBEDDING;
    }
+82 −44
Original line number Diff line number Diff line
@@ -19,8 +19,6 @@ package com.android.server.wm;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.isStartResultSuccessful;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.WindowContainerTransaction.Change.CHANGE_BOUNDS_TRANSACTION;
import static android.window.WindowContainerTransaction.Change.CHANGE_BOUNDS_TRANSACTION_RECT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_ADD_RECT_INSETS_PROVIDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT;
@@ -681,7 +679,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                        break;
                    }
                }
                effects |= deleteTaskFragment(taskFragment, errorCallbackToken);
                effects |= deleteTaskFragment(taskFragment, organizer, errorCallbackToken);
                break;
            }
            case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT: {
@@ -699,8 +697,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                        .startActivityInTaskFragment(tf, activityIntent, activityOptions,
                                hop.getCallingActivity(), caller.mUid, caller.mPid);
                if (!isStartResultSuccessful(result)) {
                    sendTaskFragmentOperationFailure(tf.getTaskFragmentOrganizer(),
                            errorCallbackToken,
                    sendTaskFragmentOperationFailure(organizer, errorCallbackToken,
                            convertStartFailureToThrowable(result, activityIntent));
                } else {
                    effects |= TRANSACT_EFFECTS_LIFECYCLE;
@@ -710,13 +707,20 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
            case HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT: {
                final IBinder fragmentToken = hop.getNewParent();
                final ActivityRecord activity = ActivityRecord.forTokenLocked(hop.getContainer());
                if (!mLaunchTaskFragments.containsKey(fragmentToken) || activity == null) {
                final TaskFragment parent = mLaunchTaskFragments.get(fragmentToken);
                if (parent == null || activity == null) {
                    final Throwable exception = new IllegalArgumentException(
                            "Not allowed to operate with invalid fragment token or activity.");
                    sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception);
                    break;
                }
                activity.reparent(mLaunchTaskFragments.get(fragmentToken), POSITION_TOP);
                if (!parent.isAllowedToEmbedActivity(activity)) {
                    final Throwable exception = new SecurityException(
                            "The task fragment is not trusted to embed the given activity.");
                    sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception);
                    break;
                }
                activity.reparent(parent, POSITION_TOP);
                effects |= TRANSACT_EFFECTS_LIFECYCLE;
                break;
            }
@@ -860,12 +864,14 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                final WindowContainer newParent = hop.getNewParent() != null
                        ? WindowContainer.fromBinder(hop.getNewParent())
                        : null;
                if (oldParent == null || !oldParent.isAttached()) {
                if (oldParent == null || oldParent.asTaskFragment() == null
                        || !oldParent.isAttached()) {
                    Slog.e(TAG, "Attempt to operate on unknown or detached container: "
                            + oldParent);
                    break;
                }
                reparentTaskFragment(oldParent, newParent, errorCallbackToken);
                reparentTaskFragment(oldParent.asTaskFragment(), newParent, organizer,
                        errorCallbackToken);
                effects |= TRANSACT_EFFECTS_LIFECYCLE;
                break;
            }
@@ -1246,7 +1252,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
        mService.enforceTaskPermission(func);
    }

    private void enforceTaskPermission(String func, WindowContainerTransaction t) {
    private void enforceTaskPermission(String func, @Nullable WindowContainerTransaction t) {
        if (t == null || t.getTaskFragmentOrganizer() == null) {
            enforceTaskPermission(func);
            return;
@@ -1271,14 +1277,11 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
        while (entries.hasNext()) {
            final Map.Entry<IBinder, WindowContainerTransaction.Change> entry = entries.next();
            // Only allow to apply changes to TaskFragment that is created by this organizer.
            WindowContainer wc = WindowContainer.fromBinder(entry.getKey());
            final WindowContainer wc = WindowContainer.fromBinder(entry.getKey());
            enforceTaskFragmentOrganized(func, wc, organizer);
            enforceTaskFragmentConfigChangeAllowed(func, wc, entry.getValue(), organizer);
        }

        // TODO(b/197364677): Enforce safety of hierarchy operations in untrusted mode. E.g. one
        // could first change a trusted TF, and then start/reparent untrusted activity there.

        // Hierarchy changes
        final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
        for (int i = hops.size() - 1; i >= 0; i--) {
@@ -1352,8 +1355,6 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
     * Makes sure that SurfaceControl transactions and the ability to set bounds outside of the
     * parent bounds are not allowed for embedding without full trust between the host and the
     * target.
     * TODO(b/197364677): Allow SC transactions when the client-driven animations are protected from
     * tapjacking.
     */
    private void enforceTaskFragmentConfigChangeAllowed(String func, @Nullable WindowContainer wc,
            WindowContainerTransaction.Change change, ITaskFragmentOrganizer organizer) {
@@ -1361,35 +1362,48 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
            Slog.e(TAG, "Attempt to operate on task fragment that no longer exists");
            return;
        }
        // Check if TaskFragment is embedded in fully trusted mode
        if (wc.asTaskFragment().isAllowedToBeEmbeddedInTrustedMode()) {
            // Fully trusted, no need to check further
            return;
        }

        if (change == null) {
            return;
        }
        final int changeMask = change.getChangeMask();
        if ((changeMask & (CHANGE_BOUNDS_TRANSACTION | CHANGE_BOUNDS_TRANSACTION_RECT)) != 0) {
        if (changeMask != 0) {
            // None of the change should be requested from a TaskFragment organizer.
            String msg = "Permission Denial: " + func + " from pid="
                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
                    + " trying to apply SurfaceControl changes to TaskFragment in non-trusted "
                    + "embedding mode, TaskFragmentOrganizer=" + organizer;
                    + " trying to apply changes of " + changeMask + " to TaskFragment"
                    + " TaskFragmentOrganizer=" + organizer;
            Slog.w(TAG, msg);
            throw new SecurityException(msg);
        }
        if (change.getWindowSetMask() == 0) {
            // Nothing else to check.
        // Check if TaskFragment is embedded in fully trusted mode.
        if (wc.asTaskFragment().isAllowedToBeEmbeddedInTrustedMode()) {
            // Fully trusted, no need to check further
            return;
        }
        WindowConfiguration requestedWindowConfig = change.getConfiguration().windowConfiguration;
        WindowContainer wcParent = wc.getParent();
        final WindowContainer wcParent = wc.getParent();
        if (wcParent == null) {
            Slog.e(TAG, "Attempt to set bounds on task fragment that has no parent");
            Slog.e(TAG, "Attempt to apply config change on task fragment that has no parent");
            return;
        }
        if (!wcParent.getBounds().contains(requestedWindowConfig.getBounds())) {
        final Configuration requestedConfig = change.getConfiguration();
        final Configuration parentConfig = wcParent.getConfiguration();
        if (parentConfig.screenWidthDp < requestedConfig.screenWidthDp
                || parentConfig.screenHeightDp < requestedConfig.screenHeightDp
                || parentConfig.smallestScreenWidthDp < requestedConfig.smallestScreenWidthDp) {
            String msg = "Permission Denial: " + func + " from pid="
                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
                    + " trying to apply screen width/height greater than parent's for non-trusted"
                    + " host, TaskFragmentOrganizer=" + organizer;
            Slog.w(TAG, msg);
            throw new SecurityException(msg);
        }
        if (change.getWindowSetMask() == 0) {
            // No bounds change.
            return;
        }
        final WindowConfiguration requestedWindowConfig = requestedConfig.windowConfiguration;
        final WindowConfiguration parentWindowConfig = parentConfig.windowConfiguration;
        if (!parentWindowConfig.getBounds().contains(requestedWindowConfig.getBounds())) {
            String msg = "Permission Denial: " + func + " from pid="
                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
                    + " trying to apply bounds outside of parent for non-trusted host,"
@@ -1397,6 +1411,17 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
            Slog.w(TAG, msg);
            throw new SecurityException(msg);
        }
        if (requestedWindowConfig.getAppBounds() != null
                && parentWindowConfig.getAppBounds() != null
                && !parentWindowConfig.getAppBounds().contains(
                        requestedWindowConfig.getAppBounds())) {
            String msg = "Permission Denial: " + func + " from pid="
                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
                    + " trying to apply app bounds outside of parent for non-trusted host,"
                    + " TaskFragmentOrganizer=" + organizer;
            Slog.w(TAG, msg);
            throw new SecurityException(msg);
        }
    }

    void createTaskFragment(@NonNull TaskFragmentCreationParams creationParams,
@@ -1422,7 +1447,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
        if (ownerActivity.getTask().effectiveUid != ownerActivity.getUid()
                || ownerActivity.getTask().effectiveUid != caller.mUid) {
            final Throwable exception =
                    new IllegalArgumentException("Not allowed to operate with the ownerToken while "
                    new SecurityException("Not allowed to operate with the ownerToken while "
                            + "the root activity of the target task belong to the different app");
            sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception);
            return;
@@ -1439,33 +1464,46 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
        mLaunchTaskFragments.put(creationParams.getFragmentToken(), taskFragment);
    }

    void reparentTaskFragment(@NonNull WindowContainer oldParent,
            @Nullable WindowContainer newParent,  @Nullable IBinder errorCallbackToken) {
        WindowContainer parent = newParent;
        if (parent == null && oldParent.asTaskFragment() != null) {
            parent = oldParent.asTaskFragment().getTask();
    void reparentTaskFragment(@NonNull TaskFragment oldParent, @Nullable WindowContainer newParent,
            @Nullable ITaskFragmentOrganizer organizer, @Nullable IBinder errorCallbackToken) {
        final TaskFragment newParentTF;
        if (newParent == null) {
            // Use the old parent's parent if the caller doesn't specify the new parent.
            newParentTF = oldParent.getTask();
        } else {
            newParentTF = newParent.asTaskFragment();
        }
        if (parent == null) {
        if (newParentTF == null) {
            final Throwable exception =
                    new IllegalArgumentException("Not allowed to operate with invalid container");
            sendTaskFragmentOperationFailure(oldParent.asTaskFragment().getTaskFragmentOrganizer(),
                    errorCallbackToken, exception);
            sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception);
            return;
        }
        if (newParentTF.getTaskFragmentOrganizer() != null) {
            // We are reparenting activities to a new embedded TaskFragment, this operation is only
            // allowed if the new parent is trusted by all reparent activities.
            final boolean isEmbeddingDisallowed = oldParent.forAllActivities(activity ->
                    !newParentTF.isAllowedToEmbedActivity(activity));
            if (isEmbeddingDisallowed) {
                final Throwable exception = new SecurityException(
                        "The new parent is not trusted to embed the activities.");
                sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception);
                return;
            }
        }
        while (oldParent.hasChild()) {
            oldParent.getChildAt(0).reparent(parent, POSITION_TOP);
            oldParent.getChildAt(0).reparent(newParentTF, POSITION_TOP);
        }
    }

    private int deleteTaskFragment(@NonNull TaskFragment taskFragment,
            @Nullable IBinder errorCallbackToken) {
            @Nullable ITaskFragmentOrganizer organizer, @Nullable IBinder errorCallbackToken) {
        final int index = mLaunchTaskFragments.indexOfValue(taskFragment);
        if (index < 0) {
            final Throwable exception =
                    new IllegalArgumentException("Not allowed to operate with invalid "
                            + "taskFragment");
            sendTaskFragmentOperationFailure(taskFragment.getTaskFragmentOrganizer(),
                    errorCallbackToken, exception);
            sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception);
            return 0;
        }
        mLaunchTaskFragments.removeAt(index);
+93 −41
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.wm;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.testing.Assert.assertThrows;

import static org.junit.Assert.assertEquals;
@@ -249,19 +250,13 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        // the organizer.
        mTransaction.setBounds(mFragmentWindowToken, new Rect(0, 0, 100, 100));

        assertThrows(SecurityException.class, () -> {
            try {
                mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
            } catch (RemoteException e) {
                fail();
            }
        });
        assertApplyTransactionDisallowed(mTransaction);

        // Allow transaction to change a TaskFragment created by the organizer.
        mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
                "Test:TaskFragmentOrganizer" /* processName */);

        mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
        assertApplyTransactionAllowed(mTransaction);
    }

    @Test
@@ -272,19 +267,13 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        // the organizer.
        mTransaction.reorder(mFragmentWindowToken, true /* onTop */);

        assertThrows(SecurityException.class, () -> {
            try {
                mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
            } catch (RemoteException e) {
                fail();
            }
        });
        assertApplyTransactionDisallowed(mTransaction);

        // Allow transaction to change a TaskFragment created by the organizer.
        mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
                "Test:TaskFragmentOrganizer" /* processName */);

        mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
        assertApplyTransactionAllowed(mTransaction);
    }

    @Test
@@ -298,27 +287,21 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        // the organizer.
        mTransaction.deleteTaskFragment(mFragmentWindowToken);

        assertThrows(SecurityException.class, () -> {
            try {
                mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
            } catch (RemoteException e) {
                fail();
            }
        });
        assertApplyTransactionDisallowed(mTransaction);

        // Allow transaction to change a TaskFragment created by the organizer.
        mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
                "Test:TaskFragmentOrganizer" /* processName */);
        clearInvocations(mAtm.mRootWindowContainer);

        mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
        assertApplyTransactionAllowed(mTransaction);

        // No lifecycle update when the TaskFragment is not recorded.
        verify(mAtm.mRootWindowContainer, never()).resumeFocusedTasksTopActivities();

        mAtm.mWindowOrganizerController.mLaunchTaskFragments
                .put(mFragmentToken, mTaskFragment);
        mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
        assertApplyTransactionAllowed(mTransaction);

        verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities();
    }
@@ -335,13 +318,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        // the organizer.
        mTransaction.setAdjacentRoots(mFragmentWindowToken, token2, false /* moveTogether */);

        assertThrows(SecurityException.class, () -> {
            try {
                mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
            } catch (RemoteException e) {
                fail();
            }
        });
        assertApplyTransactionDisallowed(mTransaction);

        // Allow transaction to change a TaskFragment created by the organizer.
        mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
@@ -350,7 +327,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
                "Test:TaskFragmentOrganizer" /* processName */);
        clearInvocations(mAtm.mRootWindowContainer);

        mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
        assertApplyTransactionAllowed(mTransaction);

        verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities();
    }
@@ -423,20 +400,14 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        // the organizer.
        mTransaction.reparentChildren(mFragmentWindowToken, null /* newParent */);

        assertThrows(SecurityException.class, () -> {
            try {
                mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
            } catch (RemoteException e) {
                fail();
            }
        });
        assertApplyTransactionDisallowed(mTransaction);

        // Allow transaction to change a TaskFragment created by the organizer.
        mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
                "Test:TaskFragmentOrganizer" /* processName */);
        clearInvocations(mAtm.mRootWindowContainer);

        mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
        assertApplyTransactionAllowed(mTransaction);

        verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities();
    }
@@ -454,6 +425,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        mAtm.mWindowOrganizerController.mLaunchTaskFragments
                .put(mFragmentToken, mTaskFragment);
        mTransaction.reparentActivityToTaskFragment(mFragmentToken, activity.token);
        doReturn(true).when(mTaskFragment).isAllowedToEmbedActivity(activity);
        clearInvocations(mAtm.mRootWindowContainer);

        mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
@@ -574,6 +546,66 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
    }

    /**
     * For config change to untrusted embedded TaskFragment, we only allow bounds change within
     * its parent bounds.
     */
    @Test
    public void testUntrustedEmbedding_configChange() throws RemoteException  {
        mController.registerOrganizer(mIOrganizer);
        mOrganizer.applyTransaction(mTransaction);
        mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
                "Test:TaskFragmentOrganizer" /* processName */);
        doReturn(false).when(mTaskFragment).isAllowedToBeEmbeddedInTrustedMode();
        final Task task = createTask(mDisplayContent);
        final Rect taskBounds = new Rect(task.getBounds());
        final Rect taskAppBounds = new Rect(task.getWindowConfiguration().getAppBounds());
        final int taskScreenWidthDp = task.getConfiguration().screenWidthDp;
        final int taskScreenHeightDp = task.getConfiguration().screenHeightDp;
        final int taskSmallestScreenWidthDp = task.getConfiguration().smallestScreenWidthDp;
        task.addChild(mTaskFragment, POSITION_TOP);

        // Throw exception if the transaction is trying to change bounds of an untrusted outside of
        // its parent's.

        // setBounds
        final Rect tfBounds = new Rect(taskBounds);
        tfBounds.right++;
        mTransaction.setBounds(mFragmentWindowToken, tfBounds);
        assertApplyTransactionDisallowed(mTransaction);

        mTransaction.setBounds(mFragmentWindowToken, taskBounds);
        assertApplyTransactionAllowed(mTransaction);

        // setAppBounds
        final Rect tfAppBounds = new Rect(taskAppBounds);
        tfAppBounds.right++;
        mTransaction.setAppBounds(mFragmentWindowToken, tfAppBounds);
        assertApplyTransactionDisallowed(mTransaction);

        mTransaction.setAppBounds(mFragmentWindowToken, taskAppBounds);
        assertApplyTransactionAllowed(mTransaction);

        // setScreenSizeDp
        mTransaction.setScreenSizeDp(mFragmentWindowToken, taskScreenWidthDp + 1,
                taskScreenHeightDp + 1);
        assertApplyTransactionDisallowed(mTransaction);

        mTransaction.setScreenSizeDp(mFragmentWindowToken, taskScreenWidthDp, taskScreenHeightDp);
        assertApplyTransactionAllowed(mTransaction);

        // setSmallestScreenWidthDp
        mTransaction.setSmallestScreenWidthDp(mFragmentWindowToken, taskSmallestScreenWidthDp + 1);
        assertApplyTransactionDisallowed(mTransaction);

        mTransaction.setSmallestScreenWidthDp(mFragmentWindowToken, taskSmallestScreenWidthDp);
        assertApplyTransactionAllowed(mTransaction);

        // Any of the change mask is not allowed.
        mTransaction.setFocusable(mFragmentWindowToken, false);
        assertApplyTransactionDisallowed(mTransaction);
    }

    /**
     * Creates a {@link TaskFragment} with the {@link WindowContainerTransaction}. Calls
     * {@link WindowOrganizerController#applyTransaction} to apply the transaction,
@@ -590,4 +622,24 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
        // Allow organizer to create TaskFragment and start/reparent activity to TaskFragment.
        wct.createTaskFragment(params);
    }

    /** Asserts that applying the given transaction will throw a {@link SecurityException}. */
    private void assertApplyTransactionDisallowed(WindowContainerTransaction t) {
        assertThrows(SecurityException.class, () -> {
            try {
                mAtm.getWindowOrganizerController().applyTransaction(t);
            } catch (RemoteException e) {
                fail();
            }
        });
    }

    /** Asserts that applying the given transaction will not throw any exception. */
    private void assertApplyTransactionAllowed(WindowContainerTransaction t) {
        try {
            mAtm.getWindowOrganizerController().applyTransaction(t);
        } catch (RemoteException e) {
            fail();
        }
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -1264,6 +1264,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
                        mOrganizer.getOrganizerToken(), DEFAULT_TASK_FRAGMENT_ORGANIZER_UID,
                        DEFAULT_TASK_FRAGMENT_ORGANIZER_PROCESS_NAME);
            }
            spyOn(taskFragment);
            return taskFragment;
        }
    }