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

Commit 5577b8f5 authored by Evan Rosky's avatar Evan Rosky Committed by Android (Google) Code Review
Browse files

Merge "Scaffolding for Shell Transitions"

parents 41bbc40b 0dd1586b
Loading
Loading
Loading
Loading
+63 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 android.window;

import android.view.SurfaceControl;
import android.window.TransitionInfo;
import android.window.WindowContainerTransaction;

/**
 * Implemented by WMShell to initiate and play transition animations.
 * The flow (with {@link IWindowOrganizerController}) looks like this:
 * <p><ol>
 *  <li>Core starts an activity and calls {@link #requestStartTransition}
 *  <li>This TransitionPlayer impl does whatever, then calls
 *      {@link IWindowOrganizerController#startTransition} to tell Core to formally start (until
 *      this happens, Core will collect changes on the transition, but won't consider it ready to
 *      animate).
 *  <li>Once all collected changes on the transition have finished drawing, Core will then call
 *      {@link #onTransitionReady} here to delegate the actual animation.
 *  <li>Once this TransitionPlayer impl finishes animating, it notifies Core via
 *      {@link IWindowOrganizerController#finishTransition}. At this point, ITransitionPlayer's
 *      responsibilities end.
 * </ul>
 *
 * {@hide}
 */
oneway interface ITransitionPlayer {

    /**
     * Called when all participants of a transition are ready to animate. This is in response to
     * {@link IWindowOrganizerController#startTransition}.
     *
     * @param transitionToken An identifying token for the transition that is now ready to animate.
     * @param info A collection of all the changes encapsulated by this transition.
     * @param t A surface transaction containing the surface state prior to animating.
     */
    void onTransitionReady(in IBinder transitionToken, in TransitionInfo info,
            in SurfaceControl.Transaction t);

    /**
     * Called when something in WMCore requires a transition to play -- for example when an Activity
     * is started in a new Task.
     *
     * @param type The {@link WindowManager#TransitionType} of the transition to start.
     * @param transitionToken An identifying token for the transition that needs to be started.
     *                        Pass this to {@link IWindowOrganizerController#startTransition}.
     */
    void requestStartTransition(int type, in IBinder transitionToken);
}
+32 −0
Original line number Diff line number Diff line
@@ -18,8 +18,10 @@ package android.window;

import android.view.SurfaceControl;

