StatusBarWindowManager.java revision 1c0ca508b9d6184beba2050e6ab3a44ac5be137a
1/* 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 19import 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; 27import android.view.Window; 28import android.view.WindowManager; 29 30import com.android.keyguard.R; 31import com.android.systemui.keyguard.KeyguardViewMediator; 32import com.android.systemui.statusbar.BaseStatusBar; 33import com.android.systemui.statusbar.StatusBarState; 34 35import java.io.FileDescriptor; 36import java.io.PrintWriter; 37import java.lang.reflect.Field; 38 39/** 40 * Encapsulates all logic for the status bar window state management. 41 */ 42public class StatusBarWindowManager { 43 44 private final Context mContext; 45 private final WindowManager mWindowManager; 46 private View mStatusBarView; 47 private WindowManager.LayoutParams mLp; 48 private WindowManager.LayoutParams mLpChanged; 49 private int mBarHeight; 50 private final boolean mKeyguardScreenRotation; 51 private final float mScreenBrightnessDoze; 52 private final State mCurrentState = new State(); 53 54 public StatusBarWindowManager(Context context) { 55 mContext = context; 56 mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 57 mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation(); 58 mScreenBrightnessDoze = mContext.getResources().getInteger( 59 com.android.internal.R.integer.config_screenBrightnessDoze) / 255f; 60 } 61 62 private boolean shouldEnableKeyguardScreenRotation() { 63 Resources res = mContext.getResources(); 64 return SystemProperties.getBoolean("lockscreen.rot_override", false) 65 || res.getBoolean(R.bool.config_enableLockScreenRotation); 66 } 67 68 /** 69 * Adds the status bar view to the window manager. 70 * 71 * @param statusBarView The view to add. 72 * @param barHeight The height of the status bar in collapsed state. 73 */ 74 public void add(View statusBarView, int barHeight) { 75 76 // Now that the status bar window encompasses the sliding panel and its 77 // translucent backdrop, the entire thing is made TRANSLUCENT and is 78 // hardware-accelerated. 79 mLp = new WindowManager.LayoutParams( 80 ViewGroup.LayoutParams.MATCH_PARENT, 81 barHeight, 82 WindowManager.LayoutParams.TYPE_STATUS_BAR, 83 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 84 | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING 85 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH 86 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 87 | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, 88 PixelFormat.TRANSLUCENT); 89 mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 90 mLp.gravity = Gravity.TOP; 91 mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 92 mLp.setTitle("StatusBar"); 93 mLp.packageName = mContext.getPackageName(); 94 mStatusBarView = statusBarView; 95 mBarHeight = barHeight; 96 mWindowManager.addView(mStatusBarView, mLp); 97 mLpChanged = new WindowManager.LayoutParams(); 98 mLpChanged.copyFrom(mLp); 99 } 100 101 private void applyKeyguardFlags(State state) { 102 if (state.keyguardShowing) { 103 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 104 mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 105 } else { 106 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 107 mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 108 } 109 } 110 111 private void adjustScreenOrientation(State state) { 112 if (state.isKeyguardShowingAndNotOccluded()) { 113 if (mKeyguardScreenRotation) { 114 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER; 115 } else { 116 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 117 } 118 } else { 119 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 120 } 121 } 122 123 private void applyFocusableFlag(State state) { 124 boolean panelFocusable = state.statusBarFocusable && state.panelExpanded; 125 if (state.keyguardShowing && state.keyguardNeedsInput && state.bouncerShowing 126 || BaseStatusBar.ENABLE_REMOTE_INPUT && state.remoteInputActive) { 127 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 128 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 129 } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) { 130 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 131 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 132 } else { 133 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 134 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 135 } 136 } 137 138 private void applyHeight(State state) { 139 boolean expanded = isExpanded(state); 140 if (expanded) { 141 mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT; 142 } else { 143 mLpChanged.height = mBarHeight; 144 } 145 } 146 147 private boolean isExpanded(State state) { 148 return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded() 149 || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing 150 || state.headsUpShowing); 151 } 152 153 private void applyFitsSystemWindows(State state) { 154 mStatusBarView.setFitsSystemWindows(!state.isKeyguardShowingAndNotOccluded()); 155 } 156 157 private void applyUserActivityTimeout(State state) { 158 if (state.isKeyguardShowingAndNotOccluded() 159 && state.statusBarState == StatusBarState.KEYGUARD 160 && !state.qsExpanded) { 161 mLpChanged.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS; 162 } else { 163 mLpChanged.userActivityTimeout = -1; 164 } 165 } 166 167 private void applyInputFeatures(State state) { 168 if (state.isKeyguardShowingAndNotOccluded() 169 && state.statusBarState == StatusBarState.KEYGUARD 170 && !state.qsExpanded) { 171 mLpChanged.inputFeatures |= 172 WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; 173 } else { 174 mLpChanged.inputFeatures &= 175 ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; 176 } 177 } 178 179 private void apply(State state) { 180 applyKeyguardFlags(state); 181 applyForceStatusBarVisibleFlag(state); 182 applyFocusableFlag(state); 183 adjustScreenOrientation(state); 184 applyHeight(state); 185 applyUserActivityTimeout(state); 186 applyInputFeatures(state); 187 applyFitsSystemWindows(state); 188 applyModalFlag(state); 189 applyBrightness(state); 190 if (mLp.copyFrom(mLpChanged) != 0) { 191 mWindowManager.updateViewLayout(mStatusBarView, mLp); 192 } 193 } 194 195 private void applyForceStatusBarVisibleFlag(State state) { 196 if (state.forceStatusBarVisible) { 197 mLpChanged.privateFlags |= WindowManager 198 .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; 199 } else { 200 mLpChanged.privateFlags &= ~WindowManager 201 .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; 202 } 203 } 204 205 private void applyModalFlag(State state) { 206 if (state.headsUpShowing) { 207 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 208 } else { 209 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 210 } 211 } 212 213 private void applyBrightness(State state) { 214 if (state.forceDozeBrightness) { 215 mLpChanged.screenBrightness = mScreenBrightnessDoze; 216 } else { 217 mLpChanged.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE; 218 } 219 } 220 221 public void setKeyguardShowing(boolean showing) { 222 mCurrentState.keyguardShowing = showing; 223 apply(mCurrentState); 224 } 225 226 public void setKeyguardOccluded(boolean occluded) { 227 mCurrentState.keyguardOccluded = occluded; 228 apply(mCurrentState); 229 } 230 231 public void setKeyguardNeedsInput(boolean needsInput) { 232 mCurrentState.keyguardNeedsInput = needsInput; 233 apply(mCurrentState); 234 } 235 236 public void setPanelVisible(boolean visible) { 237 mCurrentState.panelVisible = visible; 238 mCurrentState.statusBarFocusable = visible; 239 apply(mCurrentState); 240 } 241 242 public void setStatusBarFocusable(boolean focusable) { 243 mCurrentState.statusBarFocusable = focusable; 244 apply(mCurrentState); 245 } 246 247 public void setBouncerShowing(boolean showing) { 248 mCurrentState.bouncerShowing = showing; 249 apply(mCurrentState); 250 } 251 252 public void setKeyguardFadingAway(boolean keyguardFadingAway) { 253 mCurrentState.keyguardFadingAway = keyguardFadingAway; 254 apply(mCurrentState); 255 } 256 257 public void setQsExpanded(boolean expanded) { 258 mCurrentState.qsExpanded = expanded; 259 apply(mCurrentState); 260 } 261 262 public void setHeadsUpShowing(boolean showing) { 263 mCurrentState.headsUpShowing = showing; 264 apply(mCurrentState); 265 } 266 267 /** 268 * @param state The {@link StatusBarState} of the status bar. 269 */ 270 public void setStatusBarState(int state) { 271 mCurrentState.statusBarState = state; 272 apply(mCurrentState); 273 } 274 275 public void setForceStatusBarVisible(boolean forceStatusBarVisible) { 276 mCurrentState.forceStatusBarVisible = forceStatusBarVisible; 277 apply(mCurrentState); 278 } 279 280 /** 281 * Force the window to be collapsed, even if it should theoretically be expanded. 282 * Used for when a heads-up comes in but we still need to wait for the touchable regions to 283 * be computed. 284 */ 285 public void setForceWindowCollapsed(boolean force) { 286 mCurrentState.forceCollapsed = force; 287 apply(mCurrentState); 288 } 289 290 public void setPanelExpanded(boolean isExpanded) { 291 mCurrentState.panelExpanded = isExpanded; 292 apply(mCurrentState); 293 } 294 295 public void setRemoteInputActive(boolean remoteInputActive) { 296 mCurrentState.remoteInputActive = remoteInputActive; 297 apply(mCurrentState); 298 } 299 300 /** 301 * Set whether the screen brightness is forced to the value we use for doze mode by the status 302 * bar window. 303 */ 304 public void setForceDozeBrightness(boolean forceDozeBrightness) { 305 mCurrentState.forceDozeBrightness = forceDozeBrightness; 306 apply(mCurrentState); 307 } 308 309 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 310 pw.println("StatusBarWindowManager state:"); 311 pw.println(mCurrentState); 312 } 313 314 private static class State { 315 boolean keyguardShowing; 316 boolean keyguardOccluded; 317 boolean keyguardNeedsInput; 318 boolean panelVisible; 319 boolean panelExpanded; 320 boolean statusBarFocusable; 321 boolean bouncerShowing; 322 boolean keyguardFadingAway; 323 boolean qsExpanded; 324 boolean headsUpShowing; 325 boolean forceStatusBarVisible; 326 boolean forceCollapsed; 327 boolean forceDozeBrightness; 328 329 /** 330 * The {@link BaseStatusBar} state from the status bar. 331 */ 332 int statusBarState; 333 334 boolean remoteInputActive; 335 336 private boolean isKeyguardShowingAndNotOccluded() { 337 return keyguardShowing && !keyguardOccluded; 338 } 339 340 @Override 341 public String toString() { 342 StringBuilder result = new StringBuilder(); 343 String newLine = "\n"; 344 result.append("Window State {"); 345 result.append(newLine); 346 347 Field[] fields = this.getClass().getDeclaredFields(); 348 349 // Print field names paired with their values 350 for (Field field : fields) { 351 result.append(" "); 352 try { 353 result.append(field.getName()); 354 result.append(": "); 355 //requires access to private field: 356 result.append(field.get(this)); 357 } catch (IllegalAccessException ex) { 358 } 359 result.append(newLine); 360 } 361 result.append("}"); 362 363 return result.toString(); 364 } 365 } 366} 367