• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
19 
20 import android.util.FloatProperty;
21 import android.view.RemoteAnimationTarget;
22 import android.view.SurfaceControl;
23 import android.window.TransitionInfo;
24 
25 import androidx.annotation.VisibleForTesting;
26 
27 import com.android.quickstep.RemoteAnimationTargets;
28 import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
29 import com.android.window.flags.Flags;
30 
31 import java.util.function.Supplier;
32 
33 public class TransformParams {
34 
35     public static FloatProperty<TransformParams> PROGRESS =
36             new FloatProperty<TransformParams>("progress") {
37         @Override
38         public void setValue(TransformParams params, float v) {
39             params.setProgress(v);
40         }
41 
42         @Override
43         public Float get(TransformParams params) {
44             return params.getProgress();
45         }
46     };
47 
48     public static FloatProperty<TransformParams> TARGET_ALPHA =
49             new FloatProperty<TransformParams>("targetAlpha") {
50         @Override
51         public void setValue(TransformParams params, float v) {
52             params.setTargetAlpha(v);
53         }
54 
55         @Override
56         public Float get(TransformParams params) {
57             return params.getTargetAlpha();
58         }
59     };
60 
61     /** Progress from 0 to 1 where 0 is in-app and 1 is Overview */
62     private float mProgress;
63     private float mTargetAlpha;
64     private float mCornerRadius;
65     private RemoteAnimationTargets mTargetSet;
66     private TransitionInfo mTransitionInfo;
67     private boolean mCornerRadiusIsOverridden;
68     private SurfaceTransactionApplier mSyncTransactionApplier;
69     private Supplier<SurfaceTransaction> mSurfaceTransactionSupplier;
70 
71     private BuilderProxy mHomeBuilderProxy = BuilderProxy.ALWAYS_VISIBLE;
72     private BuilderProxy mBaseBuilderProxy = BuilderProxy.ALWAYS_VISIBLE;
73 
TransformParams()74     public TransformParams() {
75         this(SurfaceTransaction::new);
76     }
77 
78     @VisibleForTesting
TransformParams(Supplier<SurfaceTransaction> surfaceTransactionSupplier)79     public TransformParams(Supplier<SurfaceTransaction> surfaceTransactionSupplier) {
80         mProgress = 0;
81         mTargetAlpha = 1;
82         mCornerRadius = -1;
83         mSurfaceTransactionSupplier = surfaceTransactionSupplier;
84     }
85 
86     /**
87      * Sets the progress of the transformation, where 0 is the source and 1 is the target. We
88      * automatically adjust properties such as currentRect and cornerRadius based on this
89      * progress, unless they are manually overridden by setting them on this TransformParams.
90      */
setProgress(float progress)91     public TransformParams setProgress(float progress) {
92         mProgress = progress;
93         return this;
94     }
95 
96     /**
97      * Sets the corner radius of the transformed window, in pixels. If unspecified (-1), we
98      * simply interpolate between the window's corner radius to the task view's corner radius,
99      * based on {@link #mProgress}.
100      */
setCornerRadius(float cornerRadius)101     public TransformParams setCornerRadius(float cornerRadius) {
102         mCornerRadius = cornerRadius;
103         return this;
104     }
105 
106     /**
107      * Specifies the alpha of the transformed window. Default is 1.
108      */
setTargetAlpha(float targetAlpha)109     public TransformParams setTargetAlpha(float targetAlpha) {
110         mTargetAlpha = targetAlpha;
111         return this;
112     }
113 
114     /**
115      * Specifies the set of RemoteAnimationTargetCompats that are included in the transformation
116      * that these TransformParams help compute. These TransformParams generally only apply to
117      * the targetSet.apps which match the targetSet.targetMode (e.g. the MODE_CLOSING app when
118      * swiping to home).
119      */
setTargetSet(RemoteAnimationTargets targetSet)120     public TransformParams setTargetSet(RemoteAnimationTargets targetSet) {
121         mTargetSet = targetSet;
122         return this;
123     }
124 
125     /**
126      * Provides the {@code TransitionInfo} of the transition that this transformation stems from.
127      */
setTransitionInfo(TransitionInfo transitionInfo)128     public TransformParams setTransitionInfo(TransitionInfo transitionInfo) {
129         mTransitionInfo = transitionInfo;
130         mCornerRadiusIsOverridden = false;
131         return this;
132     }
133 
134     /**
135      * Sets the SyncRtSurfaceTransactionApplierCompat that will apply the SurfaceParams that
136      * are computed based on these TransformParams.
137      */
setSyncTransactionApplier(SurfaceTransactionApplier applier)138     public TransformParams setSyncTransactionApplier(SurfaceTransactionApplier applier) {
139         mSyncTransactionApplier = applier;
140         return this;
141     }
142 
143     /**
144      * Sets an alternate function to control transform for non-target apps. The default
145      * implementation keeps the targets visible with alpha=1
146      */
setBaseBuilderProxy(BuilderProxy proxy)147     public TransformParams setBaseBuilderProxy(BuilderProxy proxy) {
148         mBaseBuilderProxy = proxy;
149         return this;
150     }
151 
152     /**
153      * Sets an alternate function to control transform for home target. The default
154      * implementation keeps the targets visible with alpha=1
155      */
setHomeBuilderProxy(BuilderProxy proxy)156     public TransformParams setHomeBuilderProxy(BuilderProxy proxy) {
157         mHomeBuilderProxy = proxy;
158         return this;
159     }
160 
161     /** Builds the SurfaceTransaction from the given BuilderProxy params. */
createSurfaceParams(BuilderProxy proxy)162     public SurfaceTransaction createSurfaceParams(BuilderProxy proxy) {
163         RemoteAnimationTargets targets = mTargetSet;
164         SurfaceTransaction transaction = mSurfaceTransactionSupplier.get();
165         if (targets == null) {
166             return transaction;
167         }
168         for (int i = 0; i < targets.unfilteredApps.length; i++) {
169             RemoteAnimationTarget app = targets.unfilteredApps[i];
170             SurfaceProperties builder = transaction.forSurface(app.leash);
171             BuilderProxy targetProxy =
172                     app.windowConfiguration.getActivityType() == ACTIVITY_TYPE_HOME
173                             ? mHomeBuilderProxy
174                             : (app.mode == targets.targetMode ? proxy : mBaseBuilderProxy);
175 
176             if (app.mode == targets.targetMode) {
177                 builder.setAlpha(getTargetAlpha());
178             }
179             targetProxy.onBuildTargetParams(builder, app, this);
180             // Override the corner radius for {@code app} with the leash used by Shell, so that it
181             // doesn't interfere with the window clip and corner radius applied here.
182             // Only override the corner radius once - so that we don't accidentally override at the
183             // end of transition after WM Shell has reset the corner radius of the task.
184             if (!mCornerRadiusIsOverridden) {
185                 overrideFreeformChangeLeashCornerRadiusToZero(app, transaction.getTransaction());
186             }
187         }
188         mCornerRadiusIsOverridden = true;
189 
190         // always put wallpaper layer to bottom.
191         final int wallpaperLength = targets.wallpapers != null ? targets.wallpapers.length : 0;
192         for (int i = 0; i < wallpaperLength; i++) {
193             RemoteAnimationTarget wallpaper = targets.wallpapers[i];
194             transaction.forSurface(wallpaper.leash).setLayer(Integer.MIN_VALUE);
195         }
196         return transaction;
197     }
198 
overrideFreeformChangeLeashCornerRadiusToZero( RemoteAnimationTarget app, SurfaceControl.Transaction transaction)199     private void overrideFreeformChangeLeashCornerRadiusToZero(
200             RemoteAnimationTarget app, SurfaceControl.Transaction transaction) {
201         if (!Flags.enableDesktopRecentsTransitionsCornersBugfix()) {
202             return;
203         }
204         if (app.taskInfo == null || !app.taskInfo.isFreeform()) {
205             return;
206         }
207 
208         SurfaceControl changeLeash = getChangeLeashForApp(app);
209         if (changeLeash != null) {
210             transaction.setCornerRadius(changeLeash, 0);
211         }
212     }
213 
getChangeLeashForApp(RemoteAnimationTarget app)214     private SurfaceControl getChangeLeashForApp(RemoteAnimationTarget app) {
215         if (mTransitionInfo == null) return null;
216         for (TransitionInfo.Change change : mTransitionInfo.getChanges()) {
217             if (change.getTaskInfo() == null) continue;
218             if (change.getTaskInfo().taskId == app.taskId) {
219                 return change.getLeash();
220             }
221         }
222         return null;
223     }
224 
225     // Public getters so outside packages can read the values.
226 
getProgress()227     public float getProgress() {
228         return mProgress;
229     }
230 
getTargetAlpha()231     public float getTargetAlpha() {
232         return mTargetAlpha;
233     }
234 
getCornerRadius()235     public float getCornerRadius() {
236         return mCornerRadius;
237     }
238 
getTargetSet()239     public RemoteAnimationTargets getTargetSet() {
240         return mTargetSet;
241     }
242 
applySurfaceParams(SurfaceTransaction builder)243     public void applySurfaceParams(SurfaceTransaction builder) {
244         if (mSyncTransactionApplier != null) {
245             mSyncTransactionApplier.scheduleApply(builder);
246         } else {
247             builder.getTransaction().apply();
248         }
249     }
250 
251     @FunctionalInterface
252     public interface BuilderProxy {
253 
254         BuilderProxy NO_OP = (builder, app, params) -> { };
255         BuilderProxy ALWAYS_VISIBLE = (builder, app, params) -> builder.setAlpha(1);
256 
onBuildTargetParams(SurfaceProperties builder, RemoteAnimationTarget app, TransformParams params)257         void onBuildTargetParams(SurfaceProperties builder,
258                 RemoteAnimationTarget app, TransformParams params);
259     }
260 }
261