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

Commit 77be157a authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Add ability to filter remote animation adapter by activity type

Such that Launcher can choose not to use the remote animation
for assistant.

Test: Open assistant, close it
Test: go/wm-smoke

Bug: 72702760
Change-Id: Ib97cb5dd076afe5535e4e7951f423ccf9e78e720
parent f0927b07
Loading
Loading
Loading
Loading
+101 −10
Original line number Original line Diff line number Diff line
@@ -16,10 +16,14 @@


package android.view;
package android.view;


import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;

import android.annotation.Nullable;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.ActivityType;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseArray;
import android.util.SparseArray;
import android.view.WindowManager.TransitionType;
import android.view.WindowManager.TransitionType;


@@ -30,7 +34,7 @@ import android.view.WindowManager.TransitionType;
 */
 */
public class RemoteAnimationDefinition implements Parcelable {
public class RemoteAnimationDefinition implements Parcelable {


    private final SparseArray<RemoteAnimationAdapter> mTransitionAnimationMap;
    private final SparseArray<RemoteAnimationAdapterEntry> mTransitionAnimationMap;


    public RemoteAnimationDefinition() {
    public RemoteAnimationDefinition() {
        mTransitionAnimationMap = new SparseArray<>();
        mTransitionAnimationMap = new SparseArray<>();
@@ -40,34 +44,70 @@ public class RemoteAnimationDefinition implements Parcelable {
     * Registers a remote animation for a specific transition.
     * Registers a remote animation for a specific transition.
     *
     *
     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
     * @param activityTypeFilter The remote animation only runs if an activity with type of this
     *                           parameter is involved in the transition.
     * @param adapter The adapter that described how to run the remote animation.
     */
    public void addRemoteAnimation(@TransitionType int transition,
            @ActivityType int activityTypeFilter, RemoteAnimationAdapter adapter) {
        mTransitionAnimationMap.put(transition,
                new RemoteAnimationAdapterEntry(adapter, activityTypeFilter));
    }

    /**
     * Registers a remote animation for a specific transition without defining an activity type
     * filter.
     *
     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
     * @param adapter The adapter that described how to run the remote animation.
     * @param adapter The adapter that described how to run the remote animation.
     */
     */
    public void addRemoteAnimation(@TransitionType int transition, RemoteAnimationAdapter adapter) {
    public void addRemoteAnimation(@TransitionType int transition, RemoteAnimationAdapter adapter) {
        mTransitionAnimationMap.put(transition, adapter);
        addRemoteAnimation(transition, ACTIVITY_TYPE_UNDEFINED, adapter);
    }
    }


    /**
    /**
     * Checks whether a remote animation for specific transition is defined.
     * Checks whether a remote animation for specific transition is defined.
     *
     *
     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
     * @param activityTypes The set of activity types of activities that are involved in the
     *                      transition. Will be used for filtering.
     * @return Whether this definition has defined a remote animation for the specified transition.
     * @return Whether this definition has defined a remote animation for the specified transition.
     */
     */
    public boolean hasTransition(@TransitionType int transition) {
    public boolean hasTransition(@TransitionType int transition, ArraySet<Integer> activityTypes) {
        return mTransitionAnimationMap.get(transition) != null;
        return getAdapter(transition, activityTypes) != null;
    }
    }


    /**
    /**
     * Retrieves the remote animation for a specific transition.
     * Retrieves the remote animation for a specific transition.
     *
     *
     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
     * @param activityTypes The set of activity types of activities that are involved in the
     *                      transition. Will be used for filtering.
     * @return The remote animation adapter for the specified transition.
     * @return The remote animation adapter for the specified transition.
     */
     */
    public @Nullable RemoteAnimationAdapter getAdapter(@TransitionType int transition) {
    public @Nullable RemoteAnimationAdapter getAdapter(@TransitionType int transition,
        return mTransitionAnimationMap.get(transition);
            ArraySet<Integer> activityTypes) {
        final RemoteAnimationAdapterEntry entry = mTransitionAnimationMap.get(transition);
        if (entry == null) {
            return null;
        }
        if (entry.activityTypeFilter == ACTIVITY_TYPE_UNDEFINED
                || activityTypes.contains(entry.activityTypeFilter)) {
            return entry.adapter;
        } else {
            return null;
        }
    }
    }


    public RemoteAnimationDefinition(Parcel in) {
    public RemoteAnimationDefinition(Parcel in) {
        mTransitionAnimationMap = in.readSparseArray(null /* loader */);
        final int size = in.readInt();
        mTransitionAnimationMap = new SparseArray<>(size);
        for (int i = 0; i < size; i++) {
            final int transition = in.readInt();
            final RemoteAnimationAdapterEntry entry = in.readTypedObject(
                    RemoteAnimationAdapterEntry.CREATOR);
            mTransitionAnimationMap.put(transition, entry);
        }
    }
    }


    /**
    /**
@@ -76,7 +116,7 @@ public class RemoteAnimationDefinition implements Parcelable {
     */
     */
    public void setCallingPid(int pid) {
    public void setCallingPid(int pid) {
        for (int i = mTransitionAnimationMap.size() - 1; i >= 0; i--) {
        for (int i = mTransitionAnimationMap.size() - 1; i >= 0; i--) {
            mTransitionAnimationMap.valueAt(i).setCallingPid(pid);
            mTransitionAnimationMap.valueAt(i).adapter.setCallingPid(pid);
        }
        }
    }
    }


@@ -87,7 +127,12 @@ public class RemoteAnimationDefinition implements Parcelable {


    @Override
    @Override
    public void writeToParcel(Parcel dest, int flags) {
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeSparseArray((SparseArray) mTransitionAnimationMap);
        final int size = mTransitionAnimationMap.size();
        dest.writeInt(size);
        for (int i = 0; i < size; i++) {
            dest.writeInt(mTransitionAnimationMap.keyAt(i));
            dest.writeTypedObject(mTransitionAnimationMap.valueAt(i), flags);
        }
    }
    }


    public static final Creator<RemoteAnimationDefinition> CREATOR =
    public static final Creator<RemoteAnimationDefinition> CREATOR =
@@ -100,4 +145,50 @@ public class RemoteAnimationDefinition implements Parcelable {
            return new RemoteAnimationDefinition[size];
            return new RemoteAnimationDefinition[size];
        }
        }
    };
    };

