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

Commit f74cdbed authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge changes I0ea9aae2,I369e83cb

* changes:
  5/ Update splitscreen to use shell main thread
  4/ Update HideDisplayCutout and AppPairs to use shell main thread
parents a49fe859 cb4810a6
Loading
Loading
Loading
Loading
+77 −13
Original line number Diff line number Diff line
@@ -19,41 +19,58 @@ package com.android.wm.shell.apppairs;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;

import android.app.ActivityManager;
import android.util.Slog;
import android.util.SparseArray;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;

import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;

/**
 * Class manages app-pairs multitasking mode and implements the main interface {@link AppPairs}.
 */
public class AppPairsController implements AppPairs {
public class AppPairsController {
    private static final String TAG = AppPairsController.class.getSimpleName();

    private final ShellTaskOrganizer mTaskOrganizer;
    private final SyncTransactionQueue mSyncQueue;
    private final ShellExecutor mMainExecutor;
    private final AppPairsImpl mImpl = new AppPairsImpl();

    private AppPairsPool mPairsPool;
    // Active app-pairs mapped by root task id key.
    private final SparseArray<AppPair> mActiveAppPairs = new SparseArray<>();
    private final DisplayController mDisplayController;

    public AppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
                DisplayController displayController) {
    /**
     * Creates {@link AppPairs}, returns {@code null} if the feature is not supported.
     */
    @Nullable
    public static AppPairs create(ShellTaskOrganizer organizer,
            SyncTransactionQueue syncQueue, DisplayController displayController,
            ShellExecutor mainExecutor) {
        return new AppPairsController(organizer, syncQueue, displayController,
                mainExecutor).mImpl;
    }

    AppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
                DisplayController displayController, ShellExecutor mainExecutor) {
        mTaskOrganizer = organizer;
        mSyncQueue = syncQueue;
        mDisplayController = displayController;
        mMainExecutor = mainExecutor;
    }

