OSDN Git Service

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