blob: 0c80ffa55716dde494f946b46e7b0369e039903d [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;
21import android.os.RemoteException;
22import android.os.ServiceManager;
John Spurlockb77edbf2013-08-21 21:04:12 -040023import android.os.SystemClock;
John Spurlock27735a42013-08-14 17:57:38 -040024import android.util.Slog;
25import android.view.View;
John Spurlockbd957402013-10-03 11:38:39 -040026import android.view.WindowManager;
John Spurlock27735a42013-08-14 17:57:38 -040027import android.view.WindowManagerPolicy.WindowState;
28
29import com.android.internal.statusbar.IStatusBarService;
30
31import java.io.PrintWriter;
32
33/**
34 * Controls state/behavior specific to a system bar window.
35 */
36public class BarController {
John Spurlock7edfbca2013-09-14 11:58:55 -040037 private static final boolean DEBUG = false;
John Spurlock27735a42013-08-14 17:57:38 -040038
39 private static final int TRANSIENT_BAR_NONE = 0;
John Spurlockf25706f2013-11-07 18:02:43 -050040 private static final int TRANSIENT_BAR_SHOW_REQUESTED = 1;
41 private static final int TRANSIENT_BAR_SHOWING = 2;
42 private static final int TRANSIENT_BAR_HIDING = 3;
John Spurlock27735a42013-08-14 17:57:38 -040043
John Spurlockbd957402013-10-03 11:38:39 -040044 private static final int TRANSLUCENT_ANIMATION_DELAY_MS = 1000;
John Spurlockb77edbf2013-08-21 21:04:12 -040045
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010046 protected final String mTag;
John Spurlock27735a42013-08-14 17:57:38 -040047 private final int mTransientFlag;
John Spurlock5b9145b2013-08-20 15:13:47 -040048 private final int mUnhideFlag;
John Spurlockbd957402013-10-03 11:38:39 -040049 private final int mTranslucentFlag;
Jorim Jaggi4fa78922015-11-30 17:13:56 -080050 private final int mTransparentFlag;
John Spurlock27735a42013-08-14 17:57:38 -040051 private final int mStatusBarManagerId;
John Spurlockbd957402013-10-03 11:38:39 -040052 private final int mTranslucentWmFlag;
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010053 protected final Handler mHandler;
John Spurlock27735a42013-08-14 17:57:38 -040054 private final Object mServiceAquireLock = new Object();
Jorim Jaggi24bec7c2015-02-04 12:40:14 +010055 protected IStatusBarService mStatusBarService;
John Spurlock27735a42013-08-14 17:57:38 -040056
57 private WindowState mWin;
John Spurlockd4e65752013-08-28 14:17:09 -040058 private int mState = StatusBarManager.WINDOW_STATE_SHOWING;
John Spurlock27735a42013-08-14 17:57:38 -040059 private int mTransientBarState;
60 private boolean mPendingShow;
John Spurlockbd957402013-10-03 11:38:39 -040061 private long mLastTranslucent;
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -070062 private boolean mShowTransparent;
63 private boolean mSetUnHideFlagWhenNextTransparent;
64 private boolean mNoAnimationOnNextShow;
John Spurlock27735a42013-08-14 17:57:38 -040065
John Spurlockbd957402013-10-03 11:38:39 -040066 public BarController(String tag, int transientFlag, int unhideFlag, int translucentFlag,
Jorim Jaggi4fa78922015-11-30 17:13:56 -080067 int statusBarManagerId, int translucentWmFlag, int transparentFlag) {
John Spurlock27735a42013-08-14 17:57:38 -040068 mTag = "BarController." + tag;
69 mTransientFlag = transientFlag;
John Spurlock5b9145b2013-08-20 15:13:47 -040070 mUnhideFlag = unhideFlag;
John Spurlockbd957402013-10-03 11:38:39 -040071 mTranslucentFlag = translucentFlag;
John Spurlock27735a42013-08-14 17:57:38 -040072 mStatusBarManagerId = statusBarManagerId;
John Spurlockbd957402013-10-03 11:38:39 -040073 mTranslucentWmFlag = translucentWmFlag;
Jorim Jaggi4fa78922015-11-30 17:13:56 -080074 mTransparentFlag = transparentFlag;
John Spurlock27735a42013-08-14 17:57:38 -040075 mHandler = new Handler();
76 }
77
78 public void setWindow(WindowState win) {
79 mWin = win;
80 }
81
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -070082 public void setShowTransparent(boolean transparent) {
83 if (transparent != mShowTransparent) {
84 mShowTransparent = transparent;
85 mSetUnHideFlagWhenNextTransparent = transparent;
86 mNoAnimationOnNextShow = true;
87 }
88 }
89
John Spurlock27735a42013-08-14 17:57:38 -040090 public void showTransient() {
91 if (mWin != null) {
John Spurlockf25706f2013-11-07 18:02:43 -050092 setTransientBarState(TRANSIENT_BAR_SHOW_REQUESTED);
John Spurlock27735a42013-08-14 17:57:38 -040093 }
94 }
95
96 public boolean isTransientShowing() {
97 return mTransientBarState == TRANSIENT_BAR_SHOWING;
98 }
99
John Spurlockf25706f2013-11-07 18:02:43 -0500100 public boolean isTransientShowRequested() {
101 return mTransientBarState == TRANSIENT_BAR_SHOW_REQUESTED;
102 }
103
John Spurlockbd957402013-10-03 11:38:39 -0400104 public boolean wasRecentlyTranslucent() {
105 return (SystemClock.uptimeMillis() - mLastTranslucent) < TRANSLUCENT_ANIMATION_DELAY_MS;
John Spurlockb77edbf2013-08-21 21:04:12 -0400106 }
107
John Spurlock5b9145b2013-08-20 15:13:47 -0400108 public void adjustSystemUiVisibilityLw(int oldVis, int vis) {
John Spurlock27735a42013-08-14 17:57:38 -0400109 if (mWin != null && mTransientBarState == TRANSIENT_BAR_SHOWING &&
John Spurlock5b9145b2013-08-20 15:13:47 -0400110 (vis & mTransientFlag) == 0) {
111 // sysui requests hide
John Spurlock27735a42013-08-14 17:57:38 -0400112 setTransientBarState(TRANSIENT_BAR_HIDING);
113 setBarShowingLw(false);
John Spurlock5b9145b2013-08-20 15:13:47 -0400114 } else if (mWin != null && (oldVis & mUnhideFlag) != 0 && (vis & mUnhideFlag) == 0) {
115 // sysui ready to unhide
116 setBarShowingLw(true);
John Spurlock27735a42013-08-14 17:57:38 -0400117 }
118 }
119
John Spurlockbd957402013-10-03 11:38:39 -0400120 public int applyTranslucentFlagLw(WindowState win, int vis, int oldVis) {
121 if (mWin != null) {
122 if (win != null && (win.getAttrs().privateFlags
123 & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) == 0) {
Adrian Roosea562512014-05-05 13:33:03 +0200124 int fl = PolicyControl.getWindowFlags(win, null);
125 if ((fl & mTranslucentWmFlag) != 0) {
John Spurlockbd957402013-10-03 11:38:39 -0400126 vis |= mTranslucentFlag;
127 } else {
128 vis &= ~mTranslucentFlag;
129 }
Adrian Roosea562512014-05-05 13:33:03 +0200130 if ((fl & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
Jorim Jaggi4fa78922015-11-30 17:13:56 -0800131 vis |= mTransparentFlag;
Adrian Roosea562512014-05-05 13:33:03 +0200132 } else {
Jorim Jaggi4fa78922015-11-30 17:13:56 -0800133 vis &= ~mTransparentFlag;
Adrian Roosea562512014-05-05 13:33:03 +0200134 }
John Spurlockbd957402013-10-03 11:38:39 -0400135 } else {
136 vis = (vis & ~mTranslucentFlag) | (oldVis & mTranslucentFlag);
Jorim Jaggi4fa78922015-11-30 17:13:56 -0800137 vis = (vis & ~mTransparentFlag) | (oldVis & mTransparentFlag);
John Spurlockbd957402013-10-03 11:38:39 -0400138 }
139 }
140 return vis;
141 }
142
John Spurlock27735a42013-08-14 17:57:38 -0400143 public boolean setBarShowingLw(final boolean show) {
144 if (mWin == null) return false;
John Spurlock27735a42013-08-14 17:57:38 -0400145 if (show && mTransientBarState == TRANSIENT_BAR_HIDING) {
146 mPendingShow = true;
147 return false;
148 }
John Spurlock7edfbca2013-09-14 11:58:55 -0400149 final boolean wasVis = mWin.isVisibleLw();
150 final boolean wasAnim = mWin.isAnimatingLw();
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -0700151 final boolean change = show ? mWin.showLw(!mNoAnimationOnNextShow)
152 : mWin.hideLw(!mNoAnimationOnNextShow);
153 mNoAnimationOnNextShow = false;
John Spurlock7edfbca2013-09-14 11:58:55 -0400154 final int state = computeStateLw(wasVis, wasAnim, mWin, change);
John Spurlockc23bd802013-11-06 12:20:38 -0500155 final boolean stateChanged = updateStateLw(state);
156 return change || stateChanged;
John Spurlock7edfbca2013-09-14 11:58:55 -0400157 }
158
159 private int computeStateLw(boolean wasVis, boolean wasAnim, WindowState win, boolean change) {
Adrian Roos76d2fe42015-07-09 14:54:08 -0700160 if (win.isDrawnLw()) {
John Spurlock7edfbca2013-09-14 11:58:55 -0400161 final boolean vis = win.isVisibleLw();
162 final boolean anim = win.isAnimatingLw();
163 if (mState == StatusBarManager.WINDOW_STATE_HIDING && !change && !vis) {
164 return StatusBarManager.WINDOW_STATE_HIDDEN;
John Spurlockc23bd802013-11-06 12:20:38 -0500165 } else if (mState == StatusBarManager.WINDOW_STATE_HIDDEN && vis) {
166 return StatusBarManager.WINDOW_STATE_SHOWING;
John Spurlock7edfbca2013-09-14 11:58:55 -0400167 } else if (change) {
168 if (wasVis && vis && !wasAnim && anim) {
169 return StatusBarManager.WINDOW_STATE_HIDING;
170 } else {
171 return StatusBarManager.WINDOW_STATE_SHOWING;
172 }
173 }
John Spurlock5b9145b2013-08-20 15:13:47 -0400174 }
John Spurlock7edfbca2013-09-14 11:58:55 -0400175 return mState;
John Spurlock5b9145b2013-08-20 15:13:47 -0400176 }
177
John Spurlockc23bd802013-11-06 12:20:38 -0500178 private boolean updateStateLw(final int state) {
John Spurlock5b9145b2013-08-20 15:13:47 -0400179 if (state != mState) {
180 mState = state;
John Spurlock0ec64c62013-08-26 15:37:58 -0400181 if (DEBUG) Slog.d(mTag, "mState: " + StatusBarManager.windowStateToString(state));
John Spurlock5b9145b2013-08-20 15:13:47 -0400182 mHandler.post(new Runnable() {
183 @Override
184 public void run() {
185 try {
186 IStatusBarService statusbar = getStatusBarService();
187 if (statusbar != null) {
188 statusbar.setWindowState(mStatusBarManagerId, state);
189 }
190 } catch (RemoteException e) {
John Spurlock0ec64c62013-08-26 15:37:58 -0400191 if (DEBUG) Slog.w(mTag, "Error posting window state", e);
John Spurlock5b9145b2013-08-20 15:13:47 -0400192 // re-acquire status bar service next time it is needed.
193 mStatusBarService = null;
194 }
195 }
196 });
John Spurlockc23bd802013-11-06 12:20:38 -0500197 return true;
John Spurlock5b9145b2013-08-20 15:13:47 -0400198 }
John Spurlockc23bd802013-11-06 12:20:38 -0500199 return false;
John Spurlock27735a42013-08-14 17:57:38 -0400200 }
201
202 public boolean checkHiddenLw() {
Adrian Roos76d2fe42015-07-09 14:54:08 -0700203 if (mWin != null && mWin.isDrawnLw()) {
John Spurlock5b9145b2013-08-20 15:13:47 -0400204 if (!mWin.isVisibleLw() && !mWin.isAnimatingLw()) {
John Spurlock7edfbca2013-09-14 11:58:55 -0400205 updateStateLw(StatusBarManager.WINDOW_STATE_HIDDEN);
John Spurlock27735a42013-08-14 17:57:38 -0400206 }
John Spurlock5b9145b2013-08-20 15:13:47 -0400207 if (mTransientBarState == TRANSIENT_BAR_HIDING && !mWin.isVisibleLw()) {
208 // Finished animating out, clean up and reset style
209 setTransientBarState(TRANSIENT_BAR_NONE);
210 if (mPendingShow) {
211 setBarShowingLw(true);
212 mPendingShow = false;
213 }
214 return true;
215 }
John Spurlock27735a42013-08-14 17:57:38 -0400216 }
217 return false;
218 }
219
220 public boolean checkShowTransientBarLw() {
221 if (mTransientBarState == TRANSIENT_BAR_SHOWING) {
222 if (DEBUG) Slog.d(mTag, "Not showing transient bar, already shown");
223 return false;
John Spurlockf25706f2013-11-07 18:02:43 -0500224 } else if (mTransientBarState == TRANSIENT_BAR_SHOW_REQUESTED) {
225 if (DEBUG) Slog.d(mTag, "Not showing transient bar, already requested");
226 return false;
John Spurlock27735a42013-08-14 17:57:38 -0400227 } else if (mWin == null) {
228 if (DEBUG) Slog.d(mTag, "Not showing transient bar, bar doesn't exist");
229 return false;
230 } else if (mWin.isDisplayedLw()) {
231 if (DEBUG) Slog.d(mTag, "Not showing transient bar, bar already visible");
232 return false;
233 } else {
234 return true;
235 }
236 }
237
John Spurlockbd957402013-10-03 11:38:39 -0400238 public int updateVisibilityLw(boolean transientAllowed, int oldVis, int vis) {
John Spurlock27735a42013-08-14 17:57:38 -0400239 if (mWin == null) return vis;
John Spurlockf25706f2013-11-07 18:02:43 -0500240 if (isTransientShowing() || isTransientShowRequested()) { // transient bar requested
John Spurlockbd957402013-10-03 11:38:39 -0400241 if (transientAllowed) {
John Spurlock27735a42013-08-14 17:57:38 -0400242 vis |= mTransientFlag;
243 if ((oldVis & mTransientFlag) == 0) {
John Spurlock5b9145b2013-08-20 15:13:47 -0400244 vis |= mUnhideFlag; // tell sysui we're ready to unhide
John Spurlock27735a42013-08-14 17:57:38 -0400245 }
John Spurlockf25706f2013-11-07 18:02:43 -0500246 setTransientBarState(TRANSIENT_BAR_SHOWING); // request accepted
John Spurlock27735a42013-08-14 17:57:38 -0400247 } else {
248 setTransientBarState(TRANSIENT_BAR_NONE); // request denied
249 }
250 }
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -0700251 if (mShowTransparent) {
Jorim Jaggi4fa78922015-11-30 17:13:56 -0800252 vis |= mTransparentFlag;
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -0700253 if (mSetUnHideFlagWhenNextTransparent) {
254 vis |= mUnhideFlag;
255 mSetUnHideFlagWhenNextTransparent = false;
256 }
257 }
John Spurlock27735a42013-08-14 17:57:38 -0400258 if (mTransientBarState != TRANSIENT_BAR_NONE) {
259 vis |= mTransientFlag; // ignore clear requests until transition completes
260 vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE; // never show transient bars in low profile
261 }
Adrian Roosea562512014-05-05 13:33:03 +0200262 if ((vis & mTranslucentFlag) != 0 || (oldVis & mTranslucentFlag) != 0 ||
Jorim Jaggi4fa78922015-11-30 17:13:56 -0800263 ((vis | oldVis) & mTransparentFlag) != 0) {
John Spurlockbd957402013-10-03 11:38:39 -0400264 mLastTranslucent = SystemClock.uptimeMillis();
John Spurlockb77edbf2013-08-21 21:04:12 -0400265 }
John Spurlock27735a42013-08-14 17:57:38 -0400266 return vis;
267 }
268
269 private void setTransientBarState(int state) {
270 if (mWin != null && state != mTransientBarState) {
John Spurlockb77edbf2013-08-21 21:04:12 -0400271 if (mTransientBarState == TRANSIENT_BAR_SHOWING || state == TRANSIENT_BAR_SHOWING) {
John Spurlockbd957402013-10-03 11:38:39 -0400272 mLastTranslucent = SystemClock.uptimeMillis();
John Spurlockb77edbf2013-08-21 21:04:12 -0400273 }
John Spurlock27735a42013-08-14 17:57:38 -0400274 mTransientBarState = state;
John Spurlock0ec64c62013-08-26 15:37:58 -0400275 if (DEBUG) Slog.d(mTag, "mTransientBarState: " + transientBarStateToString(state));
John Spurlock27735a42013-08-14 17:57:38 -0400276 }
277 }
278
Jorim Jaggi24bec7c2015-02-04 12:40:14 +0100279 protected IStatusBarService getStatusBarService() {
John Spurlock27735a42013-08-14 17:57:38 -0400280 synchronized (mServiceAquireLock) {
281 if (mStatusBarService == null) {
282 mStatusBarService = IStatusBarService.Stub.asInterface(
283 ServiceManager.getService("statusbar"));
284 }
285 return mStatusBarService;
286 }
287 }
288
289 private static String transientBarStateToString(int state) {
290 if (state == TRANSIENT_BAR_HIDING) return "TRANSIENT_BAR_HIDING";
291 if (state == TRANSIENT_BAR_SHOWING) return "TRANSIENT_BAR_SHOWING";
John Spurlockf25706f2013-11-07 18:02:43 -0500292 if (state == TRANSIENT_BAR_SHOW_REQUESTED) return "TRANSIENT_BAR_SHOW_REQUESTED";
John Spurlock27735a42013-08-14 17:57:38 -0400293 if (state == TRANSIENT_BAR_NONE) return "TRANSIENT_BAR_NONE";
294 throw new IllegalArgumentException("Unknown state " + state);
295 }
296
297 public void dump(PrintWriter pw, String prefix) {
298 if (mWin != null) {
John Spurlock0ec64c62013-08-26 15:37:58 -0400299 pw.print(prefix); pw.println(mTag);
John Spurlockd4e65752013-08-28 14:17:09 -0400300 pw.print(prefix); pw.print(" "); pw.print("mState"); pw.print('=');
John Spurlock0ec64c62013-08-26 15:37:58 -0400301 pw.println(StatusBarManager.windowStateToString(mState));
John Spurlockd4e65752013-08-28 14:17:09 -0400302 pw.print(prefix); pw.print(" "); pw.print("mTransientBar"); pw.print('=');
John Spurlock27735a42013-08-14 17:57:38 -0400303 pw.println(transientBarStateToString(mTransientBarState));
304 }
305 }
306}