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

Commit 6fbb81d6 authored by Hongwei Wang's avatar Hongwei Wang
Browse files

Implement enable_pip_ui_state_callback_on_entering

- It's sent from PipTransitionController when we start and finish the
  animation
- Removed the restriction that onPictureInPictureUiStateChanged can only
  be sent to a pinned task, since this entering PiP callback would be
  received when the task is still in full-screen

Note that there is no isExitingPip API being added here since
- apps normally do not restore overlays such as video controls when
  exiting from PiP
- if apps do want to restore the overlays, it maybe preferred to do that
  in onPictureInPictureModeChanged(isInPictureInPictureMode=false)
  callback rather than the beginning of exit PiP animation

Bug: 303718131
Video: http://recall/-/aaaaaabFQoRHlzixHdtY/dXf5BdzkfR4i2ZNdTLJSaD
Video: http://recall/-/aaaaaabFQoRHlzixHdtY/ho9HTL5X7mneQoJMiHCBYY
Flag: ENABLE_PIP_UI_STATE_CALLBACK_ON_ENTERING
Test: manually, see videos
Test: atest PinnedStackTests
Change-Id: I3137b9c1505443efb633d086fbf6ceee477a4b73
parent 3bc09207
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7173,6 +7173,7 @@ package android.app {
  public final class PictureInPictureUiState implements android.os.Parcelable {
    method public int describeContents();
    method @FlaggedApi("android.app.enable_pip_ui_state_callback_on_entering") public boolean isEnteringPip();
    method public boolean isStashed();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.app.PictureInPictureUiState> CREATOR;
+3 −1
Original line number Diff line number Diff line
@@ -332,8 +332,10 @@ interface IActivityTaskManager {

    /**
     * When the Picture-in-picture state has changed.
     * @param pipState the {@link PictureInPictureUiState} is sent to current pip task if there is
     * any -or- the top most task (state like entering PiP does not require a pinned task).
     */
    void onPictureInPictureStateChanged(in PictureInPictureUiState pipState);
    void onPictureInPictureUiStateChanged(in PictureInPictureUiState pipState);

    /**
     * Re-attach navbar to the display during a recents transition.
+82 −6
Original line number Diff line number Diff line
@@ -16,8 +16,10 @@

package android.app;

import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.content.res.Configuration;
import android.os.Parcel;
import android.os.Parcelable;

@@ -28,23 +30,30 @@ import java.util.Objects;
 */
public final class PictureInPictureUiState implements Parcelable {

    private boolean mIsStashed;
    private final boolean mIsStashed;
    private final boolean mIsEnteringPip;

    /** {@hide} */
    PictureInPictureUiState(Parcel in) {
        mIsStashed = in.readBoolean();
        mIsEnteringPip = in.readBoolean();
    }

    /** {@hide} */
    @TestApi
    public PictureInPictureUiState(boolean isStashed) {
        this(isStashed, false /* isEnteringPip */);
    }

    private PictureInPictureUiState(boolean isStashed, boolean isEnteringPip) {
        mIsStashed = isStashed;
        mIsEnteringPip = isEnteringPip;
    }

    /**
     * Returns whether Picture-in-Picture is stashed or not. A stashed PiP means it is only
     * partially visible to the user, with some parts of it being off-screen. This is usually
     * an UI state that is triggered by the user, such as flinging the PiP to the edge or letting go
     * partially visible to the user, with some parts of it being off-screen. This is usually a
     * UI state that is triggered by the user, such as flinging the PiP to the edge or letting go
     * of PiP while dragging partially off-screen.
     *
     * Developers can use this in conjunction with
@@ -61,17 +70,44 @@ public final class PictureInPictureUiState implements Parcelable {
        return mIsStashed;
    }

    /**
     * Returns {@code true} if the app is going to enter Picture-in-Picture (PiP) mode.
     *
     * This state is associated with the entering PiP animation. When that animation starts,
     * whether via auto enter PiP or calling
     * {@link Activity#enterPictureInPictureMode(PictureInPictureParams)} explicitly, app can expect
     * {@link Activity#onPictureInPictureUiStateChanged(PictureInPictureUiState)} callback with
     * {@link #isEnteringPip()} to be {@code true} first,
     * followed by {@link Activity#onPictureInPictureModeChanged(boolean, Configuration)} when it
     * fully settles in PiP mode.
     *
     * When app receives the
     * {@link Activity#onPictureInPictureUiStateChanged(PictureInPictureUiState)} callback with
     * {@link #isEnteringPip()} being {@code true}, it's recommended to hide certain UI elements,
     * such as video controls, to archive a clean entering PiP animation.
     *
     * In case an application wants to restore the previously hidden UI elements when exiting
     * PiP, it is recommended to do that in
     * {@code onPictureInPictureModeChanged(isInPictureInPictureMode=false)} callback rather
     * than the beginning of exit PiP animation.
     */
    @FlaggedApi(Flags.FLAG_ENABLE_PIP_UI_STATE_CALLBACK_ON_ENTERING)
    public boolean isEnteringPip() {
        return mIsEnteringPip;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof PictureInPictureUiState)) return false;
        PictureInPictureUiState that = (PictureInPictureUiState) o;
        return Objects.equals(mIsStashed, that.mIsStashed);
        return mIsStashed == that.mIsStashed
                && mIsEnteringPip == that.mIsEnteringPip;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mIsStashed);
        return Objects.hash(mIsStashed, mIsEnteringPip);
    }

    @Override
@@ -82,6 +118,7 @@ public final class PictureInPictureUiState implements Parcelable {
    @Override
    public void writeToParcel(@NonNull Parcel out, int flags) {
        out.writeBoolean(mIsStashed);
        out.writeBoolean(mIsEnteringPip);
    }

    public static final @android.annotation.NonNull Creator<PictureInPictureUiState> CREATOR =
@@ -93,4 +130,43 @@ public final class PictureInPictureUiState implements Parcelable {
                    return new PictureInPictureUiState[size];
                }
            };

    /**
     * Builder class for {@link PictureInPictureUiState}.
     * @hide
     */
    @FlaggedApi(Flags.FLAG_ENABLE_PIP_UI_STATE_CALLBACK_ON_ENTERING)
    public static final class Builder {
        private boolean mIsStashed;
        private boolean mIsEnteringPip;

        /** Empty constructor. */
        public Builder() {
        }

        /**
         * Sets the {@link #mIsStashed} state.
         * @return The same {@link Builder} instance.
         */
        public Builder setStashed(boolean isStashed) {
            mIsStashed = isStashed;
            return this;
        }

        /**
         * Sets the {@link #mIsEnteringPip} state.
         * @return The same {@link Builder} instance.
         */
        public Builder setEnteringPip(boolean isEnteringPip) {
            mIsEnteringPip = isEnteringPip;
            return this;
        }

        /**
         * @return The constructed {@link PictureInPictureUiState} instance.
         */
        public PictureInPictureUiState build() {
            return new PictureInPictureUiState(mIsStashed, mIsEnteringPip);
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -260,7 +260,7 @@ public class PipBoundsState {

        mStashedState = stashedState;
        try {
            ActivityTaskManager.getService().onPictureInPictureStateChanged(
            ActivityTaskManager.getService().onPictureInPictureUiStateChanged(
                    new PictureInPictureUiState(stashedState != STASH_TYPE_NONE /* isStashed */)
            );
        } catch (RemoteException | IllegalStateException e) {
+0 −1
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import static android.util.RotationUtils.rotateBounds;

import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;
import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA;
Loading