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