    @Override
    public void onOrganizerRegistered() {
    void onOrganizerRegistered() {
        if (mPairsPool == null) {
            setPairsPool(new AppPairsPool(this));
        }
@@ -64,8 +81,7 @@ public class AppPairsController implements AppPairs {
        mPairsPool = pool;
    }

    @Override
    public boolean pair(int taskId1, int taskId2) {
    boolean pair(int taskId1, int taskId2) {
        final ActivityManager.RunningTaskInfo task1 = mTaskOrganizer.getRunningTaskInfo(taskId1);
        final ActivityManager.RunningTaskInfo task2 = mTaskOrganizer.getRunningTaskInfo(taskId2);
        if (task1 == null || task2 == null) {
@@ -74,8 +90,7 @@ public class AppPairsController implements AppPairs {
        return pair(task1, task2);
    }

    @Override
    public boolean pair(ActivityManager.RunningTaskInfo task1,
    boolean pair(ActivityManager.RunningTaskInfo task1,
            ActivityManager.RunningTaskInfo task2) {
        return pairInner(task1, task2) != null;
    }
@@ -94,8 +109,7 @@ public class AppPairsController implements AppPairs {
        return pair;
    }

    @Override
    public void unpair(int taskId) {
    void unpair(int taskId) {
        unpair(taskId, true /* releaseToPool */);
    }

@@ -135,8 +149,7 @@ public class AppPairsController implements AppPairs {
        return mDisplayController;
    }

    @Override
    public void dump(@NonNull PrintWriter pw, String prefix) {
    private void dump(@NonNull PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
        final String childPrefix = innerPrefix + "  ";
        pw.println(prefix + this);
@@ -155,4 +168,55 @@ public class AppPairsController implements AppPairs {
        return TAG + "#" + mActiveAppPairs.size();
    }

    private class AppPairsImpl implements AppPairs {
        @Override
        public boolean pair(int task1, int task2) {
            boolean[] result = new boolean[1];
            try {
                mMainExecutor.executeBlocking(() -> {
                    result[0] = AppPairsController.this.pair(task1, task2);
                });
            } catch (InterruptedException e) {
                Slog.e(TAG, "Failed to pair tasks: " + task1 + ", " + task2);
            }
            return result[0];
        }

        @Override
        public boolean pair(ActivityManager.RunningTaskInfo task1,
                ActivityManager.RunningTaskInfo task2) {
            boolean[] result = new boolean[1];
            try {
                mMainExecutor.executeBlocking(() -> {
                    result[0] = AppPairsController.this.pair(task1, task2);
                });
            } catch (InterruptedException e) {
                Slog.e(TAG, "Failed to pair tasks: " + task1 + ", " + task2);
            }
            return result[0];
        }

        @Override
        public void unpair(int taskId) {
            mMainExecutor.execute(() -> {
                AppPairsController.this.unpair(taskId);
            });
        }

        @Override
        public void onOrganizerRegistered() {
            mMainExecutor.execute(() -> {
                AppPairsController.this.onOrganizerRegistered();
            });
        }

        @Override
        public void dump(@NonNull PrintWriter pw, String prefix) {
            try {
                mMainExecutor.executeBlocking(() -> AppPairsController.this.dump(pw, prefix));
            } catch (InterruptedException e) {
                Slog.e(TAG, "Failed to dump AppPairsController in 2s");
            }
        }
    }
}
+26 −8
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.wm.shell.hidedisplaycutout;
import android.content.Context;
import android.content.res.Configuration;
import android.os.SystemProperties;
import android.util.Slog;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -28,17 +29,18 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;

import java.io.PrintWriter;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

/**
 * Manages the hide display cutout status.
 */
public class HideDisplayCutoutController implements HideDisplayCutout {
public class HideDisplayCutoutController {
    private static final String TAG = "HideDisplayCutoutController";

    private final Context mContext;
    private final HideDisplayCutoutOrganizer mOrganizer;
    private final ShellExecutor mMainExecutor;
    private final HideDisplayCutoutImpl mImpl = new HideDisplayCutoutImpl();
    @VisibleForTesting
    boolean mEnabled;

@@ -55,7 +57,7 @@ public class HideDisplayCutoutController implements HideDisplayCutout {
     * supported.
     */
    @Nullable
    public static HideDisplayCutoutController create(
    public static HideDisplayCutout create(
            Context context, DisplayController displayController, ShellExecutor mainExecutor) {
        // The SystemProperty is set for devices that support this feature and is used to control
        // whether to create the HideDisplayCutout instance.
@@ -66,7 +68,7 @@ public class HideDisplayCutoutController implements HideDisplayCutout {

        HideDisplayCutoutOrganizer organizer =
                new HideDisplayCutoutOrganizer(context, displayController, mainExecutor);
        return new HideDisplayCutoutController(context, organizer, mainExecutor);
        return new HideDisplayCutoutController(context, organizer, mainExecutor).mImpl;
    }

    @VisibleForTesting
@@ -88,13 +90,11 @@ public class HideDisplayCutoutController implements HideDisplayCutout {
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
    private void onConfigurationChanged(Configuration newConfig) {
        updateStatus();
    }

    @Override
    public void dump(@NonNull PrintWriter pw) {
    private void dump(@NonNull PrintWriter pw) {
        final String prefix = "  ";
        pw.print(TAG);
        pw.println(" states: ");
@@ -103,4 +103,22 @@ public class HideDisplayCutoutController implements HideDisplayCutout {
        pw.println(mEnabled);
        mOrganizer.dump(pw);
    }

    private class HideDisplayCutoutImpl implements HideDisplayCutout {
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            mMainExecutor.execute(() -> {
                HideDisplayCutoutController.this.onConfigurationChanged(newConfig);
            });
        }

        @Override
        public void dump(@NonNull PrintWriter pw) {
            try {
                mMainExecutor.executeBlocking(() -> HideDisplayCutoutController.this.dump(pw));
            } catch (InterruptedException e) {
                Slog.e(TAG, "Failed to dump HideDisplayCutoutController in 2s");
            }
        }
    }
}
+9 −10
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import android.graphics.Region;
import android.graphics.Region.Op;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Slog;
@@ -60,7 +59,6 @@ import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;

import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.policy.DividerSnapAlgorithm;
@@ -146,8 +144,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,
    private LegacySplitDisplayLayout mSplitLayout;
    private DividerImeController mImeController;
    private DividerCallbacks mCallback;
    private final AnimationHandler mAnimationHandler = new AnimationHandler();

    private AnimationHandler mSfVsyncAnimationHandler;
    private ValueAnimator mCurrentAnimator;
    private boolean mEntranceAnimationRunning;
    private boolean mExitAnimationRunning;
@@ -172,8 +170,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
    // used interact with keyguard.
    private boolean mSurfaceHidden = false;

    private final Handler mHandler = new Handler();

    private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
        @Override
        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
@@ -284,7 +280,10 @@ public class DividerView extends FrameLayout implements OnTouchListener,
        final DisplayManager displayManager =
                (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
        mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
        mAnimationHandler.setProvider(new SfVsyncFrameCallbackProvider());
    }

    public void setAnimationHandler(AnimationHandler sfVsyncAnimationHandler) {
        mSfVsyncAnimationHandler = sfVsyncAnimationHandler;
    }

    @Override
@@ -669,12 +668,12 @@ public class DividerView extends FrameLayout implements OnTouchListener,
                } else {
                    final Boolean cancelled = mCancelled;
                    if (DEBUG) Slog.d(TAG, "Posting endFling " + cancelled + " d:" + delay + "ms");
                    mHandler.postDelayed(() -> endAction.accept(cancelled), delay);
                    getHandler().postDelayed(() -> endAction.accept(cancelled), delay);
                }
            }
        });
        anim.setAnimationHandler(mAnimationHandler);
        mCurrentAnimator = anim;
        mCurrentAnimator.setAnimationHandler(mSfVsyncAnimationHandler);
        return anim;
    }

@@ -1061,8 +1060,8 @@ public class DividerView extends FrameLayout implements OnTouchListener,
            }
        }
        if (getViewRootImpl() != null) {
            mHandler.removeCallbacks(mUpdateEmbeddedMatrix);
            mHandler.post(mUpdateEmbeddedMatrix);
            getHandler().removeCallbacks(mUpdateEmbeddedMatrix);
            getHandler().post(mUpdateEmbeddedMatrix);
        }
    }

+2 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ import com.android.wm.shell.R;
/**
 * Translucent activity that gets started on top of a task in multi-window to inform the user that
 * we forced the activity below to be resizable.
 *
 * Note: This activity runs on the main thread of the process hosting the Shell lib.
 */
public class ForcedResizableInfoActivity extends Activity implements OnTouchListener {

+171 −38
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.Display.DEFAULT_DISPLAY;

import android.animation.AnimationHandler;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
@@ -40,6 +41,8 @@ import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;

import androidx.annotation.Nullable;

import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -60,14 +63,14 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

/**
 * Controls split screen feature.
 */
public class LegacySplitScreenController implements LegacySplitScreen,
        DisplayController.OnDisplaysChangedListener {
public class LegacySplitScreenController implements DisplayController.OnDisplaysChangedListener {
    static final boolean DEBUG = false;

    private static final String TAG = "SplitScreenCtrl";
@@ -81,11 +84,13 @@ public class LegacySplitScreenController implements LegacySplitScreen,
    private final DividerState mDividerState = new DividerState();
    private final ForcedResizableInfoActivityController mForcedResizableController;
    private final ShellExecutor mMainExecutor;
    private final AnimationHandler mSfVsyncAnimationHandler;
    private final LegacySplitScreenTaskListener mSplits;
    private final SystemWindows mSystemWindows;
    final TransactionPool mTransactionPool;
    private final WindowManagerProxy mWindowManagerProxy;
    private final TaskOrganizer mTaskOrganizer;
    private final SplitScreenImpl mImpl = new SplitScreenImpl();

    private final CopyOnWriteArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners
            = new CopyOnWriteArrayList<>();
@@ -106,21 +111,37 @@ public class LegacySplitScreenController implements LegacySplitScreen,

    private boolean mIsKeyguardShowing;
    private boolean mVisible = false;
    private boolean mMinimized = false;
    private boolean mAdjustedForIme = false;
    private volatile boolean mMinimized = false;
    private volatile boolean mAdjustedForIme = false;
    private boolean mHomeStackResizable = false;

    /**
     * Creates {@link SplitScreen}, returns {@code null} if the feature is not supported.
     */
    @Nullable
    public static LegacySplitScreen create(Context context,
            DisplayController displayController, SystemWindows systemWindows,
            DisplayImeController imeController, TransactionPool transactionPool,
            ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
            TaskStackListenerImpl taskStackListener, Transitions transitions,
            ShellExecutor mainExecutor, AnimationHandler sfVsyncAnimationHandler) {
        return new LegacySplitScreenController(context, displayController, systemWindows,
                imeController, transactionPool, shellTaskOrganizer, syncQueue, taskStackListener,
                transitions, mainExecutor, sfVsyncAnimationHandler).mImpl;
    }

    public LegacySplitScreenController(Context context,
            DisplayController displayController, SystemWindows systemWindows,
            DisplayImeController imeController, TransactionPool transactionPool,
            ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
            TaskStackListenerImpl taskStackListener, Transitions transitions,
            ShellExecutor mainExecutor) {
            ShellExecutor mainExecutor, AnimationHandler sfVsyncAnimationHandler) {
        mContext = context;
        mDisplayController = displayController;
        mSystemWindows = systemWindows;
        mImeController = imeController;
        mMainExecutor = mainExecutor;
        mSfVsyncAnimationHandler = sfVsyncAnimationHandler;
        mForcedResizableController = new ForcedResizableInfoActivityController(context, this,
                mainExecutor);
        mTransactionPool = transactionPool;
@@ -216,8 +237,7 @@ public class LegacySplitScreenController implements LegacySplitScreen,
        mTaskOrganizer.applyTransaction(tct);
    }

    @Override
    public void onKeyguardVisibilityChanged(boolean showing) {
    private void onKeyguardVisibilityChanged(boolean showing) {
        if (!isSplitActive() || mView == null) {
            return;
        }
@@ -273,23 +293,19 @@ public class LegacySplitScreenController implements LegacySplitScreen,
        }
    }

    @Override
    public DividerView getDividerView() {
        return mView;
    }

    @Override
    public boolean isMinimized() {
    boolean isMinimized() {
        return mMinimized;
    }

    @Override
    public boolean isHomeStackResizable() {
    boolean isHomeStackResizable() {
        return mHomeStackResizable;
    }

    @Override
    public boolean isDividerVisible() {
    DividerView getDividerView() {
        return mView;
    }

    boolean isDividerVisible() {
        return mView != null && mView.getVisibility() == View.VISIBLE;
    }

@@ -308,6 +324,7 @@ public class LegacySplitScreenController implements LegacySplitScreen,
        Context dctx = mDisplayController.getDisplayContext(mContext.getDisplayId());
        mView = (DividerView)
                LayoutInflater.from(dctx).inflate(R.layout.docked_stack_divider, null);
        mView.setAnimationHandler(mSfVsyncAnimationHandler);
        DisplayLayout displayLayout = mDisplayController.getDisplayLayout(mContext.getDisplayId());
        mView.injectDependencies(this, mWindowManager, mDividerState, mForcedResizableController,
                mSplits, mSplitLayout, mImePositionProcessor, mWindowManagerProxy);
@@ -373,8 +390,7 @@ public class LegacySplitScreenController implements LegacySplitScreen,
        }
    }

    @Override
    public void setMinimized(final boolean minimized) {
    private void setMinimized(final boolean minimized) {
        if (DEBUG) Slog.d(TAG, "posting ext setMinimized " + minimized + " vis:" + mVisible);
        mMainExecutor.execute(() -> {
            if (DEBUG) Slog.d(TAG, "run posted ext setMinimized " + minimized + " vis:" + mVisible);
@@ -437,23 +453,20 @@ public class LegacySplitScreenController implements LegacySplitScreen,
        mWindowManager.setTouchable(!mAdjustedForIme);
    }

    @Override
    public void onUndockingTask() {
    private void onUndockingTask() {
        if (mView != null) {
            mView.onUndockingTask();
        }
    }

    @Override
    public void onAppTransitionFinished() {
    private void onAppTransitionFinished() {
        if (mView == null) {
            return;
        }
        mForcedResizableController.onAppTransitionFinished();
    }

    @Override
    public void dump(PrintWriter pw) {
    private void dump(PrintWriter pw) {
        pw.print("  mVisible="); pw.println(mVisible);
        pw.print("  mMinimized="); pw.println(mMinimized);
        pw.print("  mAdjustedForIme="); pw.println(mAdjustedForIme);
@@ -469,16 +482,14 @@ public class LegacySplitScreenController implements LegacySplitScreen,
        return (long) (transitionDuration * transitionScale);
    }

    @Override
    public void registerInSplitScreenListener(Consumer<Boolean> listener) {
    void registerInSplitScreenListener(Consumer<Boolean> listener) {
        listener.accept(isDividerVisible());
        synchronized (mDockedStackExistsListeners) {
            mDockedStackExistsListeners.add(new WeakReference<>(listener));
        }
    }

    @Override
    public void unregisterInSplitScreenListener(Consumer<Boolean> listener) {
    void unregisterInSplitScreenListener(Consumer<Boolean> listener) {
        synchronized (mDockedStackExistsListeners) {
            for (int i = mDockedStackExistsListeners.size() - 1; i >= 0; i--) {
                if (mDockedStackExistsListeners.get(i) == listener) {
@@ -488,15 +499,13 @@ public class LegacySplitScreenController implements LegacySplitScreen,
        }
    }

    @Override
    public void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener) {
    private void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener) {
        synchronized (mBoundsChangedListeners) {
            mBoundsChangedListeners.add(new WeakReference<>(listener));
        }
    }

    @Override
    public boolean splitPrimaryTask() {
    private boolean splitPrimaryTask() {
        try {
            if (ActivityTaskManager.getService().getLockTaskModeState() == LOCK_TASK_MODE_PINNED
                    || isSplitActive()) {
@@ -529,8 +538,7 @@ public class LegacySplitScreenController implements LegacySplitScreen,
                topRunningTask.taskId, true /* onTop */);
    }

    @Override
    public void dismissSplitToPrimaryTask() {
    private void dismissSplitToPrimaryTask() {
        startDismissSplit(true /* toPrimaryTask */);
    }

@@ -621,11 +629,136 @@ public class LegacySplitScreenController implements LegacySplitScreen,
        return mWindowManagerProxy;
    }

    @Override
    public WindowContainerToken getSecondaryRoot() {
    WindowContainerToken getSecondaryRoot() {
        if (mSplits == null || mSplits.mSecondary == null) {
            return null;
        }
        return mSplits.mSecondary.token;
    }

    private class SplitScreenImpl implements LegacySplitScreen {
        @Override
        public boolean isMinimized() {
            return mMinimized;
        }

        @Override
        public boolean isHomeStackResizable() {
            return mHomeStackResizable;
        }

        /**
         * TODO: Remove usage from outside the shell.
         */
        @Override
        public DividerView getDividerView() {
            return LegacySplitScreenController.this.getDividerView();
        }

        @Override
        public boolean isDividerVisible() {
            boolean[] result = new boolean[1];
            try {
                mMainExecutor.executeBlocking(() -> {
                    result[0] = LegacySplitScreenController.this.isDividerVisible();
                });
            } catch (InterruptedException e) {
                Slog.e(TAG, "Failed to get divider visible");
            }
            return result[0];
        }

        @Override
        public void onKeyguardVisibilityChanged(boolean isShowing) {
            mMainExecutor.execute(() -> {
                LegacySplitScreenController.this.onKeyguardVisibilityChanged(isShowing);
            });
        }

        @Override
        public void setMinimized(boolean minimized) {
            mMainExecutor.execute(() -> {
                LegacySplitScreenController.this.setMinimized(minimized);
            });
        }

        @Override
        public void onUndockingTask() {
            mMainExecutor.execute(() -> {
                LegacySplitScreenController.this.onUndockingTask();
            });
        }

        @Override
        public void onAppTransitionFinished() {
            mMainExecutor.execute(() -> {
                LegacySplitScreenController.this.onAppTransitionFinished();
            });
        }

        @Override
        public void registerInSplitScreenListener(Consumer<Boolean> listener) {
            mMainExecutor.execute(() -> {
                LegacySplitScreenController.this.registerInSplitScreenListener(listener);
            });
        }

        @Override
        public void unregisterInSplitScreenListener(Consumer<Boolean> listener) {
            mMainExecutor.execute(() -> {
                LegacySplitScreenController.this.unregisterInSplitScreenListener(listener);
            });
        }

        @Override
        public void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener) {
            mMainExecutor.execute(() -> {
                LegacySplitScreenController.this.registerBoundsChangeListener(listener);
            });
        }

        @Override
        public WindowContainerToken getSecondaryRoot() {
            WindowContainerToken[] result = new WindowContainerToken[1];
            try {
                mMainExecutor.executeBlocking(() -> {
                    result[0] = LegacySplitScreenController.this.getSecondaryRoot();
                });
            } catch (InterruptedException e) {
                Slog.e(TAG, "Failed to get secondary root");
            }
            return result[0];
        }

        @Override
        public boolean splitPrimaryTask() {
            boolean[] result = new boolean[1];
            try {
                mMainExecutor.executeBlocking(() -> {
                    result[0] = LegacySplitScreenController.this.splitPrimaryTask();
                });
            } catch (InterruptedException e) {
                Slog.e(TAG, "Failed to split primary task");
            }
            return result[0];
        }

        @Override
        public void dismissSplitToPrimaryTask() {
            mMainExecutor.execute(() -> {
                LegacySplitScreenController.this.dismissSplitToPrimaryTask();
            });
        }

        @Override
        public void dump(PrintWriter pw) {
            try {
                mMainExecutor.executeBlocking(() -> {
                    LegacySplitScreenController.this.dump(pw);
                });
            } catch (InterruptedException e) {
                Slog.e(TAG, "Failed to dump LegacySplitScreenController in 2s");
            }
        }
    }
}
Loading