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