• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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