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

Commit 6ad6b5c3 authored by Todd Lee's avatar Todd Lee
Browse files

Update origin remote transitions/sessions for better returns

This change adds the capability to support customized return
animation behaviour based on transition filters that can be
provided to create the origin transition session/record.

Instead of having a single return animation (UI/player) that
gets configured with two standard transition filters (one for
predictive back/takeover, one for close) this change provides
for the flexibility of different returns, with corresponding
filters etc.

Bug: b/436673180
Test: atest PlatformAnimationLibCoreTests
Flag: NONE minor changes/refactoring

Change-Id: I7c19bf3ac40384cf27a30e1452ab49d8e8e0c7b2
parent f4fe424c
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -104,7 +104,12 @@ public class OriginRemoteTransition extends IRemoteTransition.Stub implements
            SurfaceControl.Transaction t,
            IBinder mergeTarget,
            IRemoteTransitionFinishedCallback finishCallback) {
        logD("mergeAnimation - " + info);
        logD("mergeAnimation for: "
                + transition
                + " target: "
                + mergeTarget
                + " info: "
                + info);
        cancel();
    }

+87 −23
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.animation;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.ActivityOptions.LaunchCookie;
@@ -31,12 +32,17 @@ import android.os.RemoteException;
import android.util.Log;
import android.window.IRemoteTransition;
import android.window.RemoteTransition;
import android.window.TransitionFilter;

