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 17 package com.android.systemui.statusbar.phone; 18 19 import android.content.Context; 20 import android.content.pm.ActivityInfo; 21 import android.content.res.Resources; 22 import android.graphics.PixelFormat; 23 import android.os.SystemProperties; 24 import android.view.Gravity; 25 import android.view.View; 26 import android.view.ViewGroup; 27 import android.view.Window; 28 import android.view.WindowManager; 29 30 import com.android.keyguard.R; 31 import com.android.systemui.keyguard.KeyguardViewMediator; 32 import com.android.systemui.statusbar.BaseStatusBar; 33 import com.android.systemui.statusbar.StatusBarState; 34 35 import java.io.FileDescriptor; 36 import java.io.PrintWriter; 37 import java.lang.reflect.Field; 38 39 /** 40 * Encapsulates all logic for the status bar window state management. 41 */ 42 public 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 StatusBarWindowManager(Context context)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 shouldEnableKeyguardScreenRotation()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 */ add(View statusBarView, int barHeight)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 applyKeyguardFlags(State state)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 adjustScreenOrientation(State state)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 applyFocusableFlag(State state)123 private void applyFocusableFlag(State state) { 124 boolean panelFocusable = state.statusBarFocusable && state.panelExpanded; 125 if (state.keyguardShowing && state.keyguardNeedsInput && state.bouncerShowing) { 126 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 127 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 128 } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) { 129 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 130 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 131 } else { 132 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 133 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 134 } 135 } 136 applyHeight(State state)137 private void applyHeight(State state) { 138 boolean expanded = isExpanded(state); 139 if (expanded) { 140 mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT; 141 } else { 142 mLpChanged.height = mBarHeight; 143 } 144 } 145 isExpanded(State state)146 private boolean isExpanded(State state) { 147 return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded() 148 || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing 149 || state.headsUpShowing); 150 } 151 applyFitsSystemWindows(State state)152 private void applyFitsSystemWindows(State state) { 153 mStatusBarView.setFitsSystemWindows(!state.isKeyguardShowingAndNotOccluded()); 154 } 155 applyUserActivityTimeout(State state)156 private void applyUserActivityTimeout(State state) { 157 if (state.isKeyguardShowingAndNotOccluded() 158 && state.statusBarState == StatusBarState.KEYGUARD 159 && !state.qsExpanded) { 160 mLpChanged.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS; 161 } else { 162 mLpChanged.userActivityTimeout = -1; 163 } 164 } 165 applyInputFeatures(State state)166 private void applyInputFeatures(State state) { 167 if (state.isKeyguardShowingAndNotOccluded() 168 && state.statusBarState == StatusBarState.KEYGUARD 169 && !state.qsExpanded) { 170 mLpChanged.inputFeatures |= 171 WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; 172 } else { 173 mLpChanged.inputFeatures &= 174 ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; 175 } 176 } 177 apply(State state)178 private void apply(State state) { 179 applyKeyguardFlags(state); 180 applyForceStatusBarVisibleFlag(state); 181 applyFocusableFlag(state); 182 adjustScreenOrientation(state); 183 applyHeight(state); 184 applyUserActivityTimeout(state); 185 applyInputFeatures(state); 186 applyFitsSystemWindows(state); 187 applyModalFlag(state); 188 applyBrightness(state); 189 if (mLp.copyFrom(mLpChanged) != 0) { 190 mWindowManager.updateViewLayout(mStatusBarView, mLp); 191 } 192 } 193 applyForceStatusBarVisibleFlag(State state)194 private void applyForceStatusBarVisibleFlag(State state) { 195 if (state.forceStatusBarVisible) { 196 mLpChanged.privateFlags |= WindowManager 197 .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; 198 } else { 199 mLpChanged.privateFlags &= ~WindowManager 200 .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; 201 } 202 } 203 applyModalFlag(State state)204 private void applyModalFlag(State state) { 205 if (state.headsUpShowing) { 206 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 207 } else { 208 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 209 } 210 } 211 applyBrightness(State state)212 private void applyBrightness(State state) { 213 if (state.forceDozeBrightness) { 214 mLpChanged.screenBrightness = mScreenBrightnessDoze; 215 } else { 216 mLpChanged.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE; 217 } 218 } 219 setKeyguardShowing(boolean showing)220 public void setKeyguardShowing(boolean showing) { 221 mCurrentState.keyguardShowing = showing; 222 apply(mCurrentState); 223 } 224 setKeyguardOccluded(boolean occluded)225 public void setKeyguardOccluded(boolean occluded) { 226 mCurrentState.keyguardOccluded = occluded; 227 apply(mCurrentState); 228 } 229 setKeyguardNeedsInput(boolean needsInput)230 public void setKeyguardNeedsInput(boolean needsInput) { 231 mCurrentState.keyguardNeedsInput = needsInput; 232 apply(mCurrentState); 233 } 234 setPanelVisible(boolean visible)235 public void setPanelVisible(boolean visible) { 236 mCurrentState.panelVisible = visible; 237 mCurrentState.statusBarFocusable = visible; 238 apply(mCurrentState); 239 } 240 setStatusBarFocusable(boolean focusable)241 public void setStatusBarFocusable(boolean focusable) { 242 mCurrentState.statusBarFocusable = focusable; 243 apply(mCurrentState); 244 } 245 setBouncerShowing(boolean showing)246 public void setBouncerShowing(boolean showing) { 247 mCurrentState.bouncerShowing = showing; 248 apply(mCurrentState); 249 } 250 setKeyguardFadingAway(boolean keyguardFadingAway)251 public void setKeyguardFadingAway(boolean keyguardFadingAway) { 252 mCurrentState.keyguardFadingAway = keyguardFadingAway; 253 apply(mCurrentState); 254 } 255 setQsExpanded(boolean expanded)256 public void setQsExpanded(boolean expanded) { 257 mCurrentState.qsExpanded = expanded; 258 apply(mCurrentState); 259 } 260 setHeadsUpShowing(boolean showing)261 public void setHeadsUpShowing(boolean showing) { 262 mCurrentState.headsUpShowing = showing; 263 apply(mCurrentState); 264 } 265 266 /** 267 * @param state The {@link StatusBarState} of the status bar. 268 */ setStatusBarState(int state)269 public void setStatusBarState(int state) { 270 mCurrentState.statusBarState = state; 271 apply(mCurrentState); 272 } 273 setForceStatusBarVisible(boolean forceStatusBarVisible)274 public void setForceStatusBarVisible(boolean forceStatusBarVisible) { 275 mCurrentState.forceStatusBarVisible = forceStatusBarVisible; 276 apply(mCurrentState); 277 } 278 279 /** 280 * Force the window to be collapsed, even if it should theoretically be expanded. 281 * Used for when a heads-up comes in but we still need to wait for the touchable regions to 282 * be computed. 283 */ setForceWindowCollapsed(boolean force)284 public void setForceWindowCollapsed(boolean force) { 285 mCurrentState.forceCollapsed = force; 286 apply(mCurrentState); 287 } 288 setPanelExpanded(boolean isExpanded)289 public void setPanelExpanded(boolean isExpanded) { 290 mCurrentState.panelExpanded = isExpanded; 291 apply(mCurrentState); 292 } 293 294 /** 295 * Set whether the screen brightness is forced to the value we use for doze mode by the status 296 * bar window. 297 */ setForceDozeBrightness(boolean forceDozeBrightness)298 public void setForceDozeBrightness(boolean forceDozeBrightness) { 299 mCurrentState.forceDozeBrightness = forceDozeBrightness; 300 apply(mCurrentState); 301 } 302 dump(FileDescriptor fd, PrintWriter pw, String[] args)303 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 304 pw.println("StatusBarWindowManager state:"); 305 pw.println(mCurrentState); 306 } 307 308 private static class State { 309 boolean keyguardShowing; 310 boolean keyguardOccluded; 311 boolean keyguardNeedsInput; 312 boolean panelVisible; 313 boolean panelExpanded; 314 boolean statusBarFocusable; 315 boolean bouncerShowing; 316 boolean keyguardFadingAway; 317 boolean qsExpanded; 318 boolean headsUpShowing; 319 boolean forceStatusBarVisible; 320 boolean forceCollapsed; 321 boolean forceDozeBrightness; 322 323 /** 324 * The {@link BaseStatusBar} state from the status bar. 325 */ 326 int statusBarState; 327 isKeyguardShowingAndNotOccluded()328 private boolean isKeyguardShowingAndNotOccluded() { 329 return keyguardShowing && !keyguardOccluded; 330 } 331 332 @Override toString()333 public String toString() { 334 StringBuilder result = new StringBuilder(); 335 String newLine = "\n"; 336 result.append("Window State {"); 337 result.append(newLine); 338 339 Field[] fields = this.getClass().getDeclaredFields(); 340 341 // Print field names paired with their values 342 for (Field field : fields) { 343 result.append(" "); 344 try { 345 result.append(field.getName()); 346 result.append(": "); 347 //requires access to private field: 348 result.append(field.get(this)); 349 } catch (IllegalAccessException ex) { 350 } 351 result.append(newLine); 352 } 353 result.append("}"); 354 355 return result.toString(); 356 } 357 } 358 } 359