Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl +14 −4 Original line number Original line Diff line number Diff line Loading @@ -93,6 +93,14 @@ interface ISplitScreen { int sideTaskId, in Bundle sideOptions, int sidePosition, int sideTaskId, in Bundle sideOptions, int sidePosition, float splitRatio, in RemoteAnimationAdapter adapter) = 11; float splitRatio, in RemoteAnimationAdapter adapter) = 11; /** * Start a pair of intent and task using legacy transition system. */ oneway void startIntentAndTaskWithLegacyTransition(in PendingIntent pendingIntent, in Intent fillInIntent, int taskId, boolean intentFirst, in Bundle mainOptions, in Bundle sideOptions, int sidePosition, float splitRatio, in RemoteAnimationAdapter adapter) = 12; /** /** * Blocking call that notifies and gets additional split-screen targets when entering * Blocking call that notifies and gets additional split-screen targets when entering * recents (for example: the dividerBar). * recents (for example: the dividerBar). Loading @@ -100,5 +108,7 @@ interface ISplitScreen { * @param appTargets apps that will be re-parented to display area * @param appTargets apps that will be re-parented to display area */ */ RemoteAnimationTarget[] onGoingToRecentsLegacy(boolean cancel, RemoteAnimationTarget[] onGoingToRecentsLegacy(boolean cancel, in RemoteAnimationTarget[] appTargets) = 12; in RemoteAnimationTarget[] appTargets) = 13; } } libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +12 −0 Original line number Original line Diff line number Diff line Loading @@ -640,6 +640,18 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, splitRatio, adapter)); splitRatio, adapter)); } } @Override public void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, Intent fillInIntent, int taskId, boolean intentFirst, Bundle mainOptions, Bundle sideOptions, int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) { executeRemoteCallWithTaskPermission(mController, "startIntentAndTaskWithLegacyTransition", (controller) -> controller.mStageCoordinator.startIntentAndTaskWithLegacyTransition( pendingIntent, fillInIntent, taskId, intentFirst, mainOptions, sideOptions, sidePosition, splitRatio, adapter)); } @Override @Override public void startTasks(int mainTaskId, @Nullable Bundle mainOptions, public void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, @Nullable Bundle sideOptions, int sideTaskId, @Nullable Bundle sideOptions, Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +112 −0 Original line number Original line Diff line number Diff line Loading @@ -57,8 +57,10 @@ import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ActivityOptions; import android.app.ActivityTaskManager; import android.app.ActivityTaskManager; import android.app.PendingIntent; import android.app.WindowConfiguration; import android.app.WindowConfiguration; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Configuration; import android.graphics.Rect; import android.graphics.Rect; import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateManager; Loading Loading @@ -467,6 +469,116 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mTaskOrganizer.applyTransaction(wct); mTaskOrganizer.applyTransaction(wct); } } /** Start an intent and a task ordered by {@code intentFirst}. */ void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, Intent fillInIntent, int taskId, boolean intentFirst, @Nullable Bundle mainOptions, @Nullable Bundle sideOptions, @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) { // TODO: try pulling the first chunk of this method into a method so that it can be shared // with startTasksWithLegacyTransition. So far attempts to do so result in failure in split. // Init divider first to make divider leash for remote animation target. mSplitLayout.init(); // Set false to avoid record new bounds with old task still on top; mShouldUpdateRecents = false; final WindowContainerTransaction wct = new WindowContainerTransaction(); final WindowContainerTransaction evictWct = new WindowContainerTransaction(); prepareEvictChildTasks(SPLIT_POSITION_TOP_OR_LEFT, evictWct); prepareEvictChildTasks(SPLIT_POSITION_BOTTOM_OR_RIGHT, evictWct); // Need to add another wrapper here in shell so that we can inject the divider bar // and also manage the process elevation via setRunningRemote IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() { @Override public void onAnimationStart(@WindowManager.TransitionOldType int transit, RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, final IRemoteAnimationFinishedCallback finishedCallback) { RemoteAnimationTarget[] augmentedNonApps = new RemoteAnimationTarget[nonApps.length + 1]; for (int i = 0; i < nonApps.length; ++i) { augmentedNonApps[i] = nonApps[i]; } augmentedNonApps[augmentedNonApps.length - 1] = getDividerBarLegacyTarget(); IRemoteAnimationFinishedCallback wrapCallback = new IRemoteAnimationFinishedCallback.Stub() { @Override public void onAnimationFinished() throws RemoteException { mShouldUpdateRecents = true; mSyncQueue.queue(evictWct); mSyncQueue.runInSync(t -> setDividerVisibility(true, t)); finishedCallback.onAnimationFinished(); } }; try { try { ActivityTaskManager.getService().setRunningRemoteTransitionDelegate( adapter.getCallingApplication()); } catch (SecurityException e) { Slog.e(TAG, "Unable to boost animation thread. This should only happen" + " during unit tests"); } adapter.getRunner().onAnimationStart(transit, apps, wallpapers, augmentedNonApps, wrapCallback); } catch (RemoteException e) { Slog.e(TAG, "Error starting remote animation", e); } } @Override public void onAnimationCancelled() { mShouldUpdateRecents = true; mSyncQueue.queue(evictWct); mSyncQueue.runInSync(t -> setDividerVisibility(true, t)); try { adapter.getRunner().onAnimationCancelled(); } catch (RemoteException e) { Slog.e(TAG, "Error starting remote animation", e); } } }; RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter( wrapper, adapter.getDuration(), adapter.getStatusBarTransitionDelay()); if (mainOptions == null) { mainOptions = ActivityOptions.makeRemoteAnimation(wrappedAdapter).toBundle(); } else { ActivityOptions mainActivityOptions = ActivityOptions.fromBundle(mainOptions); mainActivityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter)); mainOptions = mainActivityOptions.toBundle(); } sideOptions = sideOptions != null ? sideOptions : new Bundle(); setSideStagePosition(sidePosition, wct); mSplitLayout.setDivideRatio(splitRatio); if (mMainStage.isActive()) { mMainStage.moveToTop(getMainStageBounds(), wct); } else { // Build a request WCT that will launch both apps such that task 0 is on the main stage // while task 1 is on the side stage. mMainStage.activate(getMainStageBounds(), wct, false /* reparent */); } mSideStage.moveToTop(getSideStageBounds(), wct); // Make sure the launch options will put tasks in the corresponding split roots addActivityOptions(mainOptions, mMainStage); addActivityOptions(sideOptions, mSideStage); // Add task launch requests if (intentFirst) { wct.sendPendingIntent(pendingIntent, fillInIntent, mainOptions); wct.startTask(taskId, sideOptions); } else { wct.startTask(taskId, mainOptions); wct.sendPendingIntent(pendingIntent, fillInIntent, sideOptions); } // Using legacy transitions, so we can't use blast sync since it conflicts. mTaskOrganizer.applyTransaction(wct); } /** /** * Collects all the current child tasks of a specific split and prepares transaction to evict * Collects all the current child tasks of a specific split and prepares transaction to evict * them to display. * them to display. Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl +14 −4 Original line number Original line Diff line number Diff line Loading @@ -93,6 +93,14 @@ interface ISplitScreen { int sideTaskId, in Bundle sideOptions, int sidePosition, int sideTaskId, in Bundle sideOptions, int sidePosition, float splitRatio, in RemoteAnimationAdapter adapter) = 11; float splitRatio, in RemoteAnimationAdapter adapter) = 11; /** * Start a pair of intent and task using legacy transition system. */ oneway void startIntentAndTaskWithLegacyTransition(in PendingIntent pendingIntent, in Intent fillInIntent, int taskId, boolean intentFirst, in Bundle mainOptions, in Bundle sideOptions, int sidePosition, float splitRatio, in RemoteAnimationAdapter adapter) = 12; /** /** * Blocking call that notifies and gets additional split-screen targets when entering * Blocking call that notifies and gets additional split-screen targets when entering * recents (for example: the dividerBar). * recents (for example: the dividerBar). Loading @@ -100,5 +108,7 @@ interface ISplitScreen { * @param appTargets apps that will be re-parented to display area * @param appTargets apps that will be re-parented to display area */ */ RemoteAnimationTarget[] onGoingToRecentsLegacy(boolean cancel, RemoteAnimationTarget[] onGoingToRecentsLegacy(boolean cancel, in RemoteAnimationTarget[] appTargets) = 12; in RemoteAnimationTarget[] appTargets) = 13; } }
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +12 −0 Original line number Original line Diff line number Diff line Loading @@ -640,6 +640,18 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, splitRatio, adapter)); splitRatio, adapter)); } } @Override public void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, Intent fillInIntent, int taskId, boolean intentFirst, Bundle mainOptions, Bundle sideOptions, int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) { executeRemoteCallWithTaskPermission(mController, "startIntentAndTaskWithLegacyTransition", (controller) -> controller.mStageCoordinator.startIntentAndTaskWithLegacyTransition( pendingIntent, fillInIntent, taskId, intentFirst, mainOptions, sideOptions, sidePosition, splitRatio, adapter)); } @Override @Override public void startTasks(int mainTaskId, @Nullable Bundle mainOptions, public void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, @Nullable Bundle sideOptions, int sideTaskId, @Nullable Bundle sideOptions, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +112 −0 Original line number Original line Diff line number Diff line Loading @@ -57,8 +57,10 @@ import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ActivityOptions; import android.app.ActivityTaskManager; import android.app.ActivityTaskManager; import android.app.PendingIntent; import android.app.WindowConfiguration; import android.app.WindowConfiguration; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Configuration; import android.graphics.Rect; import android.graphics.Rect; import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateManager; Loading Loading @@ -467,6 +469,116 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mTaskOrganizer.applyTransaction(wct); mTaskOrganizer.applyTransaction(wct); } } /** Start an intent and a task ordered by {@code intentFirst}. */ void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, Intent fillInIntent, int taskId, boolean intentFirst, @Nullable Bundle mainOptions, @Nullable Bundle sideOptions, @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) { // TODO: try pulling the first chunk of this method into a method so that it can be shared // with startTasksWithLegacyTransition. So far attempts to do so result in failure in split. // Init divider first to make divider leash for remote animation target. mSplitLayout.init(); // Set false to avoid record new bounds with old task still on top; mShouldUpdateRecents = false; final WindowContainerTransaction wct = new WindowContainerTransaction(); final WindowContainerTransaction evictWct = new WindowContainerTransaction(); prepareEvictChildTasks(SPLIT_POSITION_TOP_OR_LEFT, evictWct); prepareEvictChildTasks(SPLIT_POSITION_BOTTOM_OR_RIGHT, evictWct); // Need to add another wrapper here in shell so that we can inject the divider bar // and also manage the process elevation via setRunningRemote IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() { @Override public void onAnimationStart(@WindowManager.TransitionOldType int transit, RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, final IRemoteAnimationFinishedCallback finishedCallback) { RemoteAnimationTarget[] augmentedNonApps = new RemoteAnimationTarget[nonApps.length + 1]; for (int i = 0; i < nonApps.length; ++i) { augmentedNonApps[i] = nonApps[i]; } augmentedNonApps[augmentedNonApps.length - 1] = getDividerBarLegacyTarget(); IRemoteAnimationFinishedCallback wrapCallback = new IRemoteAnimationFinishedCallback.Stub() { @Override public void onAnimationFinished() throws RemoteException { mShouldUpdateRecents = true; mSyncQueue.queue(evictWct); mSyncQueue.runInSync(t -> setDividerVisibility(true, t)); finishedCallback.onAnimationFinished(); } }; try { try { ActivityTaskManager.getService().setRunningRemoteTransitionDelegate( adapter.getCallingApplication()); } catch (SecurityException e) { Slog.e(TAG, "Unable to boost animation thread. This should only happen" + " during unit tests"); } adapter.getRunner().onAnimationStart(transit, apps, wallpapers, augmentedNonApps, wrapCallback); } catch (RemoteException e) { Slog.e(TAG, "Error starting remote animation", e); } } @Override public void onAnimationCancelled() { mShouldUpdateRecents = true; mSyncQueue.queue(evictWct); mSyncQueue.runInSync(t -> setDividerVisibility(true, t)); try { adapter.getRunner().onAnimationCancelled(); } catch (RemoteException e) { Slog.e(TAG, "Error starting remote animation", e); } } }; RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter( wrapper, adapter.getDuration(), adapter.getStatusBarTransitionDelay()); if (mainOptions == null) { mainOptions = ActivityOptions.makeRemoteAnimation(wrappedAdapter).toBundle(); } else { ActivityOptions mainActivityOptions = ActivityOptions.fromBundle(mainOptions); mainActivityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter)); mainOptions = mainActivityOptions.toBundle(); } sideOptions = sideOptions != null ? sideOptions : new Bundle(); setSideStagePosition(sidePosition, wct); mSplitLayout.setDivideRatio(splitRatio); if (mMainStage.isActive()) { mMainStage.moveToTop(getMainStageBounds(), wct); } else { // Build a request WCT that will launch both apps such that task 0 is on the main stage // while task 1 is on the side stage. mMainStage.activate(getMainStageBounds(), wct, false /* reparent */); } mSideStage.moveToTop(getSideStageBounds(), wct); // Make sure the launch options will put tasks in the corresponding split roots addActivityOptions(mainOptions, mMainStage); addActivityOptions(sideOptions, mSideStage); // Add task launch requests if (intentFirst) { wct.sendPendingIntent(pendingIntent, fillInIntent, mainOptions); wct.startTask(taskId, sideOptions); } else { wct.startTask(taskId, mainOptions); wct.sendPendingIntent(pendingIntent, fillInIntent, sideOptions); } // Using legacy transitions, so we can't use blast sync since it conflicts. mTaskOrganizer.applyTransaction(wct); } /** /** * Collects all the current child tasks of a specific split and prepares transaction to evict * Collects all the current child tasks of a specific split and prepares transaction to evict * them to display. * them to display. Loading