1 /*
2  * Copyright (C) 2020 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.util;
17 
18 import android.util.FloatProperty;
19 
20 import com.android.launcher3.Utilities;
21 import com.android.launcher3.anim.Interpolators;
22 import com.android.quickstep.RemoteAnimationTargets;
23 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
24 import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
25 import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
26 import com.android.systemui.shared.system.TransactionCompat;
27 
28 public class TransformParams {
29 
30     public static FloatProperty<TransformParams> PROGRESS =
31             new FloatProperty<TransformParams>("progress") {
32         @Override
33         public void setValue(TransformParams params, float v) {
34             params.setProgress(v);
35         }
36 
37         @Override
38         public Float get(TransformParams params) {
39             return params.getProgress();
40         }
41     };
42 
43     public static FloatProperty<TransformParams> TARGET_ALPHA =
44             new FloatProperty<TransformParams>("targetAlpha") {
45         @Override
46         public void setValue(TransformParams params, float v) {
47             params.setTargetAlpha(v);
48         }
49 
50         @Override
51         public Float get(TransformParams params) {
52             return params.getTargetAlpha();
53         }
54     };
55 
56     private float mProgress;
57     private float mTargetAlpha;
58     private float mCornerRadius;
59     private RemoteAnimationTargets mTargetSet;
60     private SurfaceTransactionApplier mSyncTransactionApplier;
61 
62     private BuilderProxy mHomeBuilderProxy = BuilderProxy.ALWAYS_VISIBLE;
63     private BuilderProxy mBaseBuilderProxy = BuilderProxy.ALWAYS_VISIBLE;
64 
TransformParams()65     public TransformParams() {
66         mProgress = 0;
67         mTargetAlpha = 1;
68         mCornerRadius = -1;
69     }
70 
71     /**
72      * Sets the progress of the transformation, where 0 is the source and 1 is the target. We
73      * automatically adjust properties such as currentRect and cornerRadius based on this
74      * progress, unless they are manually overridden by setting them on this TransformParams.
75      */
setProgress(float progress)76     public TransformParams setProgress(float progress) {
77         mProgress = progress;
78         return this;
79     }
80 
81     /**
82      * Sets the corner radius of the transformed window, in pixels. If unspecified (-1), we
83      * simply interpolate between the window's corner radius to the task view's corner radius,
84      * based on {@link #mProgress}.
85      */
setCornerRadius(float cornerRadius)86     public TransformParams setCornerRadius(float cornerRadius) {
87         mCornerRadius = cornerRadius;
88         return this;
89     }
90 
91     /**
92      * Specifies the alpha of the transformed window. Default is 1.
93      */
setTargetAlpha(float targetAlpha)94     public TransformParams setTargetAlpha(float targetAlpha) {
95         mTargetAlpha = targetAlpha;
96         return this;
97     }
98 
99     /**
100      * Specifies the set of RemoteAnimationTargetCompats that are included in the transformation
101      * that these TransformParams help compute. These TransformParams generally only apply to
102      * the targetSet.apps which match the targetSet.targetMode (e.g. the MODE_CLOSING app when
103      * swiping to home).
104      */
setTargetSet(RemoteAnimationTargets targetSet)105     public TransformParams setTargetSet(RemoteAnimationTargets targetSet) {
106         mTargetSet = targetSet;
107         return this;
108     }
109 
110     /**
111      * Sets the SyncRtSurfaceTransactionApplierCompat that will apply the SurfaceParams that
112      * are computed based on these TransformParams.
113      */
setSyncTransactionApplier( SurfaceTransactionApplier applier)114     public TransformParams setSyncTransactionApplier(
115             SurfaceTransactionApplier applier) {
116         mSyncTransactionApplier = applier;
117         return this;
118     }
119 
120     /**
121      * Sets an alternate function to control transform for non-target apps. The default
122      * implementation keeps the targets visible with alpha=1
123      */
setBaseBuilderProxy(BuilderProxy proxy)124     public TransformParams setBaseBuilderProxy(BuilderProxy proxy) {
125         mBaseBuilderProxy = proxy;
126         return this;
127     }
128 
129     /**
130      * Sets an alternate function to control transform for home target. The default
131      * implementation keeps the targets visible with alpha=1
132      */
setHomeBuilderProxy(BuilderProxy proxy)133     public TransformParams setHomeBuilderProxy(BuilderProxy proxy) {
134         mHomeBuilderProxy = proxy;
135         return this;
136     }
137 
createSurfaceParams(BuilderProxy proxy)138     public SurfaceParams[] createSurfaceParams(BuilderProxy proxy) {
139         RemoteAnimationTargets targets = mTargetSet;
140         SurfaceParams[] surfaceParams = new SurfaceParams[targets.unfilteredApps.length];
141         for (int i = 0; i < targets.unfilteredApps.length; i++) {
142             RemoteAnimationTargetCompat app = targets.unfilteredApps[i];
143             SurfaceParams.Builder builder = new SurfaceParams.Builder(app.leash);
144 
145             if (app.mode == targets.targetMode) {
146                 if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
147                     mHomeBuilderProxy.onBuildTargetParams(builder, app, this);
148                 } else {
149                     // Fade out Assistant overlay.
150                     if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT
151                             && app.isNotInRecents) {
152                         float progress = Utilities.boundToRange(getProgress(), 0, 1);
153                         builder.withAlpha(1 - Interpolators.DEACCEL_2_5.getInterpolation(progress));
154                     } else {
155                         builder.withAlpha(getTargetAlpha());
156                     }
157 
158                     proxy.onBuildTargetParams(builder, app, this);
159                 }
160             } else {
161                 mBaseBuilderProxy.onBuildTargetParams(builder, app, this);
162             }
163             surfaceParams[i] = builder.build();
164         }
165         return surfaceParams;
166     }
167 
168     // Pubic getters so outside packages can read the values.
169 
getProgress()170     public float getProgress() {
171         return mProgress;
172     }
173 
getTargetAlpha()174     public float getTargetAlpha() {
175         return mTargetAlpha;
176     }
177 
getCornerRadius()178     public float getCornerRadius() {
179         return mCornerRadius;
180     }
181 
getTargetSet()182     public RemoteAnimationTargets getTargetSet() {
183         return mTargetSet;
184     }
185 
applySurfaceParams(SurfaceParams[] params)186     public void applySurfaceParams(SurfaceParams[] params) {
187         if (mSyncTransactionApplier != null) {
188             mSyncTransactionApplier.scheduleApply(params);
189         } else {
190             TransactionCompat t = new TransactionCompat();
191             for (SurfaceParams param : params) {
192                 SyncRtSurfaceTransactionApplierCompat.applyParams(t, param);
193             }
194             t.apply();
195         }
196     }
197 
198     @FunctionalInterface
199     public interface BuilderProxy {
200 
201         BuilderProxy NO_OP = (builder, app, params) -> { };
202         BuilderProxy ALWAYS_VISIBLE = (builder, app, params) ->builder.withAlpha(1);
203 
onBuildTargetParams(SurfaceParams.Builder builder, RemoteAnimationTargetCompat app, TransformParams params)204         void onBuildTargetParams(SurfaceParams.Builder builder,
205                 RemoteAnimationTargetCompat app, TransformParams params);
206     }
207 }
208