blob: b1792358be5380a69f48d338ee36b97e61afade8 [file] [log] [blame]
John Spurlock27735a42013-08-14 17:57:38 -04001/*
2 * Copyright (C) 2013 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
Jorim Jaggib10e33f2015-02-04 21:57:40 +010017package com.android.server.policy;
John Spurlock27735a42013-08-14 17:57:38 -040018
19import android.app.StatusBarManager;
20import android.os.Handler;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -080021import android.os.Message;
John Spurlockb77edbf2013-08-21 21:04:12 -040022import android.os.SystemClock;
John Spurlock27735a42013-08-14 17:57:38 -040023import android.util.Slog;
24import android.view.View;
Adrian Roosdb1bc6b2016-04-14 17:49:43 -070025import android.view.ViewGroup;
John Spurlockbd957402013-10-03 11:38:39 -040026import android.view.WindowManager;
John Spurlock27735a42013-08-14 17:57:38 -040027import android.view.WindowManagerPolicy.WindowState;
28
Adrian Roosf2efdd82016-04-15 17:43:18 -070029import com.android.server.LocalServices;
30import com.android.server.statusbar.StatusBarManagerInternal;
John Spurlock27735a42013-08-14 17:57:38 -040031
32import java.io.PrintWriter;
33
34/**
35 * Controls state/behavior specific to a system bar window.
36 */
37public class BarController {
John Spurlock7edfbca2013-09-14 11:58:55 -040038 private static final boolean DEBUG = false;
John Spurlock27735a42013-08-14 17:57:38 -040039
40 private static final int TRANSIENT_BAR_NONE = 0;
John Spurlockf25706f2013-11-07 18:02:43 -050041 private static final int TRANSIENT_BAR_SHOW_REQUESTED = 1;
42 private static final int TRANSIENT_BAR_SHOWING = 2;
43 private static final int TRANSIENT_BAR_HIDING = 3;
John Spurlock27735a42013-08-14 17:57:38 -040044
John Spurlockbd957402013-10-03 11:38:39 -040045 private static final int TRANSLUCENT_ANIMATION_DELAY_MS = 1000;
John Spurlockb77edbf2013-08-21 21:04:12 -040046
Casey Burkhardt048c2bc2016-12-08 16:09:20 -080047 private static final int MSG_NAV_BAR_VISIBILITY_CHANGED = 1;
48
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010049 protected final String mTag;
John Spurlock27735a42013-08-14 17:57:38 -040050 private final int mTransientFlag;
John Spurlock5b9145b2013-08-20 15:13:47 -040051 private final int mUnhideFlag;
John Spurlockbd957402013-10-03 11:38:39 -040052 private final int mTranslucentFlag;
Jorim Jaggi4fa78922015-11-30 17:13:56 -080053 private final int mTransparentFlag;
John Spurlock27735a42013-08-14 17:57:38 -040054 private final int mStatusBarManagerId;
John Spurlockbd957402013-10-03 11:38:39 -040055 private final int mTranslucentWmFlag;
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010056 protected final Handler mHandler;
John Spurlock27735a42013-08-14 17:57:38 -040057 private final Object mServiceAquireLock = new Object();
Adrian Roosf2efdd82016-04-15 17:43:18 -070058 protected StatusBarManagerInternal mStatusBarInternal;
John Spurlock27735a42013-08-14 17:57:38 -040059
Adrian Roosdb1bc6b2016-04-14 17:49:43 -070060 protected WindowState mWin;
John Spurlockd4e65752013-08-28 14:17:09 -040061 private int mState = StatusBarManager.WINDOW_STATE_SHOWING;
John Spurlock27735a42013-08-14 17:57:38 -040062 private int mTransientBarState;
63 private boolean mPendingShow;
John Spurlockbd957402013-10-03 11:38:39 -040064 private long mLastTranslucent;
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -070065 private boolean mShowTransparent;
66 private boolean mSetUnHideFlagWhenNextTransparent;
67 private boolean mNoAnimationOnNextShow;
John Spurlock27735a42013-08-14 17:57:38 -040068
Casey Burkhardt048c2bc2016-12-08 16:09:20 -080069 private OnBarVisibilityChangedListener mVisibilityChangeListener;
70
John Spurlockbd957402013-10-03 11:38:39 -040071 public BarController(String tag, int transientFlag, int unhideFlag, int translucentFlag,
Jorim Jaggi4fa78922015-11-30 17:13:56 -080072 int statusBarManagerId, int translucentWmFlag, int transparentFlag) {
John Spurlock27735a42013-08-14 17:57:38 -040073 mTag = "BarController." + tag;
74 mTransientFlag = transientFlag;
John Spurlock5b9145b2013-08-20 15:13:47 -040075 mUnhideFlag = unhideFlag;
John Spurlockbd957402013-10-03 11:38:39 -040076 mTranslucentFlag = translucentFlag;
John Spurlock27735a42013-08-14 17:57:38 -040077 mStatusBarManagerId = statusBarManagerId;
John Spurlockbd957402013-10-03 11:38:39 -040078 mTranslucentWmFlag = translucentWmFlag;
Jorim Jaggi4fa78922015-11-30 17:13:56 -080079 mTransparentFlag = transparentFlag;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -080080 mHandler = new BarHandler();
John Spurlock27735a42013-08-14 17:57:38 -040081 }
82
83 public void setWindow(WindowState win) {
84 mWin = win;
85 }
86
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -070087 public void setShowTransparent(boolean transparent) {
88 if (transparent != mShowTransparent) {
89 mShowTransparent = transparent;
90 mSetUnHideFlagWhenNextTransparent = transparent;
91 mNoAnimationOnNextShow = true;
92 }
93 }
94
John Spurlock27735a42013-08-14 17:57:38 -040095 public void showTransient() {
96 if (mWin != null) {
John Spurlockf25706f2013-11-07 18:02:43 -050097 setTransientBarState(TRANSIENT_BAR_SHOW_REQUESTED);
John Spurlock27735a42013-08-14 17:57:38 -040098 }
99 }
100
101 public boolean isTransientShowing() {
102 return mTransientBarState == TRANSIENT_BAR_SHOWING;
103 }
104
John Spurlockf25706f2013-11-07 18:02:43 -0500105 public boolean isTransientShowRequested() {
106 return mTransientBarState == TRANSIENT_BAR_SHOW_REQUESTED;
107 }
108
John Spurlockbd957402013-10-03 11:38:39 -0400109 public boolean wasRecentlyTranslucent() {
110 return (SystemClock.uptimeMillis() - mLastTranslucent) < TRANSLUCENT_ANIMATION_DELAY_MS;
John Spurlockb77edbf2013-08-21 21:04:12 -0400111 }
112
John Spurlock5b9145b2013-08-20 15:13:47 -0400113 public void adjustSystemUiVisibilityLw(int oldVis, int vis) {
John Spurlock27735a42013-08-14 17:57:38 -0400114 if (mWin != null && mTransientBarState == TRANSIENT_BAR_SHOWING &&
John Spurlock5b9145b2013-08-20 15:13:47 -0400115 (vis & mTransientFlag) == 0) {
116 // sysui requests hide
John Spurlock27735a42013-08-14 17:57:38 -0400117 setTransientBarState(TRANSIENT_BAR_HIDING);
118 setBarShowingLw(false);
John Spurlock5b9145b2013-08-20 15:13:47 -0400119 } else if (mWin != null && (oldVis & mUnhideFlag) != 0 && (vis & mUnhideFlag) == 0) {
120 // sysui ready to unhide
121 setBarShowingLw(true);
John Spurlock27735a42013-08-14 17:57:38 -0400122 }
123 }
124
John Spurlockbd957402013-10-03 11:38:39 -0400125 public int applyTranslucentFlagLw(WindowState win, int vis, int oldVis) {
126 if (mWin != null) {
127 if (win != null && (win.getAttrs().privateFlags
128 & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) == 0) {
Adrian Roosea562512014-05-05 13:33:03 +0200129 int fl = PolicyControl.getWindowFlags(win, null);
130 if ((fl & mTranslucentWmFlag) != 0) {
John Spurlockbd957402013-10-03 11:38:39 -0400131 vis |= mTranslucentFlag;
132 } else {
133 vis &= ~mTranslucentFlag;
134 }
Adrian Roosea562512014-05-05 13:33:03 +0200135 if ((fl & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
Jorim Jaggi4fa78922015-11-30 17:13:56 -0800136 vis |= mTransparentFlag;
Adrian Roosea562512014-05-05 13:33:03 +0200137 } else {
Jorim Jaggi4fa78922015-11-30 17:13:56 -0800138 vis &= ~mTransparentFlag;
Adrian Roosea562512014-05-05 13:33:03 +0200139 }
John Spurlockbd957402013-10-03 11:38:39 -0400140 } else {
141 vis = (vis & ~mTranslucentFlag) | (oldVis & mTranslucentFlag);
Jorim Jaggi4fa78922015-11-30 17:13:56 -0800142 vis = (vis & ~mTransparentFlag) | (oldVis & mTransparentFlag);
John Spurlockbd957402013-10-03 11:38:39 -0400143 }
144 }
145 return vis;
146 }
147
John Spurlock27735a42013-08-14 17:57:38 -0400148 public boolean setBarShowingLw(final boolean show) {
149 if (mWin == null) return false;
John Spurlock27735a42013-08-14 17:57:38 -0400150 if (show && mTransientBarState == TRANSIENT_BAR_HIDING) {
151 mPendingShow = true;
152 return false;
153 }
John Spurlock7edfbca2013-09-14 11:58:55 -0400154 final boolean wasVis = mWin.isVisibleLw();
155 final boolean wasAnim = mWin.isAnimatingLw();
Adrian Roosdb1bc6b2016-04-14 17:49:43 -0700156 final boolean change = show ? mWin.showLw(!mNoAnimationOnNextShow && !skipAnimation())
157 : mWin.hideLw(!mNoAnimationOnNextShow && !skipAnimation());
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -0700158 mNoAnimationOnNextShow = false;
John Spurlock7edfbca2013-09-14 11:58:55 -0400159 final int state = computeStateLw(wasVis, wasAnim, mWin, change);
John Spurlockc23bd802013-11-06 12:20:38 -0500160 final boolean stateChanged = updateStateLw(state);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800161
162 if (change && (mVisibilityChangeListener != null)) {
163 mHandler.obtainMessage(MSG_NAV_BAR_VISIBILITY_CHANGED, show ? 1 : 0, 0).sendToTarget();
164 }
165
John Spurlockc23bd802013-11-06 12:20:38 -0500166 return change || stateChanged;
John Spurlock7edfbca2013-09-14 11:58:55 -0400167 }
168
Casey Burkhardt469a2082017-06-13 20:12:42 -0700169 void setOnBarVisibilityChangedListener(OnBarVisibilityChangedListener listener,
170 boolean invokeWithState) {
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800171 mVisibilityChangeListener = listener;
Casey Burkhardt469a2082017-06-13 20:12:42 -0700172 if (invokeWithState) {
173 // Optionally report the initial window state for initialization purposes
174 mHandler.obtainMessage(MSG_NAV_BAR_VISIBILITY_CHANGED,
175 (mState == StatusBarManager.WINDOW_STATE_SHOWING) ? 1 : 0, 0).sendToTarget();
176 }
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800177 }
178
Adrian Roosdb1bc6b2016-04-14 17:49:43 -0700179 protected boolean skipAnimation() {
180 return false;
181 }
182
John Spurlock7edfbca2013-09-14 11:58:55 -0400183 private int computeStateLw(boolean wasVis, boolean wasAnim, WindowState win, boolean change) {
Adrian Roos76d2fe42015-07-09 14:54:08 -0700184 if (win.isDrawnLw()) {
John Spurlock7edfbca2013-09-14 11:58:55 -0400185 final boolean vis = win.isVisibleLw();
186 final boolean anim = win.isAnimatingLw();
187 if (mState == StatusBarManager.WINDOW_STATE_HIDING && !change && !vis) {
188 return StatusBarManager.WINDOW_STATE_HIDDEN;
John Spurlockc23bd802013-11-06 12:20:38 -0500189 } else if (mState == StatusBarManager.WINDOW_STATE_HIDDEN && vis) {
190 return StatusBarManager.WINDOW_STATE_SHOWING;
John Spurlock7edfbca2013-09-14 11:58:55 -0400191 } else if (change) {
192 if (wasVis && vis && !wasAnim && anim) {
193 return StatusBarManager.WINDOW_STATE_HIDING;
194 } else {
195 return StatusBarManager.WINDOW_STATE_SHOWING;
196 }
197 }
John Spurlock5b9145b2013-08-20 15:13:47 -0400198 }
John Spurlock7edfbca2013-09-14 11:58:55 -0400199 return mState;
John Spurlock5b9145b2013-08-20 15:13:47 -0400200 }
201
John Spurlockc23bd802013-11-06 12:20:38 -0500202 private boolean updateStateLw(final int state) {
John Spurlock5b9145b2013-08-20 15:13:47 -0400203 if (state != mState) {
204 mState = state;
John Spurlock0ec64c62013-08-26 15:37:58 -0400205 if (DEBUG) Slog.d(mTag, "mState: " + StatusBarManager.windowStateToString(state));
John Spurlock5b9145b2013-08-20 15:13:47 -0400206 mHandler.post(new Runnable() {
207 @Override
208 public void run() {
Adrian Roosf2efdd82016-04-15 17:43:18 -0700209 StatusBarManagerInternal statusbar = getStatusBarInternal();
210 if (statusbar != null) {
211 statusbar.setWindowState(mStatusBarManagerId, state);
John Spurlock5b9145b2013-08-20 15:13:47 -0400212 }
213 }
214 });
John Spurlockc23bd802013-11-06 12:20:38 -0500215 return true;
John Spurlock5b9145b2013-08-20 15:13:47 -0400216 }
John Spurlockc23bd802013-11-06 12:20:38 -0500217 return false;
John Spurlock27735a42013-08-14 17:57:38 -0400218 }
219
220 public boolean checkHiddenLw() {
Adrian Roos76d2fe42015-07-09 14:54:08 -0700221 if (mWin != null && mWin.isDrawnLw()) {
John Spurlock5b9145b2013-08-20 15:13:47 -0400222 if (!mWin.isVisibleLw() && !mWin.isAnimatingLw()) {
John Spurlock7edfbca2013-09-14 11:58:55 -0400223 updateStateLw(StatusBarManager.WINDOW_STATE_HIDDEN);
John Spurlock27735a42013-08-14 17:57:38 -0400224 }
John Spurlock5b9145b2013-08-20 15:13:47 -0400225 if (mTransientBarState == TRANSIENT_BAR_HIDING && !mWin.isVisibleLw()) {
226 // Finished animating out, clean up and reset style
227 setTransientBarState(TRANSIENT_BAR_NONE);
228 if (mPendingShow) {
229 setBarShowingLw(true);
230 mPendingShow = false;
231 }
232 return true;
233 }
John Spurlock27735a42013-08-14 17:57:38 -0400234 }
235 return false;
236 }
237
238 public boolean checkShowTransientBarLw() {
239 if (mTransientBarState == TRANSIENT_BAR_SHOWING) {
240 if (DEBUG) Slog.d(mTag, "Not showing transient bar, already shown");
241 return false;
John Spurlockf25706f2013-11-07 18:02:43 -0500242 } else if (mTransientBarState == TRANSIENT_BAR_SHOW_REQUESTED) {
243 if (DEBUG) Slog.d(mTag, "Not showing transient bar, already requested");
244 return false;
John Spurlock27735a42013-08-14 17:57:38 -0400245 } else if (mWin == null) {
246 if (DEBUG) Slog.d(mTag, "Not showing transient bar, bar doesn't exist");
247 return false;
248 } else if (mWin.isDisplayedLw()) {
249 if (DEBUG) Slog.d(mTag, "Not showing transient bar, bar already visible");
250 return false;
251 } else {
252 return true;
253 }
254 }
255
John Spurlockbd957402013-10-03 11:38:39 -0400256 public int updateVisibilityLw(boolean transientAllowed, int oldVis, int vis) {
John Spurlock27735a42013-08-14 17:57:38 -0400257 if (mWin == null) return vis;
John Spurlockf25706f2013-11-07 18:02:43 -0500258 if (isTransientShowing() || isTransientShowRequested()) { // transient bar requested
John Spurlockbd957402013-10-03 11:38:39 -0400259 if (transientAllowed) {
John Spurlock27735a42013-08-14 17:57:38 -0400260 vis |= mTransientFlag;
261 if ((oldVis & mTransientFlag) == 0) {
John Spurlock5b9145b2013-08-20 15:13:47 -0400262 vis |= mUnhideFlag; // tell sysui we're ready to unhide
John Spurlock27735a42013-08-14 17:57:38 -0400263 }
John Spurlockf25706f2013-11-07 18:02:43 -0500264 setTransientBarState(TRANSIENT_BAR_SHOWING); // request accepted
John Spurlock27735a42013-08-14 17:57:38 -0400265 } else {
266 setTransientBarState(TRANSIENT_BAR_NONE); // request denied
267 }
268 }
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -0700269 if (mShowTransparent) {
Jorim Jaggi4fa78922015-11-30 17:13:56 -0800270 vis |= mTransparentFlag;
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -0700271 if (mSetUnHideFlagWhenNextTransparent) {
272 vis |= mUnhideFlag;
273 mSetUnHideFlagWhenNextTransparent = false;
274 }
275 }
John Spurlock27735a42013-08-14 17:57:38 -0400276 if (mTransientBarState != TRANSIENT_BAR_NONE) {
277 vis |= mTransientFlag; // ignore clear requests until transition completes
278 vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE; // never show transient bars in low profile
279 }
Adrian Roosea562512014-05-05 13:33:03 +0200280 if ((vis & mTranslucentFlag) != 0 || (oldVis & mTranslucentFlag) != 0 ||
Jorim Jaggi4fa78922015-11-30 17:13:56 -0800281 ((vis | oldVis) & mTransparentFlag) != 0) {
John Spurlockbd957402013-10-03 11:38:39 -0400282 mLastTranslucent = SystemClock.uptimeMillis();
John Spurlockb77edbf2013-08-21 21:04:12 -0400283 }
John Spurlock27735a42013-08-14 17:57:38 -0400284 return vis;
285 }
286
287 private void setTransientBarState(int state) {
288 if (mWin != null && state != mTransientBarState) {
John Spurlockb77edbf2013-08-21 21:04:12 -0400289 if (mTransientBarState == TRANSIENT_BAR_SHOWING || state == TRANSIENT_BAR_SHOWING) {
John Spurlockbd957402013-10-03 11:38:39 -0400290 mLastTranslucent = SystemClock.uptimeMillis();
John Spurlockb77edbf2013-08-21 21:04:12 -0400291 }
John Spurlock27735a42013-08-14 17:57:38 -0400292 mTransientBarState = state;
John Spurlock0ec64c62013-08-26 15:37:58 -0400293 if (DEBUG) Slog.d(mTag, "mTransientBarState: " + transientBarStateToString(state));
John Spurlock27735a42013-08-14 17:57:38 -0400294 }
295 }
296
Adrian Roosf2efdd82016-04-15 17:43:18 -0700297 protected StatusBarManagerInternal getStatusBarInternal() {
John Spurlock27735a42013-08-14 17:57:38 -0400298 synchronized (mServiceAquireLock) {
Adrian Roosf2efdd82016-04-15 17:43:18 -0700299 if (mStatusBarInternal == null) {
300 mStatusBarInternal = LocalServices.getService(StatusBarManagerInternal.class);
John Spurlock27735a42013-08-14 17:57:38 -0400301 }
Adrian Roosf2efdd82016-04-15 17:43:18 -0700302 return mStatusBarInternal;
John Spurlock27735a42013-08-14 17:57:38 -0400303 }
304 }
305
306 private static String transientBarStateToString(int state) {
307 if (state == TRANSIENT_BAR_HIDING) return "TRANSIENT_BAR_HIDING";
308 if (state == TRANSIENT_BAR_SHOWING) return "TRANSIENT_BAR_SHOWING";
John Spurlockf25706f2013-11-07 18:02:43 -0500309 if (state == TRANSIENT_BAR_SHOW_REQUESTED) return "TRANSIENT_BAR_SHOW_REQUESTED";
John Spurlock27735a42013-08-14 17:57:38 -0400310 if (state == TRANSIENT_BAR_NONE) return "TRANSIENT_BAR_NONE";
311 throw new IllegalArgumentException("Unknown state " + state);
312 }
313
314 public void dump(PrintWriter pw, String prefix) {
315 if (mWin != null) {
John Spurlock0ec64c62013-08-26 15:37:58 -0400316 pw.print(prefix); pw.println(mTag);
John Spurlockd4e65752013-08-28 14:17:09 -0400317 pw.print(prefix); pw.print(" "); pw.print("mState"); pw.print('=');
John Spurlock0ec64c62013-08-26 15:37:58 -0400318 pw.println(StatusBarManager.windowStateToString(mState));
John Spurlockd4e65752013-08-28 14:17:09 -0400319 pw.print(prefix); pw.print(" "); pw.print("mTransientBar"); pw.print('=');
John Spurlock27735a42013-08-14 17:57:38 -0400320 pw.println(transientBarStateToString(mTransientBarState));
321 }
322 }
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800323
324 private class BarHandler extends Handler {
325 @Override
326 public void handleMessage(Message msg) {
327 switch (msg.what) {
328 case MSG_NAV_BAR_VISIBILITY_CHANGED:
329 final boolean visible = msg.arg1 != 0;
330 if (mVisibilityChangeListener != null) {
331 mVisibilityChangeListener.onBarVisibilityChanged(visible);
332 }
333 break;
334 }
335 }
336 }
337
338 interface OnBarVisibilityChangedListener {
339 void onBarVisibilityChanged(boolean visible);
340 }
John Spurlock27735a42013-08-14 17:57:38 -0400341}