Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java +13 −2 Original line number Diff line number Diff line Loading @@ -17,10 +17,13 @@ package com.android.wm.shell.splitscreen; import android.annotation.IntDef; import android.annotation.NonNull; import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.common.split.SplitLayout.SplitPosition; import java.util.concurrent.Executor; /** * Interface to engage split-screen feature. * TODO: Figure out which of these are actually needed outside of the Shell Loading Loading @@ -53,10 +56,18 @@ public interface SplitScreen { /** Callback interface for listening to changes in a split-screen stage. */ interface SplitScreenListener { void onStagePositionChanged(@StageType int stage, @SplitPosition int position); void onTaskStageChanged(int taskId, @StageType int stage, boolean visible); default void onStagePositionChanged(@StageType int stage, @SplitPosition int position) {} default void onTaskStageChanged(int taskId, @StageType int stage, boolean visible) {} default void onSplitVisibilityChanged(boolean visible) {} } /** Registers listener that gets split screen callback. */ void registerSplitScreenListener(@NonNull SplitScreenListener listener, @NonNull Executor executor); /** Unregisters listener that gets split screen callback. */ void unregisterSplitScreenListener(@NonNull SplitScreenListener listener); /** * Returns a binder that can be passed to an external process to manipulate SplitScreen. */ Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +62 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.util.ArrayMap; import android.util.Slog; import android.view.IRemoteAnimationFinishedCallback; import android.view.RemoteAnimationAdapter; Loading Loading @@ -64,6 +65,7 @@ import com.android.wm.shell.transition.LegacyTransitions; import com.android.wm.shell.transition.Transitions; import java.io.PrintWriter; import java.util.concurrent.Executor; /** * Class manages split-screen multitasking mode and implements the main interface Loading Loading @@ -293,6 +295,38 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, @ExternalThread private class SplitScreenImpl implements SplitScreen { private ISplitScreenImpl mISplitScreen; private final ArrayMap<SplitScreenListener, Executor> mExecutors = new ArrayMap<>(); private final SplitScreen.SplitScreenListener mListener = new SplitScreenListener() { @Override public void onStagePositionChanged(int stage, int position) { for (int i = 0; i < mExecutors.size(); i++) { final int index = i; mExecutors.valueAt(index).execute(() -> { mExecutors.keyAt(index).onStagePositionChanged(stage, position); }); } } @Override public void onTaskStageChanged(int taskId, int stage, boolean visible) { for (int i = 0; i < mExecutors.size(); i++) { final int index = i; mExecutors.valueAt(index).execute(() -> { mExecutors.keyAt(index).onTaskStageChanged(taskId, stage, visible); }); } } @Override public void onSplitVisibilityChanged(boolean visible) { for (int i = 0; i < mExecutors.size(); i++) { final int index = i; mExecutors.valueAt(index).execute(() -> { mExecutors.keyAt(index).onSplitVisibilityChanged(visible); }); } } }; @Override public ISplitScreen createExternalInterface() { Loading @@ -309,6 +343,34 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, SplitScreenController.this.onKeyguardOccludedChanged(occluded); }); } @Override public void registerSplitScreenListener(SplitScreenListener listener, Executor executor) { if (mExecutors.containsKey(listener)) return; mMainExecutor.execute(() -> { if (mExecutors.size() == 0) { SplitScreenController.this.registerSplitScreenListener(mListener); } mExecutors.put(listener, executor); }); executor.execute(() -> { mStageCoordinator.sendStatusToListener(listener); }); } @Override public void unregisterSplitScreenListener(SplitScreenListener listener) { mMainExecutor.execute(() -> { mExecutors.remove(listener); if (mExecutors.size() == 0) { SplitScreenController.this.unregisterSplitScreenListener(mListener); } }); } } /** Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +17 −4 Original line number Diff line number Diff line Loading @@ -501,16 +501,21 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, void registerSplitScreenListener(SplitScreen.SplitScreenListener listener) { if (mListeners.contains(listener)) return; mListeners.add(listener); listener.onStagePositionChanged(STAGE_TYPE_MAIN, getMainStagePosition()); listener.onStagePositionChanged(STAGE_TYPE_SIDE, getSideStagePosition()); mSideStage.onSplitScreenListenerRegistered(listener, STAGE_TYPE_SIDE); mMainStage.onSplitScreenListenerRegistered(listener, STAGE_TYPE_MAIN); sendStatusToListener(listener); } void unregisterSplitScreenListener(SplitScreen.SplitScreenListener listener) { mListeners.remove(listener); } void sendStatusToListener(SplitScreen.SplitScreenListener listener) { listener.onStagePositionChanged(STAGE_TYPE_MAIN, getMainStagePosition()); listener.onStagePositionChanged(STAGE_TYPE_SIDE, getSideStagePosition()); listener.onSplitVisibilityChanged(isSplitScreenVisible()); mSideStage.onSplitScreenListenerRegistered(listener, STAGE_TYPE_SIDE); mMainStage.onSplitScreenListenerRegistered(listener, STAGE_TYPE_MAIN); } private void sendOnStagePositionChanged() { for (int i = mListeners.size() - 1; i >= 0; --i) { final SplitScreen.SplitScreenListener l = mListeners.get(i); Loading @@ -535,6 +540,13 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } private void sendSplitVisibilityChanged() { for (int i = mListeners.size() - 1; i >= 0; --i) { final SplitScreen.SplitScreenListener l = mListeners.get(i); l.onSplitVisibilityChanged(mDividerVisible); } } private void onStageRootTaskAppeared(StageListenerImpl stageListener) { if (mMainStageListener.mHasRootTask && mSideStageListener.mHasRootTask) { mUseLegacySplit = mContext.getResources().getBoolean(R.bool.config_useLegacySplit); Loading Loading @@ -574,6 +586,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } else { mSplitLayout.release(); } sendSplitVisibilityChanged(); } private void onStageVisibilityChanged(StageListenerImpl stageListener) { Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java +13 −2 Original line number Diff line number Diff line Loading @@ -17,10 +17,13 @@ package com.android.wm.shell.splitscreen; import android.annotation.IntDef; import android.annotation.NonNull; import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.common.split.SplitLayout.SplitPosition; import java.util.concurrent.Executor; /** * Interface to engage split-screen feature. * TODO: Figure out which of these are actually needed outside of the Shell Loading Loading @@ -53,10 +56,18 @@ public interface SplitScreen { /** Callback interface for listening to changes in a split-screen stage. */ interface SplitScreenListener { void onStagePositionChanged(@StageType int stage, @SplitPosition int position); void onTaskStageChanged(int taskId, @StageType int stage, boolean visible); default void onStagePositionChanged(@StageType int stage, @SplitPosition int position) {} default void onTaskStageChanged(int taskId, @StageType int stage, boolean visible) {} default void onSplitVisibilityChanged(boolean visible) {} } /** Registers listener that gets split screen callback. */ void registerSplitScreenListener(@NonNull SplitScreenListener listener, @NonNull Executor executor); /** Unregisters listener that gets split screen callback. */ void unregisterSplitScreenListener(@NonNull SplitScreenListener listener); /** * Returns a binder that can be passed to an external process to manipulate SplitScreen. */ Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +62 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.util.ArrayMap; import android.util.Slog; import android.view.IRemoteAnimationFinishedCallback; import android.view.RemoteAnimationAdapter; Loading Loading @@ -64,6 +65,7 @@ import com.android.wm.shell.transition.LegacyTransitions; import com.android.wm.shell.transition.Transitions; import java.io.PrintWriter; import java.util.concurrent.Executor; /** * Class manages split-screen multitasking mode and implements the main interface Loading Loading @@ -293,6 +295,38 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, @ExternalThread private class SplitScreenImpl implements SplitScreen { private ISplitScreenImpl mISplitScreen; private final ArrayMap<SplitScreenListener, Executor> mExecutors = new ArrayMap<>(); private final SplitScreen.SplitScreenListener mListener = new SplitScreenListener() { @Override public void onStagePositionChanged(int stage, int position) { for (int i = 0; i < mExecutors.size(); i++) { final int index = i; mExecutors.valueAt(index).execute(() -> { mExecutors.keyAt(index).onStagePositionChanged(stage, position); }); } } @Override public void onTaskStageChanged(int taskId, int stage, boolean visible) { for (int i = 0; i < mExecutors.size(); i++) { final int index = i; mExecutors.valueAt(index).execute(() -> { mExecutors.keyAt(index).onTaskStageChanged(taskId, stage, visible); }); } } @Override public void onSplitVisibilityChanged(boolean visible) { for (int i = 0; i < mExecutors.size(); i++) { final int index = i; mExecutors.valueAt(index).execute(() -> { mExecutors.keyAt(index).onSplitVisibilityChanged(visible); }); } } }; @Override public ISplitScreen createExternalInterface() { Loading @@ -309,6 +343,34 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, SplitScreenController.this.onKeyguardOccludedChanged(occluded); }); } @Override public void registerSplitScreenListener(SplitScreenListener listener, Executor executor) { if (mExecutors.containsKey(listener)) return; mMainExecutor.execute(() -> { if (mExecutors.size() == 0) { SplitScreenController.this.registerSplitScreenListener(mListener); } mExecutors.put(listener, executor); }); executor.execute(() -> { mStageCoordinator.sendStatusToListener(listener); }); } @Override public void unregisterSplitScreenListener(SplitScreenListener listener) { mMainExecutor.execute(() -> { mExecutors.remove(listener); if (mExecutors.size() == 0) { SplitScreenController.this.unregisterSplitScreenListener(mListener); } }); } } /** Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +17 −4 Original line number Diff line number Diff line Loading @@ -501,16 +501,21 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, void registerSplitScreenListener(SplitScreen.SplitScreenListener listener) { if (mListeners.contains(listener)) return; mListeners.add(listener); listener.onStagePositionChanged(STAGE_TYPE_MAIN, getMainStagePosition()); listener.onStagePositionChanged(STAGE_TYPE_SIDE, getSideStagePosition()); mSideStage.onSplitScreenListenerRegistered(listener, STAGE_TYPE_SIDE); mMainStage.onSplitScreenListenerRegistered(listener, STAGE_TYPE_MAIN); sendStatusToListener(listener); } void unregisterSplitScreenListener(SplitScreen.SplitScreenListener listener) { mListeners.remove(listener); } void sendStatusToListener(SplitScreen.SplitScreenListener listener) { listener.onStagePositionChanged(STAGE_TYPE_MAIN, getMainStagePosition()); listener.onStagePositionChanged(STAGE_TYPE_SIDE, getSideStagePosition()); listener.onSplitVisibilityChanged(isSplitScreenVisible()); mSideStage.onSplitScreenListenerRegistered(listener, STAGE_TYPE_SIDE); mMainStage.onSplitScreenListenerRegistered(listener, STAGE_TYPE_MAIN); } private void sendOnStagePositionChanged() { for (int i = mListeners.size() - 1; i >= 0; --i) { final SplitScreen.SplitScreenListener l = mListeners.get(i); Loading @@ -535,6 +540,13 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } private void sendSplitVisibilityChanged() { for (int i = mListeners.size() - 1; i >= 0; --i) { final SplitScreen.SplitScreenListener l = mListeners.get(i); l.onSplitVisibilityChanged(mDividerVisible); } } private void onStageRootTaskAppeared(StageListenerImpl stageListener) { if (mMainStageListener.mHasRootTask && mSideStageListener.mHasRootTask) { mUseLegacySplit = mContext.getResources().getBoolean(R.bool.config_useLegacySplit); Loading Loading @@ -574,6 +586,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } else { mSplitLayout.release(); } sendSplitVisibilityChanged(); } private void onStageVisibilityChanged(StageListenerImpl stageListener) { Loading