Home | History | Annotate | Download | only in phone
      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 
     48     public StatusBarWindowManager(Context context) {
     49         mContext = context;
     50         mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
     51         mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
     52     }
     53 
     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      */
     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 
     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 
    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 
    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 
    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 
    139     private void applyFitsSystemWindows(State state) {
    140         mStatusBarView.setFitsSystemWindows(!state.isKeyguardShowingAndNotOccluded());
    141     }
    142 
    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 
    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 
    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 
    178     public void setKeyguardShowing(boolean showing) {
    179         mCurrentState.keyguardShowing = showing;
    180         apply(mCurrentState);
    181     }
    182 
    183     public void setKeyguardOccluded(boolean occluded) {
    184         mCurrentState.keyguardOccluded = occluded;
    185         apply(mCurrentState);
    186     }
    187 
    188     public void setKeyguardNeedsInput(boolean needsInput) {
    189         mCurrentState.keyguardNeedsInput = needsInput;
    190         apply(mCurrentState);
    191     }
    192 
    193     public void setStatusBarExpanded(boolean expanded) {
    194         mCurrentState.statusBarExpanded = expanded;
    195         mCurrentState.statusBarFocusable = expanded;
    196         apply(mCurrentState);
    197     }
    198 
    199     public void setStatusBarFocusable(boolean focusable) {
    200         mCurrentState.statusBarFocusable = focusable;
    201         apply(mCurrentState);
    202     }
    203 
    204     public void setKeyguardUserActivityTimeout(long timeout) {
    205         mCurrentState.keyguardUserActivityTimeout = timeout;
    206         apply(mCurrentState);
    207     }
    208 
    209     public void setBouncerShowing(boolean showing) {
    210         mCurrentState.bouncerShowing = showing;
    211         apply(mCurrentState);
    212     }
    213 
    214     public void setKeyguardFadingAway(boolean keyguardFadingAway) {
    215         mCurrentState.keyguardFadingAway = keyguardFadingAway;
    216         apply(mCurrentState);
    217     }
    218 
    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      */
    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 
    248         private boolean isKeyguardShowingAndNotOccluded() {
    249             return keyguardShowing && !keyguardOccluded;
    250         }
    251     }
    252 }
    253