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