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