blob: 9504d456bec8bdc381c33a839521b1546393634b [file] [log] [blame]
Jorim Jaggi21c39a72017-10-20 15:47:51 +02001/*
2 * Copyright (C) 2017 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
17package com.android.server.wm;
18
Jorim Jaggif5f9e122017-10-24 18:21:09 +020019import static com.android.server.wm.AnimationAdapter.STATUS_BAR_TRANSITION_DURATION;
20
Jorim Jaggi21c39a72017-10-20 15:47:51 +020021import android.graphics.Point;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020022import android.os.SystemClock;
Jorim Jaggi21c39a72017-10-20 15:47:51 +020023import android.view.SurfaceControl;
24import android.view.SurfaceControl.Transaction;
25import android.view.animation.Animation;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020026import android.view.animation.AnimationSet;
27import android.view.animation.Interpolator;
Jorim Jaggi21c39a72017-10-20 15:47:51 +020028import android.view.animation.Transformation;
Jorim Jaggif5f9e122017-10-24 18:21:09 +020029import android.view.animation.TranslateAnimation;
Jorim Jaggi21c39a72017-10-20 15:47:51 +020030
31import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
32
33/**
34 * Animation spec for regular window animations.
35 */
36public class WindowAnimationSpec implements AnimationSpec {
37
38 private Animation mAnimation;
39 private final Point mPosition = new Point();
Jorim Jaggia5e10572017-11-15 14:36:26 +010040 private final ThreadLocal<TmpValues> mThreadLocalTmps = ThreadLocal.withInitial(TmpValues::new);
Jorim Jaggi21c39a72017-10-20 15:47:51 +020041
42 public WindowAnimationSpec(Animation animation, Point position) {
43 mAnimation = animation;
44 mPosition.set(position.x, position.y);
45 }
46
47 @Override
48 public boolean getDetachWallpaper() {
49 return mAnimation.getDetachWallpaper();
50 }
51
52 @Override
53 public int getBackgroundColor() {
54 return mAnimation.getBackgroundColor();
55 }
56
57 @Override
58 public long getDuration() {
59 return mAnimation.computeDurationHint();
60 }
61
62 @Override
63 public void apply(Transaction t, SurfaceControl leash, long currentPlayTime) {
Jorim Jaggia5e10572017-11-15 14:36:26 +010064 final TmpValues tmp = mThreadLocalTmps.get();
Jorim Jaggi21c39a72017-10-20 15:47:51 +020065 tmp.transformation.clear();
66 mAnimation.getTransformation(currentPlayTime, tmp.transformation);
67 tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y);
68 t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats);
69 t.setAlpha(leash, tmp.transformation.getAlpha());
Jorim Jaggif5f9e122017-10-24 18:21:09 +020070 t.setWindowCrop(leash, tmp.transformation.getClipRect());
71 }
72
73 @Override
74 public long calculateStatusBarTransitionStartTime() {
75 TranslateAnimation openTranslateAnimation = findTranslateAnimation(mAnimation);
76 if (openTranslateAnimation != null) {
77
78 // Some interpolators are extremely quickly mostly finished, but not completely. For
79 // our purposes, we need to find the fraction for which ther interpolator is mostly
80 // there, and use that value for the calculation.
81 float t = findAlmostThereFraction(openTranslateAnimation.getInterpolator());
82 return SystemClock.uptimeMillis()
83 + openTranslateAnimation.getStartOffset()
84 + (long)(openTranslateAnimation.getDuration() * t)
85 - STATUS_BAR_TRANSITION_DURATION;
86 } else {
87 return SystemClock.uptimeMillis();
88 }
89 }
90
91 /**
92 * Tries to find a {@link TranslateAnimation} inside the {@code animation}.
93 *
94 * @return the found animation, {@code null} otherwise
95 */
96 private static TranslateAnimation findTranslateAnimation(Animation animation) {
97 if (animation instanceof TranslateAnimation) {
98 return (TranslateAnimation) animation;
99 } else if (animation instanceof AnimationSet) {
100 AnimationSet set = (AnimationSet) animation;
101 for (int i = 0; i < set.getAnimations().size(); i++) {
102 Animation a = set.getAnimations().get(i);
103 if (a instanceof TranslateAnimation) {
104 return (TranslateAnimation) a;
105 }
106 }
107 }
108 return null;
109 }
110
111 /**
112 * Binary searches for a {@code t} such that there exists a {@code -0.01 < eps < 0.01} for which
113 * {@code interpolator(t + eps) > 0.99}.
114 */
115 private static float findAlmostThereFraction(Interpolator interpolator) {
116 float val = 0.5f;
117 float adj = 0.25f;
118 while (adj >= 0.01f) {
119 if (interpolator.getInterpolation(val) < 0.99f) {
120 val += adj;
121 } else {
122 val -= adj;
123 }
124 adj /= 2;
125 }
126 return val;
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200127 }
128
Jorim Jaggia5e10572017-11-15 14:36:26 +0100129 private static class TmpValues {
Jorim Jaggi21c39a72017-10-20 15:47:51 +0200130 final Transformation transformation = new Transformation();
131 final float[] floats = new float[9];
132 }
133}