BarController.java revision 5b9145bf990a9bbf4fdef1739e61ff8c70ec868f
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 17package com.android.internal.policy.impl; 18 19import android.app.StatusBarManager; 20import android.os.Handler; 21import android.os.RemoteException; 22import android.os.ServiceManager; 23import android.util.Slog; 24import android.view.View; 25import android.view.WindowManagerPolicy.WindowState; 26 27import com.android.internal.statusbar.IStatusBarService; 28 29import java.io.PrintWriter; 30 31/** 32 * Controls state/behavior specific to a system bar window. 33 */ 34public class BarController { 35 private static final boolean DEBUG = false; 36 37 private static final int TRANSIENT_BAR_NONE = 0; 38 private static final int TRANSIENT_BAR_SHOWING = 1; 39 private static final int TRANSIENT_BAR_HIDING = 2; 40 41 private final String mTag; 42 private final int mTransientFlag; 43 private final int mUnhideFlag; 44 private final int mStatusBarManagerId; 45 private final Handler mHandler; 46 private final Object mServiceAquireLock = new Object(); 47 private IStatusBarService mStatusBarService; 48 49 private WindowState mWin; 50 private int mState; 51 private int mTransientBarState; 52 private boolean mPendingShow; 53 54 public BarController(String tag, int transientFlag, int unhideFlag, int statusBarManagerId) { 55 mTag = "BarController." + tag; 56 mTransientFlag = transientFlag; 57 mUnhideFlag = unhideFlag; 58 mStatusBarManagerId = statusBarManagerId; 59 mHandler = new Handler(); 60 } 61 62 public void setWindow(WindowState win) { 63 mWin = win; 64 } 65 66 public boolean isHidden() { 67 return mState == StatusBarManager.WINDOW_STATE_HIDDEN; 68 } 69 70 public void showTransient() { 71 if (mWin != null) { 72 setTransientBarState(TRANSIENT_BAR_SHOWING); 73 } 74 } 75 76 public boolean isTransientShowing() { 77 return mTransientBarState == TRANSIENT_BAR_SHOWING; 78 } 79 80 public void adjustSystemUiVisibilityLw(int oldVis, int vis) { 81 if (mWin != null && mTransientBarState == TRANSIENT_BAR_SHOWING && 82 (vis & mTransientFlag) == 0) { 83 // sysui requests hide 84 setTransientBarState(TRANSIENT_BAR_HIDING); 85 setBarShowingLw(false); 86 } else if (mWin != null && (oldVis & mUnhideFlag) != 0 && (vis & mUnhideFlag) == 0) { 87 // sysui ready to unhide 88 setBarShowingLw(true); 89 } 90 } 91 92 public boolean setBarShowingLw(final boolean show) { 93 if (mWin == null) return false; 94 if (show && mTransientBarState == TRANSIENT_BAR_HIDING) { 95 mPendingShow = true; 96 return false; 97 } 98 final boolean oldVis = mWin.isVisibleLw(); 99 final boolean oldAnim = mWin.isAnimatingLw(); 100 final boolean rt = show ? mWin.showLw(true) : mWin.hideLw(true); 101 final int state = computeState(oldVis, oldAnim, mWin.isVisibleLw(), mWin.isAnimatingLw()); 102 if (state > -1) { 103 updateState(state); 104 } 105 return rt; 106 } 107 108 private int computeState(boolean oldVis, boolean oldAnim, boolean newVis, boolean newAnim) { 109 return (!newVis && !newAnim) ? StatusBarManager.WINDOW_STATE_HIDDEN 110 : (!oldVis && newVis && newAnim) ? StatusBarManager.WINDOW_STATE_SHOWING 111 : (oldVis && newVis && !oldAnim && newAnim) ? StatusBarManager.WINDOW_STATE_HIDING 112 : -1; 113 } 114 115 private void updateState(final int state) { 116 if (state != mState) { 117 mState = state; 118 mHandler.post(new Runnable() { 119 @Override 120 public void run() { 121 try { 122 IStatusBarService statusbar = getStatusBarService(); 123 if (statusbar != null) { 124 statusbar.setWindowState(mStatusBarManagerId, state); 125 } 126 } catch (RemoteException e) { 127 // re-acquire status bar service next time it is needed. 128 mStatusBarService = null; 129 } 130 } 131 }); 132 } 133 } 134 135 public boolean checkHiddenLw() { 136 if (mWin != null) { 137 if (!mWin.isVisibleLw() && !mWin.isAnimatingLw()) { 138 updateState(StatusBarManager.WINDOW_STATE_HIDDEN); 139 } 140 if (mTransientBarState == TRANSIENT_BAR_HIDING && !mWin.isVisibleLw()) { 141 // Finished animating out, clean up and reset style 142 setTransientBarState(TRANSIENT_BAR_NONE); 143 if (mPendingShow) { 144 setBarShowingLw(true); 145 mPendingShow = false; 146 } 147 return true; 148 } 149 } 150 return false; 151 } 152 153 public boolean checkShowTransientBarLw() { 154 if (mTransientBarState == TRANSIENT_BAR_SHOWING) { 155 if (DEBUG) Slog.d(mTag, "Not showing transient bar, already shown"); 156 return false; 157 } else if (mWin == null) { 158 if (DEBUG) Slog.d(mTag, "Not showing transient bar, bar doesn't exist"); 159 return false; 160 } else if (mWin.isDisplayedLw()) { 161 if (DEBUG) Slog.d(mTag, "Not showing transient bar, bar already visible"); 162 return false; 163 } else { 164 return true; 165 } 166 } 167 168 public int updateVisibilityLw(boolean allowed, int oldVis, int vis) { 169 if (mWin == null) return vis; 170 if (mTransientBarState == TRANSIENT_BAR_SHOWING) { // transient bar requested 171 if (allowed) { 172 vis |= mTransientFlag; 173 if ((oldVis & mTransientFlag) == 0) { 174 vis |= mUnhideFlag; // tell sysui we're ready to unhide 175 } 176 } else { 177 setTransientBarState(TRANSIENT_BAR_NONE); // request denied 178 } 179 } 180 if (mTransientBarState != TRANSIENT_BAR_NONE) { 181 vis |= mTransientFlag; // ignore clear requests until transition completes 182 vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE; // never show transient bars in low profile 183 } 184 return vis; 185 } 186 187 private void setTransientBarState(int state) { 188 if (mWin != null && state != mTransientBarState) { 189 mTransientBarState = state; 190 if (DEBUG) Slog.d(mTag, "New state: " + transientBarStateToString(state)); 191 } 192 } 193 194 private IStatusBarService getStatusBarService() { 195 synchronized (mServiceAquireLock) { 196 if (mStatusBarService == null) { 197 mStatusBarService = IStatusBarService.Stub.asInterface( 198 ServiceManager.getService("statusbar")); 199 } 200 return mStatusBarService; 201 } 202 } 203 204 private static String transientBarStateToString(int state) { 205 if (state == TRANSIENT_BAR_HIDING) return "TRANSIENT_BAR_HIDING"; 206 if (state == TRANSIENT_BAR_SHOWING) return "TRANSIENT_BAR_SHOWING"; 207 if (state == TRANSIENT_BAR_NONE) return "TRANSIENT_BAR_NONE"; 208 throw new IllegalArgumentException("Unknown state " + state); 209 } 210 211 public void dump(PrintWriter pw, String prefix) { 212 if (mWin != null) { 213 pw.print(prefix); pw.print(mTag); pw.print(' '); 214 pw.print("mTransientBar"); pw.print('='); 215 pw.println(transientBarStateToString(mTransientBarState)); 216 } 217 } 218} 219