import com.android.systemui.animation.OriginRemoteTransition.TransitionPlayer;
import com.android.systemui.animation.shared.IOriginTransitions;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.function.Supplier;
@@ -63,7 +69,7 @@ public class OriginTransitionSession {
    @Nullable private final IOriginTransitions mOriginTransitions;
    private final Predicate<RemoteTransition> mIntentStarter;
    @Nullable private final IRemoteTransition mEntryTransition;
    @Nullable private final IRemoteTransition mExitTransition;
    @NonNull private final Map<IRemoteTransition, TransitionFilter> mExitTransitionMap;
    private final AtomicInteger mState = new AtomicInteger(NOT_STARTED);
    @Nullable private RemoteTransition mOriginTransition;

@@ -72,12 +78,12 @@ public class OriginTransitionSession {
            @Nullable IOriginTransitions originTransitions,
            Predicate<RemoteTransition> intentStarter,
            @Nullable IRemoteTransition entryTransition,
            @Nullable IRemoteTransition exitTransition) {
            @NonNull Map<IRemoteTransition, TransitionFilter> exitTransitionMap) {
        mName = name;
        mOriginTransitions = originTransitions;
        mIntentStarter = intentStarter;
        mEntryTransition = entryTransition;
        mExitTransition = exitTransition;
        mExitTransitionMap = exitTransitionMap;
        if (hasExitTransition() && !hasEntryTransition()) {
            throw new IllegalArgumentException(
                    "Entry transition must be supplied if you want to play an exit transition!");
@@ -100,11 +106,25 @@ public class OriginTransitionSession {
        if (hasEntryTransition() && hasExitTransition()) {
            logD("start: starting with entry and exit transition.");
            try {
                if (!mExitTransitionMap.isEmpty()) {
                    int index = 0;
                    final List<RemoteTransition> transitions = new ArrayList<>();
                    final List<TransitionFilter> filters = new ArrayList<>();
                    for (Map.Entry<IRemoteTransition, TransitionFilter> entry
                            : mExitTransitionMap.entrySet()) {
                        transitions.add(new RemoteTransition(
                                entry.getKey(), mName + "-exit:" + index));
                        filters.add(entry.getValue());
                        logD("mapping exit transition[" + index + "]: "
                                + entry.getKey() + " and filter: " + entry.getValue());
                    }
                    remoteTransition =
                            mOriginTransition =
                                mOriginTransitions.makeOriginTransition(
                                    mOriginTransitions.makeOriginTransitionWithReturnFilters(
                                        new RemoteTransition(mEntryTransition, mName + "-entry"),
                                        new RemoteTransition(mExitTransition, mName + "-exit"));
                                        transitions,
                                        filters);
                }
            } catch (Exception e) {
                logE("Unable to create origin transition!", e);
            }
@@ -165,8 +185,10 @@ public class OriginTransitionSession {
        if (mEntryTransition instanceof OriginRemoteTransition) {
            ((OriginRemoteTransition) mEntryTransition).cancel();
        }
        if (mExitTransition instanceof OriginRemoteTransition) {
            ((OriginRemoteTransition) mExitTransition).cancel();
        for (IRemoteTransition transition : mExitTransitionMap.keySet()) {
            if (transition instanceof OriginRemoteTransition) {
                ((OriginRemoteTransition) transition).cancel();
            }
        }
    }

@@ -175,7 +197,7 @@ public class OriginTransitionSession {
    }

    private boolean hasExitTransition() {
        return mOriginTransitions != null && mExitTransition != null;
        return mOriginTransitions != null && !mExitTransitionMap.isEmpty();
    }

    private void setupTransactionQueues() {
@@ -189,8 +211,10 @@ public class OriginTransitionSession {
        if (mEntryTransition != null && mEntryTransition instanceof OriginRemoteTransition) {
            ((OriginRemoteTransition) mEntryTransition).setShellTransactionToken(shellApplyToken);
        }
        if (mExitTransition != null && mExitTransition instanceof OriginRemoteTransition) {
            ((OriginRemoteTransition) mExitTransition).setShellTransactionToken(shellApplyToken);
        for (IRemoteTransition transition : mExitTransitionMap.keySet()) {
            if (transition instanceof OriginRemoteTransition) {
                ((OriginRemoteTransition) transition).setShellTransactionToken(shellApplyToken);
            }
        }
    }

@@ -230,7 +254,8 @@ public class OriginTransitionSession {
        private final Context mContext;
        @Nullable private final IOriginTransitions mOriginTransitions;
        @Nullable private Supplier<IRemoteTransition> mEntryTransitionSupplier;
        @Nullable private Supplier<IRemoteTransition> mExitTransitionSupplier;
        private final Map<IRemoteTransition, TransitionFilter> mReturnTransitionMap =
                new HashMap<>();
        private Handler mHandler = new Handler(Looper.getMainLooper());
        private String mName;
        @Nullable private Predicate<RemoteTransition> mIntentStarter;
@@ -325,21 +350,55 @@ public class OriginTransitionSession {

        /** Add an exit transition to the builder. */
        public Builder withExitTransition(IRemoteTransition transition) {
            mExitTransitionSupplier = () -> transition;
            mReturnTransitionMap.clear();
            mReturnTransitionMap.put(transition, null);
            return this;
        }

        /** Add an origin exit transition to the builder. */
        public Builder withExitTransition(
                UIComponent exitTarget, TransitionPlayer exitPlayer) {
            mExitTransitionSupplier =
                    () ->
                            new OriginRemoteTransition(
            mReturnTransitionMap.clear();
            mReturnTransitionMap.put(new OriginRemoteTransition(
                                        mContext,
                                        /* isEntry= */ false,
                                        exitTarget,
                                        exitPlayer,
                                    mHandler);
                                        mHandler), null);
            return this;
        }

        /** Add an exit transition/filter to the builder. */
        public Builder addExitTransitionWithFilter(
                IRemoteTransition transition,
                TransitionFilter filter) {
            if (mReturnTransitionMap.size() == 1
                    && mReturnTransitionMap.entrySet().contains(null)) {
                Log.w(TAG, "Exit transition already set using `withExitTransition()` "
                        + "- ignoring list addition");
                return this;
            }
            mReturnTransitionMap.put(transition, filter);
            return this;
        }

        /** Add an exit transition/filter to the builder. */
        public Builder addExitTransitionWithFilter(
                UIComponent exitTarget,
                TransitionPlayer exitPlayer,
                TransitionFilter filter) {
            if (mReturnTransitionMap.size() == 1
                    && mReturnTransitionMap.entrySet().contains(null)) {
                Log.w(TAG, "Exit transition already set using `withExitTransition()` "
                        + "- ignoring list addition");
                return this;
            }
            mReturnTransitionMap.put(new OriginRemoteTransition(
                    mContext,
                    /* isEntry= */ false,
                    exitTarget,
                    exitPlayer,
                    mHandler), filter);
            return this;
        }

@@ -354,12 +413,17 @@ public class OriginTransitionSession {
            if (mIntentStarter == null) {
                throw new IllegalArgumentException("No intent, pending intent, or intent starter!");
            }

            final Map<IRemoteTransition, TransitionFilter> returnTransitionMap =
                    new HashMap<>(mReturnTransitionMap);
            mReturnTransitionMap.clear();

            return new OriginTransitionSession(
                    mName,
                    mOriginTransitions,
                    mIntentStarter,
                    mEntryTransitionSupplier == null ? null : mEntryTransitionSupplier.get(),
                    mExitTransitionSupplier == null ? null : mExitTransitionSupplier.get());
                    returnTransitionMap);
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -270,7 +270,7 @@ public class ViewUIComponent implements UIComponent {
    }

    private void setVisible(boolean visible) {
        logD("setVisibility: " + visible);
        logD("setVisibility: " + visible + " (attached: " + isAttachedToLeash() + ")");
        if (isAttachedToLeash()) {
            mVisibleOverride = visible;
            postDraw();
+313 −110

File changed.

Preview size limit exceeded, changes collapsed.

+18 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.animation.shared;

import android.window.RemoteTransition;
import android.window.TransitionFilter;

/**
 * An interface for an app to link a launch transition and a return transition together into an
@@ -46,4 +47,21 @@ interface IOriginTransitions {
     * Returns the token to be used as the default `apply` token with SurfaceControl.Transaction.
     */
    IBinder getDefaultTransactionApplyToken() = 3;

    /**
     * Create a new "origin transition" which wraps a launch transition and a set of possible
     * return transitions (where the return transition options are defined by a pair of lists -
     * the first specifying the set of returns and the second the corresponding filters).
     * The returned {@link RemoteTransition} is expected to be passed to
     * {@link ActivityOptions#makeRemoteTransition(RemoteTransition)} to create an
     * {@link ActivityOptions} and being used to launch an intent. When being used with
     * {@link ActivityOptions}, the launch transition will be triggered for launching the intent,
     * and the return transitions will be remembered with the selected one being triggered for
     * returning from the launched activity based on filter matching.
     * Note that the list elements (filters/transitions) will be paired in order, that is the
     * first filter will correspond to the first transition and so on. The lists must be
     * non-empty and of matching length otherwise an exception will be thrown.
     */
    RemoteTransition makeOriginTransitionWithReturnFilters(in RemoteTransition launchTransition,
            in List<RemoteTransition> returnTransitions, in List<TransitionFilter> returnFilters) = 4;
}
Loading