    private static class RemoteAnimationAdapterEntry implements Parcelable {

        final RemoteAnimationAdapter adapter;

        /**
         * Only run the transition if one of the activities matches the filter.
         * {@link WindowConfiguration.ACTIVITY_TYPE_UNDEFINED} means no filter
         */
        @ActivityType final int activityTypeFilter;

        RemoteAnimationAdapterEntry(RemoteAnimationAdapter adapter, int activityTypeFilter) {
            this.adapter = adapter;
            this.activityTypeFilter = activityTypeFilter;
        }

        private RemoteAnimationAdapterEntry(Parcel in) {
            adapter = in.readParcelable(RemoteAnimationAdapter.class.getClassLoader());
            activityTypeFilter = in.readInt();
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeParcelable(adapter, flags);
            dest.writeInt(activityTypeFilter);
        }

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

        private static final Creator<RemoteAnimationAdapterEntry> CREATOR
                = new Creator<RemoteAnimationAdapterEntry>() {

            @Override
            public RemoteAnimationAdapterEntry createFromParcel(Parcel in) {
                return new RemoteAnimationAdapterEntry(in);
            }

            @Override
            public RemoteAnimationAdapterEntry[] newArray(int size) {
                return new RemoteAnimationAdapterEntry[size];
            }
        };
    }
}
}
+5 −0
Original line number Original line Diff line number Diff line
@@ -29,6 +29,11 @@ public class RemoteAnimationDefinitionCompat {
        mWrapped.addRemoteAnimation(transition, adapter.getWrapped());
        mWrapped.addRemoteAnimation(transition, adapter.getWrapped());
    }
    }


    public void addRemoteAnimation(int transition, int activityTypeFilter,
            RemoteAnimationAdapterCompat adapter) {
        mWrapped.addRemoteAnimation(transition, activityTypeFilter, adapter.getWrapped());
    }

    RemoteAnimationDefinition getWrapped() {
    RemoteAnimationDefinition getWrapped() {
        return mWrapped;
        return mWrapped;
    }
    }
