Home | History | Annotate | Download | only in policy
      1 /*
      2  * Copyright (C) 2013 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.server.policy;
     18 
     19 import android.app.StatusBarManager;
     20 import android.os.Handler;
     21 import android.os.SystemClock;
     22 import android.util.Slog;
     23 import android.view.View;
     24 import android.view.ViewGroup;
     25 import android.view.WindowManager;
     26 import android.view.WindowManagerPolicy.WindowState;
     27 
     28 import com.android.server.LocalServices;
     29 import com.android.server.statusbar.StatusBarManagerInternal;
     30 
     31 import java.io.PrintWriter;
     32 
     33 /**
     34  * Controls state/behavior specific to a system bar window.
     35  */
     36 public class BarController {
     37     private static final boolean DEBUG = false;
     38 
     39     private static final int TRANSIENT_BAR_NONE = 0;
     40     private static final int TRANSIENT_BAR_SHOW_REQUESTED = 1;
     41     private static final int TRANSIENT_BAR_SHOWING = 2;
     42     private static final int TRANSIENT_BAR_HIDING = 3;
     43 
     44     private static final int TRANSLUCENT_ANIMATION_DELAY_MS = 1000;
     45 
     46     protected final String mTag;
     47     private final int mTransientFlag;
     48     private final int mUnhideFlag;
     49     private final int mTranslucentFlag;
     50     private final int mTransparentFlag;
     51     private final int mStatusBarManagerId;
     52     private final int mTranslucentWmFlag;
     53     protected final Handler mHandler;
     54     private final Object mServiceAquireLock = new Object();
     55     protected StatusBarManagerInternal mStatusBarInternal;
     56 
     57     protected WindowState mWin;
     58     private int mState = StatusBarManager.WINDOW_STATE_SHOWING;
     59     private int mTransientBarState;
     60     private boolean mPendingShow;
     61     private long mLastTranslucent;
     62     private boolean mShowTransparent;
     63     private boolean mSetUnHideFlagWhenNextTransparent;
     64     private boolean mNoAnimationOnNextShow;
     65 
     66     public BarController(String tag, int transientFlag, int unhideFlag, int translucentFlag,
     67             int statusBarManagerId, int translucentWmFlag, int transparentFlag) {
     68         mTag = "BarController." + tag;
     69         mTransientFlag = transientFlag;
     70         mUnhideFlag = unhideFlag;
     71         mTranslucentFlag = translucentFlag;
     72         mStatusBarManagerId = statusBarManagerId;
     73         mTranslucentWmFlag = translucentWmFlag;
     74         mTransparentFlag = transparentFlag;
     75         mHandler = new Handler();
     76     }
     77 
     78     public void setWindow(WindowState win) {
     79         mWin = win;
     80     }
     81 
     82     public void setShowTransparent(boolean transparent) {
     83         if (transparent != mShowTransparent) {
     84             mShowTransparent = transparent;
     85             mSetUnHideFlagWhenNextTransparent = transparent;
     86             mNoAnimationOnNextShow = true;
     87         }
     88     }
     89 
     90     public void showTransient() {
     91         if (mWin != null) {
     92             setTransientBarState(TRANSIENT_BAR_SHOW_REQUESTED);
     93         }
     94     }
     95 
     96     public boolean isTransientShowing() {
     97         return mTransientBarState == TRANSIENT_BAR_SHOWING;
     98     }
     99 
    100     public boolean isTransientShowRequested() {
    101         return mTransientBarState == TRANSIENT_BAR_SHOW_REQUESTED;
    102     }
    103 
    104     public boolean wasRecentlyTranslucent() {
    105         return (SystemClock.uptimeMillis() - mLastTranslucent) < TRANSLUCENT_ANIMATION_DELAY_MS;
    106     }
    107 
    108     public void adjustSystemUiVisibilityLw(int oldVis, int vis) {
    109         if (mWin != null && mTransientBarState == TRANSIENT_BAR_SHOWING &&
    110                 (vis & mTransientFlag) == 0) {
    111             // sysui requests hide
    112             setTransientBarState(TRANSIENT_BAR_HIDING);
    113             setBarShowingLw(false);
    114         } else if (mWin != null && (oldVis & mUnhideFlag) != 0 && (vis & mUnhideFlag) == 0) {
    115             // sysui ready to unhide
    116             setBarShowingLw(true);
    117         }
    118     }
    119 
    120     public int applyTranslucentFlagLw(WindowState win, int vis, int oldVis) {
    121         if (mWin != null) {
    122             if (win != null && (win.getAttrs().privateFlags
    123                     & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) == 0) {
    124                 int fl = PolicyControl.getWindowFlags(win, null);
    125                 if ((fl & mTranslucentWmFlag) != 0) {
    126                     vis |= mTranslucentFlag;
    127                 } else {
    128                     vis &= ~mTranslucentFlag;
    129                 }
    130                 if ((fl & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
    131                     vis |= mTransparentFlag;
    132                 } else {
    133                     vis &= ~mTransparentFlag;
    134                 }
    135             } else {
    136                 vis = (vis & ~mTranslucentFlag) | (oldVis & mTranslucentFlag);
    137                 vis = (vis & ~mTransparentFlag) | (oldVis & mTransparentFlag);
    138             }
    139         }
    140         return vis;
    141     }
    142 
    143     public boolean setBarShowingLw(final boolean show) {
    144         if (mWin == null) return false;
    145         if (show && mTransientBarState == TRANSIENT_BAR_HIDING) {
    146             mPendingShow = true;
    147             return false;
    148         }
    149         final boolean wasVis = mWin.isVisibleLw();
    150         final boolean wasAnim = mWin.isAnimatingLw();
    151         final boolean change = show ? mWin.showLw(!mNoAnimationOnNextShow && !skipAnimation())
    152                 : mWin.hideLw(!mNoAnimationOnNextShow && !skipAnimation());
    153         mNoAnimationOnNextShow = false;
    154         final int state = computeStateLw(wasVis, wasAnim, mWin, change);
    155         final boolean stateChanged = updateStateLw(state);
    156         return change || stateChanged;
    157     }
    158 
    159     protected boolean skipAnimation() {
    160         return false;
    161     }
    162 
    163     private int computeStateLw(boolean wasVis, boolean wasAnim, WindowState win, boolean change) {
    164         if (win.isDrawnLw()) {
    165             final boolean vis = win.isVisibleLw();
    166             final boolean anim = win.isAnimatingLw();
    167             if (mState == StatusBarManager.WINDOW_STATE_HIDING && !change && !vis) {
    168                 return StatusBarManager.WINDOW_STATE_HIDDEN;
    169             } else if (mState == StatusBarManager.WINDOW_STATE_HIDDEN && vis) {
    170                 return StatusBarManager.WINDOW_STATE_SHOWING;
    171             } else if (change) {
    172                 if (wasVis && vis && !wasAnim && anim) {
    173                     return StatusBarManager.WINDOW_STATE_HIDING;
    174                 } else {
    175                     return StatusBarManager.WINDOW_STATE_SHOWING;
    176                 }
    177             }
    178         }
    179         return mState;
    180     }
    181 
    182     private boolean updateStateLw(final int state) {
    183         if (state != mState) {
    184             mState = state;
    185             if (DEBUG) Slog.d(mTag, "mState: " + StatusBarManager.windowStateToString(state));
    186             mHandler.post(new Runnable() {
    187                 @Override
    188                 public void run() {
    189                     StatusBarManagerInternal statusbar = getStatusBarInternal();
    190                     if (statusbar != null) {
    191                         statusbar.setWindowState(mStatusBarManagerId, state);
    192                     }
    193                 }
    194             });
    195             return true;
    196         }
    197         return false;
    198     }
    199 
    200     public boolean checkHiddenLw() {
    201         if (mWin != null && mWin.isDrawnLw()) {
    202             if (!mWin.isVisibleLw() && !mWin.isAnimatingLw()) {
    203                 updateStateLw(StatusBarManager.WINDOW_STATE_HIDDEN);
    204             }
    205             if (mTransientBarState == TRANSIENT_BAR_HIDING && !mWin.isVisibleLw()) {
    206                 // Finished animating out, clean up and reset style
    207                 setTransientBarState(TRANSIENT_BAR_NONE);
    208                 if (mPendingShow) {
    209                     setBarShowingLw(true);
    210                     mPendingShow = false;
    211                 }
    212                 return true;
    213             }
    214         }
    215         return false;
    216     }
    217 
    218     public boolean checkShowTransientBarLw() {
    219         if (mTransientBarState == TRANSIENT_BAR_SHOWING) {
    220             if (DEBUG) Slog.d(mTag, "Not showing transient bar, already shown");
    221             return false;
    222         } else if (mTransientBarState == TRANSIENT_BAR_SHOW_REQUESTED) {
    223             if (DEBUG) Slog.d(mTag, "Not showing transient bar, already requested");
    224             return false;
    225         } else if (mWin == null) {
    226             if (DEBUG) Slog.d(mTag, "Not showing transient bar, bar doesn't exist");
    227             return false;
    228         } else if (mWin.isDisplayedLw()) {
    229             if (DEBUG) Slog.d(mTag, "Not showing transient bar, bar already visible");
    230             return false;
    231         } else {
    232             return true;
    233         }
    234     }
    235 
    236     public int updateVisibilityLw(boolean transientAllowed, int oldVis, int vis) {
    237         if (mWin == null) return vis;
    238         if (isTransientShowing() || isTransientShowRequested()) { // transient bar requested
    239             if (transientAllowed) {
    240                 vis |= mTransientFlag;
    241                 if ((oldVis & mTransientFlag) == 0) {
    242                     vis |= mUnhideFlag;  // tell sysui we're ready to unhide
    243                 }
    244                 setTransientBarState(TRANSIENT_BAR_SHOWING);  // request accepted
    245             } else {
    246                 setTransientBarState(TRANSIENT_BAR_NONE);  // request denied
    247             }
    248         }
    249         if (mShowTransparent) {
    250             vis |= mTransparentFlag;
    251             if (mSetUnHideFlagWhenNextTransparent) {
    252                 vis |= mUnhideFlag;
    253                 mSetUnHideFlagWhenNextTransparent = false;
    254             }
    255         }
    256         if (mTransientBarState != TRANSIENT_BAR_NONE) {
    257             vis |= mTransientFlag;  // ignore clear requests until transition completes
    258             vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;  // never show transient bars in low profile
    259         }
    260         if ((vis & mTranslucentFlag) != 0 || (oldVis & mTranslucentFlag) != 0 ||
    261                 ((vis | oldVis) & mTransparentFlag) != 0) {
    262             mLastTranslucent = SystemClock.uptimeMillis();
    263         }
    264         return vis;
    265     }
    266 
    267     private void setTransientBarState(int state) {
    268         if (mWin != null && state != mTransientBarState) {
    269             if (mTransientBarState == TRANSIENT_BAR_SHOWING || state == TRANSIENT_BAR_SHOWING) {
    270                 mLastTranslucent = SystemClock.uptimeMillis();
    271             }
    272             mTransientBarState = state;
    273             if (DEBUG) Slog.d(mTag, "mTransientBarState: " + transientBarStateToString(state));
    274         }
    275     }
    276 
    277     protected StatusBarManagerInternal getStatusBarInternal() {
    278         synchronized (mServiceAquireLock) {
    279             if (mStatusBarInternal == null) {
    280                 mStatusBarInternal = LocalServices.getService(StatusBarManagerInternal.class);
    281             }
    282             return mStatusBarInternal;
    283         }
    284     }
    285 
    286     private static String transientBarStateToString(int state) {
    287         if (state == TRANSIENT_BAR_HIDING) return "TRANSIENT_BAR_HIDING";
    288         if (state == TRANSIENT_BAR_SHOWING) return "TRANSIENT_BAR_SHOWING";
    289         if (state == TRANSIENT_BAR_SHOW_REQUESTED) return "TRANSIENT_BAR_SHOW_REQUESTED";
    290         if (state == TRANSIENT_BAR_NONE) return "TRANSIENT_BAR_NONE";
    291         throw new IllegalArgumentException("Unknown state " + state);
    292     }
    293 
    294     public void dump(PrintWriter pw, String prefix) {
    295         if (mWin != null) {
    296             pw.print(prefix); pw.println(mTag);
    297             pw.print(prefix); pw.print("  "); pw.print("mState"); pw.print('=');
    298             pw.println(StatusBarManager.windowStateToString(mState));
    299             pw.print(prefix); pw.print("  "); pw.print("mTransientBar"); pw.print('=');
    300             pw.println(transientBarStateToString(mTransientBarState));
    301         }
    302     }
    303 }
    304