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 static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 20 21 import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT; 22 23 import android.app.ActivityManager; 24 import android.app.IActivityManager; 25 import android.content.Context; 26 import android.content.pm.ActivityInfo; 27 import android.content.res.Resources; 28 import android.graphics.PixelFormat; 29 import android.os.Binder; 30 import android.os.RemoteException; 31 import android.os.SystemProperties; 32 import android.util.Log; 33 import android.view.Gravity; 34 import android.view.View; 35 import android.view.ViewGroup; 36 import android.view.WindowManager; 37 import android.view.WindowManager.LayoutParams; 38 39 import com.android.internal.annotations.VisibleForTesting; 40 import com.android.keyguard.R; 41 import com.android.systemui.Dependency; 42 import com.android.systemui.Dumpable; 43 import com.android.systemui.colorextraction.SysuiColorExtractor; 44 import com.android.systemui.keyguard.KeyguardViewMediator; 45 import com.android.systemui.plugins.statusbar.StatusBarStateController; 46 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; 47 import com.android.systemui.statusbar.RemoteInputController.Callback; 48 import com.android.systemui.statusbar.StatusBarState; 49 import com.android.systemui.statusbar.SysuiStatusBarStateController; 50 import com.android.systemui.statusbar.policy.ConfigurationController; 51 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; 52 53 import com.google.android.collect.Lists; 54 import java.io.FileDescriptor; 55 import java.io.PrintWriter; 56 import java.lang.ref.WeakReference; 57 import java.lang.reflect.Field; 58 59 import java.util.ArrayList; 60 import javax.inject.Inject; 61 import javax.inject.Singleton; 62 63 /** 64 * Encapsulates all logic for the status bar window state management. 65 */ 66 @Singleton 67 public class StatusBarWindowController implements Callback, Dumpable, ConfigurationListener { 68 69 private static final String TAG = "StatusBarWindowController"; 70 71 private final Context mContext; 72 private final WindowManager mWindowManager; 73 private final IActivityManager mActivityManager; 74 private final DozeParameters mDozeParameters; 75 private final WindowManager.LayoutParams mLpChanged; 76 private final boolean mKeyguardScreenRotation; 77 private ViewGroup mStatusBarView; 78 private WindowManager.LayoutParams mLp; 79 private boolean mHasTopUi; 80 private boolean mHasTopUiChanged; 81 private int mBarHeight; 82 private float mScreenBrightnessDoze; 83 private final State mCurrentState = new State(); 84 private OtherwisedCollapsedListener mListener; 85 private final ArrayList<WeakReference<StatusBarWindowCallback>> 86 mCallbacks = Lists.newArrayList(); 87 88 private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class); 89 90 @Inject StatusBarWindowController(Context context)91 public StatusBarWindowController(Context context) { 92 this(context, context.getSystemService(WindowManager.class), ActivityManager.getService(), 93 DozeParameters.getInstance(context)); 94 } 95 96 @VisibleForTesting StatusBarWindowController(Context context, WindowManager windowManager, IActivityManager activityManager, DozeParameters dozeParameters)97 public StatusBarWindowController(Context context, WindowManager windowManager, 98 IActivityManager activityManager, DozeParameters dozeParameters) { 99 mContext = context; 100 mWindowManager = windowManager; 101 mActivityManager = activityManager; 102 mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation(); 103 mDozeParameters = dozeParameters; 104 mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze(); 105 mLpChanged = new WindowManager.LayoutParams(); 106 ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class)) 107 .addCallback(mStateListener, 108 SysuiStatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER); 109 Dependency.get(ConfigurationController.class).addCallback(this); 110 } 111 112 /** 113 * Register to receive notifications about status bar window state changes. 114 */ registerCallback(StatusBarWindowCallback callback)115 public void registerCallback(StatusBarWindowCallback callback) { 116 // Prevent adding duplicate callbacks 117 for (int i = 0; i < mCallbacks.size(); i++) { 118 if (mCallbacks.get(i).get() == callback) { 119 return; 120 } 121 } 122 mCallbacks.add(new WeakReference<StatusBarWindowCallback>(callback)); 123 } 124 shouldEnableKeyguardScreenRotation()125 private boolean shouldEnableKeyguardScreenRotation() { 126 Resources res = mContext.getResources(); 127 return SystemProperties.getBoolean("lockscreen.rot_override", false) 128 || res.getBoolean(R.bool.config_enableLockScreenRotation); 129 } 130 131 /** 132 * Adds the status bar view to the window manager. 133 * 134 * @param statusBarView The view to add. 135 * @param barHeight The height of the status bar in collapsed state. 136 */ add(ViewGroup statusBarView, int barHeight)137 public void add(ViewGroup statusBarView, int barHeight) { 138 139 // Now that the status bar window encompasses the sliding panel and its 140 // translucent backdrop, the entire thing is made TRANSLUCENT and is 141 // hardware-accelerated. 142 mLp = new WindowManager.LayoutParams( 143 ViewGroup.LayoutParams.MATCH_PARENT, 144 barHeight, 145 WindowManager.LayoutParams.TYPE_STATUS_BAR, 146 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 147 | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING 148 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH 149 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 150 | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, 151 PixelFormat.TRANSLUCENT); 152 mLp.token = new Binder(); 153 mLp.gravity = Gravity.TOP; 154 mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 155 mLp.setTitle("StatusBar"); 156 mLp.packageName = mContext.getPackageName(); 157 mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 158 mStatusBarView = statusBarView; 159 mBarHeight = barHeight; 160 mWindowManager.addView(mStatusBarView, mLp); 161 mLpChanged.copyFrom(mLp); 162 onThemeChanged(); 163 } 164 getStatusBarView()165 public ViewGroup getStatusBarView() { 166 return mStatusBarView; 167 } 168 setDozeScreenBrightness(int value)169 public void setDozeScreenBrightness(int value) { 170 mScreenBrightnessDoze = value / 255f; 171 } 172 setKeyguardDark(boolean dark)173 private void setKeyguardDark(boolean dark) { 174 int vis = mStatusBarView.getSystemUiVisibility(); 175 if (dark) { 176 vis = vis | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 177 vis = vis | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 178 } else { 179 vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 180 vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 181 } 182 mStatusBarView.setSystemUiVisibility(vis); 183 } 184 applyKeyguardFlags(State state)185 private void applyKeyguardFlags(State state) { 186 if (state.keyguardShowing) { 187 mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 188 } else { 189 mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 190 } 191 192 final boolean scrimsOccludingWallpaper = 193 state.scrimsVisibility == ScrimController.VISIBILITY_FULLY_OPAQUE; 194 final boolean keyguardOrAod = state.keyguardShowing 195 || (state.dozing && mDozeParameters.getAlwaysOn()); 196 if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper) { 197 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 198 } else { 199 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 200 } 201 202 if (state.dozing) { 203 mLpChanged.privateFlags |= LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 204 } else { 205 mLpChanged.privateFlags &= ~LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 206 } 207 } 208 adjustScreenOrientation(State state)209 private void adjustScreenOrientation(State state) { 210 if (state.isKeyguardShowingAndNotOccluded() || state.dozing) { 211 if (mKeyguardScreenRotation) { 212 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER; 213 } else { 214 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 215 } 216 } else { 217 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 218 } 219 } 220 applyFocusableFlag(State state)221 private void applyFocusableFlag(State state) { 222 boolean panelFocusable = state.statusBarFocusable && state.panelExpanded; 223 if (state.bouncerShowing && (state.keyguardOccluded || state.keyguardNeedsInput) 224 || ENABLE_REMOTE_INPUT && state.remoteInputActive 225 || state.bubbleExpanded) { 226 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 227 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 228 } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) { 229 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 230 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 231 } else { 232 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 233 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 234 } 235 236 mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 237 } 238 applyForceShowNavigationFlag(State state)239 private void applyForceShowNavigationFlag(State state) { 240 if (state.panelExpanded || state.bouncerShowing 241 || ENABLE_REMOTE_INPUT && state.remoteInputActive) { 242 mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; 243 } else { 244 mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; 245 } 246 } 247 applyHeight(State state)248 private void applyHeight(State state) { 249 boolean expanded = isExpanded(state); 250 if (state.forcePluginOpen) { 251 if (mListener != null) { 252 mListener.setWouldOtherwiseCollapse(expanded); 253 } 254 expanded = true; 255 } 256 if (expanded) { 257 mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT; 258 } else { 259 mLpChanged.height = mBarHeight; 260 } 261 } 262 isExpanded(State state)263 private boolean isExpanded(State state) { 264 return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded() 265 || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing 266 || state.headsUpShowing || state.bubblesShowing 267 || state.scrimsVisibility != ScrimController.VISIBILITY_FULLY_TRANSPARENT); 268 } 269 applyFitsSystemWindows(State state)270 private void applyFitsSystemWindows(State state) { 271 boolean fitsSystemWindows = !state.isKeyguardShowingAndNotOccluded(); 272 if (mStatusBarView != null && mStatusBarView.getFitsSystemWindows() != fitsSystemWindows) { 273 mStatusBarView.setFitsSystemWindows(fitsSystemWindows); 274 mStatusBarView.requestApplyInsets(); 275 } 276 } 277 applyUserActivityTimeout(State state)278 private void applyUserActivityTimeout(State state) { 279 if (state.isKeyguardShowingAndNotOccluded() 280 && state.statusBarState == StatusBarState.KEYGUARD 281 && !state.qsExpanded) { 282 mLpChanged.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS; 283 } else { 284 mLpChanged.userActivityTimeout = -1; 285 } 286 } 287 applyInputFeatures(State state)288 private void applyInputFeatures(State state) { 289 if (state.isKeyguardShowingAndNotOccluded() 290 && state.statusBarState == StatusBarState.KEYGUARD 291 && !state.qsExpanded && !state.forceUserActivity) { 292 mLpChanged.inputFeatures |= 293 WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; 294 } else { 295 mLpChanged.inputFeatures &= 296 ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY; 297 } 298 } 299 applyStatusBarColorSpaceAgnosticFlag(State state)300 private void applyStatusBarColorSpaceAgnosticFlag(State state) { 301 if (!isExpanded(state)) { 302 mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC; 303 } else { 304 mLpChanged.privateFlags &= 305 ~WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC; 306 } 307 } 308 apply(State state)309 private void apply(State state) { 310 applyKeyguardFlags(state); 311 applyForceStatusBarVisibleFlag(state); 312 applyFocusableFlag(state); 313 applyForceShowNavigationFlag(state); 314 adjustScreenOrientation(state); 315 applyHeight(state); 316 applyUserActivityTimeout(state); 317 applyInputFeatures(state); 318 applyFitsSystemWindows(state); 319 applyModalFlag(state); 320 applyBrightness(state); 321 applyHasTopUi(state); 322 applyNotTouchable(state); 323 applyStatusBarColorSpaceAgnosticFlag(state); 324 if (mLp != null && mLp.copyFrom(mLpChanged) != 0) { 325 mWindowManager.updateViewLayout(mStatusBarView, mLp); 326 } 327 if (mHasTopUi != mHasTopUiChanged) { 328 try { 329 mActivityManager.setHasTopUi(mHasTopUiChanged); 330 } catch (RemoteException e) { 331 Log.e(TAG, "Failed to call setHasTopUi", e); 332 } 333 mHasTopUi = mHasTopUiChanged; 334 } 335 notifyStateChangedCallbacks(); 336 } 337 notifyStateChangedCallbacks()338 public void notifyStateChangedCallbacks() { 339 for (int i = 0; i < mCallbacks.size(); i++) { 340 StatusBarWindowCallback cb = mCallbacks.get(i).get(); 341 if (cb != null) { 342 cb.onStateChanged(mCurrentState.keyguardShowing, 343 mCurrentState.keyguardOccluded, 344 mCurrentState.bouncerShowing); 345 } 346 } 347 } 348 applyForceStatusBarVisibleFlag(State state)349 private void applyForceStatusBarVisibleFlag(State state) { 350 if (state.forceStatusBarVisible) { 351 mLpChanged.privateFlags |= WindowManager 352 .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; 353 } else { 354 mLpChanged.privateFlags &= ~WindowManager 355 .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; 356 } 357 } 358 applyModalFlag(State state)359 private void applyModalFlag(State state) { 360 if (state.headsUpShowing) { 361 mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 362 } else { 363 mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 364 } 365 } 366 applyBrightness(State state)367 private void applyBrightness(State state) { 368 if (state.forceDozeBrightness) { 369 mLpChanged.screenBrightness = mScreenBrightnessDoze; 370 } else { 371 mLpChanged.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE; 372 } 373 } 374 applyHasTopUi(State state)375 private void applyHasTopUi(State state) { 376 mHasTopUiChanged = isExpanded(state); 377 } 378 applyNotTouchable(State state)379 private void applyNotTouchable(State state) { 380 if (state.notTouchable) { 381 mLpChanged.flags |= LayoutParams.FLAG_NOT_TOUCHABLE; 382 } else { 383 mLpChanged.flags &= ~LayoutParams.FLAG_NOT_TOUCHABLE; 384 } 385 } 386 setKeyguardShowing(boolean showing)387 public void setKeyguardShowing(boolean showing) { 388 mCurrentState.keyguardShowing = showing; 389 apply(mCurrentState); 390 } 391 setKeyguardOccluded(boolean occluded)392 public void setKeyguardOccluded(boolean occluded) { 393 mCurrentState.keyguardOccluded = occluded; 394 apply(mCurrentState); 395 } 396 setKeyguardNeedsInput(boolean needsInput)397 public void setKeyguardNeedsInput(boolean needsInput) { 398 mCurrentState.keyguardNeedsInput = needsInput; 399 apply(mCurrentState); 400 } 401 setPanelVisible(boolean visible)402 public void setPanelVisible(boolean visible) { 403 mCurrentState.panelVisible = visible; 404 mCurrentState.statusBarFocusable = visible; 405 apply(mCurrentState); 406 } 407 setStatusBarFocusable(boolean focusable)408 public void setStatusBarFocusable(boolean focusable) { 409 mCurrentState.statusBarFocusable = focusable; 410 apply(mCurrentState); 411 } 412 setBouncerShowing(boolean showing)413 public void setBouncerShowing(boolean showing) { 414 mCurrentState.bouncerShowing = showing; 415 apply(mCurrentState); 416 } 417 setBackdropShowing(boolean showing)418 public void setBackdropShowing(boolean showing) { 419 mCurrentState.backdropShowing = showing; 420 apply(mCurrentState); 421 } 422 setKeyguardFadingAway(boolean keyguardFadingAway)423 public void setKeyguardFadingAway(boolean keyguardFadingAway) { 424 mCurrentState.keyguardFadingAway = keyguardFadingAway; 425 apply(mCurrentState); 426 } 427 setQsExpanded(boolean expanded)428 public void setQsExpanded(boolean expanded) { 429 mCurrentState.qsExpanded = expanded; 430 apply(mCurrentState); 431 } 432 setForceUserActivity(boolean forceUserActivity)433 public void setForceUserActivity(boolean forceUserActivity) { 434 mCurrentState.forceUserActivity = forceUserActivity; 435 apply(mCurrentState); 436 } 437 setScrimsVisibility(int scrimsVisibility)438 public void setScrimsVisibility(int scrimsVisibility) { 439 mCurrentState.scrimsVisibility = scrimsVisibility; 440 apply(mCurrentState); 441 } 442 setHeadsUpShowing(boolean showing)443 public void setHeadsUpShowing(boolean showing) { 444 mCurrentState.headsUpShowing = showing; 445 apply(mCurrentState); 446 } 447 setWallpaperSupportsAmbientMode(boolean supportsAmbientMode)448 public void setWallpaperSupportsAmbientMode(boolean supportsAmbientMode) { 449 mCurrentState.wallpaperSupportsAmbientMode = supportsAmbientMode; 450 apply(mCurrentState); 451 } 452 453 /** 454 * @param state The {@link StatusBarStateController} of the status bar. 455 */ setStatusBarState(int state)456 private void setStatusBarState(int state) { 457 mCurrentState.statusBarState = state; 458 apply(mCurrentState); 459 } 460 setForceStatusBarVisible(boolean forceStatusBarVisible)461 public void setForceStatusBarVisible(boolean forceStatusBarVisible) { 462 mCurrentState.forceStatusBarVisible = forceStatusBarVisible; 463 apply(mCurrentState); 464 } 465 466 /** 467 * Force the window to be collapsed, even if it should theoretically be expanded. 468 * Used for when a heads-up comes in but we still need to wait for the touchable regions to 469 * be computed. 470 */ setForceWindowCollapsed(boolean force)471 public void setForceWindowCollapsed(boolean force) { 472 mCurrentState.forceCollapsed = force; 473 apply(mCurrentState); 474 } 475 setPanelExpanded(boolean isExpanded)476 public void setPanelExpanded(boolean isExpanded) { 477 mCurrentState.panelExpanded = isExpanded; 478 apply(mCurrentState); 479 } 480 481 @Override onRemoteInputActive(boolean remoteInputActive)482 public void onRemoteInputActive(boolean remoteInputActive) { 483 mCurrentState.remoteInputActive = remoteInputActive; 484 apply(mCurrentState); 485 } 486 487 /** 488 * Set whether the screen brightness is forced to the value we use for doze mode by the status 489 * bar window. 490 */ setForceDozeBrightness(boolean forceDozeBrightness)491 public void setForceDozeBrightness(boolean forceDozeBrightness) { 492 mCurrentState.forceDozeBrightness = forceDozeBrightness; 493 apply(mCurrentState); 494 } 495 setDozing(boolean dozing)496 public void setDozing(boolean dozing) { 497 mCurrentState.dozing = dozing; 498 apply(mCurrentState); 499 } 500 setBarHeight(int barHeight)501 public void setBarHeight(int barHeight) { 502 mBarHeight = barHeight; 503 apply(mCurrentState); 504 } 505 setForcePluginOpen(boolean forcePluginOpen)506 public void setForcePluginOpen(boolean forcePluginOpen) { 507 mCurrentState.forcePluginOpen = forcePluginOpen; 508 apply(mCurrentState); 509 } 510 setNotTouchable(boolean notTouchable)511 public void setNotTouchable(boolean notTouchable) { 512 mCurrentState.notTouchable = notTouchable; 513 apply(mCurrentState); 514 } 515 516 /** 517 * Sets whether there are bubbles showing on the screen. 518 */ setBubblesShowing(boolean bubblesShowing)519 public void setBubblesShowing(boolean bubblesShowing) { 520 mCurrentState.bubblesShowing = bubblesShowing; 521 apply(mCurrentState); 522 } 523 524 /** 525 * The bubbles showing state for the status bar. 526 */ getBubblesShowing()527 public boolean getBubblesShowing() { 528 return mCurrentState.bubblesShowing; 529 } 530 531 /** 532 * Sets if there is a bubble being expanded on the screen. 533 */ setBubbleExpanded(boolean bubbleExpanded)534 public void setBubbleExpanded(boolean bubbleExpanded) { 535 mCurrentState.bubbleExpanded = bubbleExpanded; 536 apply(mCurrentState); 537 } 538 539 /** 540 * Whether the bubble is shown in expanded state for the status bar. 541 */ getBubbleExpanded()542 public boolean getBubbleExpanded() { 543 return mCurrentState.bubbleExpanded; 544 } 545 546 /** 547 * Whether the status bar panel is expanded or not. 548 */ getPanelExpanded()549 public boolean getPanelExpanded() { 550 return mCurrentState.panelExpanded; 551 } 552 setStateListener(OtherwisedCollapsedListener listener)553 public void setStateListener(OtherwisedCollapsedListener listener) { 554 mListener = listener; 555 } 556 dump(FileDescriptor fd, PrintWriter pw, String[] args)557 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 558 pw.println("StatusBarWindowController state:"); 559 pw.println(mCurrentState); 560 } 561 isShowingWallpaper()562 public boolean isShowingWallpaper() { 563 return !mCurrentState.backdropShowing; 564 } 565 566 @Override onThemeChanged()567 public void onThemeChanged() { 568 if (mStatusBarView == null) { 569 return; 570 } 571 572 final boolean useDarkText = mColorExtractor.getNeutralColors().supportsDarkText(); 573 // Make sure we have the correct navbar/statusbar colors. 574 setKeyguardDark(useDarkText); 575 } 576 577 private static class State { 578 boolean keyguardShowing; 579 boolean keyguardOccluded; 580 boolean keyguardNeedsInput; 581 boolean panelVisible; 582 boolean panelExpanded; 583 boolean statusBarFocusable; 584 boolean bouncerShowing; 585 boolean keyguardFadingAway; 586 boolean qsExpanded; 587 boolean headsUpShowing; 588 boolean forceStatusBarVisible; 589 boolean forceCollapsed; 590 boolean forceDozeBrightness; 591 boolean forceUserActivity; 592 boolean backdropShowing; 593 boolean wallpaperSupportsAmbientMode; 594 boolean notTouchable; 595 boolean bubblesShowing; 596 boolean bubbleExpanded; 597 598 /** 599 * The {@link StatusBar} state from the status bar. 600 */ 601 int statusBarState; 602 603 boolean remoteInputActive; 604 boolean forcePluginOpen; 605 boolean dozing; 606 int scrimsVisibility; 607 isKeyguardShowingAndNotOccluded()608 private boolean isKeyguardShowingAndNotOccluded() { 609 return keyguardShowing && !keyguardOccluded; 610 } 611 612 @Override toString()613 public String toString() { 614 StringBuilder result = new StringBuilder(); 615 String newLine = "\n"; 616 result.append("Window State {"); 617 result.append(newLine); 618 619 Field[] fields = this.getClass().getDeclaredFields(); 620 621 // Print field names paired with their values 622 for (Field field : fields) { 623 result.append(" "); 624 try { 625 result.append(field.getName()); 626 result.append(": "); 627 //requires access to private field: 628 result.append(field.get(this)); 629 } catch (IllegalAccessException ex) { 630 } 631 result.append(newLine); 632 } 633 result.append("}"); 634 635 return result.toString(); 636 } 637 } 638 639 private final StateListener mStateListener = new StateListener() { 640 @Override 641 public void onStateChanged(int newState) { 642 setStatusBarState(newState); 643 } 644 645 @Override 646 public void onDozingChanged(boolean isDozing) { 647 setDozing(isDozing); 648 } 649 }; 650 651 /** 652 * Custom listener to pipe data back to plugins about whether or not the status bar would be 653 * collapsed if not for the plugin. 654 * TODO: Find cleaner way to do this. 655 */ 656 public interface OtherwisedCollapsedListener { setWouldOtherwiseCollapse(boolean otherwiseCollapse)657 void setWouldOtherwiseCollapse(boolean otherwiseCollapse); 658 } 659 } 660