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

Commit 5711b8fd authored by Hongwei Wang's avatar Hongwei Wang
Browse files

Move PIP/MW mode callbacks to be on the client side

We now infer the PIP/MW mode change from the new configuration.
Note also that both
- Activity#isInPictureInPictureMode
- Activity#isInMultiWindowMode
infer the current state from the configuration rather than querying
against the WM.

Also in this CL:
- When in removePinnedStackInSurfaceTransaction, keep the pinned stack
hidden till the windowing mode is set to fullscreen, this is to surpress
the attempt to set the activities to be started in reparenting
- When in ActivityRecord#shouldBeVisible, should take account the force
hidden flag, which is not actually in use before

Bug: 144097203
Bug: 142282126
Bug: 138329093
Test: atest ActivityLifecyclePipTests \
            ActivityLifecycleSplitScreenTests \
            ActivityLifecycleTopResumedStateTests \
            PinnedStackTests \
            SplitScreenTests \
            ActivityTaskManagerServiceTests \
            RecentsAnimationTest \
            AssistantStackTests \
            StartActivityTests \
            ActivityVisibilityTests \
            MultiDisplaySecurityTests \
            MultiDisplaySystemDecorationTests
Change-Id: Ibe032b5e50ba5c6d6bc44ebb54d07ac974ebe656
parent 265622e3
Loading
Loading
Loading
Loading
+2 −10
Original line number Diff line number Diff line
@@ -2748,11 +2748,7 @@ public class Activity extends ContextThemeWrapper
     * @return True if the activity is in multi-window mode.
     */
    public boolean isInMultiWindowMode() {
        try {
            return ActivityTaskManager.getService().isInMultiWindowMode(mToken);
        } catch (RemoteException e) {
        }
        return false;
        return mLastDispatchedIsInMultiWindowMode == Boolean.TRUE;
    }

    /**
@@ -2795,11 +2791,7 @@ public class Activity extends ContextThemeWrapper
     * @return True if the activity is in picture-in-picture mode.
     */
    public boolean isInPictureInPictureMode() {
        try {
            return ActivityTaskManager.getService().isInPictureInPictureMode(mToken);
        } catch (RemoteException e) {
        }
        return false;
        return mLastDispatchedIsInPictureInPictureMode == Boolean.TRUE;
    }

    /**
+47 −26
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package android.app;

import static android.app.ActivityManager.PROCESS_STATE_UNKNOWN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.servertransaction.ActivityLifecycleItem.ON_CREATE;
import static android.app.servertransaction.ActivityLifecycleItem.ON_DESTROY;
import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
@@ -407,6 +409,9 @@ public final class ActivityThread extends ClientTransactionHandler {
    @GuardedBy("this")
    private @Nullable Map<SafeCancellationTransport, CancellationSignal> mRemoteCancellations;

    private final Map<IBinder, Integer> mLastReportedWindowingMode = Collections.synchronizedMap(
            new ArrayMap<>());

    private static final class ProviderKey {
        final String authority;
        final int userId;
@@ -3324,6 +3329,8 @@ public final class ActivityThread extends ClientTransactionHandler {
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                mLastReportedWindowingMode.put(activity.getActivityToken(),
                        config.windowConfiguration.getWindowingMode());
            }
            r.setState(ON_CREATE);

@@ -3746,32 +3753,6 @@ public final class ActivityThread extends ClientTransactionHandler {
        }
    }

    @Override
    public void handleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode,
            Configuration overrideConfig) {
        final ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            final Configuration newConfig = new Configuration(mConfiguration);
            if (overrideConfig != null) {
                newConfig.updateFrom(overrideConfig);
            }
            r.activity.dispatchMultiWindowModeChanged(isInMultiWindowMode, newConfig);
        }
    }

    @Override
    public void handlePictureInPictureModeChanged(IBinder token, boolean isInPipMode,
            Configuration overrideConfig) {
        final ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            final Configuration newConfig = new Configuration(mConfiguration);
            if (overrideConfig != null) {
                newConfig.updateFrom(overrideConfig);
            }
            r.activity.dispatchPictureInPictureModeChanged(isInPipMode, newConfig);
        }
    }

    @Override
    public void handlePictureInPictureRequested(IBinder token) {
        final ActivityClientRecord r = mActivities.get(token);
@@ -5269,8 +5250,15 @@ public final class ActivityThread extends ClientTransactionHandler {
            throw e.rethrowFromSystemServer();
        }

        // Save the current windowing mode to be restored and compared to the new configuration's
        // windowing mode (needed because we update the last reported windowing mode when launching
        // an activity and we can't tell inside performLaunchActivity whether we are relaunching)
        final int oldWindowingMode = mLastReportedWindowingMode.getOrDefault(
                r.activity.getActivityToken(), WINDOWING_MODE_UNDEFINED);
        handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents,
                pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity");
        mLastReportedWindowingMode.put(r.activity.getActivityToken(), oldWindowingMode);
        handleWindowingModeChangeIfNeeded(r.activity, r.activity.mCurrentConfig);

        if (pendingActions != null) {
            // Only report a successful relaunch to WindowManager.
@@ -5553,6 +5541,10 @@ public final class ActivityThread extends ClientTransactionHandler {
            throw new IllegalArgumentException("Activity token not set. Is the activity attached?");
        }

        // multi-window / pip mode changes, if any, should be sent before the configuration change
        // callback, see also PinnedStackTests#testConfigurationChangeOrderDuringTransition
        handleWindowingModeChangeIfNeeded(activity, newConfig);

        boolean shouldChangeConfig = false;
        if (activity.mCurrentConfig == null) {
            shouldChangeConfig = true;
@@ -5746,6 +5738,35 @@ public final class ActivityThread extends ClientTransactionHandler {
        }
    }

    /**
     * Sends windowing mode change callbacks to {@link Activity} if applicable.
     *
     * See also {@link Activity#onMultiWindowModeChanged(boolean, Configuration)} and
     * {@link Activity#onPictureInPictureModeChanged(boolean, Configuration)}
     */
    private void handleWindowingModeChangeIfNeeded(Activity activity,
            Configuration newConfiguration) {
        final int newWindowingMode = newConfiguration.windowConfiguration.getWindowingMode();
        final IBinder token = activity.getActivityToken();
        final int oldWindowingMode = mLastReportedWindowingMode.getOrDefault(token,
                WINDOWING_MODE_UNDEFINED);
        if (oldWindowingMode == newWindowingMode) return;
        // PiP callback is sent before the MW one.
        if (newWindowingMode == WINDOWING_MODE_PINNED) {
            activity.dispatchPictureInPictureModeChanged(true, newConfiguration);
        } else if (oldWindowingMode == WINDOWING_MODE_PINNED) {
            activity.dispatchPictureInPictureModeChanged(false, newConfiguration);
        }
        final boolean wasInMultiWindowMode = WindowConfiguration.inMultiWindowMode(
                oldWindowingMode);
        final boolean nowInMultiWindowMode = WindowConfiguration.inMultiWindowMode(
                newWindowingMode);
        if (wasInMultiWindowMode != nowInMultiWindowMode) {
            activity.dispatchMultiWindowModeChanged(nowInMultiWindowMode, newConfiguration);
        }
        mLastReportedWindowingMode.put(token, newWindowingMode);
    }

    /**
     * Updates the application info.
     *
+0 −8
Original line number Diff line number Diff line
@@ -146,17 +146,9 @@ public abstract class ClientTransactionHandler {
    /** Deliver result from another activity. */
    public abstract void handleSendResult(IBinder token, List<ResultInfo> results, String reason);

    /** Deliver multi-window mode change notification. */
    public abstract void handleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode,
            Configuration overrideConfig);

    /** Deliver new intent. */
    public abstract void handleNewIntent(IBinder token, List<ReferrerIntent> intents);

    /** Deliver picture-in-picture mode change notification. */
    public abstract void handlePictureInPictureModeChanged(IBinder token, boolean isInPipMode,
            Configuration overrideConfig);

    /** Request that an activity enter picture-in-picture. */
    public abstract void handlePictureInPictureRequested(IBinder token);

+0 −2
Original line number Diff line number Diff line
@@ -300,8 +300,6 @@ interface IActivityTaskManager {

    void suppressResizeConfigChanges(boolean suppress);
    boolean moveTopActivityToPinnedStack(int stackId, in Rect bounds);
    boolean isInMultiWindowMode(in IBinder token);
    boolean isInPictureInPictureMode(in IBinder token);
    boolean enterPictureInPictureMode(in IBinder token, in PictureInPictureParams params);
    void setPictureInPictureParams(in IBinder token, in PictureInPictureParams params);
    void requestPictureInPictureMode(in IBinder token);
+10 −0
Original line number Diff line number Diff line
@@ -726,6 +726,16 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
        return windowingMode == WINDOWING_MODE_FREEFORM || windowingMode == WINDOWING_MODE_PINNED;
    }

    /**
     * Returns {@code true} if the windowingMode represents a window in multi-window mode.
     * I.e. sharing the screen with another activity.
     * @hide
     */
    public static boolean inMultiWindowMode(int windowingMode) {
        return windowingMode != WINDOWING_MODE_FULLSCREEN
                && windowingMode != WINDOWING_MODE_UNDEFINED;
    }

    /**
     * Returns true if the windowingMode represents a split window.
     * @hide
Loading