• 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 android.content.Context;
20 import android.content.pm.ActivityInfo;
21 import android.content.res.Resources;
22 import android.graphics.PixelFormat;
23 import android.os.SystemProperties;
24 import android.view.Gravity;
25 import android.view.View;
26 import android.view.ViewGroup;
27 import android.view.WindowManager;
28 
29 import com.android.keyguard.R;
30 import com.android.systemui.keyguard.KeyguardViewMediator;
31 import com.android.systemui.statusbar.BaseStatusBar;
32 import com.android.systemui.statusbar.RemoteInputController;
33 import com.android.systemui.statusbar.StatusBarState;
34 
35 import java.io.FileDescriptor;
36 import java.io.PrintWriter;
37 import java.lang.reflect.Field;
38 
39 /**
40  * Encapsulates all logic for the status bar window state management.
41  */
42 public class StatusBarWindowManager implements RemoteInputController.Callback {
43 
44     private final Context mContext;
45     private final WindowManager mWindowManager;
46     private View mStatusBarView;
47     private WindowManager.LayoutParams mLp;
48     private WindowManager.LayoutParams mLpChanged;
49     private int mBarHeight;
50     private final boolean mKeyguardScreenRotation;
51     private final float mScreenBrightnessDoze;
52     private final State mCurrentState = new State();
53 
StatusBarWindowManager(Context context)54     public StatusBarWindowManager(Context context) {
55         mContext = context;
56         mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
57         mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
58         mScreenBrightnessDoze = mContext.getResources().getInteger(
59                 com.android.internal.R.integer.config_screenBrightnessDoze) / 255f;
60     }
61 
shouldEnableKeyguardScreenRotation()62     private boolean shouldEnableKeyguardScreenRotation() {
63         Resources res = mContext.getResources();
64         return SystemProperties.getBoolean("lockscreen.rot_override", false)
65                 || res.getBoolean(R.bool.config_enableLockScreenRotation);
66     }
67 
68     /**
69      * Adds the status bar view to the window manager.
70      *
71      * @param statusBarView The view to add.
72      * @param barHeight The height of the status bar in collapsed state.
73      */
add(View statusBarView, int barHeight)74     public void add(View statusBarView, int barHeight) {
75 
76         // Now that the status bar window encompasses the sliding panel and its
77         // translucent backdrop, the entire thing is made TRANSLUCENT and is
78         // hardware-accelerated.
79         mLp = new WindowManager.LayoutParams(
80                 ViewGroup.LayoutParams.MATCH_PARENT,
81                 barHeight,
82                 WindowManager.LayoutParams.TYPE_STATUS_BAR,
83                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
84                         | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
85                         | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
86                         | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
87                         | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
88                 PixelFormat.TRANSLUCENT);
89         mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
90         mLp.gravity = Gravity.TOP;
91         mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
92         mLp.setTitle("StatusBar");
93         mLp.packageName = mContext.getPackageName();
94         mStatusBarView = statusBarView;
95         mBarHeight = barHeight;
96         mWindowManager.addView(mStatusBarView, mLp);
97         mLpChanged = new WindowManager.LayoutParams();
98         mLpChanged.copyFrom(mLp);
99     }
100 
applyKeyguardFlags(State state)101     private void applyKeyguardFlags(State state) {
102         if (state.keyguardShowing) {
103             mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
104         } else {
105             mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
106         }
107 
108         if (state.keyguardShowing && !state.backdropShowing) {
109             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
110         } else {
111             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
112         }
113     }
114 
adjustScreenOrientation(State state)115     private void adjustScreenOrientation(State state) {
116         if (state.isKeyguardShowingAndNotOccluded()) {
117             if (mKeyguardScreenRotation) {
118                 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
119             } else {
120                 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
121             }
122         } else {
123             mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
124         }
125     }
126 
applyFocusableFlag(State state)127     private void applyFocusableFlag(State state) {
128         boolean panelFocusable = state.statusBarFocusable && state.panelExpanded;
129         if (state.keyguardShowing && state.keyguardNeedsInput && state.bouncerShowing
130                 || BaseStatusBar.ENABLE_REMOTE_INPUT && state.remoteInputActive) {
131             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
132             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
133         } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
134             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
135             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
136         } else {
137             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
138             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
139         }
140 
141         mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
142     }
143 
applyHeight(State state)144     private void applyHeight(State state) {
145         boolean expanded = isExpanded(state);
146         if (expanded) {
147             mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT;
148         } else {
149             mLpChanged.height = mBarHeight;
150         }
151     }
152 
isExpanded(State state)153     private boolean isExpanded(State state) {
154         return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded()
155                 || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing
156                 || state.headsUpShowing);
157     }
158 
applyFitsSystemWindows(State state)159     private void applyFitsSystemWindows(State state) {
160         mStatusBarView.setFitsSystemWindows(!state.isKeyguardShowingAndNotOccluded());
161     }
162 
applyUserActivityTimeout(State state)163     private void applyUserActivityTimeout(State state) {
164         if (state.isKeyguardShowingAndNotOccluded()
165                 && state.statusBarState == StatusBarState.KEYGUARD
166                 && !state.qsExpanded) {
167             mLpChanged.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
168         } else {
169             mLpChanged.userActivityTimeout = -1;
170         }
171     }
172 
applyInputFeatures(State state)173     private void applyInputFeatures(State state) {
174         if (state.isKeyguardShowingAndNotOccluded()
175                 && state.statusBarState == StatusBarState.KEYGUARD
176                 && !state.qsExpanded && !state.forceUserActivity) {
177             mLpChanged.inputFeatures |=
178                     WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
179         } else {
180             mLpChanged.inputFeatures &=
181                     ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
182         }
183     }
184 
apply(State state)185     private void apply(State state) {
186         applyKeyguardFlags(state);
187         applyForceStatusBarVisibleFlag(state);
188         applyFocusableFlag(state);
189         adjustScreenOrientation(state);
190         applyHeight(state);
191         applyUserActivityTimeout(state);
192         applyInputFeatures(state);
193         applyFitsSystemWindows(state);
194         applyModalFlag(state);
195         applyBrightness(state);
196         if (mLp.copyFrom(mLpChanged) != 0) {
197             mWindowManager.updateViewLayout(mStatusBarView, mLp);
198         }
199     }
200 
applyForceStatusBarVisibleFlag(State state)201     private void applyForceStatusBarVisibleFlag(State state) {
202         if (state.forceStatusBarVisible) {
203             mLpChanged.privateFlags |= WindowManager
204                     .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
205         } else {
206             mLpChanged.privateFlags &= ~WindowManager
207                     .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
208         }
209     }
210 
applyModalFlag(State state)211     private void applyModalFlag(State state) {
212         if (state.headsUpShowing) {
213             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
214         } else {
215             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
216         }
217     }
218 
applyBrightness(State state)219     private void applyBrightness(State state) {
220         if (state.forceDozeBrightness) {
221             mLpChanged.screenBrightness = mScreenBrightnessDoze;
222         } else {
223             mLpChanged.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
224         }
225     }
226 
setKeyguardShowing(boolean showing)227     public void setKeyguardShowing(boolean showing) {
228         mCurrentState.keyguardShowing = showing;
229         apply(mCurrentState);
230     }
231 
setKeyguardOccluded(boolean occluded)232     public void setKeyguardOccluded(boolean occluded) {
233         mCurrentState.keyguardOccluded = occluded;
234         apply(mCurrentState);
235     }
236 
setKeyguardNeedsInput(boolean needsInput)237     public void setKeyguardNeedsInput(boolean needsInput) {
238         mCurrentState.keyguardNeedsInput = needsInput;
239         apply(mCurrentState);
240     }
241 
setPanelVisible(boolean visible)242     public void setPanelVisible(boolean visible) {
243         mCurrentState.panelVisible = visible;
244         mCurrentState.statusBarFocusable = visible;
245         apply(mCurrentState);
246     }
247 
setStatusBarFocusable(boolean focusable)248     public void setStatusBarFocusable(boolean focusable) {
249         mCurrentState.statusBarFocusable = focusable;
250         apply(mCurrentState);
251     }
252 
setBouncerShowing(boolean showing)253     public void setBouncerShowing(boolean showing) {
254         mCurrentState.bouncerShowing = showing;
255         apply(mCurrentState);
256     }
257 
setBackdropShowing(boolean showing)258     public void setBackdropShowing(boolean showing) {
259         mCurrentState.backdropShowing = showing;
260         apply(mCurrentState);
261     }
262 
setKeyguardFadingAway(boolean keyguardFadingAway)263     public void setKeyguardFadingAway(boolean keyguardFadingAway) {
264         mCurrentState.keyguardFadingAway = keyguardFadingAway;
265         apply(mCurrentState);
266     }
267 
setQsExpanded(boolean expanded)268     public void setQsExpanded(boolean expanded) {
269         mCurrentState.qsExpanded = expanded;
270         apply(mCurrentState);
271     }
272 
setForceUserActivity(boolean forceUserActivity)273     public void setForceUserActivity(boolean forceUserActivity) {
274         mCurrentState.forceUserActivity = forceUserActivity;
275         apply(mCurrentState);
276     }
277 
setHeadsUpShowing(boolean showing)278     public void setHeadsUpShowing(boolean showing) {
279         mCurrentState.headsUpShowing = showing;
280         apply(mCurrentState);
281     }
282 
283     /**
284      * @param state The {@link StatusBarState} of the status bar.
285      */
setStatusBarState(int state)286     public void setStatusBarState(int state) {
287         mCurrentState.statusBarState = state;
288         apply(mCurrentState);
289     }
290 
setForceStatusBarVisible(boolean forceStatusBarVisible)291     public void setForceStatusBarVisible(boolean forceStatusBarVisible) {
292         mCurrentState.forceStatusBarVisible = forceStatusBarVisible;
293         apply(mCurrentState);
294     }
295 
296     /**
297      * Force the window to be collapsed, even if it should theoretically be expanded.
298      * Used for when a heads-up comes in but we still need to wait for the touchable regions to
299      * be computed.
300      */
setForceWindowCollapsed(boolean force)301     public void setForceWindowCollapsed(boolean force) {
302         mCurrentState.forceCollapsed = force;
303         apply(mCurrentState);
304     }
305 
setPanelExpanded(boolean isExpanded)306     public void setPanelExpanded(boolean isExpanded) {
307         mCurrentState.panelExpanded = isExpanded;
308         apply(mCurrentState);
309     }
310 
311     @Override
onRemoteInputActive(boolean remoteInputActive)312     public void onRemoteInputActive(boolean remoteInputActive) {
313         mCurrentState.remoteInputActive = remoteInputActive;
314         apply(mCurrentState);
315     }
316 
317     /**
318      * Set whether the screen brightness is forced to the value we use for doze mode by the status
319      * bar window.
320      */
setForceDozeBrightness(boolean forceDozeBrightness)321     public void setForceDozeBrightness(boolean forceDozeBrightness) {
322         mCurrentState.forceDozeBrightness = forceDozeBrightness;
323         apply(mCurrentState);
324     }
325 
setBarHeight(int barHeight)326     public void setBarHeight(int barHeight) {
327         mBarHeight = barHeight;
328         apply(mCurrentState);
329     }
330 
dump(FileDescriptor fd, PrintWriter pw, String[] args)331     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
332         pw.println("StatusBarWindowManager state:");
333         pw.println(mCurrentState);
334     }
335 
isShowingWallpaper()336     public boolean isShowingWallpaper() {
337         return !mCurrentState.backdropShowing;
338     }
339 
340     private static class State {
341         boolean keyguardShowing;
342         boolean keyguardOccluded;
343         boolean keyguardNeedsInput;
344         boolean panelVisible;
345         boolean panelExpanded;
346         boolean statusBarFocusable;
347         boolean bouncerShowing;
348         boolean keyguardFadingAway;
349         boolean qsExpanded;
350         boolean headsUpShowing;
351         boolean forceStatusBarVisible;
352         boolean forceCollapsed;
353         boolean forceDozeBrightness;
354         boolean forceUserActivity;
355         boolean backdropShowing;
356 
357         /**
358          * The {@link BaseStatusBar} state from the status bar.
359          */
360         int statusBarState;
361 
362         boolean remoteInputActive;
363 
isKeyguardShowingAndNotOccluded()364         private boolean isKeyguardShowingAndNotOccluded() {
365             return keyguardShowing && !keyguardOccluded;
366         }
367 
368         @Override
toString()369         public String toString() {
370             StringBuilder result = new StringBuilder();
371             String newLine = "\n";
372             result.append("Window State {");
373             result.append(newLine);
374 
375             Field[] fields = this.getClass().getDeclaredFields();
376 
377             // Print field names paired with their values
378             for (Field field : fields) {
379                 result.append("  ");
380                 try {
381                     result.append(field.getName());
382                     result.append(": ");
383                     //requires access to private field:
384                     result.append(field.get(this));
385                 } catch (IllegalAccessException ex) {
386                 }
387                 result.append(newLine);
388             }
389             result.append("}");
390 
391             return result.toString();
392         }
393     }
394 }
395