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