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

Commit d2928c59 authored by Jon Miranda's avatar Jon Miranda
Browse files

Add IHomeTransitionListener to shell.

This allows launcher to listen in on any transitions that include the home
activity.

Bug: 279514548
Bug: 284474103
Test: Enable ENABLE_HOME_TRANSITION_LISTENER in launcher dev options
      App launch => Hotseat -> Taskbar -> Stash
      Launch translucent activity => No animation
      Go home from app => Taskbaer -> Hotseat

Change-Id: I574b8164bd61475ba05bbb86aef358f364227e66
parent 6e7cf312
Loading
Loading
Loading
Loading
+119 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 com.android.wm.shell.transition;

import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;

import static com.android.wm.shell.transition.Transitions.TransitionObserver;

import android.annotation.NonNull;
import android.app.ActivityManager;
import android.content.Context;
import android.os.IBinder;
import android.view.SurfaceControl;
import android.window.TransitionInfo;

import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SingleInstanceRemoteListener;
import com.android.wm.shell.util.TransitionUtil;

/**
 * The {@link TransitionObserver} that observes for transitions involving the home
 * activity. It reports transitions to the caller via {@link IHomeTransitionListener}.
 */
public class HomeTransitionObserver implements TransitionObserver,
        RemoteCallable<HomeTransitionObserver> {
    private final SingleInstanceRemoteListener<HomeTransitionObserver, IHomeTransitionListener>
            mListener;

    private @NonNull final Context mContext;
    private @NonNull final ShellExecutor mMainExecutor;
    private @NonNull final Transitions mTransitions;

    public HomeTransitionObserver(@NonNull Context context,
            @NonNull ShellExecutor mainExecutor,
            @NonNull Transitions transitions) {
        mContext = context;
        mMainExecutor = mainExecutor;
        mTransitions = transitions;

        mListener = new SingleInstanceRemoteListener<>(this,
                c -> mTransitions.registerObserver(this),
                c -> mTransitions.unregisterObserver(this));

    }

    @Override
    public void onTransitionReady(@NonNull IBinder transition,
            @NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startTransaction,
            @NonNull SurfaceControl.Transaction finishTransaction) {
        for (TransitionInfo.Change change : info.getChanges()) {
            final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
            if (taskInfo == null || taskInfo.taskId == -1) {
                continue;
            }

            final int mode = change.getMode();
            if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME
                    && TransitionUtil.isOpenOrCloseMode(mode)) {
                mListener.call(l -> l.onHomeVisibilityChanged(TransitionUtil.isOpeningType(mode)));
            }
        }
    }

    @Override
    public void onTransitionStarting(@NonNull IBinder transition) {}

    @Override
    public void onTransitionMerged(@NonNull IBinder merged,
            @NonNull IBinder playing) {}

    @Override
    public void onTransitionFinished(@NonNull IBinder transition,
            boolean aborted) {}

    /**
     * Sets the home transition listener that receives any transitions resulting in a change of
     *
     */
    public void setHomeTransitionListener(IHomeTransitionListener listener) {
        if (listener != null) {
            mListener.register(listener);
        } else {
            mListener.unregister();
        }
    }

    @Override
    public Context getContext() {
        return mContext;
    }

    @Override
    public ShellExecutor getRemoteCallExecutor() {
        return mMainExecutor;
    }

    /**
     * Invalidates this controller, preventing future calls to send updates.
     */
    public void invalidate() {
        mTransitions.unregisterObserver(this);
    }
}
+32 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 com.android.wm.shell.transition;

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

/**
 *  Listener interface that Launcher attaches to SystemUI to get home activity transition callbacks.
 */
interface IHomeTransitionListener {

    /**
     * Called when a transition changes the visibility of the home activity.
     */
    void onHomeVisibilityChanged(in boolean isVisible);
}
+5 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.wm.shell.transition;
import android.window.RemoteTransition;
import android.window.TransitionFilter;

import com.android.wm.shell.transition.IHomeTransitionListener;

/**
 * Interface that is exposed to remote callers to manipulate the transitions feature.
 */
@@ -39,4 +41,7 @@ interface IShellTransitions {
     * Retrieves the apply-token used by transactions in Shell
     */
    IBinder getShellApplyToken() = 3;

    /** Set listener that will receive callbacks about transitions involving home activity */
    oneway void setHomeTransitionListener(in IHomeTransitionListener listener) = 4;
}
+14 −2
Original line number Diff line number Diff line
@@ -356,7 +356,7 @@ public class Transitions implements RemoteCallable<Transitions>,
    }

    private ExternalInterfaceBinder createExternalInterface() {
        return new IShellTransitionsImpl(this);
        return new IShellTransitionsImpl(mContext, getMainExecutor(), this);
    }

    @Override
@@ -1400,9 +1400,12 @@ public class Transitions implements RemoteCallable<Transitions>,
    private static class IShellTransitionsImpl extends IShellTransitions.Stub
            implements ExternalInterfaceBinder {
        private Transitions mTransitions;
        private final HomeTransitionObserver mHomeTransitionObserver;

        IShellTransitionsImpl(Transitions transitions) {
        IShellTransitionsImpl(Context context, ShellExecutor executor, Transitions transitions) {
            mTransitions = transitions;
            mHomeTransitionObserver = new HomeTransitionObserver(context, executor,
                    mTransitions);
        }

        /**
@@ -1410,6 +1413,7 @@ public class Transitions implements RemoteCallable<Transitions>,
         */
        @Override
        public void invalidate() {
            mHomeTransitionObserver.invalidate();
            mTransitions = null;
        }

@@ -1434,6 +1438,14 @@ public class Transitions implements RemoteCallable<Transitions>,
        public IBinder getShellApplyToken() {
            return SurfaceControl.Transaction.getDefaultApplyToken();
        }

        @Override
        public void setHomeTransitionListener(IHomeTransitionListener listener) {
            executeRemoteCallWithTaskPermission(mTransitions, "setHomeTransitionListener",
                    (transitions) -> {
                        mHomeTransitionObserver.setHomeTransitionListener(listener);
                    });
        }
    }

    private class SettingsObserver extends ContentObserver {