• 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.Window;
28 import android.view.WindowManager;
29 
30 import com.android.keyguard.R;
31 import com.android.systemui.keyguard.KeyguardViewMediator;
32 import com.android.systemui.statusbar.BaseStatusBar;
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 {
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.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
104             mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
105         } else {
106             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
107             mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
108         }
109     }
110 
adjustScreenOrientation(State state)111     private void adjustScreenOrientation(State state) {
112         if (state.isKeyguardShowingAndNotOccluded()) {
113             if (mKeyguardScreenRotation) {
114                 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
115             } else {
116                 mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
117             }
118         } else {
119             mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
120         }
121     }
122 
applyFocusableFlag(State state)123     private void applyFocusableFlag(State state) {
124         boolean panelFocusable = state.statusBarFocusable && state.panelExpanded;
125         if (state.keyguardShowing && state.keyguardNeedsInput && state.bouncerShowing) {
126             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
127             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
128         } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
129             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
130             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
131         } else {
132             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
133             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
134         }
135     }
136 
applyHeight(State state)137     private void applyHeight(State state) {
138         boolean expanded = isExpanded(state);
139         if (expanded) {
140             mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT;
141         } else {
142             mLpChanged.height = mBarHeight;
143         }
144     }
145 
isExpanded(State state)146     private boolean isExpanded(State state) {
147         return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded()
148                 || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing
149                 || state.headsUpShowing);
150     }
151 
applyFitsSystemWindows(State state)152     private void applyFitsSystemWindows(State state) {
153         mStatusBarView.setFitsSystemWindows(!state.isKeyguardShowingAndNotOccluded());
154     }
155 
applyUserActivityTimeout(State state)156     private void applyUserActivityTimeout(State state) {
157         if (state.isKeyguardShowingAndNotOccluded()
158                 && state.statusBarState == StatusBarState.KEYGUARD
159                 && !state.qsExpanded) {
160             mLpChanged.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
161         } else {
162             mLpChanged.userActivityTimeout = -1;
163         }
164     }
165 
applyInputFeatures(State state)166     private void applyInputFeatures(State state) {
167         if (state.isKeyguardShowingAndNotOccluded()
168                 && state.statusBarState == StatusBarState.KEYGUARD
169                 && !state.qsExpanded) {
170             mLpChanged.inputFeatures |=
171                     WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
172         } else {
173             mLpChanged.inputFeatures &=
174                     ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
175         }
176     }
177 
apply(State state)178     private void apply(State state) {
179         applyKeyguardFlags(state);
180         applyForceStatusBarVisibleFlag(state);
181         applyFocusableFlag(state);
182         adjustScreenOrientation(state);
183         applyHeight(state);
184         applyUserActivityTimeout(state);
185         applyInputFeatures(state);
186         applyFitsSystemWindows(state);
187         applyModalFlag(state);
188         applyBrightness(state);
189         if (mLp.copyFrom(mLpChanged) != 0) {
190             mWindowManager.updateViewLayout(mStatusBarView, mLp);
191         }
192     }
193 
applyForceStatusBarVisibleFlag(State state)194     private void applyForceStatusBarVisibleFlag(State state) {
195         if (state.forceStatusBarVisible) {
196             mLpChanged.privateFlags |= WindowManager
197                     .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
198         } else {
199             mLpChanged.privateFlags &= ~WindowManager
200                     .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
201         }
202     }
203 
applyModalFlag(State state)204     private void applyModalFlag(State state) {
205         if (state.headsUpShowing) {
206             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
207         } else {
208             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
209         }
210     }
211 
applyBrightness(State state)212     private void applyBrightness(State state) {
213         if (state.forceDozeBrightness) {
214             mLpChanged.screenBrightness = mScreenBrightnessDoze;
215         } else {
216             mLpChanged.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
217         }
218     }
219 
setKeyguardShowing(boolean showing)220     public void setKeyguardShowing(boolean showing) {
221         mCurrentState.keyguardShowing = showing;
222         apply(mCurrentState);
223     }
224 
setKeyguardOccluded(boolean occluded)225     public void setKeyguardOccluded(boolean occluded) {
226         mCurrentState.keyguardOccluded = occluded;
227         apply(mCurrentState);
228     }
229 
setKeyguardNeedsInput(boolean needsInput)230     public void setKeyguardNeedsInput(boolean needsInput) {
231         mCurrentState.keyguardNeedsInput = needsInput;
232         apply(mCurrentState);
233     }
234 
setPanelVisible(boolean visible)235     public void setPanelVisible(boolean visible) {
236         mCurrentState.panelVisible = visible;
237         mCurrentState.statusBarFocusable = visible;
238         apply(mCurrentState);
239     }
240 
setStatusBarFocusable(boolean focusable)241     public void setStatusBarFocusable(boolean focusable) {
242         mCurrentState.statusBarFocusable = focusable;
243         apply(mCurrentState);
244     }
245 
setBouncerShowing(boolean showing)246     public void setBouncerShowing(boolean showing) {
247         mCurrentState.bouncerShowing = showing;
248         apply(mCurrentState);
249     }
250 
setKeyguardFadingAway(boolean keyguardFadingAway)251     public void setKeyguardFadingAway(boolean keyguardFadingAway) {
252         mCurrentState.keyguardFadingAway = keyguardFadingAway;
253         apply(mCurrentState);
254     }
255 
setQsExpanded(boolean expanded)256     public void setQsExpanded(boolean expanded) {
257         mCurrentState.qsExpanded = expanded;
258         apply(mCurrentState);
259     }
260 
setHeadsUpShowing(boolean showing)261     public void setHeadsUpShowing(boolean showing) {
262         mCurrentState.headsUpShowing = showing;
263         apply(mCurrentState);
264     }
265 
266     /**
267      * @param state The {@link StatusBarState} of the status bar.
268      */
setStatusBarState(int state)269     public void setStatusBarState(int state) {
270         mCurrentState.statusBarState = state;
271         apply(mCurrentState);
272     }
273 
setForceStatusBarVisible(boolean forceStatusBarVisible)274     public void setForceStatusBarVisible(boolean forceStatusBarVisible) {
275         mCurrentState.forceStatusBarVisible = forceStatusBarVisible;
276         apply(mCurrentState);
277     }
278 
279     /**
280      * Force the window to be collapsed, even if it should theoretically be expanded.
281      * Used for when a heads-up comes in but we still need to wait for the touchable regions to
282      * be computed.
283      */
setForceWindowCollapsed(boolean force)284     public void setForceWindowCollapsed(boolean force) {
285         mCurrentState.forceCollapsed = force;
286         apply(mCurrentState);
287     }
288 
setPanelExpanded(boolean isExpanded)289     public void setPanelExpanded(boolean isExpanded) {
290         mCurrentState.panelExpanded = isExpanded;
291         apply(mCurrentState);
292     }
293 
294     /**
295      * Set whether the screen brightness is forced to the value we use for doze mode by the status
296      * bar window.
297      */
setForceDozeBrightness(boolean forceDozeBrightness)298     public void setForceDozeBrightness(boolean forceDozeBrightness) {
299         mCurrentState.forceDozeBrightness = forceDozeBrightness;
300         apply(mCurrentState);
301     }
302 
dump(FileDescriptor fd, PrintWriter pw, String[] args)303     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
304         pw.println("StatusBarWindowManager state:");
305         pw.println(mCurrentState);
306     }
307 
308     private static class State {
309         boolean keyguardShowing;
310         boolean keyguardOccluded;
311         boolean keyguardNeedsInput;
312         boolean panelVisible;
313         boolean panelExpanded;
314         boolean statusBarFocusable;
315         boolean bouncerShowing;
316         boolean keyguardFadingAway;
317         boolean qsExpanded;
318         boolean headsUpShowing;
319         boolean forceStatusBarVisible;
320         boolean forceCollapsed;
321         boolean forceDozeBrightness;
322 
323         /**
324          * The {@link BaseStatusBar} state from the status bar.
325          */
326         int statusBarState;
327 
isKeyguardShowingAndNotOccluded()328         private boolean isKeyguardShowingAndNotOccluded() {
329             return keyguardShowing && !keyguardOccluded;
330         }
331 
332         @Override
toString()333         public String toString() {
334             StringBuilder result = new StringBuilder();
335             String newLine = "\n";
336             result.append("Window State {");
337             result.append(newLine);
338 
339             Field[] fields = this.getClass().getDeclaredFields();
340 
341             // Print field names paired with their values
342             for (Field field : fields) {
343                 result.append("  ");
344                 try {
345                     result.append(field.getName());
346                     result.append(": ");
347                     //requires access to private field:
348                     result.append(field.get(this));
349                 } catch (IllegalAccessException ex) {
350                 }
351                 result.append(newLine);
352             }
353             result.append("}");
354 
355             return result.toString();
356         }
357     }
358 }
359