StatusBarWindowManager.java revision 737bff3476a3af8f930d29fccce16d033fbc3efa
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.WindowManager; 28 29import com.android.keyguard.R; 30import com.android.systemui.keyguard.KeyguardViewMediator; 31import com.android.systemui.statusbar.BaseStatusBar; 32import com.android.systemui.statusbar.StatusBarState; 33 34/** 35 * Encapsulates all logic for the status bar window state management. 36 */ 37public class StatusBarWindowManager { 38 39 private final Context mContext; 40 private final WindowManager mWindowManager; 41 private View mStatusBarView; 42 private WindowManager.LayoutParams mLp; 43 private WindowManager.LayoutParams mLpChanged; 44 private int mBarHeight; 45 private final boolean mKeyguardScreenRotation; 46 47 private final State mCurrentState = new State(); 48 49 public StatusBarWindowManager(Context context) { 50 mContext = context; 51 mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 52 mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation(); 53 } 54 55 private boolean shouldEnableKeyguardScreenRotation() { 56 Resources res = mContext.getResources(); 57 return SystemProperties.getBoolean("lockscreen.rot_override", false) 58 || res.getBoolean(R.bool.config_enableLockScreenRotation); 59 } 60 61 /** 62 * Adds the status bar view to the window manager. 63 * 64 * @param statusBarView The view to add. 65 * @param barHeight The height of the status bar in collapsed state. 66 */ 67 public void add(View statusBarView, int barHeight) { 68 69 // Now that the status bar window encompasses the sliding panel and its 70 // translucent backdrop, the entire thing is made TRANSLUCENT and is 71 // hardware-accelerated. 72 mLp = new WindowManager.LayoutParams( 73 ViewGroup.LayoutParams.MATCH_PARENT, 74 barHeight, 75 WindowManager.LayoutParams.TYPE_STATUS_BAR, 76 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 77 | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING 78 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH 79 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 80 | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, 81 PixelFormat.TRANSLUCENT); 82 mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 83 mLp.gravity = Gravity.TOP; 84 mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 85 mLp.setTitle("StatusBar"); 86 mLp.packageName = mContext.getPackageName(); 87 mStatusBarView = statusBarView; 88 mBarHeight = barHeight; 89 mWindowManager.addView(mStatusBarView, mLp); 90 mLpChanged = new WindowManager.LayoutParams(); 91 mLpChanged.copyFrom(mLp); 92 } 93 94 private void applyKeyguardFlags(State state) { 95 if (state.keyguardShowing) { 96 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 97 mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 98 } else { 99 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 100 mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 101 } 102 } 103 104 private void adjustScreenOrientation(State state) { 105 if (state.isKeyguardShowingAndNotOccluded()) { 106 if (mKeyguardScreenRotation) { 107 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER; 108 } else { 109 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 110 } 111 } else { 112 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 113 } 114 } 115 116 private void applyFocusableFlag(State state) { 117 if (state.isKeyguardShowingAndNotOccluded() && state.keyguardNeedsInput 118 && state.bouncerShowing 119 || BaseStatusBar.ENABLE_REMOTE_INPUT && state.statusBarExpanded) { 120 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 121 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 122 } else if (state.isKeyguardShowingAndNotOccluded() || state.statusBarFocusable) { 123 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 124 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 125 } else { 126 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 127 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 128 } 129 } 130 131 private void applyHeight(State state) { 132 boolean expanded = !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded() 133 || state.statusBarExpanded || state.keyguardFadingAway || state.bouncerShowing 134 || state.headsUpShowing); 135 if (expanded) { 136 mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT; 137 } else { 138 mLpChanged.height = mBarHeight; 139 } 140 } 141 142 private void applyFitsSystemWindows(State state) { 143 mStatusBarView.setFitsSystemWindows(!state.isKeyguardShowingAndNotOccluded()); 144 } 145 146 private void applyUserActivityTimeout(State state) { 147 if (state.isKeyguardShowingAndNotOccluded() 148 && state.statusBarState == StatusBarState.KEYGUARD 149 && !state.qsExpanded) { 150 mLpChanged.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS; 151 } else { 152 mLpChanged.userActivityTimeout = -1; 153 } 154 } 155 156 private void applyInputFeatures(State state) { 157 if (state.isKeyguardShowingAndNotOccluded() 158 && state.statusBarState == StatusBarState.KEYGUARD 159 && !state.qsExpanded) { 160 mLpChanged.inputFeatures |= 161 WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; 162 } else { 163 mLpChanged.inputFeatures &= 164 ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; 165 } 166 } 167 168 private void apply(State state) { 169 applyKeyguardFlags(state); 170 applyForceStatusBarVisibleFlag(state); 171 applyFocusableFlag(state); 172 adjustScreenOrientation(state); 173 applyHeight(state); 174 applyUserActivityTimeout(state); 175 applyInputFeatures(state); 176 applyFitsSystemWindows(state); 177 applyModalFlag(state); 178 if (mLp.copyFrom(mLpChanged) != 0) { 179 mWindowManager.updateViewLayout(mStatusBarView, mLp); 180 } 181 } 182 183 private void applyForceStatusBarVisibleFlag(State state) { 184 if (state.forceStatusBarVisible) { 185 mLpChanged.privateFlags |= WindowManager 186 .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; 187 } else { 188 mLpChanged.privateFlags &= ~WindowManager 189 .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; 190 } 191 } 192 193 private void applyModalFlag(State state) { 194 if (state.headsUpShowing) { 195 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 196 } else { 197 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 198 } 199 } 200 201 public void setKeyguardShowing(boolean showing) { 202 mCurrentState.keyguardShowing = showing; 203 apply(mCurrentState); 204 } 205 206 public void setKeyguardOccluded(boolean occluded) { 207 mCurrentState.keyguardOccluded = occluded; 208 apply(mCurrentState); 209 } 210 211 public void setKeyguardNeedsInput(boolean needsInput) { 212 mCurrentState.keyguardNeedsInput = needsInput; 213 apply(mCurrentState); 214 } 215 216 public void setStatusBarExpanded(boolean expanded) { 217 mCurrentState.statusBarExpanded = expanded; 218 mCurrentState.statusBarFocusable = expanded; 219 apply(mCurrentState); 220 } 221 222 public void setStatusBarFocusable(boolean focusable) { 223 mCurrentState.statusBarFocusable = focusable; 224 apply(mCurrentState); 225 } 226 227 public void setBouncerShowing(boolean showing) { 228 mCurrentState.bouncerShowing = showing; 229 apply(mCurrentState); 230 } 231 232 public void setKeyguardFadingAway(boolean keyguardFadingAway) { 233 mCurrentState.keyguardFadingAway = keyguardFadingAway; 234 apply(mCurrentState); 235 } 236 237 public void setQsExpanded(boolean expanded) { 238 mCurrentState.qsExpanded = expanded; 239 apply(mCurrentState); 240 } 241 242 public void setHeadsUpShowing(boolean showing) { 243 mCurrentState.headsUpShowing = showing; 244 apply(mCurrentState); 245 } 246 247 /** 248 * @param state The {@link StatusBarState} of the status bar. 249 */ 250 public void setStatusBarState(int state) { 251 mCurrentState.statusBarState = state; 252 apply(mCurrentState); 253 } 254 255 public void setForceStatusBarVisible(boolean forceStatusBarVisible) { 256 mCurrentState.forceStatusBarVisible = forceStatusBarVisible; 257 apply(mCurrentState); 258 } 259 260 /** 261 * Force the window to be collapsed, even if it should theoretically be expanded. 262 * Used for when a heads-up comes in but we still need to wait for the touchable regions to 263 * be computed. 264 */ 265 public void setForceWindowCollapsed(boolean force) { 266 mCurrentState.forceCollapsed = force; 267 apply(mCurrentState); 268 } 269 270 private static class State { 271 boolean keyguardShowing; 272 boolean keyguardOccluded; 273 boolean keyguardNeedsInput; 274 boolean statusBarExpanded; 275 boolean statusBarFocusable; 276 boolean bouncerShowing; 277 boolean keyguardFadingAway; 278 boolean qsExpanded; 279 boolean headsUpShowing; 280 boolean forceStatusBarVisible; 281 boolean forceCollapsed; 282 283 /** 284 * The {@link BaseStatusBar} state from the status bar. 285 */ 286 int statusBarState; 287 288 private boolean isKeyguardShowingAndNotOccluded() { 289 return keyguardShowing && !keyguardOccluded; 290 } 291 } 292} 293