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