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