+3 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.shared.system;


import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.DEFAULT_DISPLAY;


import android.app.WindowConfiguration;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Handler;
import android.os.RemoteException;
import android.os.RemoteException;
@@ -58,6 +59,8 @@ public class WindowManagerWrapper {
    public static final int TRANSIT_KEYGUARD_OCCLUDE = WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
    public static final int TRANSIT_KEYGUARD_OCCLUDE = WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
    public static final int TRANSIT_KEYGUARD_UNOCCLUDE = WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
    public static final int TRANSIT_KEYGUARD_UNOCCLUDE = WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;


    public static final int ACTIVITY_TYPE_STANDARD = WindowConfiguration.ACTIVITY_TYPE_STANDARD;

    private static final WindowManagerWrapper sInstance = new WindowManagerWrapper();
    private static final WindowManagerWrapper sInstance = new WindowManagerWrapper();


    public static WindowManagerWrapper getInstance() {
    public static WindowManagerWrapper getInstance() {
+30 −12
Original line number Original line Diff line number Diff line
@@ -52,6 +52,7 @@ import static com.android.server.wm.WindowManagerService.H.REPORT_WINDOWS_CHANGE
import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;


import android.app.WindowConfiguration;
import android.os.Debug;
import android.os.Debug;
import android.os.Trace;
import android.os.Trace;
import android.util.ArraySet;
import android.util.ArraySet;
@@ -294,12 +295,14 @@ class WindowSurfacePlacer {
        // what will control the animation theme. If all closing windows are obscured, then there is
        // what will control the animation theme. If all closing windows are obscured, then there is
        // no need to do an animation. This is the case, for example, when this transition is being
        // no need to do an animation. This is the case, for example, when this transition is being
        // done behind a dream window.
        // done behind a dream window.
        final ArraySet<Integer> activityTypes = collectActivityTypes(mService.mOpeningApps,
                mService.mClosingApps);
        final AppWindowToken animLpToken = mService.mPolicy.allowAppAnimationsLw()
        final AppWindowToken animLpToken = mService.mPolicy.allowAppAnimationsLw()
                ? findAnimLayoutParamsToken(transit)
                ? findAnimLayoutParamsToken(transit, activityTypes)
                : null;
                : null;


        final LayoutParams animLp = getAnimLp(animLpToken);
        final LayoutParams animLp = getAnimLp(animLpToken);
        overrideWithRemoteAnimationIfSet(animLpToken, transit);
        overrideWithRemoteAnimationIfSet(animLpToken, transit, activityTypes);


        final boolean voiceInteraction = containsVoiceInteraction(mService.mOpeningApps)
        final boolean voiceInteraction = containsVoiceInteraction(mService.mOpeningApps)
                || containsVoiceInteraction(mService.mOpeningApps);
                || containsVoiceInteraction(mService.mOpeningApps);
@@ -361,13 +364,14 @@ class WindowSurfacePlacer {
     * Overrides the pending transition with the remote animation defined for the transition in the
     * Overrides the pending transition with the remote animation defined for the transition in the
     * set of defined remote animations in the app window token.
     * set of defined remote animations in the app window token.
     */
     */
    private void overrideWithRemoteAnimationIfSet(AppWindowToken animLpToken, int transit) {
    private void overrideWithRemoteAnimationIfSet(AppWindowToken animLpToken, int transit,
            ArraySet<Integer> activityTypes) {
        if (animLpToken == null) {
        if (animLpToken == null) {
            return;
            return;
        }
        }
        final RemoteAnimationDefinition definition = animLpToken.getRemoteAnimationDefinition();
        final RemoteAnimationDefinition definition = animLpToken.getRemoteAnimationDefinition();
        if (definition != null) {
        if (definition != null) {
            final RemoteAnimationAdapter adapter = definition.getAdapter(transit);
            final RemoteAnimationAdapter adapter = definition.getAdapter(transit, activityTypes);
            if (adapter != null) {
            if (adapter != null) {
                mService.mAppTransition.overridePendingAppTransitionRemote(adapter);
                mService.mAppTransition.overridePendingAppTransitionRemote(adapter);
            }
            }
@@ -377,13 +381,14 @@ class WindowSurfacePlacer {
    /**
    /**
     * @return The window token that determines the animation theme.
     * @return The window token that determines the animation theme.
     */
     */
    private AppWindowToken findAnimLayoutParamsToken(@TransitionType int transit) {
    private AppWindowToken findAnimLayoutParamsToken(@TransitionType int transit,
            ArraySet<Integer> activityTypes) {
        AppWindowToken result;
        AppWindowToken result;


        // Remote animations always win, but fullscreen tokens override non-fullscreen tokens.
        // Remote animations always win, but fullscreen tokens override non-fullscreen tokens.
        result = lookForHighestTokenWithFilter(mService.mClosingApps, mService.mOpeningApps,
        result = lookForHighestTokenWithFilter(mService.mClosingApps, mService.mOpeningApps,
                w -> w.getRemoteAnimationDefinition() != null
                w -> w.getRemoteAnimationDefinition() != null
                        && w.getRemoteAnimationDefinition().hasTransition(transit));
                        && w.getRemoteAnimationDefinition().hasTransition(transit, activityTypes));
        if (result != null) {
        if (result != null) {
            return result;
            return result;
        }
        }
@@ -396,6 +401,22 @@ class WindowSurfacePlacer {
                w -> w.findMainWindow() != null);
                w -> w.findMainWindow() != null);
    }
    }


    /**
     * @return The set of {@link WindowConfiguration.ActivityType}s contained in the set of apps in
     *         {@code array1} and {@code array2}.
     */
    private ArraySet<Integer> collectActivityTypes(ArraySet<AppWindowToken> array1,
            ArraySet<AppWindowToken> array2) {
        final ArraySet<Integer> result = new ArraySet<>();
        for (int i = array1.size() - 1; i >= 0; i--) {
            result.add(array1.valueAt(i).getActivityType());
        }
        for (int i = array2.size() - 1; i >= 0; i--) {
            result.add(array2.valueAt(i).getActivityType());
        }
        return result;
    }

    private AppWindowToken lookForHighestTokenWithFilter(ArraySet<AppWindowToken> array1,
    private AppWindowToken lookForHighestTokenWithFilter(ArraySet<AppWindowToken> array1,
            ArraySet<AppWindowToken> array2, Predicate<AppWindowToken> filter) {
            ArraySet<AppWindowToken> array2, Predicate<AppWindowToken> filter) {
        final int array1count = array1.size();
        final int array1count = array1.size();
@@ -403,12 +424,9 @@ class WindowSurfacePlacer {
        int bestPrefixOrderIndex = Integer.MIN_VALUE;
        int bestPrefixOrderIndex = Integer.MIN_VALUE;
        AppWindowToken bestToken = null;
        AppWindowToken bestToken = null;
        for (int i = 0; i < count; i++) {
        for (int i = 0; i < count; i++) {
            final AppWindowToken wtoken;
            final AppWindowToken wtoken = i < array1count
            if (i < array1count) {
                    ? array1.valueAt(i)
                wtoken = array1.valueAt(i);
                    : array2.valueAt(i - array1count);
            } else {
                wtoken = array2.valueAt(i - array1count);
            }
            final int prefixOrderIndex = wtoken.getPrefixOrderIndex();
            final int prefixOrderIndex = wtoken.getPrefixOrderIndex();
            if (filter.test(wtoken) && prefixOrderIndex > bestPrefixOrderIndex) {
            if (filter.test(wtoken) && prefixOrderIndex > bestPrefixOrderIndex) {
                bestPrefixOrderIndex = prefixOrderIndex;
                bestPrefixOrderIndex = prefixOrderIndex;