blob: af7e91c5bfa60436a5ab7e3cc29f44010d295414 [file] [log] [blame]
Jorim Jaggi24bec7c2015-02-04 12:40:14 +01001/*
2 * Copyright (C) 2015 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.policy;
18
Adrian Roosdb1bc6b2016-04-14 17:49:43 -070019import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
20import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
Adrian Roose99bc052017-11-20 17:55:31 +010021import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
Adrian Roosdb1bc6b2016-04-14 17:49:43 -070022
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010023import android.app.StatusBarManager;
24import android.os.IBinder;
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010025import android.os.SystemClock;
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010026import android.view.View;
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010027import android.view.animation.Animation;
28import android.view.animation.AnimationSet;
29import android.view.animation.Interpolator;
30import android.view.animation.TranslateAnimation;
31
Jorim Jaggi2adba072016-03-03 13:43:39 +010032import com.android.server.LocalServices;
33import com.android.server.statusbar.StatusBarManagerInternal;
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010034
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010035/**
36 * Implements status bar specific behavior.
37 */
38public class StatusBarController extends BarController {
39
40 private static final long TRANSITION_DURATION = 120L;
41
42 private final AppTransitionListener mAppTransitionListener
43 = new AppTransitionListener() {
44
45 @Override
46 public void onAppTransitionPendingLocked() {
47 mHandler.post(new Runnable() {
48 @Override
49 public void run() {
Adrian Roosf2efdd82016-04-15 17:43:18 -070050 StatusBarManagerInternal statusbar = getStatusBarInternal();
51 if (statusbar != null) {
52 statusbar.appTransitionPending();
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010053 }
54 }
55 });
56 }
57
58 @Override
Jorim Jaggife762342016-10-13 14:33:27 +020059 public int onAppTransitionStartingLocked(int transit, IBinder openToken,
60 IBinder closeToken, final Animation openAnimation, final Animation closeAnimation) {
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010061 mHandler.post(new Runnable() {
62 @Override
63 public void run() {
Adrian Roosf2efdd82016-04-15 17:43:18 -070064 StatusBarManagerInternal statusbar = getStatusBarInternal();
65 if (statusbar != null) {
66 long startTime = calculateStatusBarTransitionStartTime(openAnimation,
67 closeAnimation);
68 long duration = closeAnimation != null || openAnimation != null
69 ? TRANSITION_DURATION : 0;
70 statusbar.appTransitionStarting(startTime, duration);
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010071 }
72 }
73 });
Jorim Jaggife762342016-10-13 14:33:27 +020074 return 0;
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010075 }
76
77 @Override
Jorim Jaggife762342016-10-13 14:33:27 +020078 public void onAppTransitionCancelledLocked(int transit) {
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010079 mHandler.post(new Runnable() {
80 @Override
81 public void run() {
Adrian Roosf2efdd82016-04-15 17:43:18 -070082 StatusBarManagerInternal statusbar = getStatusBarInternal();
83 if (statusbar != null) {
84 statusbar.appTransitionCancelled();
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010085 }
86 }
87 });
88 }
Jorim Jaggi2adba072016-03-03 13:43:39 +010089
90 @Override
91 public void onAppTransitionFinishedLocked(IBinder token) {
92 mHandler.post(new Runnable() {
93 @Override
94 public void run() {
95 StatusBarManagerInternal statusbar = LocalServices.getService(
96 StatusBarManagerInternal.class);
97 if (statusbar != null) {
98 statusbar.appTransitionFinished();
99 }
100 }
101 });
102 }
Jorim Jaggi24bec7c2015-02-04 12:40:14 +0100103 };
104
105 public StatusBarController() {
106 super("StatusBar",
107 View.STATUS_BAR_TRANSIENT,
108 View.STATUS_BAR_UNHIDE,
109 View.STATUS_BAR_TRANSLUCENT,
110 StatusBarManager.WINDOW_STATUS_BAR,
Adrian Roosdb1bc6b2016-04-14 17:49:43 -0700111 FLAG_TRANSLUCENT_STATUS,
Jorim Jaggi4fa78922015-11-30 17:13:56 -0800112 View.STATUS_BAR_TRANSPARENT);
Jorim Jaggi24bec7c2015-02-04 12:40:14 +0100113 }
114
Selim Cinek3a49ba22017-08-10 11:17:39 -0700115
116 public void setTopAppHidesStatusBar(boolean hidesStatusBar) {
117 StatusBarManagerInternal statusbar = getStatusBarInternal();
118 if (statusbar != null) {
119 statusbar.setTopAppHidesStatusBar(hidesStatusBar);
120 }
121 }
122
Adrian Roosdb1bc6b2016-04-14 17:49:43 -0700123 @Override
124 protected boolean skipAnimation() {
125 return mWin.getAttrs().height == MATCH_PARENT;
126 }
127
Jorim Jaggi24bec7c2015-02-04 12:40:14 +0100128 public AppTransitionListener getAppTransitionListener() {
129 return mAppTransitionListener;
130 }
131
132 /**
133 * For a given app transition with {@code openAnimation} and {@code closeAnimation}, this
134 * calculates the timings for the corresponding status bar transition.
135 *
136 * @return the desired start time of the status bar transition, in uptime millis
137 */
Filip Gruszczynski170192a2015-08-16 17:46:34 -0700138 private static long calculateStatusBarTransitionStartTime(Animation openAnimation,
Jorim Jaggi24bec7c2015-02-04 12:40:14 +0100139 Animation closeAnimation) {
140 if (openAnimation != null && closeAnimation != null) {
141 TranslateAnimation openTranslateAnimation = findTranslateAnimation(openAnimation);
142 TranslateAnimation closeTranslateAnimation = findTranslateAnimation(closeAnimation);
143 if (openTranslateAnimation != null) {
144
145 // Some interpolators are extremely quickly mostly finished, but not completely. For
146 // our purposes, we need to find the fraction for which ther interpolator is mostly
147 // there, and use that value for the calculation.
148 float t = findAlmostThereFraction(openTranslateAnimation.getInterpolator());
149 return SystemClock.uptimeMillis()
150 + openTranslateAnimation.getStartOffset()
151 + (long)(openTranslateAnimation.getDuration()*t) - TRANSITION_DURATION;
152 } else if (closeTranslateAnimation != null) {
153 return SystemClock.uptimeMillis();
154 } else {
155 return SystemClock.uptimeMillis();
156 }
157 } else {
158 return SystemClock.uptimeMillis();
159 }
160 }
161
162 /**
163 * Tries to find a {@link TranslateAnimation} inside the {@code animation}.
164 *
165 * @return the found animation, {@code null} otherwise
166 */
Filip Gruszczynski170192a2015-08-16 17:46:34 -0700167 private static TranslateAnimation findTranslateAnimation(Animation animation) {
Jorim Jaggi24bec7c2015-02-04 12:40:14 +0100168 if (animation instanceof TranslateAnimation) {
169 return (TranslateAnimation) animation;
170 } else if (animation instanceof AnimationSet) {
171 AnimationSet set = (AnimationSet) animation;
172 for (int i = 0; i < set.getAnimations().size(); i++) {
173 Animation a = set.getAnimations().get(i);
174 if (a instanceof TranslateAnimation) {
175 return (TranslateAnimation) a;
176 }
177 }
178 }
179 return null;
180 }
181
182 /**
183 * Binary searches for a {@code t} such that there exists a {@code -0.01 < eps < 0.01} for which
184 * {@code interpolator(t + eps) > 0.99}.
185 */
Filip Gruszczynski170192a2015-08-16 17:46:34 -0700186 private static float findAlmostThereFraction(Interpolator interpolator) {
Jorim Jaggi24bec7c2015-02-04 12:40:14 +0100187 float val = 0.5f;
188 float adj = 0.25f;
189 while (adj >= 0.01f) {
190 if (interpolator.getInterpolation(val) < 0.99f) {
191 val += adj;
192 } else {
193 val -= adj;
194 }
195 adj /= 2;
196 }
197 return val;
198 }
199}