1 /* 2 * Copyright (C) 2021 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 17 package android.view; 18 19 import static android.view.InsetsAnimationControlImplProto.CURRENT_ALPHA; 20 import static android.view.InsetsAnimationControlImplProto.IS_CANCELLED; 21 import static android.view.InsetsAnimationControlImplProto.IS_FINISHED; 22 import static android.view.InsetsAnimationControlImplProto.PENDING_ALPHA; 23 import static android.view.InsetsAnimationControlImplProto.PENDING_FRACTION; 24 import static android.view.InsetsAnimationControlImplProto.PENDING_INSETS; 25 import static android.view.InsetsAnimationControlImplProto.SHOWN_ON_FINISH; 26 import static android.view.InsetsAnimationControlImplProto.TMP_MATRIX; 27 import static android.view.InsetsController.ANIMATION_TYPE_RESIZE; 28 29 import android.animation.Animator; 30 import android.animation.AnimatorListenerAdapter; 31 import android.animation.ValueAnimator; 32 import android.graphics.Insets; 33 import android.graphics.Rect; 34 import android.util.SparseArray; 35 import android.util.proto.ProtoOutputStream; 36 import android.view.WindowInsets.Type.InsetsType; 37 import android.view.WindowInsetsAnimation.Bounds; 38 import android.view.animation.Interpolator; 39 import android.view.inputmethod.ImeTracker; 40 41 /** 42 * Runs a fake animation of resizing insets to produce insets animation callbacks. 43 * @hide 44 */ 45 public class InsetsResizeAnimationRunner implements InsetsAnimationControlRunner, 46 InternalInsetsAnimationController, WindowInsetsAnimationControlListener { 47 48 private final InsetsState mFromState; 49 private final InsetsState mToState; 50 private final @InsetsType int mTypes; 51 private final WindowInsetsAnimation mAnimation; 52 private final InsetsAnimationControlCallbacks mController; 53 private ValueAnimator mAnimator; 54 private boolean mCancelled; 55 private boolean mFinished; 56 InsetsResizeAnimationRunner(Rect frame, InsetsState fromState, InsetsState toState, Interpolator interpolator, long duration, @InsetsType int types, InsetsAnimationControlCallbacks controller)57 public InsetsResizeAnimationRunner(Rect frame, InsetsState fromState, InsetsState toState, 58 Interpolator interpolator, long duration, @InsetsType int types, 59 InsetsAnimationControlCallbacks controller) { 60 mFromState = fromState; 61 mToState = toState; 62 mTypes = types; 63 mController = controller; 64 mAnimation = new WindowInsetsAnimation(types, interpolator, duration); 65 mAnimation.setAlpha(1f); 66 final Insets fromInsets = fromState.calculateInsets( 67 frame, types, false /* ignoreVisibility */); 68 final Insets toInsets = toState.calculateInsets( 69 frame, types, false /* ignoreVisibility */); 70 controller.startAnimation(this, this, types, mAnimation, 71 new Bounds(Insets.min(fromInsets, toInsets), Insets.max(fromInsets, toInsets))); 72 } 73 74 @Override getTypes()75 public int getTypes() { 76 return mTypes; 77 } 78 79 @Override getControllingTypes()80 public int getControllingTypes() { 81 return mTypes; 82 } 83 84 @Override getAnimation()85 public WindowInsetsAnimation getAnimation() { 86 return mAnimation; 87 } 88 89 @Override getAnimationType()90 public int getAnimationType() { 91 return ANIMATION_TYPE_RESIZE; 92 } 93 94 @Override getStatsToken()95 public ImeTracker.Token getStatsToken() { 96 // Return null as resizing the IME view is not explicitly tracked. 97 return null; 98 } 99 100 @Override cancel()101 public void cancel() { 102 if (mCancelled || mFinished) { 103 return; 104 } 105 mCancelled = true; 106 if (mAnimator != null) { 107 mAnimator.cancel(); 108 } 109 } 110 111 @Override isCancelled()112 public boolean isCancelled() { 113 return mCancelled; 114 } 115 116 @Override onReady(WindowInsetsAnimationController controller, int types)117 public void onReady(WindowInsetsAnimationController controller, int types) { 118 if (mCancelled) { 119 return; 120 } 121 mAnimator = ValueAnimator.ofFloat(0f, 1f); 122 mAnimator.setDuration(mAnimation.getDurationMillis()); 123 mAnimator.addUpdateListener(animation -> { 124 mAnimation.setFraction(animation.getAnimatedFraction()); 125 mController.scheduleApplyChangeInsets(InsetsResizeAnimationRunner.this); 126 }); 127 mAnimator.addListener(new AnimatorListenerAdapter() { 128 129 @Override 130 public void onAnimationEnd(Animator animation) { 131 mFinished = true; 132 mController.scheduleApplyChangeInsets(InsetsResizeAnimationRunner.this); 133 } 134 }); 135 mAnimator.start(); 136 } 137 138 @Override applyChangeInsets(InsetsState outState)139 public boolean applyChangeInsets(InsetsState outState) { 140 if (mCancelled) { 141 return false; 142 } 143 final float fraction = mAnimation.getInterpolatedFraction(); 144 InsetsState.traverse(mFromState, mToState, new InsetsState.OnTraverseCallbacks() { 145 @Override 146 public void onIdMatch(InsetsSource fromSource, InsetsSource toSource) { 147 final Rect fromFrame = fromSource.getFrame(); 148 final Rect toFrame = toSource.getFrame(); 149 final Rect frame = new Rect( 150 (int) (fromFrame.left + fraction * (toFrame.left - fromFrame.left)), 151 (int) (fromFrame.top + fraction * (toFrame.top - fromFrame.top)), 152 (int) (fromFrame.right + fraction * (toFrame.right - fromFrame.right)), 153 (int) (fromFrame.bottom + fraction * (toFrame.bottom - fromFrame.bottom))); 154 final InsetsSource source = 155 new InsetsSource(fromSource.getId(), fromSource.getType()); 156 source.setFrame(frame); 157 source.setVisible(toSource.isVisible()); 158 outState.addSource(source); 159 } 160 }); 161 if (mFinished) { 162 mController.notifyFinished(this, true /* shown */); 163 } 164 return mFinished; 165 } 166 167 @Override dumpDebug(ProtoOutputStream proto, long fieldId)168 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 169 final long token = proto.start(fieldId); 170 proto.write(IS_CANCELLED, mCancelled); 171 proto.write(IS_FINISHED, mFinished); 172 proto.write(TMP_MATRIX, "null"); 173 proto.write(PENDING_INSETS, "null"); 174 proto.write(PENDING_FRACTION, mAnimation.getInterpolatedFraction()); 175 proto.write(SHOWN_ON_FINISH, true); 176 proto.write(CURRENT_ALPHA, 1f); 177 proto.write(PENDING_ALPHA, 1f); 178 proto.end(token); 179 } 180 181 @Override getHiddenStateInsets()182 public Insets getHiddenStateInsets() { 183 return Insets.NONE; 184 } 185 186 @Override getShownStateInsets()187 public Insets getShownStateInsets() { 188 return Insets.NONE; 189 } 190 191 @Override getCurrentInsets()192 public Insets getCurrentInsets() { 193 return Insets.NONE; 194 } 195 196 @Override getCurrentFraction()197 public float getCurrentFraction() { 198 return 0; 199 } 200 201 @Override getCurrentAlpha()202 public float getCurrentAlpha() { 203 return 0; 204 } 205 206 @Override setInsetsAndAlpha(Insets insets, float alpha, float fraction)207 public void setInsetsAndAlpha(Insets insets, float alpha, float fraction) { 208 } 209 210 @Override finish(boolean shown)211 public void finish(boolean shown) { 212 } 213 214 @Override isFinished()215 public boolean isFinished() { 216 return false; 217 } 218 219 @Override notifyControlRevoked(int types)220 public void notifyControlRevoked(int types) { 221 } 222 223 @Override updateSurfacePosition(SparseArray<InsetsSourceControl> controls)224 public void updateSurfacePosition(SparseArray<InsetsSourceControl> controls) { 225 } 226 227 @Override hasZeroInsetsIme()228 public boolean hasZeroInsetsIme() { 229 return false; 230 } 231 232 @Override setReadyDispatched(boolean dispatched)233 public void setReadyDispatched(boolean dispatched) { 234 } 235 236 @Override onFinished(WindowInsetsAnimationController controller)237 public void onFinished(WindowInsetsAnimationController controller) { 238 } 239 240 @Override onCancelled(WindowInsetsAnimationController controller)241 public void onCancelled(WindowInsetsAnimationController controller) { 242 } 243 } 244