StatusBarWindowManager.java revision 737bff3476a3af8f930d29fccce16d033fbc3efa
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
34/**
35 * Encapsulates all logic for the status bar window state management.
36 */
37public class StatusBarWindowManager {
38
39    private final Context mContext;
40    private final WindowManager mWindowManager;
41    private View mStatusBarView;
42    private WindowManager.LayoutParams mLp;
43    private WindowManager.LayoutParams mLpChanged;
44    private int mBarHeight;
45    private final boolean mKeyguardScreenRotation;
46
47    private final State mCurrentState = new State();
48
49    public StatusBarWindowManager(Context context) {
50        mContext = context;
51        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
52        mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
53    }
54
55    private boolean shouldEnableKeyguardScreenRotation() {
56        Resources res = mContext.getResources();
57        return SystemProperties.getBoolean("lockscreen.rot_override", false)
58                || res.getBoolean(R.bool.config_enableLockScreenRotation);
59    }
60
61    /**
62     * Adds the status bar view to the window manager.
63     *
64     * @param statusBarView The view to add.
65     * @param barHeight The height of the status bar in collapsed state.
66     */
67    public void add(View statusBarView, int barHeight) {
68
69        // Now that the status bar window encompasses the sliding panel and its
70        // translucent backdrop, the entire thing is made TRANSLUCENT and is
71        // hardware-accelerated.
72        mLp = new WindowManager.LayoutParams(
73                ViewGroup.LayoutParams.MATCH_PARENT,
74                barHeight,
75                WindowManager.LayoutParams.TYPE_STATUS_BAR,
76                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
77                        | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
78                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
79                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
80                        | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
81                PixelFormat.TRANSLUCENT);
82        mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
83        mLp.gravity = Gravity.TOP;
84        mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
85        mLp.setTitle("StatusBar");
86        mLp.packageName = mContext.getPackageName();
87        mStatusBarView = statusBarView;
88        mBarHeight = barHeight;
89        mWindowManager.addView(mStatusBarView, mLp);
90        mLpChanged = new WindowManager.LayoutParams();
91        mLpChanged.copyFrom(mLp);
92    }
93
94    private void applyKeyguardFlags(State state) {
95        if (state.keyguardShowing) {
96            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
97            mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
98        } else {
99            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
100            mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
101        }
102    }
103
104    private void adjustScreenOrientation(State state) {
105        if (state.isKeyguardShowingAndNotOccluded()) {
106            if (mKeyguardScreenRotation) {
107                mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
108            } else {
109                mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
110            }
111        } else {
112            mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
113        }
114    }
115
116    private void applyFocusableFlag(State state) {
117        if (state.isKeyguardShowingAndNotOccluded() && state.keyguardNeedsInput
118                && state.bouncerShowing
119                || BaseStatusBar.ENABLE_REMOTE_INPUT && state.statusBarExpanded) {
120            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
121            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
122        } else if (state.isKeyguardShowingAndNotOccluded() || state.statusBarFocusable) {
123            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
124            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
125        } else {
126            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
127            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
128        }
129    }
130
131    private void applyHeight(State state) {
132        boolean expanded = !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded()
133                || state.statusBarExpanded || state.keyguardFadingAway || state.bouncerShowing
134                || state.headsUpShowing);
135        if (expanded) {
136            mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT;
137        } else {
138            mLpChanged.height = mBarHeight;
139        }
140    }
141
142    private void applyFitsSystemWindows(State state) {
143        mStatusBarView.setFitsSystemWindows(!state.isKeyguardShowingAndNotOccluded());
144    }
145
146    private void applyUserActivityTimeout(State state) {
147        if (state.isKeyguardShowingAndNotOccluded()
148                && state.statusBarState == StatusBarState.KEYGUARD
149                && !state.qsExpanded) {
150            mLpChanged.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
151        } else {
152            mLpChanged.userActivityTimeout = -1;
153        }
154    }
155
156    private void applyInputFeatures(State state) {
157        if (state.isKeyguardShowingAndNotOccluded()
158                && state.statusBarState == StatusBarState.KEYGUARD
159                && !state.qsExpanded) {
160            mLpChanged.inputFeatures |=
161                    WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
162        } else {
163            mLpChanged.inputFeatures &=
164                    ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
165        }
166    }
167
168    private void apply(State state) {
169        applyKeyguardFlags(state);
170        applyForceStatusBarVisibleFlag(state);
171        applyFocusableFlag(state);
172        adjustScreenOrientation(state);
173        applyHeight(state);
174        applyUserActivityTimeout(state);
175        applyInputFeatures(state);
176        applyFitsSystemWindows(state);
177        applyModalFlag(state);
178        if (mLp.copyFrom(mLpChanged) != 0) {
179            mWindowManager.updateViewLayout(mStatusBarView, mLp);
180        }
181    }
182
183    private void applyForceStatusBarVisibleFlag(State state) {
184        if (state.forceStatusBarVisible) {
185            mLpChanged.privateFlags |= WindowManager
186                    .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
187        } else {
188            mLpChanged.privateFlags &= ~WindowManager
189                    .LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
190        }
191    }
192
193    private void applyModalFlag(State state) {
194        if (state.headsUpShowing) {
195            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
196        } else {
197            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
198        }
199    }
200
201    public void setKeyguardShowing(boolean showing) {
202        mCurrentState.keyguardShowing = showing;
203        apply(mCurrentState);
204    }
205
206    public void setKeyguardOccluded(boolean occluded) {
207        mCurrentState.keyguardOccluded = occluded;
208        apply(mCurrentState);
209    }
210
211    public void setKeyguardNeedsInput(boolean needsInput) {
212        mCurrentState.keyguardNeedsInput = needsInput;
213        apply(mCurrentState);
214    }
215
216    public void setStatusBarExpanded(boolean expanded) {
217        mCurrentState.statusBarExpanded = expanded;
218        mCurrentState.statusBarFocusable = expanded;
219        apply(mCurrentState);
220    }
221
222    public void setStatusBarFocusable(boolean focusable) {
223        mCurrentState.statusBarFocusable = focusable;
224        apply(mCurrentState);
225    }
226
227    public void setBouncerShowing(boolean showing) {
228        mCurrentState.bouncerShowing = showing;
229        apply(mCurrentState);
230    }
231
232    public void setKeyguardFadingAway(boolean keyguardFadingAway) {
233        mCurrentState.keyguardFadingAway = keyguardFadingAway;
234        apply(mCurrentState);
235    }
236
237    public void setQsExpanded(boolean expanded) {
238        mCurrentState.qsExpanded = expanded;
239        apply(mCurrentState);
240    }
241
242    public void setHeadsUpShowing(boolean showing) {
243        mCurrentState.headsUpShowing = showing;
244        apply(mCurrentState);
245    }
246
247    /**
248     * @param state The {@link StatusBarState} of the status bar.
249     */
250    public void setStatusBarState(int state) {
251        mCurrentState.statusBarState = state;
252        apply(mCurrentState);
253    }
254
255    public void setForceStatusBarVisible(boolean forceStatusBarVisible) {
256        mCurrentState.forceStatusBarVisible = forceStatusBarVisible;
257        apply(mCurrentState);
258    }
259
260    /**
261     * Force the window to be collapsed, even if it should theoretically be expanded.
262     * Used for when a heads-up comes in but we still need to wait for the touchable regions to
263     * be computed.
264     */
265    public void setForceWindowCollapsed(boolean force) {
266        mCurrentState.forceCollapsed = force;
267        apply(mCurrentState);
268    }
269
270    private static class State {
271        boolean keyguardShowing;
272        boolean keyguardOccluded;
273        boolean keyguardNeedsInput;
274        boolean statusBarExpanded;
275        boolean statusBarFocusable;
276        boolean bouncerShowing;
277        boolean keyguardFadingAway;
278        boolean qsExpanded;
279        boolean headsUpShowing;
280        boolean forceStatusBarVisible;
281        boolean forceCollapsed;
282
283        /**
284         * The {@link BaseStatusBar} state from the status bar.
285         */
286        int statusBarState;
287
288        private boolean isKeyguardShowingAndNotOccluded() {
289            return keyguardShowing && !keyguardOccluded;
290        }
291    }
292}
293