• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 package com.android.quickstep;
17 
18 import static com.android.launcher3.Utilities.postAsyncCallback;
19 import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
20 import static com.android.quickstep.views.IconRecentsView.REMOTE_APP_TO_OVERVIEW_DURATION;
21 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
22 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
23 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
24 
25 import android.animation.AnimatorSet;
26 import android.animation.ValueAnimator;
27 import android.app.ActivityOptions;
28 import android.os.Handler;
29 import android.util.Log;
30 
31 import com.android.launcher3.BaseDraggingActivity;
32 import com.android.launcher3.LauncherAnimationRunner;
33 import com.android.quickstep.util.RemoteAnimationProvider;
34 import com.android.quickstep.util.RemoteAnimationTargetSet;
35 import com.android.quickstep.views.IconRecentsView;
36 import com.android.systemui.shared.system.ActivityOptionsCompat;
37 import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
38 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
39 
40 /**
41  * Provider for the atomic remote window animation from the app to the overview.
42  *
43  * @param <T> activity that contains the overview
44  */
45 final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> implements
46         RemoteAnimationProvider {
47     private static final String TAG = "AppToOverviewAnimationProvider";
48 
49     private final ActivityControlHelper<T> mHelper;
50     private final int mTargetTaskId;
51     private IconRecentsView mRecentsView;
52     private AppToOverviewAnimationListener mAnimationReadyListener;
53 
AppToOverviewAnimationProvider(ActivityControlHelper<T> helper, int targetTaskId)54     AppToOverviewAnimationProvider(ActivityControlHelper<T> helper, int targetTaskId) {
55         mHelper = helper;
56         mTargetTaskId = targetTaskId;
57     }
58 
59     /**
60      * Set listener to various points in the animation preparing to animate.
61      *
62      * @param listener listener
63      */
setAnimationListener(AppToOverviewAnimationListener listener)64     void setAnimationListener(AppToOverviewAnimationListener listener) {
65         mAnimationReadyListener = listener;
66     }
67 
68     /**
69      * Callback for when the activity is ready/initialized.
70      *
71      * @param activity the activity that is ready
72      * @param wasVisible true if it was visible before
73      */
onActivityReady(T activity, Boolean wasVisible)74     boolean onActivityReady(T activity, Boolean wasVisible) {
75         if (mAnimationReadyListener != null) {
76             mAnimationReadyListener.onActivityReady(activity);
77         }
78         ActivityControlHelper.AnimationFactory factory =
79                 mHelper.prepareRecentsUI(activity, wasVisible,
80                         false /* animate activity */, (controller) -> {
81                             controller.dispatchOnStart();
82                             ValueAnimator anim = controller.getAnimationPlayer()
83                                     .setDuration(getRecentsLaunchDuration());
84                             anim.setInterpolator(FAST_OUT_SLOW_IN);
85                             anim.start();
86                         });
87         factory.onRemoteAnimationReceived(null);
88         factory.createActivityController(getRecentsLaunchDuration());
89         mRecentsView = activity.getOverviewPanel();
90         return false;
91     }
92 
93     /**
94      * Create remote window animation from the currently running app to the overview panel. Should
95      * be called after {@link #onActivityReady}.
96      *
97      * @param targetCompats the target apps
98      * @return animation from app to overview
99      */
100     @Override
createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats)101     public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats) {
102         if (mAnimationReadyListener != null) {
103             mAnimationReadyListener.onWindowAnimationCreated();
104         }
105         AnimatorSet anim = new AnimatorSet();
106         if (mRecentsView == null) {
107             if (Log.isLoggable(TAG, Log.WARN)) {
108                 Log.w(TAG, "No recents view. Using stub animation.");
109             }
110             anim.play(ValueAnimator.ofInt(0, 1).setDuration(getRecentsLaunchDuration()));
111             return anim;
112         }
113 
114         RemoteAnimationTargetSet targetSet =
115                 new RemoteAnimationTargetSet(targetCompats, MODE_CLOSING);
116         mRecentsView.setTransitionedFromApp(!targetSet.isAnimatingHome());
117 
118         RemoteAnimationTargetCompat recentsTarget = null;
119         RemoteAnimationTargetCompat closingAppTarget = null;
120 
121         for (RemoteAnimationTargetCompat target : targetCompats) {
122             if (target.mode == MODE_OPENING) {
123                 recentsTarget = target;
124             } else if (target.mode == MODE_CLOSING && target.taskId == mTargetTaskId) {
125                 closingAppTarget = target;
126             }
127         }
128 
129         if (closingAppTarget == null) {
130             if (Log.isLoggable(TAG, Log.WARN)) {
131                 Log.w(TAG, "No closing app target. Using stub animation.");
132             }
133             anim.play(ValueAnimator.ofInt(0, 1).setDuration(getRecentsLaunchDuration()));
134             return anim;
135         }
136         if (recentsTarget == null) {
137             if (Log.isLoggable(TAG, Log.WARN)) {
138                 Log.w(TAG, "No recents target. Using stub animation.");
139             }
140             anim.play(ValueAnimator.ofInt(0, 1).setDuration(getRecentsLaunchDuration()));
141             return anim;
142         }
143 
144         if (closingAppTarget.activityType == ACTIVITY_TYPE_HOME) {
145             mRecentsView.playRemoteHomeToRecentsAnimation(anim, closingAppTarget, recentsTarget);
146         } else {
147             mRecentsView.playRemoteAppToRecentsAnimation(anim, closingAppTarget, recentsTarget);
148         }
149 
150         return anim;
151     }
152 
153     @Override
toActivityOptions(Handler handler, long duration)154     public ActivityOptions toActivityOptions(Handler handler, long duration) {
155         LauncherAnimationRunner runner = new LauncherAnimationRunner(handler,
156                 false /* startAtFrontOfQueue */) {
157 
158             @Override
159             public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats,
160                     AnimationResult result) {
161                 IconRecentsView recentsView = mRecentsView;
162                 if (!recentsView.isReadyForRemoteAnim()) {
163                     recentsView.setOnReadyForRemoteAnimCallback(() -> postAsyncCallback(handler,
164                             () -> onCreateAnimation(targetCompats, result))
165                     );
166                     return;
167                 }
168                 result.setAnimation(createWindowAnimation(targetCompats));
169             }
170         };
171         return ActivityOptionsCompat.makeRemoteAnimation(
172                 new RemoteAnimationAdapterCompat(runner, duration,
173                         0 /* statusBarTransitionDelay */));
174     }
175 
176     /**
177      * Get duration of animation from app to overview.
178      *
179      * @return duration of animation
180      */
getRecentsLaunchDuration()181     long getRecentsLaunchDuration() {
182         return REMOTE_APP_TO_OVERVIEW_DURATION;
183     }
184 
185     /**
186      * Listener for various points in the app to overview animation preparing to animate.
187      */
188     interface AppToOverviewAnimationListener {
189         /**
190          * Logic for when activity we're animating to is ready
191          *
192          * @param activity activity to animate to
193          */
onActivityReady(BaseDraggingActivity activity)194         void onActivityReady(BaseDraggingActivity activity);
195 
196         /**
197          * Logic for when we've created the app to recents animation.
198          */
onWindowAnimationCreated()199         void onWindowAnimationCreated();
200     }
201 }
202