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

Commit 0799ee7f authored by Wale Ogunwale's avatar Wale Ogunwale Committed by Android (Google) Code Review
Browse files

Merge "Added shared lib APIs for Launcher to use split-screen APIs." into sc-dev

parents cab4131e a5f9ba6c
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.shared.recents;

/**
 * Listener interface that Launcher attaches to SystemUI to get split-screen callbacks.
 */
oneway interface ISplitScreenListener {
    void onStagePositionChanged(int stage, int position);
    void onTaskStageChanged(int taskId, int stage);
}
 No newline at end of file
+48 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.shared.recents;

import android.app.PendingIntent;
import android.app.PictureInPictureParams;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
@@ -23,9 +24,11 @@ import android.graphics.Bitmap;
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.UserHandle;
import android.view.MotionEvent;

import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
import com.android.systemui.shared.recents.ISplitScreenListener;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteTransitionCompat;

@@ -202,4 +205,49 @@ interface ISystemUiProxy {

    /** Unegisters a RemoteTransitionCompat that will handle transitions. */
    void unregisterRemoteTransition(in RemoteTransitionCompat remoteTransition) = 33;

// SplitScreen APIs...copied from SplitScreen.java
    /**
     * Stage position isn't specified normally meaning to use what ever it is currently set to.
     */
    //int STAGE_POSITION_UNDEFINED = -1;
    /**
     * Specifies that a stage is positioned at the top half of the screen if
     * in portrait mode or at the left half of the screen if in landscape mode.
     */
    //int STAGE_POSITION_TOP_OR_LEFT = 0;
    /**
     * Specifies that a stage is positioned at the bottom half of the screen if
     * in portrait mode or at the right half of the screen if in landscape mode.
     */
    //int STAGE_POSITION_BOTTOM_OR_RIGHT = 1;

    /**
     * Stage type isn't specified normally meaning to use what ever the default is.
     * E.g. exit split-screen and launch the app in fullscreen.
     */
    //int STAGE_TYPE_UNDEFINED = -1;
    /**
     * The main stage type.
     * @see MainStage
     */
    //int STAGE_TYPE_MAIN = 0;
    /**
     * The side stage type.
     * @see SideStage
     */
    //int STAGE_TYPE_SIDE = 1;

    void registerSplitScreenListener(in ISplitScreenListener listener) = 34;
    void unregisterSplitScreenListener(in ISplitScreenListener listener) = 35;

    /** Hides the side-stage if it is currently visible. */
    void setSideStageVisibility(in boolean visible) = 36;
    /** Removes the split-screen stages. */
    void exitSplitScreen() = 37;
    void startTask(in int taskId, in int stage, in int position, in Bundle options) = 38;
    void startShortcut(in String packageName, in String shortcutId, in int stage, in int position,
            in Bundle options, in UserHandle user) = 39;
    void startIntent(
            in PendingIntent intent, in int stage, in int position, in Bundle options) = 40;
}
+138 −7
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_T

import android.annotation.FloatRange;
import android.app.ActivityTaskManager;
import android.app.PendingIntent;
import android.app.PictureInPictureParams;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -83,6 +84,7 @@ import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
import com.android.systemui.shared.recents.ISplitScreenListener;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -98,6 +100,7 @@ import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.transition.Transitions;

import java.io.FileDescriptor;
@@ -133,7 +136,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
    private final Context mContext;
    private final Optional<Pip> mPipOptional;
    private final Optional<Lazy<StatusBar>> mStatusBarOptionalLazy;
    private final Optional<LegacySplitScreen> mSplitScreenOptional;
    private final Optional<LegacySplitScreen> mLegacySplitScreenOptional;
    private final Optional<SplitScreen> mSplitScreenOptional;
    private SysUiState mSysUiState;
    private final Handler mHandler;
    private final Lazy<NavigationBarController> mNavBarControllerLazy;
