133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi/*
233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi * Copyright (C) 2018 The Android Open Source Project
333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi *
433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License");
533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi * you may not use this file except in compliance with the License.
633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi * You may obtain a copy of the License at
733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi *
833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi *      http://www.apache.org/licenses/LICENSE-2.0
933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi *
1033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi * Unless required by applicable law or agreed to in writing, software
1133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS,
1233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi * See the License for the specific language governing permissions and
1433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi * limitations under the License
1533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi */
1633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
1733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggipackage com.android.server.wm;
1833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
19ab20e1623b81076357a08cebeda7e58cbf3e1891Jorim Jaggiimport static com.android.server.wm.AnimationAdapterProto.REMOTE;
20ab20e1623b81076357a08cebeda7e58cbf3e1891Jorim Jaggiimport static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
21f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggiimport static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
22c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chungimport static com.android.server.wm.WindowManagerDebugConfig.DEBUG_REMOTE_ANIMATIONS;
2333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
2433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
2533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
2633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport android.graphics.Point;
2733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport android.graphics.Rect;
28ab20e1623b81076357a08cebeda7e58cbf3e1891Jorim Jaggiimport android.os.Binder;
2933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport android.os.Handler;
30842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roosimport android.os.IBinder.DeathRecipient;
3133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport android.os.RemoteException;
3233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport android.os.SystemClock;
3333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport android.util.Slog;
34f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggiimport android.util.proto.ProtoOutputStream;
3533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport android.view.IRemoteAnimationFinishedCallback;
3633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport android.view.RemoteAnimationAdapter;
3733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport android.view.RemoteAnimationTarget;
3833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport android.view.SurfaceControl;
3933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport android.view.SurfaceControl.Transaction;
4033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
41f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggiimport com.android.internal.util.FastPrintWriter;
4233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
43817ebdd94d6e31caf8371587c553a5ba17a03c2aJorim Jaggiimport com.android.server.wm.utils.InsetUtils;
4433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
45f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggiimport java.io.PrintWriter;
46f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggiimport java.io.StringWriter;
4733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggiimport java.util.ArrayList;
4833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
4933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi/**
5033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi * Helper class to run app animations in a remote process.
5133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi */
52842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roosclass RemoteAnimationController implements DeathRecipient {
53c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung    private static final String TAG = TAG_WITH_CLASS_NAME
54c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung            || (DEBUG_REMOTE_ANIMATIONS && !DEBUG_APP_TRANSITIONS)
55c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung                    ? "RemoteAnimationController" : TAG_WM;
5633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    private static final long TIMEOUT_MS = 2000;
5733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
5833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    private final WindowManagerService mService;
5933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    private final RemoteAnimationAdapter mRemoteAnimationAdapter;
6033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    private final ArrayList<RemoteAnimationAdapterWrapper> mPendingAnimations = new ArrayList<>();
6133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    private final Rect mTmpRect = new Rect();
6233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    private final Handler mHandler;
63c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung    private final Runnable mTimeoutRunnable = () -> cancelAnimation("timeoutRunnable");
6433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
65842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos    private FinishedCallback mFinishedCallback;
66842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos    private boolean mCanceled;
67653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos    private boolean mLinkedToDeathOfRunner;
6833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
6933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    RemoteAnimationController(WindowManagerService service,
7033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            RemoteAnimationAdapter remoteAnimationAdapter, Handler handler) {
7133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        mService = service;
7233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        mRemoteAnimationAdapter = remoteAnimationAdapter;
7333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        mHandler = handler;
7433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    }
7533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
7633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    /**
7733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi     * Creates an animation for each individual {@link AppWindowToken}.
7833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi     *
7933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi     * @param appWindowToken The app to animate.
8033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi     * @param position The position app bounds, in screen coordinates.
8133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi     * @param stackBounds The stack bounds of the app.
8233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi     * @return The adapter to be run on the app.
8333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi     */
8433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    AnimationAdapter createAnimationAdapter(AppWindowToken appWindowToken, Point position,
8533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            Rect stackBounds) {
86703719be15d4ab520caeecf9e13e6e801f29bd12Winson Chung        if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "createAnimationAdapter(): token="
87703719be15d4ab520caeecf9e13e6e801f29bd12Winson Chung                + appWindowToken);
8833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        final RemoteAnimationAdapterWrapper adapter = new RemoteAnimationAdapterWrapper(
8933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                appWindowToken, position, stackBounds);
9033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        mPendingAnimations.add(adapter);
9133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        return adapter;
9233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    }
9333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
9433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    /**
9533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi     * Called when the transition is ready to be started, and all leashes have been set up.
9633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi     */
9733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    void goodToGo() {
98c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung        if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "goodToGo()");
99842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos        if (mPendingAnimations.isEmpty() || mCanceled) {
100703719be15d4ab520caeecf9e13e6e801f29bd12Winson Chung            if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "goodToGo(): Animation finished already,"
101703719be15d4ab520caeecf9e13e6e801f29bd12Winson Chung                    + " canceled=" + mCanceled
102703719be15d4ab520caeecf9e13e6e801f29bd12Winson Chung                    + " mPendingAnimations=" + mPendingAnimations.size());
10393f9fe342be78bc90dc8aede1dd32e55be32657eJorim Jaggi            onAnimationFinished();
10493f9fe342be78bc90dc8aede1dd32e55be32657eJorim Jaggi            return;
10593f9fe342be78bc90dc8aede1dd32e55be32657eJorim Jaggi        }
106a19d781a8a03757334a4dd1be8cfe2bc5e0299a7Jorim Jaggi
107a19d781a8a03757334a4dd1be8cfe2bc5e0299a7Jorim Jaggi        // Scale the timeout with the animator scale the controlling app is using.
108a19d781a8a03757334a4dd1be8cfe2bc5e0299a7Jorim Jaggi        mHandler.postDelayed(mTimeoutRunnable,
109a19d781a8a03757334a4dd1be8cfe2bc5e0299a7Jorim Jaggi                (long) (TIMEOUT_MS * mService.getCurrentAnimatorScale()));
11091f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi        mFinishedCallback = new FinishedCallback(this);
11116d0d07df83eb00edd719715e6e42d91b600602fChavi Weingarten
11216d0d07df83eb00edd719715e6e42d91b600602fChavi Weingarten        final RemoteAnimationTarget[] animations = createAnimations();
113c4d29f2a1c6e8e9c3cdb3fc2bf8a8151fb24716bJorim Jaggi        if (animations.length == 0) {
114c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung            if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "goodToGo(): No apps to animate");
115c4d29f2a1c6e8e9c3cdb3fc2bf8a8151fb24716bJorim Jaggi            onAnimationFinished();
116c4d29f2a1c6e8e9c3cdb3fc2bf8a8151fb24716bJorim Jaggi            return;
117c4d29f2a1c6e8e9c3cdb3fc2bf8a8151fb24716bJorim Jaggi        }
11816d0d07df83eb00edd719715e6e42d91b600602fChavi Weingarten        mService.mAnimator.addAfterPrepareSurfacesRunnable(() -> {
11916d0d07df83eb00edd719715e6e42d91b600602fChavi Weingarten            try {
120653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos                linkToDeathOfRunner();
121842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos                mRemoteAnimationAdapter.getRunner().onAnimationStart(animations, mFinishedCallback);
12216d0d07df83eb00edd719715e6e42d91b600602fChavi Weingarten            } catch (RemoteException e) {
12316d0d07df83eb00edd719715e6e42d91b600602fChavi Weingarten                Slog.e(TAG, "Failed to start remote animation", e);
12416d0d07df83eb00edd719715e6e42d91b600602fChavi Weingarten                onAnimationFinished();
12516d0d07df83eb00edd719715e6e42d91b600602fChavi Weingarten            }
126c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung            if (DEBUG_REMOTE_ANIMATIONS) {
127c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung                Slog.d(TAG, "startAnimation(): Notify animation start:");
128c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung                writeStartDebugStatement();
129c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung            }
13016d0d07df83eb00edd719715e6e42d91b600602fChavi Weingarten        });
131bc2aabe84568c6b1a54c1b1467a539781488c8caJorim Jaggi        sendRunningRemoteAnimation(true);
132f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi    }
133f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi
134c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung    private void cancelAnimation(String reason) {
135c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung        if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "cancelAnimation(): reason=" + reason);
136842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos        synchronized (mService.getWindowManagerLock()) {
137842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos            if (mCanceled) {
138842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos                return;
139842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos            }
140842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos            mCanceled = true;
141842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos        }
142842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos        onAnimationFinished();
143842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos        invokeAnimationCancelled();
144842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos    }
145842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos
146f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi    private void writeStartDebugStatement() {
147f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        Slog.i(TAG, "Starting remote animation");
148f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        final StringWriter sw = new StringWriter();
149f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        final FastPrintWriter pw = new FastPrintWriter(sw);
150f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
151f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi            mPendingAnimations.get(i).dump(pw, "");
152f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        }
153f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        pw.close();
154f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        Slog.i(TAG, sw.toString());
15533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    }
15633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
15733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    private RemoteAnimationTarget[] createAnimations() {
158c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung        if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "createAnimations()");
1591777021fcf989c0a1d2b7aa533a7b464ad85a807Jorim Jaggi        final ArrayList<RemoteAnimationTarget> targets = new ArrayList<>();
16033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
161b8a9cbe4d8f7d2af99e487fe89ca2c42578c6f88Jorim Jaggi            final RemoteAnimationAdapterWrapper wrapper = mPendingAnimations.get(i);
162c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung            final RemoteAnimationTarget target = wrapper.createRemoteAppAnimation();
1631777021fcf989c0a1d2b7aa533a7b464ad85a807Jorim Jaggi            if (target != null) {
164c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung                if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "\tAdd token=" + wrapper.mAppWindowToken);
1651777021fcf989c0a1d2b7aa533a7b464ad85a807Jorim Jaggi                targets.add(target);
166c4d29f2a1c6e8e9c3cdb3fc2bf8a8151fb24716bJorim Jaggi            } else {
167703719be15d4ab520caeecf9e13e6e801f29bd12Winson Chung                if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "\tRemove token="
168703719be15d4ab520caeecf9e13e6e801f29bd12Winson Chung                        + wrapper.mAppWindowToken);
169b8a9cbe4d8f7d2af99e487fe89ca2c42578c6f88Jorim Jaggi
170b8a9cbe4d8f7d2af99e487fe89ca2c42578c6f88Jorim Jaggi                // We can't really start an animation but we still need to make sure to finish the
171b8a9cbe4d8f7d2af99e487fe89ca2c42578c6f88Jorim Jaggi                // pending animation that was started by SurfaceAnimator
172b8a9cbe4d8f7d2af99e487fe89ca2c42578c6f88Jorim Jaggi                if (wrapper.mCapturedFinishCallback != null) {
173b8a9cbe4d8f7d2af99e487fe89ca2c42578c6f88Jorim Jaggi                    wrapper.mCapturedFinishCallback.onAnimationFinished(wrapper);
174b8a9cbe4d8f7d2af99e487fe89ca2c42578c6f88Jorim Jaggi                }
175c4d29f2a1c6e8e9c3cdb3fc2bf8a8151fb24716bJorim Jaggi                mPendingAnimations.remove(i);
1761777021fcf989c0a1d2b7aa533a7b464ad85a807Jorim Jaggi            }
17733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        }
1781777021fcf989c0a1d2b7aa533a7b464ad85a807Jorim Jaggi        return targets.toArray(new RemoteAnimationTarget[targets.size()]);
17933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    }
18033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
18133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    private void onAnimationFinished() {
182c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung        if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "onAnimationFinished(): mPendingAnimations="
183c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung                + mPendingAnimations.size());
18433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        mHandler.removeCallbacks(mTimeoutRunnable);
18533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        synchronized (mService.mWindowMap) {
186653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos            unlinkToDeathOfRunner();
18791f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi            releaseFinishedCallback();
18833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            mService.openSurfaceTransaction();
18933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            try {
190703719be15d4ab520caeecf9e13e6e801f29bd12Winson Chung                if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG,
191703719be15d4ab520caeecf9e13e6e801f29bd12Winson Chung                        "onAnimationFinished(): Notify animation finished:");
19233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
19333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                    final RemoteAnimationAdapterWrapper adapter = mPendingAnimations.get(i);
19433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                    adapter.mCapturedFinishCallback.onAnimationFinished(adapter);
195c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung                    if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "\t" + adapter.mAppWindowToken);
19633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                }
197c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung            } catch (Exception e) {
198c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung                Slog.e(TAG, "Failed to finish remote animation", e);
199c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung                throw e;
20033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            } finally {
20133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                mService.closeSurfaceTransaction("RemoteAnimationController#finished");
20233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            }
20333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        }
204bc2aabe84568c6b1a54c1b1467a539781488c8caJorim Jaggi        sendRunningRemoteAnimation(false);
205c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung        if (DEBUG_REMOTE_ANIMATIONS) Slog.i(TAG, "Finishing remote animation");
20633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    }
20733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
20833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    private void invokeAnimationCancelled() {
20933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        try {
21033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            mRemoteAnimationAdapter.getRunner().onAnimationCancelled();
21133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        } catch (RemoteException e) {
21233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            Slog.e(TAG, "Failed to notify cancel", e);
21333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        }
21433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    }
21533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
21691f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi    private void releaseFinishedCallback() {
21791f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi        if (mFinishedCallback != null) {
21891f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi            mFinishedCallback.release();
21991f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi            mFinishedCallback = null;
22091f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi        }
22191f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi    }
22291f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi
223bc2aabe84568c6b1a54c1b1467a539781488c8caJorim Jaggi    private void sendRunningRemoteAnimation(boolean running) {
224bc2aabe84568c6b1a54c1b1467a539781488c8caJorim Jaggi        final int pid = mRemoteAnimationAdapter.getCallingPid();
225bc2aabe84568c6b1a54c1b1467a539781488c8caJorim Jaggi        if (pid == 0) {
226bc2aabe84568c6b1a54c1b1467a539781488c8caJorim Jaggi            throw new RuntimeException("Calling pid of remote animation was null");
227bc2aabe84568c6b1a54c1b1467a539781488c8caJorim Jaggi        }
228bc2aabe84568c6b1a54c1b1467a539781488c8caJorim Jaggi        mService.sendSetRunningRemoteAnimation(pid, running);
229bc2aabe84568c6b1a54c1b1467a539781488c8caJorim Jaggi    }
230bc2aabe84568c6b1a54c1b1467a539781488c8caJorim Jaggi
231653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos    private void linkToDeathOfRunner() throws RemoteException {
232653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos        if (!mLinkedToDeathOfRunner) {
233653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos            mRemoteAnimationAdapter.getRunner().asBinder().linkToDeath(this, 0);
234653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos            mLinkedToDeathOfRunner = true;
235653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos        }
236653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos    }
237653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos
238653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos    private void unlinkToDeathOfRunner() {
239653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos        if (mLinkedToDeathOfRunner) {
240653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos            mRemoteAnimationAdapter.getRunner().asBinder().unlinkToDeath(this, 0);
241653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos            mLinkedToDeathOfRunner = false;
242653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos        }
243653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos    }
244653c6c1100d9093d0850dc21365b0b91db8cfffbAdrian Roos
245842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos    @Override
246842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos    public void binderDied() {
247c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung        cancelAnimation("binderDied");
248842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos    }
249842e788ffc7f2964d6d5877511e3762d4908bb95Adrian Roos
25091f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi    private static final class FinishedCallback extends IRemoteAnimationFinishedCallback.Stub {
25191f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi
25291f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi        RemoteAnimationController mOuter;
25391f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi
25491f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi        FinishedCallback(RemoteAnimationController outer) {
25591f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi            mOuter = outer;
25691f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi        }
25791f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi
25891f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi        @Override
25991f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi        public void onAnimationFinished() throws RemoteException {
260c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung            if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "app-onAnimationFinished(): mOuter=" + mOuter);
261ab20e1623b81076357a08cebeda7e58cbf3e1891Jorim Jaggi            final long token = Binder.clearCallingIdentity();
262ab20e1623b81076357a08cebeda7e58cbf3e1891Jorim Jaggi            try {
263ab20e1623b81076357a08cebeda7e58cbf3e1891Jorim Jaggi                if (mOuter != null) {
264ab20e1623b81076357a08cebeda7e58cbf3e1891Jorim Jaggi                    mOuter.onAnimationFinished();
26591f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi
266ab20e1623b81076357a08cebeda7e58cbf3e1891Jorim Jaggi                    // In case the client holds on to the finish callback, make sure we don't leak
267ab20e1623b81076357a08cebeda7e58cbf3e1891Jorim Jaggi                    // RemoteAnimationController which in turn would leak the runner on the client.
268ab20e1623b81076357a08cebeda7e58cbf3e1891Jorim Jaggi                    mOuter = null;
269ab20e1623b81076357a08cebeda7e58cbf3e1891Jorim Jaggi                }
270ab20e1623b81076357a08cebeda7e58cbf3e1891Jorim Jaggi            } finally {
271ab20e1623b81076357a08cebeda7e58cbf3e1891Jorim Jaggi                Binder.restoreCallingIdentity(token);
27291f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi            }
27391f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi        }
27491f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi
27591f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi        /**
27691f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi         * Marks this callback as not be used anymore by releasing the reference to the outer class
27791f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi         * to prevent memory leak.
27891f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi         */
27991f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi        void release() {
280c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung            if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "app-release(): mOuter=" + mOuter);
28191f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi            mOuter = null;
28291f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi        }
28391f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi    };
28491f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi
28533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    private class RemoteAnimationAdapterWrapper implements AnimationAdapter {
28633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
28733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        private final AppWindowToken mAppWindowToken;
28833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        private SurfaceControl mCapturedLeash;
28933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        private OnAnimationFinishedCallback mCapturedFinishCallback;
29033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        private final Point mPosition = new Point();
29133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        private final Rect mStackBounds = new Rect();
292f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        private RemoteAnimationTarget mTarget;
29333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
29433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        RemoteAnimationAdapterWrapper(AppWindowToken appWindowToken, Point position,
29533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                Rect stackBounds) {
29633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            mAppWindowToken = appWindowToken;
29733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            mPosition.set(position.x, position.y);
29833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            mStackBounds.set(stackBounds);
29933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        }
30033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
30133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        RemoteAnimationTarget createRemoteAppAnimation() {
3021777021fcf989c0a1d2b7aa533a7b464ad85a807Jorim Jaggi            final Task task = mAppWindowToken.getTask();
3031777021fcf989c0a1d2b7aa533a7b464ad85a807Jorim Jaggi            final WindowState mainWindow = mAppWindowToken.findMainWindow();
304c4d29f2a1c6e8e9c3cdb3fc2bf8a8151fb24716bJorim Jaggi            if (task == null || mainWindow == null || mCapturedFinishCallback == null
305c4d29f2a1c6e8e9c3cdb3fc2bf8a8151fb24716bJorim Jaggi                    || mCapturedLeash == null) {
3061777021fcf989c0a1d2b7aa533a7b464ad85a807Jorim Jaggi                return null;
3071777021fcf989c0a1d2b7aa533a7b464ad85a807Jorim Jaggi            }
308817ebdd94d6e31caf8371587c553a5ba17a03c2aJorim Jaggi            final Rect insets = new Rect(mainWindow.mContentInsets);
309817ebdd94d6e31caf8371587c553a5ba17a03c2aJorim Jaggi            InsetUtils.addInsets(insets, mAppWindowToken.getLetterboxInsets());
310f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi            mTarget = new RemoteAnimationTarget(task.mTaskId, getMode(),
31133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                    mCapturedLeash, !mAppWindowToken.fillsParent(),
312817ebdd94d6e31caf8371587c553a5ba17a03c2aJorim Jaggi                    mainWindow.mWinAnimator.mLastClipRect, insets,
313e2d721781fc024cbd9a14929741e5b476242291fWinson Chung                    mAppWindowToken.getPrefixOrderIndex(), mPosition, mStackBounds,
314593e9567fdc2a7b5c7e06c12c9af4b32f4216d85Vadim Tryshev                    task.getWindowConfiguration(), false /*isNotInRecents*/);
315f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi            return mTarget;
31633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        }
31733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
31833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        private int getMode() {
31933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            if (mService.mOpeningApps.contains(mAppWindowToken)) {
32033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                return RemoteAnimationTarget.MODE_OPENING;
32133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            } else {
32233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                return RemoteAnimationTarget.MODE_CLOSING;
32333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            }
32433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        }
32533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
32633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        @Override
32733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        public boolean getDetachWallpaper() {
32833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            return false;
32933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        }
33033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
33133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        @Override
33282c1786e2c19201d02e014afc6458296b4f29e79Jorim Jaggi        public boolean getShowWallpaper() {
33382c1786e2c19201d02e014afc6458296b4f29e79Jorim Jaggi            return false;
33482c1786e2c19201d02e014afc6458296b4f29e79Jorim Jaggi        }
33582c1786e2c19201d02e014afc6458296b4f29e79Jorim Jaggi
33682c1786e2c19201d02e014afc6458296b4f29e79Jorim Jaggi        @Override
33733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        public int getBackgroundColor() {
33833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            return 0;
33933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        }
34033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
34133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        @Override
34233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        public void startAnimation(SurfaceControl animationLeash, Transaction t,
34333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                OnAnimationFinishedCallback finishCallback) {
344c6c3f851dc0c2e7f17581b55d08f17b508c791afWinson Chung            if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "startAnimation");
34533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
34633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            // Restore z-layering, position and stack crop until client has a chance to modify it.
34733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            t.setLayer(animationLeash, mAppWindowToken.getPrefixOrderIndex());
34833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            t.setPosition(animationLeash, mPosition.x, mPosition.y);
34933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            mTmpRect.set(mStackBounds);
35033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            mTmpRect.offsetTo(0, 0);
35133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            t.setWindowCrop(animationLeash, mTmpRect);
35233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            mCapturedLeash = animationLeash;
35333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            mCapturedFinishCallback = finishCallback;
35433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        }
35533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
35633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        @Override
35733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        public void onAnimationCancelled(SurfaceControl animationLeash) {
35833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            mPendingAnimations.remove(this);
35933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            if (mPendingAnimations.isEmpty()) {
36033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                mHandler.removeCallbacks(mTimeoutRunnable);
36191f9f348dc6a8e062e2f2dee9e687ae9ca558ac9Jorim Jaggi                releaseFinishedCallback();
36233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                invokeAnimationCancelled();
363bc2aabe84568c6b1a54c1b1467a539781488c8caJorim Jaggi                sendRunningRemoteAnimation(false);
36433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            }
36533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        }
36633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
36733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        @Override
36833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        public long getDurationHint() {
36933a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            return mRemoteAnimationAdapter.getDuration();
37033a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        }
37133a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi
37233a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        @Override
37333a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        public long getStatusBarTransitionsStartTime() {
37433a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi            return SystemClock.uptimeMillis()
37533a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi                    + mRemoteAnimationAdapter.getStatusBarTransitionDelay();
37633a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi        }
377f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi
378f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        @Override
379f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        public void dump(PrintWriter pw, String prefix) {
380f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi            pw.print(prefix); pw.print("token="); pw.println(mAppWindowToken);
381f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi            if (mTarget != null) {
382f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi                pw.print(prefix); pw.println("Target:");
383f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi                mTarget.dump(pw, prefix + "  ");
384f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi            } else {
385f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi                pw.print(prefix); pw.println("Target: null");
386f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi            }
387f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        }
388f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi
389f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        @Override
390f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        public void writeToProto(ProtoOutputStream proto) {
391f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi            final long token = proto.start(REMOTE);
392f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi            if (mTarget != null) {
393f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi                mTarget.writeToProto(proto, TARGET);
394f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi            }
395f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi            proto.end(token);
396f75d161dd84f90b1a014e7c48ce0654cf806c0ddJorim Jaggi        }
39733a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi    }
39833a701a55c28dd20390acee1ba7881a500830d7dJorim Jaggi}
399