blob: 75f5023ce48a586d46cd380a5944f7e0be5e4cb9 [file] [log] [blame]
wilsonshihe8321942019-10-18 18:39:46 +08001/*
2 * Copyright (C) 2020 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 Jaggi026ed752020-01-29 00:30:24 +010019import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
wilsonshihe8321942019-10-18 18:39:46 +080020import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
Jorim Jaggi026ed752020-01-29 00:30:24 +010021import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
wilsonshihf587b632020-02-12 13:16:12 +080022
wilsonshihe8321942019-10-18 18:39:46 +080023import static com.android.systemui.DejankUtils.whitelistIpcs;
24import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
25
26import android.app.IActivityManager;
27import android.content.Context;
28import android.content.pm.ActivityInfo;
29import android.content.res.Resources;
30import android.graphics.PixelFormat;
31import android.os.Binder;
32import android.os.RemoteException;
33import android.os.SystemProperties;
34import android.os.Trace;
35import android.util.Log;
36import android.view.Display;
37import android.view.Gravity;
38import android.view.View;
39import android.view.ViewGroup;
40import android.view.WindowManager;
41import android.view.WindowManager.LayoutParams;
42
43import com.android.systemui.Dumpable;
44import com.android.systemui.R;
45import com.android.systemui.colorextraction.SysuiColorExtractor;
Ned Burnsaaeb44b2020-02-12 23:48:26 -050046import com.android.systemui.dump.DumpManager;
wilsonshihe8321942019-10-18 18:39:46 +080047import com.android.systemui.keyguard.KeyguardViewMediator;
48import com.android.systemui.plugins.statusbar.StatusBarStateController;
49import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
50import com.android.systemui.statusbar.RemoteInputController.Callback;
51import com.android.systemui.statusbar.StatusBarState;
wilsonshihe8321942019-10-18 18:39:46 +080052import com.android.systemui.statusbar.SysuiStatusBarStateController;
53import com.android.systemui.statusbar.policy.ConfigurationController;
54import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
55
56import com.google.android.collect.Lists;
57
58import java.io.FileDescriptor;
59import java.io.PrintWriter;
60import java.lang.ref.WeakReference;
61import java.lang.reflect.Field;
62import java.util.ArrayList;
63import java.util.Arrays;
64
65import javax.inject.Inject;
66import javax.inject.Singleton;
67
68/**
69 * Encapsulates all logic for the notification shade window state management.
70 */
71@Singleton
72public class NotificationShadeWindowController implements Callback, Dumpable,
73 ConfigurationListener {
74
75 private static final String TAG = "NotificationShadeWindowController";
76 private static final boolean DEBUG = false;
77
78 private final Context mContext;
79 private final WindowManager mWindowManager;
80 private final IActivityManager mActivityManager;
81 private final DozeParameters mDozeParameters;
82 private final LayoutParams mLpChanged;
83 private final boolean mKeyguardScreenRotation;
84 private final long mLockScreenDisplayTimeout;
85 private final Display.Mode mKeyguardDisplayMode;
86 private final KeyguardBypassController mKeyguardBypassController;
87 private ViewGroup mNotificationShadeView;
88 private LayoutParams mLp;
89 private boolean mHasTopUi;
90 private boolean mHasTopUiChanged;
91 private float mScreenBrightnessDoze;
92 private final State mCurrentState = new State();
93 private OtherwisedCollapsedListener mListener;
94 private ForcePluginOpenListener mForcePluginOpenListener;
95 private final ArrayList<WeakReference<StatusBarWindowCallback>>
96 mCallbacks = Lists.newArrayList();
97
98 private final SysuiColorExtractor mColorExtractor;
wilsonshihe8321942019-10-18 18:39:46 +080099
100 @Inject
101 public NotificationShadeWindowController(Context context, WindowManager windowManager,
102 IActivityManager activityManager, DozeParameters dozeParameters,
103 StatusBarStateController statusBarStateController,
104 ConfigurationController configurationController,
Lucas Dupind73410a2020-02-18 12:54:41 -0800105 KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor,
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500106 DumpManager dumpManager) {
wilsonshihe8321942019-10-18 18:39:46 +0800107 mContext = context;
108 mWindowManager = windowManager;
109 mActivityManager = activityManager;
110 mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
111 mDozeParameters = dozeParameters;
112 mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
113 mLpChanged = new LayoutParams();
114 mKeyguardBypassController = keyguardBypassController;
115 mColorExtractor = colorExtractor;
Ned Burnsaaeb44b2020-02-12 23:48:26 -0500116 dumpManager.registerDumpable(getClass().getName(), this);
wilsonshihe8321942019-10-18 18:39:46 +0800117
118 mLockScreenDisplayTimeout = context.getResources()
119 .getInteger(R.integer.config_lockScreenDisplayTimeout);
120 ((SysuiStatusBarStateController) statusBarStateController)
121 .addCallback(mStateListener,
122 SysuiStatusBarStateController.RANK_STATUS_BAR_WINDOW_CONTROLLER);
123 configurationController.addCallback(this);
124
125 Display.Mode[] supportedModes = context.getDisplay().getSupportedModes();
126 Display.Mode currentMode = context.getDisplay().getMode();
127 // Running on the highest frame rate available can be expensive.
128 // Let's specify a preferred refresh rate, and allow higher FPS only when we
129 // know that we're not falsing (because we unlocked.)
130 int keyguardRefreshRate = context.getResources()
131 .getInteger(R.integer.config_keyguardRefreshRate);
132 // Find supported display mode with the same resolution and requested refresh rate.
133 mKeyguardDisplayMode = Arrays.stream(supportedModes).filter(mode ->
134 (int) mode.getRefreshRate() == keyguardRefreshRate
135 && mode.getPhysicalWidth() == currentMode.getPhysicalWidth()
136 && mode.getPhysicalHeight() == currentMode.getPhysicalHeight())
137 .findFirst().orElse(null);
138 }
139
140 /**
141 * Register to receive notifications about status bar window state changes.
142 */
143 public void registerCallback(StatusBarWindowCallback callback) {
144 // Prevent adding duplicate callbacks
145 for (int i = 0; i < mCallbacks.size(); i++) {
146 if (mCallbacks.get(i).get() == callback) {
147 return;
148 }
149 }
150 mCallbacks.add(new WeakReference<StatusBarWindowCallback>(callback));
151 }
152
153 private boolean shouldEnableKeyguardScreenRotation() {
154 Resources res = mContext.getResources();
155 return SystemProperties.getBoolean("lockscreen.rot_override", false)
156 || res.getBoolean(R.bool.config_enableLockScreenRotation);
157 }
158
159 /**
160 * Adds the notification shade view to the window manager.
161 */
162 public void attach() {
163 // Now that the notification shade encompasses the sliding panel and its
164 // translucent backdrop, the entire thing is made TRANSLUCENT and is
165 // hardware-accelerated.
166 mLp = new LayoutParams(
167 ViewGroup.LayoutParams.MATCH_PARENT,
168 ViewGroup.LayoutParams.MATCH_PARENT,
169 LayoutParams.TYPE_NOTIFICATION_SHADE,
170 LayoutParams.FLAG_NOT_FOCUSABLE
171 | LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
172 | LayoutParams.FLAG_SPLIT_TOUCH
173 | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
174 | LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
175 PixelFormat.TRANSLUCENT);
176 mLp.token = new Binder();
177 mLp.gravity = Gravity.TOP;
Tiger Huang52724442020-01-20 21:38:42 +0800178 mLp.setFitInsetsTypes(0 /* types */);
wilsonshihe8321942019-10-18 18:39:46 +0800179 mLp.softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
180 mLp.setTitle("NotificationShade");
181 mLp.packageName = mContext.getPackageName();
182 mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
Jorim Jaggi026ed752020-01-29 00:30:24 +0100183
184 // We use BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE here, however, there is special logic in
185 // window manager which disables the transient show behavior.
186 // TODO: Clean this up once that behavior moves into the Shell.
187 mLp.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
188 mLp.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
189
wilsonshihe8321942019-10-18 18:39:46 +0800190 mWindowManager.addView(mNotificationShadeView, mLp);
191 mLpChanged.copyFrom(mLp);
192 onThemeChanged();
193 }
194
wilsonshihf587b632020-02-12 13:16:12 +0800195 public void setNotificationShadeView(ViewGroup view) {
196 mNotificationShadeView = view;
197 }
198
wilsonshihe8321942019-10-18 18:39:46 +0800199 public ViewGroup getNotificationShadeView() {
200 return mNotificationShadeView;
201 }
202
203 public void setDozeScreenBrightness(int value) {
204 mScreenBrightnessDoze = value / 255f;
205 }
206
207 private void setKeyguardDark(boolean dark) {
208 int vis = mNotificationShadeView.getSystemUiVisibility();
209 if (dark) {
210 vis = vis | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
211 vis = vis | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
212 } else {
213 vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
214 vis = vis & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
215 }
216 mNotificationShadeView.setSystemUiVisibility(vis);
217 }
218
219 private void applyKeyguardFlags(State state) {
220 final boolean scrimsOccludingWallpaper =
221 state.mScrimsVisibility == ScrimController.OPAQUE;
222 final boolean keyguardOrAod = state.mKeyguardShowing
223 || (state.mDozing && mDozeParameters.getAlwaysOn());
224 if (keyguardOrAod && !state.mBackdropShowing && !scrimsOccludingWallpaper) {
225 mLpChanged.flags |= LayoutParams.FLAG_SHOW_WALLPAPER;
226 } else {
227 mLpChanged.flags &= ~LayoutParams.FLAG_SHOW_WALLPAPER;
228 }
229
230 if (state.mDozing) {
231 mLpChanged.privateFlags |= LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
232 } else {
233 mLpChanged.privateFlags &= ~LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
234 }
235
236 if (mKeyguardDisplayMode != null) {
237 boolean bypassOnKeyguard = mKeyguardBypassController.getBypassEnabled()
238 && state.mStatusBarState == StatusBarState.KEYGUARD
239 && !state.mKeyguardFadingAway && !state.mKeyguardGoingAway;
240 if (state.mDozing || bypassOnKeyguard) {
241 mLpChanged.preferredDisplayModeId = mKeyguardDisplayMode.getModeId();
242 } else {
243 mLpChanged.preferredDisplayModeId = 0;
244 }
245 Trace.setCounter("display_mode_id", mLpChanged.preferredDisplayModeId);
246 }
247 }
248
249 private void adjustScreenOrientation(State state) {
250 if (state.isKeyguardShowingAndNotOccluded() || state.mDozing) {
251 if (mKeyguardScreenRotation) {
252 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
253 } else {
254 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
255 }
256 } else {
257 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
258 }
259 }
260
261 private void applyFocusableFlag(State state) {
262 boolean panelFocusable = state.mNotificationShadeFocusable && state.mPanelExpanded;
263 if (state.mBouncerShowing && (state.mKeyguardOccluded || state.mKeyguardNeedsInput)
264 || ENABLE_REMOTE_INPUT && state.mRemoteInputActive
265 || state.mBubbleExpanded) {
266 mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
267 mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
268 } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
269 mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
lumark26d1d0d2020-01-21 13:16:23 +0800270 // Make sure to remove FLAG_ALT_FOCUSABLE_IM when keyguard needs input.
271 if (state.mKeyguardNeedsInput) {
272 mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
273 } else {
274 mLpChanged.flags |= LayoutParams.FLAG_ALT_FOCUSABLE_IM;
275 }
wilsonshihe8321942019-10-18 18:39:46 +0800276 } else {
277 mLpChanged.flags |= LayoutParams.FLAG_NOT_FOCUSABLE;
278 mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
279 }
280
281 mLpChanged.softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
282 }
283
284 private void applyForceShowNavigationFlag(State state) {
285 if (state.mPanelExpanded || state.mBouncerShowing
286 || ENABLE_REMOTE_INPUT && state.mRemoteInputActive) {
287 mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
288 } else {
289 mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
290 }
291 }
292
293 private void applyVisibility(State state) {
294 boolean visible = isExpanded(state);
295 if (state.mForcePluginOpen) {
296 if (mListener != null) {
297 mListener.setWouldOtherwiseCollapse(visible);
298 }
299 visible = true;
300 }
301 if (visible) {
302 mNotificationShadeView.setVisibility(View.VISIBLE);
303 } else {
304 mNotificationShadeView.setVisibility(View.INVISIBLE);
305 }
306 }
307
308 private boolean isExpanded(State state) {
309 return !state.mForceCollapsed && (state.isKeyguardShowingAndNotOccluded()
310 || state.mPanelVisible || state.mKeyguardFadingAway || state.mBouncerShowing
311 || state.mHeadsUpShowing || state.mBubblesShowing
312 || state.mScrimsVisibility != ScrimController.TRANSPARENT);
313 }
314
315 private void applyFitsSystemWindows(State state) {
316 boolean fitsSystemWindows = !state.isKeyguardShowingAndNotOccluded();
317 if (mNotificationShadeView != null
318 && mNotificationShadeView.getFitsSystemWindows() != fitsSystemWindows) {
319 mNotificationShadeView.setFitsSystemWindows(fitsSystemWindows);
320 mNotificationShadeView.requestApplyInsets();
321 }
322 }
323
324 private void applyUserActivityTimeout(State state) {
325 if (state.isKeyguardShowingAndNotOccluded()
326 && state.mStatusBarState == StatusBarState.KEYGUARD
327 && !state.mQsExpanded) {
328 mLpChanged.userActivityTimeout = state.mBouncerShowing
329 ? KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS : mLockScreenDisplayTimeout;
330 } else {
331 mLpChanged.userActivityTimeout = -1;
332 }
333 }
334
335 private void applyInputFeatures(State state) {
336 if (state.isKeyguardShowingAndNotOccluded()
337 && state.mStatusBarState == StatusBarState.KEYGUARD
338 && !state.mQsExpanded && !state.mForceUserActivity) {
339 mLpChanged.inputFeatures |=
340 LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
341 } else {
342 mLpChanged.inputFeatures &=
343 ~LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
344 }
345 }
346
347 private void applyStatusBarColorSpaceAgnosticFlag(State state) {
348 if (!isExpanded(state)) {
349 mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
350 } else {
351 mLpChanged.privateFlags &=
352 ~LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
353 }
354 }
355
356 private void apply(State state) {
357 applyKeyguardFlags(state);
358 applyFocusableFlag(state);
359 applyForceShowNavigationFlag(state);
360 adjustScreenOrientation(state);
361 applyVisibility(state);
362 applyUserActivityTimeout(state);
363 applyInputFeatures(state);
364 applyFitsSystemWindows(state);
365 applyModalFlag(state);
366 applyBrightness(state);
367 applyHasTopUi(state);
368 applyNotTouchable(state);
369 applyStatusBarColorSpaceAgnosticFlag(state);
370 if (mLp != null && mLp.copyFrom(mLpChanged) != 0) {
371 mWindowManager.updateViewLayout(mNotificationShadeView, mLp);
372 }
373 if (mHasTopUi != mHasTopUiChanged) {
374 whitelistIpcs(() -> {
375 try {
376 mActivityManager.setHasTopUi(mHasTopUiChanged);
377 } catch (RemoteException e) {
378 Log.e(TAG, "Failed to call setHasTopUi", e);
379 }
380 mHasTopUi = mHasTopUiChanged;
381 });
382 }
383 notifyStateChangedCallbacks();
384 }
385
386 public void notifyStateChangedCallbacks() {
387 for (int i = 0; i < mCallbacks.size(); i++) {
388 StatusBarWindowCallback cb = mCallbacks.get(i).get();
389 if (cb != null) {
390 cb.onStateChanged(mCurrentState.mKeyguardShowing,
391 mCurrentState.mKeyguardOccluded,
392 mCurrentState.mBouncerShowing);
393 }
394 }
395 }
396
397 private void applyModalFlag(State state) {
398 if (state.mHeadsUpShowing) {
399 mLpChanged.flags |= LayoutParams.FLAG_NOT_TOUCH_MODAL;
400 } else {
401 mLpChanged.flags &= ~LayoutParams.FLAG_NOT_TOUCH_MODAL;
402 }
403 }
404
405 private void applyBrightness(State state) {
406 if (state.mForceDozeBrightness) {
407 mLpChanged.screenBrightness = mScreenBrightnessDoze;
408 } else {
409 mLpChanged.screenBrightness = LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
410 }
411 }
412
413 private void applyHasTopUi(State state) {
414 mHasTopUiChanged = state.mForceHasTopUi || isExpanded(state);
415 }
416
417 private void applyNotTouchable(State state) {
418 if (state.mNotTouchable) {
419 mLpChanged.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
420 } else {
421 mLpChanged.flags &= ~LayoutParams.FLAG_NOT_TOUCHABLE;
422 }
423 }
424
425 public void setKeyguardShowing(boolean showing) {
426 mCurrentState.mKeyguardShowing = showing;
427 apply(mCurrentState);
428 }
429
430 public void setKeyguardOccluded(boolean occluded) {
431 mCurrentState.mKeyguardOccluded = occluded;
432 apply(mCurrentState);
433 }
434
435 public void setKeyguardNeedsInput(boolean needsInput) {
436 mCurrentState.mKeyguardNeedsInput = needsInput;
437 apply(mCurrentState);
438 }
439
440 public void setPanelVisible(boolean visible) {
441 mCurrentState.mPanelVisible = visible;
442 mCurrentState.mNotificationShadeFocusable = visible;
443 apply(mCurrentState);
444 }
445
446 public void setNotificationShadeFocusable(boolean focusable) {
447 mCurrentState.mNotificationShadeFocusable = focusable;
448 apply(mCurrentState);
449 }
450
451 public void setBouncerShowing(boolean showing) {
452 mCurrentState.mBouncerShowing = showing;
453 apply(mCurrentState);
454 }
455
456 public void setBackdropShowing(boolean showing) {
457 mCurrentState.mBackdropShowing = showing;
458 apply(mCurrentState);
459 }
460
461 public void setKeyguardFadingAway(boolean keyguardFadingAway) {
462 mCurrentState.mKeyguardFadingAway = keyguardFadingAway;
463 apply(mCurrentState);
464 }
465
466 public void setQsExpanded(boolean expanded) {
467 mCurrentState.mQsExpanded = expanded;
468 apply(mCurrentState);
469 }
470
471 public void setForceUserActivity(boolean forceUserActivity) {
472 mCurrentState.mForceUserActivity = forceUserActivity;
473 apply(mCurrentState);
474 }
475
476 public void setScrimsVisibility(int scrimsVisibility) {
477 mCurrentState.mScrimsVisibility = scrimsVisibility;
478 apply(mCurrentState);
479 }
480
481 public void setHeadsUpShowing(boolean showing) {
482 mCurrentState.mHeadsUpShowing = showing;
483 apply(mCurrentState);
484 }
485
486 public void setWallpaperSupportsAmbientMode(boolean supportsAmbientMode) {
487 mCurrentState.mWallpaperSupportsAmbientMode = supportsAmbientMode;
488 apply(mCurrentState);
489 }
490
491 /**
492 * @param state The {@link StatusBarStateController} of the status bar.
493 */
494 private void setStatusBarState(int state) {
495 mCurrentState.mStatusBarState = state;
496 apply(mCurrentState);
497 }
498
499 /**
500 * Force the window to be collapsed, even if it should theoretically be expanded.
501 * Used for when a heads-up comes in but we still need to wait for the touchable regions to
502 * be computed.
503 */
504 public void setForceWindowCollapsed(boolean force) {
505 mCurrentState.mForceCollapsed = force;
506 apply(mCurrentState);
507 }
508
509 public void setPanelExpanded(boolean isExpanded) {
510 mCurrentState.mPanelExpanded = isExpanded;
511 apply(mCurrentState);
512 }
513
514 @Override
515 public void onRemoteInputActive(boolean remoteInputActive) {
516 mCurrentState.mRemoteInputActive = remoteInputActive;
517 apply(mCurrentState);
518 }
519
520 /**
521 * Set whether the screen brightness is forced to the value we use for doze mode by the status
522 * bar window.
523 */
524 public void setForceDozeBrightness(boolean forceDozeBrightness) {
525 mCurrentState.mForceDozeBrightness = forceDozeBrightness;
526 apply(mCurrentState);
527 }
528
529 public void setDozing(boolean dozing) {
530 mCurrentState.mDozing = dozing;
531 apply(mCurrentState);
532 }
533
534 public void setForcePluginOpen(boolean forcePluginOpen) {
535 mCurrentState.mForcePluginOpen = forcePluginOpen;
536 apply(mCurrentState);
537 if (mForcePluginOpenListener != null) {
538 mForcePluginOpenListener.onChange(forcePluginOpen);
539 }
540 }
541
542 /**
543 * The forcePluginOpen state for the status bar.
544 */
545 public boolean getForcePluginOpen() {
546 return mCurrentState.mForcePluginOpen;
547 }
548
549 public void setNotTouchable(boolean notTouchable) {
550 mCurrentState.mNotTouchable = notTouchable;
551 apply(mCurrentState);
552 }
553
554 /**
555 * Sets whether there are bubbles showing on the screen.
556 */
557 public void setBubblesShowing(boolean bubblesShowing) {
558 mCurrentState.mBubblesShowing = bubblesShowing;
559 apply(mCurrentState);
560 }
561
562 /**
563 * The bubbles showing state for the status bar.
564 */
565 public boolean getBubblesShowing() {
566 return mCurrentState.mBubblesShowing;
567 }
568
569 /**
570 * Sets if there is a bubble being expanded on the screen.
571 */
572 public void setBubbleExpanded(boolean bubbleExpanded) {
573 mCurrentState.mBubbleExpanded = bubbleExpanded;
574 apply(mCurrentState);
575 }
576
577 /**
578 * Whether the bubble is shown in expanded state for the status bar.
579 */
580 public boolean getBubbleExpanded() {
581 return mCurrentState.mBubbleExpanded;
582 }
583
584 /**
585 * Whether the status bar panel is expanded or not.
586 */
587 public boolean getPanelExpanded() {
588 return mCurrentState.mPanelExpanded;
589 }
590
591 public void setStateListener(OtherwisedCollapsedListener listener) {
592 mListener = listener;
593 }
594
595 public void setForcePluginOpenListener(ForcePluginOpenListener listener) {
596 mForcePluginOpenListener = listener;
597 }
598
599 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Lucas Dupind73410a2020-02-18 12:54:41 -0800600 pw.println(TAG + ":");
wilsonshihe8321942019-10-18 18:39:46 +0800601 pw.println(" mKeyguardDisplayMode=" + mKeyguardDisplayMode);
602 pw.println(mCurrentState);
603 }
604
605 public boolean isShowingWallpaper() {
606 return !mCurrentState.mBackdropShowing;
607 }
608
609 @Override
610 public void onThemeChanged() {
611 if (mNotificationShadeView == null) {
612 return;
613 }
614
615 final boolean useDarkText = mColorExtractor.getNeutralColors().supportsDarkText();
616 // Make sure we have the correct navbar/statusbar colors.
617 setKeyguardDark(useDarkText);
618 }
619
620 /**
621 * When keyguard will be dismissed but didn't start animation yet.
622 */
623 public void setKeyguardGoingAway(boolean goingAway) {
624 mCurrentState.mKeyguardGoingAway = goingAway;
625 apply(mCurrentState);
626 }
627
628 public boolean getForceHasTopUi() {
629 return mCurrentState.mForceHasTopUi;
630 }
631
632 public void setForceHasTopUi(boolean forceHasTopUi) {
633 mCurrentState.mForceHasTopUi = forceHasTopUi;
634 apply(mCurrentState);
635 }
636
637 private static class State {
638 boolean mKeyguardShowing;
639 boolean mKeyguardOccluded;
640 boolean mKeyguardNeedsInput;
641 boolean mPanelVisible;
642 boolean mPanelExpanded;
643 boolean mNotificationShadeFocusable;
644 boolean mBouncerShowing;
645 boolean mKeyguardFadingAway;
646 boolean mKeyguardGoingAway;
647 boolean mQsExpanded;
648 boolean mHeadsUpShowing;
649 boolean mForceCollapsed;
650 boolean mForceDozeBrightness;
651 boolean mForceUserActivity;
652 boolean mBackdropShowing;
653 boolean mWallpaperSupportsAmbientMode;
654 boolean mNotTouchable;
655 boolean mBubblesShowing;
656 boolean mBubbleExpanded;
657 boolean mForceHasTopUi;
658
659 /**
660 * The {@link StatusBar} state from the status bar.
661 */
662 int mStatusBarState;
663
664 boolean mRemoteInputActive;
665 boolean mForcePluginOpen;
666 boolean mDozing;
667 int mScrimsVisibility;
668
669 private boolean isKeyguardShowingAndNotOccluded() {
670 return mKeyguardShowing && !mKeyguardOccluded;
671 }
672
673 @Override
674 public String toString() {
675 StringBuilder result = new StringBuilder();
676 String newLine = "\n";
677 result.append("Window State {");
678 result.append(newLine);
679
680 Field[] fields = this.getClass().getDeclaredFields();
681
682 // Print field names paired with their values
683 for (Field field : fields) {
684 result.append(" ");
685 try {
686 result.append(field.getName());
687 result.append(": ");
688 //requires access to private field:
689 result.append(field.get(this));
690 } catch (IllegalAccessException ex) {
691 }
692 result.append(newLine);
693 }
694 result.append("}");
695
696 return result.toString();
697 }
698 }
699
700 private final StateListener mStateListener = new StateListener() {
701 @Override
702 public void onStateChanged(int newState) {
703 setStatusBarState(newState);
704 }
705
706 @Override
707 public void onDozingChanged(boolean isDozing) {
708 setDozing(isDozing);
709 }
710 };
711
712 /**
713 * Custom listener to pipe data back to plugins about whether or not the status bar would be
714 * collapsed if not for the plugin.
715 * TODO: Find cleaner way to do this.
716 */
717 public interface OtherwisedCollapsedListener {
718 void setWouldOtherwiseCollapse(boolean otherwiseCollapse);
719 }
720
721 /**
722 * Listener to indicate forcePluginOpen has changed
723 */
724 public interface ForcePluginOpenListener {
725 /**
726 * Called when mState.forcePluginOpen is changed
727 */
728 void onChange(boolean forceOpen);
729 }
730}