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

Commit d69d2865 authored by Tony Huang's avatar Tony Huang
Browse files

Add api for systemUi getting split visibility

Bug: 193713566
Test: manual
Change-Id: I6dddfb5ae213da8a7da0b1b9eba45ed7dfff6983
parent c7efed22
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -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
@@ -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.
     */
+62 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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
@@ -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() {
@@ -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);
                }
            });
        }
    }

    /**
+17 −4
Original line number Diff line number Diff line
@@ -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);
@@ -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);
@@ -574,6 +586,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        } else {
            mSplitLayout.release();
        }
        sendSplitVisibilityChanged();
    }

    private void onStageVisibilityChanged(StageListenerImpl stageListener) {