Loading core/java/android/window/ITaskFragmentOrganizerController.aidl +5 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.window; import android.os.IBinder; import android.view.RemoteAnimationDefinition; import android.window.ITaskFragmentOrganizer; import android.window.RemoteTransition; import android.window.WindowContainerTransaction; /** @hide */ Loading Loading @@ -65,7 +66,10 @@ interface ITaskFragmentOrganizerController { /** * Requests the server to apply the given {@link WindowContainerTransaction}. * * {@link RemoteTransition} can only be used by a system organizer and * {@code shouldApplyIndependently} must be {@code true}. See {@link registerOrganizer}. */ void applyTransaction(in WindowContainerTransaction wct, int transitionType, boolean shouldApplyIndependently); boolean shouldApplyIndependently, in RemoteTransition remoteTransition); } core/java/android/window/TaskFragmentOrganizer.java +25 −1 Original line number Diff line number Diff line Loading @@ -275,7 +275,31 @@ public class TaskFragmentOrganizer extends WindowOrganizer { } wct.setTaskFragmentOrganizer(mInterface); try { getController().applyTransaction(wct, transitionType, shouldApplyIndependently); getController().applyTransaction( wct, transitionType, shouldApplyIndependently, null /* remoteTransition */); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Applies a transaction with a {@link RemoteTransition}. Only a system organizer is allowed to * use {@link RemoteTransition}. See {@link TaskFragmentOrganizer#registerOrganizer(boolean)}. * * @hide */ @FlaggedApi(Flags.FLAG_TASK_FRAGMENT_SYSTEM_ORGANIZER_FLAG) public void applySystemTransaction(@NonNull WindowContainerTransaction wct, @TaskFragmentTransitionType int transitionType, @Nullable RemoteTransition remoteTransition) { if (wct.isEmpty()) { return; } wct.setTaskFragmentOrganizer(mInterface); try { getController().applyTransaction( wct, transitionType, remoteTransition != null /* shouldApplyIndependently */, remoteTransition); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +7 −3 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.view.RemoteAnimationDefinition; import android.view.WindowManager; import android.window.ITaskFragmentOrganizer; import android.window.ITaskFragmentOrganizerController; import android.window.RemoteTransition; import android.window.TaskFragmentInfo; import android.window.TaskFragmentOperation; import android.window.TaskFragmentParentInfo; Loading Loading @@ -566,7 +567,8 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr // Keep the calling identity to avoid unsecure change. synchronized (mGlobalLock) { if (isValidTransaction(wct)) { applyTransaction(wct, transitionType, shouldApplyIndependently); applyTransaction( wct, transitionType, shouldApplyIndependently, null /* remoteTransition */); } // Even if the transaction is empty, we still need to invoke #onTransactionFinished // unless the organizer has been unregistered. Loading @@ -587,14 +589,15 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr @Override public void applyTransaction(@NonNull WindowContainerTransaction wct, @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) { @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently, @Nullable RemoteTransition remoteTransition) { // Keep the calling identity to avoid unsecure change. synchronized (mGlobalLock) { if (!isValidTransaction(wct)) { return; } mWindowOrganizerController.applyTaskFragmentTransactionLocked(wct, transitionType, shouldApplyIndependently); shouldApplyIndependently, remoteTransition); } } Loading Loading @@ -839,6 +842,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr Slog.e(TAG, "Caller organizer=" + organizer + " is no longer registered"); return false; } return true; } Loading services/core/java/com/android/server/wm/WindowOrganizerController.java +11 −2 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ import android.window.ITransitionMetricsReporter; import android.window.ITransitionPlayer; import android.window.IWindowContainerTransactionCallback; import android.window.IWindowOrganizerController; import android.window.RemoteTransition; import android.window.TaskFragmentAnimationParams; import android.window.TaskFragmentCreationParams; import android.window.TaskFragmentOperation; Loading Loading @@ -464,12 +465,20 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub * transition, which will be queued until the sync engine is * free if there is any other active sync. If {@code false}, * the {@code wct} will be directly applied to the active sync. * @param remoteTransition {@link RemoteTransition} to apply for the transaction. Only available * for system organizers. */ void applyTaskFragmentTransactionLocked(@NonNull WindowContainerTransaction wct, @WindowManager.TransitionType int type, boolean shouldApplyIndependently) { @WindowManager.TransitionType int type, boolean shouldApplyIndependently, @Nullable RemoteTransition remoteTransition) { enforceTaskFragmentOrganizerPermission("applyTaskFragmentTransaction()", Objects.requireNonNull(wct.getTaskFragmentOrganizer()), Objects.requireNonNull(wct)); if (remoteTransition != null && !mTaskFragmentOrganizerController.isSystemOrganizer( wct.getTaskFragmentOrganizer().asBinder())) { throw new SecurityException( "Only a system organizer is allowed to use remote transition!"); } final CallerInfo caller = new CallerInfo(); final long ident = Binder.clearCallingIdentity(); try { Loading Loading @@ -512,7 +521,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub return; } mTransitionController.requestStartTransition(transition, null /* startTask */, null /* remoteTransition */, null /* displayChange */); remoteTransition, null /* displayChange */); transition.setAllReady(); }; mTransitionController.startCollectOrQueue(transition, doApply); Loading services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +33 −2 Original line number Diff line number Diff line Loading @@ -86,7 +86,9 @@ import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import android.view.RemoteAnimationDefinition; import android.view.SurfaceControl; import android.window.IRemoteTransition; import android.window.ITaskFragmentOrganizer; import android.window.RemoteTransition; import android.window.TaskFragmentAnimationParams; import android.window.TaskFragmentCreationParams; import android.window.TaskFragmentInfo; Loading Loading @@ -545,6 +547,35 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { assertNull(mController.getRemoteAnimationDefinition(mIOrganizer)); } @Test public void testApplyTransaction_disallowRemoteTransitionForNonSystemOrganizer() { mTransaction.setRelativeBounds(mFragmentWindowToken, new Rect(0, 0, 100, 100)); mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */, "Test:TaskFragmentOrganizer" /* processName */); // Throw exception if the transaction has remote transition and is not requested by system // organizer assertThrows(SecurityException.class, () -> mController.applyTransaction(mTransaction, TASK_FRAGMENT_TRANSIT_CHANGE, true /* shouldApplyIndependently */, new RemoteTransition(mock(IRemoteTransition.class)))); } @Test public void testApplyTransaction_allowRemoteTransitionForSystemOrganizer() { mController.unregisterOrganizer(mIOrganizer); mController.registerOrganizerInternal(mIOrganizer, true /* isSystemOrganizer */); mTransaction.setRelativeBounds(mFragmentWindowToken, new Rect(0, 0, 100, 100)); mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */, "Test:TaskFragmentOrganizer" /* processName */); // Remote transition is allowed for system organizer mController.applyTransaction(mTransaction, TASK_FRAGMENT_TRANSIT_CHANGE, true /* shouldApplyIndependently */, new RemoteTransition(mock(IRemoteTransition.class))); } @Test public void testApplyTransaction_enforceConfigurationChangeOnOrganizedTaskFragment() { // Throw exception if the transaction is trying to change a window that is not organized by Loading Loading @@ -1801,13 +1832,13 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { private void assertApplyTransactionDisallowed(WindowContainerTransaction t) { assertThrows(SecurityException.class, () -> mController.applyTransaction(t, TASK_FRAGMENT_TRANSIT_CHANGE, false /* shouldApplyIndependently */)); false /* shouldApplyIndependently */, null /* remoteTransition */)); } /** Asserts that applying the given transaction will not throw any exception. */ private void assertApplyTransactionAllowed(WindowContainerTransaction t) { mController.applyTransaction(t, TASK_FRAGMENT_TRANSIT_CHANGE, false /* shouldApplyIndependently */); false /* shouldApplyIndependently */, null /* remoteTransition */); } /** Asserts that there will be a transaction for TaskFragment appeared. */ Loading Loading
core/java/android/window/ITaskFragmentOrganizerController.aidl +5 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.window; import android.os.IBinder; import android.view.RemoteAnimationDefinition; import android.window.ITaskFragmentOrganizer; import android.window.RemoteTransition; import android.window.WindowContainerTransaction; /** @hide */ Loading Loading @@ -65,7 +66,10 @@ interface ITaskFragmentOrganizerController { /** * Requests the server to apply the given {@link WindowContainerTransaction}. * * {@link RemoteTransition} can only be used by a system organizer and * {@code shouldApplyIndependently} must be {@code true}. See {@link registerOrganizer}. */ void applyTransaction(in WindowContainerTransaction wct, int transitionType, boolean shouldApplyIndependently); boolean shouldApplyIndependently, in RemoteTransition remoteTransition); }
core/java/android/window/TaskFragmentOrganizer.java +25 −1 Original line number Diff line number Diff line Loading @@ -275,7 +275,31 @@ public class TaskFragmentOrganizer extends WindowOrganizer { } wct.setTaskFragmentOrganizer(mInterface); try { getController().applyTransaction(wct, transitionType, shouldApplyIndependently); getController().applyTransaction( wct, transitionType, shouldApplyIndependently, null /* remoteTransition */); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Applies a transaction with a {@link RemoteTransition}. Only a system organizer is allowed to * use {@link RemoteTransition}. See {@link TaskFragmentOrganizer#registerOrganizer(boolean)}. * * @hide */ @FlaggedApi(Flags.FLAG_TASK_FRAGMENT_SYSTEM_ORGANIZER_FLAG) public void applySystemTransaction(@NonNull WindowContainerTransaction wct, @TaskFragmentTransitionType int transitionType, @Nullable RemoteTransition remoteTransition) { if (wct.isEmpty()) { return; } wct.setTaskFragmentOrganizer(mInterface); try { getController().applyTransaction( wct, transitionType, remoteTransition != null /* shouldApplyIndependently */, remoteTransition); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading
services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +7 −3 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.view.RemoteAnimationDefinition; import android.view.WindowManager; import android.window.ITaskFragmentOrganizer; import android.window.ITaskFragmentOrganizerController; import android.window.RemoteTransition; import android.window.TaskFragmentInfo; import android.window.TaskFragmentOperation; import android.window.TaskFragmentParentInfo; Loading Loading @@ -566,7 +567,8 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr // Keep the calling identity to avoid unsecure change. synchronized (mGlobalLock) { if (isValidTransaction(wct)) { applyTransaction(wct, transitionType, shouldApplyIndependently); applyTransaction( wct, transitionType, shouldApplyIndependently, null /* remoteTransition */); } // Even if the transaction is empty, we still need to invoke #onTransactionFinished // unless the organizer has been unregistered. Loading @@ -587,14 +589,15 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr @Override public void applyTransaction(@NonNull WindowContainerTransaction wct, @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) { @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently, @Nullable RemoteTransition remoteTransition) { // Keep the calling identity to avoid unsecure change. synchronized (mGlobalLock) { if (!isValidTransaction(wct)) { return; } mWindowOrganizerController.applyTaskFragmentTransactionLocked(wct, transitionType, shouldApplyIndependently); shouldApplyIndependently, remoteTransition); } } Loading Loading @@ -839,6 +842,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr Slog.e(TAG, "Caller organizer=" + organizer + " is no longer registered"); return false; } return true; } Loading
services/core/java/com/android/server/wm/WindowOrganizerController.java +11 −2 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ import android.window.ITransitionMetricsReporter; import android.window.ITransitionPlayer; import android.window.IWindowContainerTransactionCallback; import android.window.IWindowOrganizerController; import android.window.RemoteTransition; import android.window.TaskFragmentAnimationParams; import android.window.TaskFragmentCreationParams; import android.window.TaskFragmentOperation; Loading Loading @@ -464,12 +465,20 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub * transition, which will be queued until the sync engine is * free if there is any other active sync. If {@code false}, * the {@code wct} will be directly applied to the active sync. * @param remoteTransition {@link RemoteTransition} to apply for the transaction. Only available * for system organizers. */ void applyTaskFragmentTransactionLocked(@NonNull WindowContainerTransaction wct, @WindowManager.TransitionType int type, boolean shouldApplyIndependently) { @WindowManager.TransitionType int type, boolean shouldApplyIndependently, @Nullable RemoteTransition remoteTransition) { enforceTaskFragmentOrganizerPermission("applyTaskFragmentTransaction()", Objects.requireNonNull(wct.getTaskFragmentOrganizer()), Objects.requireNonNull(wct)); if (remoteTransition != null && !mTaskFragmentOrganizerController.isSystemOrganizer( wct.getTaskFragmentOrganizer().asBinder())) { throw new SecurityException( "Only a system organizer is allowed to use remote transition!"); } final CallerInfo caller = new CallerInfo(); final long ident = Binder.clearCallingIdentity(); try { Loading Loading @@ -512,7 +521,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub return; } mTransitionController.requestStartTransition(transition, null /* startTask */, null /* remoteTransition */, null /* displayChange */); remoteTransition, null /* displayChange */); transition.setAllReady(); }; mTransitionController.startCollectOrQueue(transition, doApply); Loading
services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +33 −2 Original line number Diff line number Diff line Loading @@ -86,7 +86,9 @@ import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import android.view.RemoteAnimationDefinition; import android.view.SurfaceControl; import android.window.IRemoteTransition; import android.window.ITaskFragmentOrganizer; import android.window.RemoteTransition; import android.window.TaskFragmentAnimationParams; import android.window.TaskFragmentCreationParams; import android.window.TaskFragmentInfo; Loading Loading @@ -545,6 +547,35 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { assertNull(mController.getRemoteAnimationDefinition(mIOrganizer)); } @Test public void testApplyTransaction_disallowRemoteTransitionForNonSystemOrganizer() { mTransaction.setRelativeBounds(mFragmentWindowToken, new Rect(0, 0, 100, 100)); mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */, "Test:TaskFragmentOrganizer" /* processName */); // Throw exception if the transaction has remote transition and is not requested by system // organizer assertThrows(SecurityException.class, () -> mController.applyTransaction(mTransaction, TASK_FRAGMENT_TRANSIT_CHANGE, true /* shouldApplyIndependently */, new RemoteTransition(mock(IRemoteTransition.class)))); } @Test public void testApplyTransaction_allowRemoteTransitionForSystemOrganizer() { mController.unregisterOrganizer(mIOrganizer); mController.registerOrganizerInternal(mIOrganizer, true /* isSystemOrganizer */); mTransaction.setRelativeBounds(mFragmentWindowToken, new Rect(0, 0, 100, 100)); mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */, "Test:TaskFragmentOrganizer" /* processName */); // Remote transition is allowed for system organizer mController.applyTransaction(mTransaction, TASK_FRAGMENT_TRANSIT_CHANGE, true /* shouldApplyIndependently */, new RemoteTransition(mock(IRemoteTransition.class))); } @Test public void testApplyTransaction_enforceConfigurationChangeOnOrganizedTaskFragment() { // Throw exception if the transaction is trying to change a window that is not organized by Loading Loading @@ -1801,13 +1832,13 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { private void assertApplyTransactionDisallowed(WindowContainerTransaction t) { assertThrows(SecurityException.class, () -> mController.applyTransaction(t, TASK_FRAGMENT_TRANSIT_CHANGE, false /* shouldApplyIndependently */)); false /* shouldApplyIndependently */, null /* remoteTransition */)); } /** Asserts that applying the given transaction will not throw any exception. */ private void assertApplyTransactionAllowed(WindowContainerTransaction t) { mController.applyTransaction(t, TASK_FRAGMENT_TRANSIT_CHANGE, false /* shouldApplyIndependently */); false /* shouldApplyIndependently */, null /* remoteTransition */); } /** Asserts that there will be a transaction for TaskFragment appeared. */ Loading