import android.os.IBinder;
import android.window.IDisplayAreaOrganizerController;
import android.window.ITaskOrganizerController;
import android.window.ITransitionPlayer;
import android.window.IWindowContainerTransactionCallback;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -45,6 +47,30 @@ interface IWindowOrganizerController {
    int applySyncTransaction(in WindowContainerTransaction t,
            in IWindowContainerTransactionCallback callback);

    /**
     * Starts a transition.
     * @param type The transition type.
     * @param transitionToken A token associated with the transition to start. If null, a new
     *                        transition will be created of the provided type.
     * @param t Operations that are part of the transition.
     * @return a token representing the transition. This will just be transitionToken if it was
     *         non-null.
     */
    IBinder startTransition(int type, in @nullable IBinder transitionToken,
            in @nullable WindowContainerTransaction t);

    /**
     * Finishes a transition. This must be called for all created transitions.
     * @param transitionToken Which transition to finish
     * @param t Changes to make before finishing but in the same SF Transaction. Can be null.
     * @param callback Called when t is finished applying.
     * @return An ID for the sync operation (see {@link #applySyncTransaction}. This will be
     *         negative if no sync transaction was attached (null t or callback)
     */
    int finishTransition(in IBinder transitionToken,
            in @nullable WindowContainerTransaction t,
            in IWindowContainerTransactionCallback callback);

    /** @return An interface enabling the management of task organizers. */
    ITaskOrganizerController getTaskOrganizerController();

@@ -61,4 +87,10 @@ interface IWindowOrganizerController {
     * @return true if the screenshot was successful, false otherwise.
     */
    boolean takeScreenshot(in WindowContainerToken token, out SurfaceControl outSurfaceControl);

    /**
     * Registers a transition player with Core. There is only one of these at a time and calling
     * this will replace the existing one if set.
     */
    void registerTransitionPlayer(in ITransitionPlayer player);
}
+20 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 android.window;

parcelable TransitionInfo;
parcelable TransitionInfo.Change;
+290 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 android.window;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.SurfaceControl;
import android.view.WindowManager;

import java.util.ArrayList;
import java.util.List;

/**
 * Used to communicate information about what is changing during a transition to a TransitionPlayer.
 * @hide
 */
public final class TransitionInfo implements Parcelable {

    /** No transition mode. This is a placeholder, don't use this as an actual mode. */
    public static final int TRANSIT_NONE = 0;

    /** The container didn't exist before but will exist and be visible after. */
    public static final int TRANSIT_OPEN = 1;

    /** The container existed and was visible before but won't exist after. */
    public static final int TRANSIT_CLOSE = 2;

    /** The container existed before but was invisible and will be visible after. */
    public static final int TRANSIT_SHOW = 3;

    /** The container is going from visible to invisible but it will still exist after. */
    public static final int TRANSIT_HIDE = 4;

    /** The container exists and is visible before and after but it changes. */
    public static final int TRANSIT_CHANGE = 5;

    /** @hide */
    @IntDef(prefix = { "TRANSIT_" }, value = {
            TRANSIT_NONE,
            TRANSIT_OPEN,
            TRANSIT_CLOSE,
            TRANSIT_SHOW,
            TRANSIT_HIDE,
            TRANSIT_CHANGE
    })
    public @interface TransitionMode {}

    private final @WindowManager.TransitionType int mType;
    private final ArrayList<Change> mChanges = new ArrayList<>();

    /** @hide */
    public TransitionInfo(@WindowManager.TransitionType int type) {
        mType = type;
    }

    private TransitionInfo(Parcel in) {
        mType = in.readInt();
        in.readList(mChanges, null /* classLoader */);
    }

    @Override
    /** @hide */
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeInt(mType);
        dest.writeList(mChanges);
    }

    @NonNull
    public static final Creator<TransitionInfo> CREATOR =
            new Creator<TransitionInfo>() {
                @Override
                public TransitionInfo createFromParcel(Parcel in) {
                    return new TransitionInfo(in);
                }

                @Override
                public TransitionInfo[] newArray(int size) {
                    return new TransitionInfo[size];
                }
            };

    @Override
    /** @hide */
    public int describeContents() {
        return 0;
    }

    public int getType() {
        return mType;
    }

    @NonNull
    public List<Change> getChanges() {
        return mChanges;
    }

    /**
     * @return the Change that a window is undergoing or {@code null} if not directly
     * represented.
     */
    @Nullable
    public Change getChange(@NonNull WindowContainerToken token) {
        for (int i = mChanges.size() - 1; i >= 0; --i) {
            if (mChanges.get(i).mContainer == token) {
                return mChanges.get(i);
            }
        }
        return null;
    }

    /**
     * Add a {@link Change} to this transition.
     */
    public void addChange(@NonNull Change change) {
        mChanges.add(change);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{t=" + mType + " c=[");
        for (int i = 0; i < mChanges.size(); ++i) {
            if (i > 0) {
                sb.append(',');
            }
            sb.append(mChanges.get(i));
        }
        sb.append("]}");
        return sb.toString();
    }

    /** Converts a transition mode/action to its string representation. */
    @NonNull
    public static String modeToString(@TransitionMode int mode) {
        switch(mode) {
            case TRANSIT_NONE: return "NONE";
            case TRANSIT_OPEN: return "OPEN";
            case TRANSIT_CLOSE: return "CLOSE";
            case TRANSIT_SHOW: return "SHOW";
            case TRANSIT_HIDE: return "HIDE";
            case TRANSIT_CHANGE: return "CHANGE";
            default: return "<unknown:" + mode + ">";
        }
    }

    /** Represents the change a WindowContainer undergoes during a transition */
    public static final class Change implements Parcelable {
        private final WindowContainerToken mContainer;
        private WindowContainerToken mParent;
        private final SurfaceControl mLeash;
        private int mMode = TRANSIT_NONE;
        private final Rect mStartBounds = new Rect();
        private final Rect mEndBounds = new Rect();

        public Change(@NonNull WindowContainerToken container, @NonNull SurfaceControl leash) {
            mContainer = container;
            mLeash = leash;
        }

        private Change(Parcel in) {
            mContainer = WindowContainerToken.CREATOR.createFromParcel(in);
            mParent = in.readParcelable(WindowContainerToken.class.getClassLoader());
            mLeash = new SurfaceControl();
            mLeash.readFromParcel(in);
            mMode = in.readInt();
            mStartBounds.readFromParcel(in);
            mEndBounds.readFromParcel(in);
        }

        /** Sets the parent of this change's container. The parent must be a participant or null. */
        public void setParent(@Nullable WindowContainerToken parent) {
            mParent = parent;
        }

        /** Sets the transition mode for this change */
        public void setMode(@TransitionMode int mode) {
            mMode = mode;
        }

        /** Sets the bounds this container occupied before the change */
        public void setStartBounds(@Nullable Rect rect) {
            mStartBounds.set(rect);
        }

        /** Sets the bounds this container will occupy after the change */
        public void setEndBounds(@Nullable Rect rect) {
            mEndBounds.set(rect);
        }

        /** @return the container that is changing */
        @NonNull
        public WindowContainerToken getContainer() {
            return mContainer;
        }

        /**
         * @return the parent of the changing container. This is the parent within the participants,
         * not necessarily the actual parent.
         */
        @Nullable
        public WindowContainerToken getParent() {
            return mParent;
        }

        /** @return which action this change represents. */
        public @TransitionMode int getMode() {
            return mMode;
        }

        /**
         * @return the bounds of the container before the change. It may be empty if the container
         * is coming into existence.
         */
        @NonNull
        public Rect getStartBounds() {
            return mStartBounds;
        }

        /**
         * @return the bounds of the container after the change. It may be empty if the container
         * is disappearing.
         */
        @NonNull
        public Rect getEndBounds() {
            return mEndBounds;
        }

        /** @return the leash or surface to animate for this container */
        @NonNull
        public SurfaceControl getLeash() {
            return mLeash;
        }

        @Override
        /** @hide */
        public void writeToParcel(@NonNull Parcel dest, int flags) {
            mContainer.writeToParcel(dest, flags);
            dest.writeParcelable(mParent, 0);
            mLeash.writeToParcel(dest, flags);
            dest.writeInt(mMode);
            mStartBounds.writeToParcel(dest, flags);
            mEndBounds.writeToParcel(dest, flags);
        }

        @NonNull
        public static final Creator<Change> CREATOR =
                new Creator<Change>() {
                    @Override
                    public Change createFromParcel(Parcel in) {
                        return new Change(in);
                    }

                    @Override
                    public Change[] newArray(int size) {
                        return new Change[size];
                    }
                };

        @Override
        /** @hide */
        public int describeContents() {
            return 0;
        }

        @Override
        public String toString() {
            return "{" + mContainer + "(" + mParent + ") leash=" + mLeash
                    + " m=" + modeToString(mMode) + " sb=" + mStartBounds
                    + " eb=" + mEndBounds + "}";
        }
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -77,6 +77,11 @@ public final class WindowContainerToken implements Parcelable {
        return mRealToken.asBinder().hashCode();
    }

    @Override
    public String toString() {
        return "WCT{" + mRealToken + "}";
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof WindowContainerToken)) {
Loading