@@ -263,7 +267,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
            }
            final long token = Binder.clearCallingIdentity();
            try {
                return mSplitScreenOptional.map(splitScreen ->
                return mLegacySplitScreenOptional.map(splitScreen ->
                        splitScreen.getDividerView().getNonMinimizedSplitScreenSecondaryBounds())
                        .orElse(null);
            } finally {
@@ -401,7 +405,7 @@ public class OverviewProxyService extends CurrentUserTracker implements

        @Override
        public void setSplitScreenMinimized(boolean minimized) {
            mSplitScreenOptional.ifPresent(
            mLegacySplitScreenOptional.ifPresent(
                    splitScreen -> splitScreen.setMinimized(minimized));
        }

@@ -559,6 +563,105 @@ public class OverviewProxyService extends CurrentUserTracker implements
            }
        }

        @Override
        public void registerSplitScreenListener(ISplitScreenListener listener) {
            if (!verifyCaller("registerSplitScreenListener")) {
                return;
            }
            mISplitScreenListener = listener;
            final long token = Binder.clearCallingIdentity();
            try {
                mSplitScreenOptional.ifPresent(
                        s -> s.registerSplitScreenListener(mSplitScreenListener));
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void unregisterSplitScreenListener(ISplitScreenListener listener) {
            if (!verifyCaller("unregisterSplitScreenListener")) {
                return;
            }
            mISplitScreenListener = null;
            final long token = Binder.clearCallingIdentity();
            try {
                mSplitScreenOptional.ifPresent(
                        s -> s.unregisterSplitScreenListener(mSplitScreenListener));
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void setSideStageVisibility(boolean visible) {
            if (!verifyCaller("setSideStageVisibility")) {
                return;
            }
            final long token = Binder.clearCallingIdentity();
            try {
                mSplitScreenOptional.ifPresent(s -> s.setSideStageVisibility(visible));
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void exitSplitScreen() {
            if (!verifyCaller("exitSplitScreen")) {
                return;
            }
            final long token = Binder.clearCallingIdentity();
            try {
                mSplitScreenOptional.ifPresent(s -> s.exitSplitScreen());
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void startTask(int taskId, int stage, int position, Bundle options) {
            if (!verifyCaller("startTask")) {
                return;
            }
            final long token = Binder.clearCallingIdentity();
            try {
                mSplitScreenOptional.ifPresent(
                        s -> s.startTask(taskId, stage, position, options));
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void startShortcut(String packageName, String shortcutId, int stage, int position,
                Bundle options, UserHandle user) {
            if (!verifyCaller("startShortcut")) {
                return;
            }
            final long token = Binder.clearCallingIdentity();
            try {
                mSplitScreenOptional.ifPresent(s ->
                        s.startShortcut(packageName, shortcutId, stage, position, options, user));
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void startIntent(PendingIntent intent, int stage, int position, Bundle options) {
            if (!verifyCaller("startIntent")) {
                return;
            }
            final long token = Binder.clearCallingIdentity();
            try {
                mSplitScreenOptional.ifPresent(s ->
                        s.startIntent(intent, stage, position, options));
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        private boolean verifyCaller(String reason) {
            final int callerId = Binder.getCallingUserHandle().getIdentifier();
            if (callerId != mCurrentBoundedUserId) {
@@ -658,6 +761,32 @@ public class OverviewProxyService extends CurrentUserTracker implements
    private final IBinder.DeathRecipient mOverviewServiceDeathRcpt
            = this::cleanupAfterDeath;

    private ISplitScreenListener mISplitScreenListener;
    private final SplitScreen.SplitScreenListener mSplitScreenListener =
            new SplitScreen.SplitScreenListener() {
        @Override
        public void onStagePositionChanged(int stage, int position) {
            try {
                if (mISplitScreenListener != null) {
                    mISplitScreenListener.onStagePositionChanged(stage, position);
                }
            } catch (RemoteException e) {
                Log.e(TAG_OPS, "onStagePositionChanged", e);
            }
        }

        @Override
        public void onTaskStageChanged(int taskId, int stage) {
            try {
                if (mISplitScreenListener != null) {
                    mISplitScreenListener.onTaskStageChanged(taskId, stage);
                }
            } catch (RemoteException e) {
                Log.e(TAG_OPS, "onTaskStageChanged", e);
            }
        }
    };

    @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
    @Inject
    public OverviewProxyService(Context context, CommandQueue commandQueue,
@@ -665,7 +794,8 @@ public class OverviewProxyService extends CurrentUserTracker implements
            NavigationModeController navModeController,
            NotificationShadeWindowController statusBarWinController, SysUiState sysUiState,
            Optional<Pip> pipOptional,
            Optional<LegacySplitScreen> splitScreenOptional,
            Optional<LegacySplitScreen> legacySplitScreenOptional,
            Optional<SplitScreen> splitScreenOptional,
            Optional<Lazy<StatusBar>> statusBarOptionalLazy,
            Optional<OneHanded> oneHandedOptional,
            BroadcastDispatcher broadcastDispatcher,
@@ -718,9 +848,10 @@ public class OverviewProxyService extends CurrentUserTracker implements
        });
        mCommandQueue = commandQueue;

        splitScreenOptional.ifPresent(splitScreen ->
                splitScreen.registerBoundsChangeListener(mSplitScreenBoundsChangeListener));
        mSplitScreenOptional = splitScreenOptional;
        legacySplitScreenOptional.ifPresent(splitScreen ->
                splitScreen.registerBoundsChangeListener(mSplitScreenBoundsChangeListener));
        mLegacySplitScreenOptional = legacySplitScreenOptional;

        // Listen for user setup
        startTracking();
@@ -835,7 +966,7 @@ public class OverviewProxyService extends CurrentUserTracker implements
        startConnectionToCurrentUser();

        // Clean up the minimized state if launcher dies
        mSplitScreenOptional.ifPresent(
        mLegacySplitScreenOptional.ifPresent(
                splitScreen -> splitScreen.setMinimized(false));

        // Clean up any registered remote transitions
+5 −3
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.transition.Transitions;

import org.junit.Before;
@@ -71,7 +72,8 @@ public class OverviewProxyServiceTest extends SysuiTestCase {
    @Mock private NavigationModeController mMockNavModeController;
    @Mock private NotificationShadeWindowController mMockStatusBarWinController;
    @Mock private Optional<Pip> mMockPipOptional;
    @Mock private Optional<LegacySplitScreen> mMockSplitScreenOptional;
    @Mock private Optional<LegacySplitScreen> mMockLegacySplitScreenOptional;
    @Mock private Optional<SplitScreen> mMockSplitScreenOptional;
    @Mock private Optional<Lazy<StatusBar>> mMockStatusBarOptionalLazy;
    @Mock private Optional<com.android.wm.shell.onehanded.OneHanded> mMockOneHandedOptional;
    @Mock private PackageManager mPackageManager;
@@ -89,8 +91,8 @@ public class OverviewProxyServiceTest extends SysuiTestCase {

        mSpiedOverviewProxyService = spy(new OverviewProxyService(mSpiedContext, mMockCommandQueue,
                mMockNavBarControllerLazy, mMockNavModeController, mMockStatusBarWinController,
                mMockSysUiState, mMockPipOptional, mMockSplitScreenOptional,
                mMockStatusBarOptionalLazy, mMockOneHandedOptional,
                mMockSysUiState, mMockPipOptional, mMockLegacySplitScreenOptional,
                mMockSplitScreenOptional, mMockStatusBarOptionalLazy, mMockOneHandedOptional,
                mMockBroadcastDispatcher, mMockTransitions));
    }