blob: 382de198d0146dba3dc74bfac4498184df1d413f [file] [log] [blame]
Jorim Jaggi5cf17872014-03-26 18:31:48 +01001/*
2 * Copyright (C) 2014 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.systemui.statusbar.phone;
18
Jorim Jaggi5cf17872014-03-26 18:31:48 +010019import android.content.Context;
20import android.content.pm.ActivityInfo;
21import android.content.res.Resources;
22import android.graphics.PixelFormat;
23import android.os.SystemProperties;
24import android.view.Gravity;
25import android.view.View;
26import android.view.ViewGroup;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070027import android.view.Window;
Jorim Jaggi5cf17872014-03-26 18:31:48 +010028import android.view.WindowManager;
29
30import com.android.keyguard.R;
Jorim Jaggi6b88cdf2014-12-22 20:56:50 +010031import com.android.systemui.keyguard.KeyguardViewMediator;
Jorim Jaggiecbab362014-04-23 16:13:15 +020032import com.android.systemui.statusbar.BaseStatusBar;
Adrian Roosd28ccd72016-01-06 15:23:14 +010033import com.android.systemui.statusbar.RemoteInputController;
Jorim Jaggiecbab362014-04-23 16:13:15 +020034import com.android.systemui.statusbar.StatusBarState;
Jorim Jaggi5cf17872014-03-26 18:31:48 +010035
Selim Cinek7025f262015-07-13 16:22:48 -070036import java.io.FileDescriptor;
37import java.io.PrintWriter;
Selim Cinek6a1bd2b2015-06-02 16:02:41 +020038import java.lang.reflect.Field;
39
Jorim Jaggi5cf17872014-03-26 18:31:48 +010040/**
41 * Encapsulates all logic for the status bar window state management.
42 */
Adrian Roosd28ccd72016-01-06 15:23:14 +010043public class StatusBarWindowManager implements RemoteInputController.Callback {
Jorim Jaggi5cf17872014-03-26 18:31:48 +010044
45 private final Context mContext;
46 private final WindowManager mWindowManager;
47 private View mStatusBarView;
48 private WindowManager.LayoutParams mLp;
Jorim Jaggi95e89ca2014-11-24 20:12:50 +010049 private WindowManager.LayoutParams mLpChanged;
Jorim Jaggi5cf17872014-03-26 18:31:48 +010050 private int mBarHeight;
51 private final boolean mKeyguardScreenRotation;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070052 private final float mScreenBrightnessDoze;
Jorim Jaggi5cf17872014-03-26 18:31:48 +010053 private final State mCurrentState = new State();
54
55 public StatusBarWindowManager(Context context) {
56 mContext = context;
57 mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
58 mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -070059 mScreenBrightnessDoze = mContext.getResources().getInteger(
60 com.android.internal.R.integer.config_screenBrightnessDoze) / 255f;
Jorim Jaggi5cf17872014-03-26 18:31:48 +010061 }
62
63 private boolean shouldEnableKeyguardScreenRotation() {
64 Resources res = mContext.getResources();
65 return SystemProperties.getBoolean("lockscreen.rot_override", false)
66 || res.getBoolean(R.bool.config_enableLockScreenRotation);
67 }
68
69 /**
70 * Adds the status bar view to the window manager.
71 *
72 * @param statusBarView The view to add.
73 * @param barHeight The height of the status bar in collapsed state.
74 */
75 public void add(View statusBarView, int barHeight) {
76
77 // Now that the status bar window encompasses the sliding panel and its
78 // translucent backdrop, the entire thing is made TRANSLUCENT and is
79 // hardware-accelerated.
80 mLp = new WindowManager.LayoutParams(
81 ViewGroup.LayoutParams.MATCH_PARENT,
82 barHeight,
83 WindowManager.LayoutParams.TYPE_STATUS_BAR,
84 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
85 | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
86 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
87 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
Adrian Roosea562512014-05-05 13:33:03 +020088 | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
Jorim Jaggi5cf17872014-03-26 18:31:48 +010089 PixelFormat.TRANSLUCENT);
Jorim Jaggi5cf17872014-03-26 18:31:48 +010090 mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
Jorim Jaggi76aaef52014-05-08 19:16:49 +020091 mLp.gravity = Gravity.TOP;
Jorim Jaggi5cf17872014-03-26 18:31:48 +010092 mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
Jorim Jaggi5cf17872014-03-26 18:31:48 +010093 mLp.setTitle("StatusBar");
94 mLp.packageName = mContext.getPackageName();
95 mStatusBarView = statusBarView;
96 mBarHeight = barHeight;
97 mWindowManager.addView(mStatusBarView, mLp);
Jorim Jaggi95e89ca2014-11-24 20:12:50 +010098 mLpChanged = new WindowManager.LayoutParams();
99 mLpChanged.copyFrom(mLp);
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100100 }
101
102 private void applyKeyguardFlags(State state) {
103 if (state.keyguardShowing) {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100104 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
105 mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100106 } else {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100107 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
108 mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100109 }
110 }
111
112 private void adjustScreenOrientation(State state) {
Jorim Jaggica36cf72014-04-17 20:36:15 +0200113 if (state.isKeyguardShowingAndNotOccluded()) {
114 if (mKeyguardScreenRotation) {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100115 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
Jorim Jaggica36cf72014-04-17 20:36:15 +0200116 } else {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100117 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
Jorim Jaggica36cf72014-04-17 20:36:15 +0200118 }
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100119 } else {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100120 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100121 }
122 }
123
124 private void applyFocusableFlag(State state) {
Selim Cinek4a21a7f2015-05-19 11:00:38 -0700125 boolean panelFocusable = state.statusBarFocusable && state.panelExpanded;
Jorim Jaggiaa806142015-05-20 18:04:16 -0700126 if (state.keyguardShowing && state.keyguardNeedsInput && state.bouncerShowing
Adrian Roos1c0ca502015-10-07 12:20:42 -0700127 || BaseStatusBar.ENABLE_REMOTE_INPUT && state.remoteInputActive) {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100128 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
129 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
Selim Cinek4a21a7f2015-05-19 11:00:38 -0700130 } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100131 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
132 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100133 } else {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100134 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
135 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100136 }
Adrian Roosdc5b4532016-01-06 20:49:41 +0100137
138 if (state.remoteInputActive) {
139 mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
140 } else {
141 mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
142 }
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100143 }
144
145 private void applyHeight(State state) {
Selim Cinek6a1bd2b2015-06-02 16:02:41 +0200146 boolean expanded = isExpanded(state);
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100147 if (expanded) {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100148 mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT;
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100149 } else {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100150 mLpChanged.height = mBarHeight;
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100151 }
152 }
153
Selim Cinek6a1bd2b2015-06-02 16:02:41 +0200154 private boolean isExpanded(State state) {
155 return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded()
156 || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing
157 || state.headsUpShowing);
158 }
159
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200160 private void applyFitsSystemWindows(State state) {
161 mStatusBarView.setFitsSystemWindows(!state.isKeyguardShowingAndNotOccluded());
162 }
163
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100164 private void applyUserActivityTimeout(State state) {
Jorim Jaggiecbab362014-04-23 16:13:15 +0200165 if (state.isKeyguardShowingAndNotOccluded()
Jorim Jaggib690f0d2014-07-03 23:25:44 +0200166 && state.statusBarState == StatusBarState.KEYGUARD
167 && !state.qsExpanded) {
Jorim Jaggi6b88cdf2014-12-22 20:56:50 +0100168 mLpChanged.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100169 } else {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100170 mLpChanged.userActivityTimeout = -1;
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100171 }
172 }
173
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200174 private void applyInputFeatures(State state) {
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200175 if (state.isKeyguardShowingAndNotOccluded()
Jorim Jaggib690f0d2014-07-03 23:25:44 +0200176 && state.statusBarState == StatusBarState.KEYGUARD
177 && !state.qsExpanded) {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100178 mLpChanged.inputFeatures |=
179 WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200180 } else {
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100181 mLpChanged.inputFeatures &=
182 ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200183 }
184 }
185
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100186 private void apply(State state) {
187 applyKeyguardFlags(state);
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -0700188 applyForceStatusBarVisibleFlag(state);
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100189 applyFocusableFlag(state);
190 adjustScreenOrientation(state);
191 applyHeight(state);
192 applyUserActivityTimeout(state);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200193 applyInputFeatures(state);
Jorim Jaggia005f1b2014-04-16 19:06:10 +0200194 applyFitsSystemWindows(state);
Selim Cineka59ecc32015-04-07 10:51:49 -0700195 applyModalFlag(state);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700196 applyBrightness(state);
Jorim Jaggi95e89ca2014-11-24 20:12:50 +0100197 if (mLp.copyFrom(mLpChanged) != 0) {
198 mWindowManager.updateViewLayout(mStatusBarView, mLp);
199 }
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100200 }
201
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -0700202 private void applyForceStatusBarVisibleFlag(State state) {
203 if (state.forceStatusBarVisible) {
204 mLpChanged.privateFlags |= WindowManager
205 .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
206 } else {
207 mLpChanged.privateFlags &= ~WindowManager
208 .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
209 }
210 }
211
Selim Cineka59ecc32015-04-07 10:51:49 -0700212 private void applyModalFlag(State state) {
213 if (state.headsUpShowing) {
214 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
215 } else {
216 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
217 }
218 }
219
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700220 private void applyBrightness(State state) {
221 if (state.forceDozeBrightness) {
222 mLpChanged.screenBrightness = mScreenBrightnessDoze;
223 } else {
224 mLpChanged.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
225 }
226 }
227
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100228 public void setKeyguardShowing(boolean showing) {
229 mCurrentState.keyguardShowing = showing;
230 apply(mCurrentState);
231 }
232
233 public void setKeyguardOccluded(boolean occluded) {
234 mCurrentState.keyguardOccluded = occluded;
235 apply(mCurrentState);
236 }
237
238 public void setKeyguardNeedsInput(boolean needsInput) {
239 mCurrentState.keyguardNeedsInput = needsInput;
240 apply(mCurrentState);
241 }
242
Selim Cinek4a21a7f2015-05-19 11:00:38 -0700243 public void setPanelVisible(boolean visible) {
244 mCurrentState.panelVisible = visible;
245 mCurrentState.statusBarFocusable = visible;
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100246 apply(mCurrentState);
247 }
248
249 public void setStatusBarFocusable(boolean focusable) {
250 mCurrentState.statusBarFocusable = focusable;
251 apply(mCurrentState);
252 }
253
Jorim Jaggi5fd4d052014-05-13 22:50:20 +0200254 public void setBouncerShowing(boolean showing) {
255 mCurrentState.bouncerShowing = showing;
256 apply(mCurrentState);
257 }
258
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200259 public void setKeyguardFadingAway(boolean keyguardFadingAway) {
260 mCurrentState.keyguardFadingAway = keyguardFadingAway;
261 apply(mCurrentState);
262 }
263
Jorim Jaggib690f0d2014-07-03 23:25:44 +0200264 public void setQsExpanded(boolean expanded) {
265 mCurrentState.qsExpanded = expanded;
266 apply(mCurrentState);
267 }
268
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700269 public void setHeadsUpShowing(boolean showing) {
270 mCurrentState.headsUpShowing = showing;
271 apply(mCurrentState);
272 }
273
Jorim Jaggiecbab362014-04-23 16:13:15 +0200274 /**
275 * @param state The {@link StatusBarState} of the status bar.
276 */
277 public void setStatusBarState(int state) {
278 mCurrentState.statusBarState = state;
279 apply(mCurrentState);
280 }
281
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -0700282 public void setForceStatusBarVisible(boolean forceStatusBarVisible) {
283 mCurrentState.forceStatusBarVisible = forceStatusBarVisible;
284 apply(mCurrentState);
285 }
286
Selim Cinek737bff32015-05-08 16:08:35 -0700287 /**
288 * Force the window to be collapsed, even if it should theoretically be expanded.
289 * Used for when a heads-up comes in but we still need to wait for the touchable regions to
290 * be computed.
291 */
292 public void setForceWindowCollapsed(boolean force) {
293 mCurrentState.forceCollapsed = force;
294 apply(mCurrentState);
295 }
296
Selim Cinek4a21a7f2015-05-19 11:00:38 -0700297 public void setPanelExpanded(boolean isExpanded) {
298 mCurrentState.panelExpanded = isExpanded;
299 apply(mCurrentState);
300 }
301
Adrian Roosd28ccd72016-01-06 15:23:14 +0100302 @Override
303 public void onRemoteInputActive(boolean remoteInputActive) {
Adrian Roos1c0ca502015-10-07 12:20:42 -0700304 mCurrentState.remoteInputActive = remoteInputActive;
305 apply(mCurrentState);
306 }
307
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700308 /**
309 * Set whether the screen brightness is forced to the value we use for doze mode by the status
310 * bar window.
311 */
312 public void setForceDozeBrightness(boolean forceDozeBrightness) {
313 mCurrentState.forceDozeBrightness = forceDozeBrightness;
314 apply(mCurrentState);
315 }
316
Selim Cinek7025f262015-07-13 16:22:48 -0700317 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
318 pw.println("StatusBarWindowManager state:");
319 pw.println(mCurrentState);
Selim Cinek6a1bd2b2015-06-02 16:02:41 +0200320 }
321
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100322 private static class State {
323 boolean keyguardShowing;
324 boolean keyguardOccluded;
325 boolean keyguardNeedsInput;
Selim Cinek4a21a7f2015-05-19 11:00:38 -0700326 boolean panelVisible;
327 boolean panelExpanded;
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100328 boolean statusBarFocusable;
Jorim Jaggi5fd4d052014-05-13 22:50:20 +0200329 boolean bouncerShowing;
Jorim Jaggie29b2db2014-05-30 23:17:03 +0200330 boolean keyguardFadingAway;
Jorim Jaggib690f0d2014-07-03 23:25:44 +0200331 boolean qsExpanded;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700332 boolean headsUpShowing;
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -0700333 boolean forceStatusBarVisible;
Selim Cinek737bff32015-05-08 16:08:35 -0700334 boolean forceCollapsed;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700335 boolean forceDozeBrightness;
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100336
Jorim Jaggiecbab362014-04-23 16:13:15 +0200337 /**
338 * The {@link BaseStatusBar} state from the status bar.
339 */
340 int statusBarState;
341
Adrian Roos1c0ca502015-10-07 12:20:42 -0700342 boolean remoteInputActive;
343
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100344 private boolean isKeyguardShowingAndNotOccluded() {
345 return keyguardShowing && !keyguardOccluded;
346 }
Selim Cinek6a1bd2b2015-06-02 16:02:41 +0200347
348 @Override
349 public String toString() {
350 StringBuilder result = new StringBuilder();
351 String newLine = "\n";
352 result.append("Window State {");
353 result.append(newLine);
354
355 Field[] fields = this.getClass().getDeclaredFields();
356
357 // Print field names paired with their values
358 for (Field field : fields) {
359 result.append(" ");
360 try {
361 result.append(field.getName());
362 result.append(": ");
363 //requires access to private field:
364 result.append(field.get(this));
365 } catch (IllegalAccessException ex) {
366 }
367 result.append(newLine);
368 }
369 result.append("}");
370
371 return result.toString();
372 }
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100373 }
374}