1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.wm.shell.back; 18 19 import static android.view.WindowManager.TRANSIT_OLD_UNSET; 20 21 import android.annotation.NonNull; 22 import android.content.Context; 23 import android.os.RemoteException; 24 import android.util.Log; 25 import android.view.IRemoteAnimationFinishedCallback; 26 import android.view.IRemoteAnimationRunner; 27 import android.view.RemoteAnimationTarget; 28 import android.window.IBackAnimationRunner; 29 import android.window.IOnBackInvokedCallback; 30 31 import com.android.internal.annotations.VisibleForTesting; 32 import com.android.internal.jank.Cuj.CujType; 33 import com.android.wm.shell.common.InteractionJankMonitorUtils; 34 35 /** 36 * Used to register the animation callback and runner, it will trigger result if gesture was finish 37 * before it received IBackAnimationRunner#onAnimationStart, so the controller could continue 38 * trigger the real back behavior. 39 */ 40 public class BackAnimationRunner { 41 private static final int NO_CUJ = -1; 42 private static final String TAG = "ShellBackPreview"; 43 44 private final IOnBackInvokedCallback mCallback; 45 private final IRemoteAnimationRunner mRunner; 46 private final @CujType int mCujType; 47 private final Context mContext; 48 49 // Whether we are waiting to receive onAnimationStart 50 private boolean mWaitingAnimation; 51 52 /** True when the back animation is cancelled */ 53 private boolean mAnimationCancelled; 54 BackAnimationRunner( @onNull IOnBackInvokedCallback callback, @NonNull IRemoteAnimationRunner runner, @NonNull Context context, @CujType int cujType)55 public BackAnimationRunner( 56 @NonNull IOnBackInvokedCallback callback, 57 @NonNull IRemoteAnimationRunner runner, 58 @NonNull Context context, 59 @CujType int cujType) { 60 mCallback = callback; 61 mRunner = runner; 62 mCujType = cujType; 63 mContext = context; 64 } 65 BackAnimationRunner( @onNull IOnBackInvokedCallback callback, @NonNull IRemoteAnimationRunner runner, @NonNull Context context)66 public BackAnimationRunner( 67 @NonNull IOnBackInvokedCallback callback, 68 @NonNull IRemoteAnimationRunner runner, 69 @NonNull Context context) { 70 this(callback, runner, context, NO_CUJ); 71 } 72 73 /** Returns the registered animation runner */ getRunner()74 IRemoteAnimationRunner getRunner() { 75 return mRunner; 76 } 77 78 /** Returns the registered animation callback */ getCallback()79 IOnBackInvokedCallback getCallback() { 80 return mCallback; 81 } 82 83 /** 84 * Called from {@link IBackAnimationRunner}, it will deliver these 85 * {@link RemoteAnimationTarget}s to the corresponding runner. 86 */ startAnimation(RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, Runnable finishedCallback)87 void startAnimation(RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, 88 RemoteAnimationTarget[] nonApps, Runnable finishedCallback) { 89 final IRemoteAnimationFinishedCallback callback = 90 new IRemoteAnimationFinishedCallback.Stub() { 91 @Override 92 public void onAnimationFinished() { 93 if (shouldMonitorCUJ(apps)) { 94 InteractionJankMonitorUtils.endTracing(mCujType); 95 } 96 finishedCallback.run(); 97 } 98 }; 99 mWaitingAnimation = false; 100 if (shouldMonitorCUJ(apps)) { 101 InteractionJankMonitorUtils.beginTracing( 102 mCujType, mContext, apps[0].leash, /* tag */ null); 103 } 104 try { 105 getRunner().onAnimationStart(TRANSIT_OLD_UNSET, apps, wallpapers, 106 nonApps, callback); 107 } catch (RemoteException e) { 108 Log.w(TAG, "Failed call onAnimationStart", e); 109 } 110 } 111 112 @VisibleForTesting shouldMonitorCUJ(RemoteAnimationTarget[] apps)113 boolean shouldMonitorCUJ(RemoteAnimationTarget[] apps) { 114 return apps.length > 0 && mCujType != NO_CUJ; 115 } 116 startGesture()117 void startGesture() { 118 mWaitingAnimation = true; 119 mAnimationCancelled = false; 120 } 121 isWaitingAnimation()122 boolean isWaitingAnimation() { 123 return mWaitingAnimation; 124 } 125 cancelAnimation()126 void cancelAnimation() { 127 mWaitingAnimation = false; 128 mAnimationCancelled = true; 129 } 130 isAnimationCancelled()131 boolean isAnimationCancelled() { 132 return mAnimationCancelled; 133 } 134 resetWaitingAnimation()135 void resetWaitingAnimation() { 136 mWaitingAnimation = false; 137 } 138 } 139