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

Commit 21549e7d authored by Hongwei Wang's avatar Hongwei Wang Committed by Android (Google) Code Review
Browse files

Merge "Implement enable_pip_ui_state_callback_on_entering" into main

parents cd05fe7a 6fbb81d6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7225,6 +7225,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) {
+28 −0
Original line number Diff line number Diff line
@@ -23,12 +23,16 @@ import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTI
import static com.android.wm.shell.pip.PipAnimationController.isInPipDirection;

import android.annotation.Nullable;
import android.app.ActivityTaskManager;
import android.app.Flags;
import android.app.PictureInPictureParams;
import android.app.PictureInPictureUiState;
import android.app.TaskInfo;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.TransitionInfo;
@@ -37,11 +41,13 @@ import android.window.WindowContainerTransaction;

import androidx.annotation.NonNull;

import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
import com.android.wm.shell.common.pip.PipBoundsState;
import com.android.wm.shell.common.pip.PipMenuController;
import com.android.wm.shell.common.split.SplitScreenUtils;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;

@@ -181,6 +187,17 @@ public abstract class PipTransitionController implements Transitions.TransitionH
            final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
            callback.onPipTransitionStarted(direction, pipBounds);
        }
        if (isInPipDirection(direction) && Flags.enablePipUiStateCallbackOnEntering()) {
            try {
                ActivityTaskManager.getService().onPictureInPictureUiStateChanged(
                        new PictureInPictureUiState.Builder()
                                .setEnteringPip(true)
                                .build());
            } catch (RemoteException | IllegalStateException e) {
                ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                        "Failed to set alert PiP state change.");
            }
        }
    }

    protected void sendOnPipTransitionFinished(
@@ -189,6 +206,17 @@ public abstract class PipTransitionController implements Transitions.TransitionH
            final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
            callback.onPipTransitionFinished(direction);
        }
        if (isInPipDirection(direction) && Flags.enablePipUiStateCallbackOnEntering()) {
            try {
                ActivityTaskManager.getService().onPictureInPictureUiStateChanged(
                        new PictureInPictureUiState.Builder()
                                .setEnteringPip(false)
                                .build());
            } catch (RemoteException | IllegalStateException e) {
                ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                        "Failed to set alert PiP state change.");
            }
        }
    }

    protected void sendOnPipTransitionCancelled(
Loading