一 framework层对状态栏颜色以及分屏状态时颜色的处理过程。
PWM根据所有窗口状态选择合适窗口的WindowState,依据WindowState开始更新SystemUI的状态。此处主要分析对状态栏有影响的重要函数步奏。
(1)frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
PWM开始更新SystemUI的状态,此处我们重点关注updateLightStatusBarLw函数
private int updateSystemUiVisibilityLw() {
// If there is no window focused, there will be nobody to handle the events
// anyway, so just hang on in whatever state we're in until things settle down.
WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
: mTopFullscreenOpaqueWindowState;
if (winCandidate == null) {
return 0;
}
if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) {
// The immersive mode confirmation should never affect the system bar visibility,
// otherwise it will unhide the navigation bar and hide itself.
winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState;
if (winCandidate == null) {
return 0;
}
}
final WindowState win = winCandidate;
if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
// We are updating at a point where the keyguard has gotten
// focus, but we were last in a state where the top window is
// hiding it. This is probably because the keyguard as been
// shown while the top window was displayed, so we want to ignore
// it here because this is just a very transient change and it
// will quickly lose focus once it correctly gets hidden.
return 0;
}
int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null)
& ~mResettingSystemUiFlags
& ~mForceClearedSystemUiFlags;
if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) {
tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
}
final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
mWindowManagerFuncs.getStackBounds(
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mNonDockedStackBounds);
mWindowManagerFuncs.getStackBounds(
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, mDockedStackBounds);
final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
final int diff = visibility ^ mLastSystemUiFlags;
final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu
&& mFocusedApp == win.getAppToken()
&& mLastNonDockedStackBounds.equals(mNonDockedStackBounds)
&& mLastDockedStackBounds.equals(mDockedStackBounds)) {
return 0;
}
mLastSystemUiFlags = visibility;
mLastFullscreenStackSysUiFlags = fullscreenVisibility;
mLastDockedStackSysUiFlags = dockedVisibility;
mLastFocusNeedsMenu = needsMenu;
mFocusedApp = win.getAppToken();
final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds);
final Rect dockedStackBounds = new Rect(mDockedStackBounds);
mHandler.post(new Runnable() {
@Override
public void run() {
StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
if (statusbar != null) {
statusbar.setSystemUiVisibility(visibility, fullscreenVisibility,
dockedVisibility, 0xffffffff, fullscreenStackBounds,
dockedStackBounds, win.toString());
statusbar.topAppWindowChanged(needsMenu);
}
}
});
return diff;
}
updateLightStatusBarLw根据最上层的窗口确认是否为Light SystemUI的,接下来看下PolicyControl.getSystemUiVisibility
private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
final boolean onKeyguard = isStatusBarKeyguard() && !mKeyguardOccluded;
final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
// If the top fullscreen-or-dimming window is also the top fullscreen, respect
// its light flag.
vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
& View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else if (statusColorWin != null && statusColorWin.isDimming()) {
// Otherwise if it's dimming, clear the light flag.
vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
return vis;
}
(2)frameworks/base/services/core/java/com/android/server/policy/PolicyControl.java
在getSystemUiVisibility中又没有相关LIGHT的操作,那么有跑到了WindowState.getSystemUiVisibility中
public static int getSystemUiVisibility(WindowState win, LayoutParams attrs) {
attrs = attrs != null ? attrs : win.getAttrs();
int vis = win != null ? win.getSystemUiVisibility()
: (attrs.systemUiVisibility | attrs.subtreeSystemUiVisibility);
if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)) {
vis |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
vis &= ~(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.STATUS_BAR_TRANSLUCENT);
}
if (sImmersiveNavigationFilter != null && sImmersiveNavigationFilter.matches(attrs)) {
vis |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
vis &= ~(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.NAVIGATION_BAR_TRANSLUCENT);
}
return vis;
}
(3)frameworks/base/services/core/java/com/android/server/wm/WindowState.java
此处很简单的就是获取mSystemUiVisibility,而mSystemUiVisibility最终是从哪里来的呢,那就要跳到PhoneWindow.java。
(此处跳动有点大,主要是从ViewRootImpl的relayout界面时携带的WindowManager.LayoutParams决定的)
@Override
public int getSystemUiVisibility() {
return mSystemUiVisibility;
}
(4)frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
从此处可以看到,下拉栏颜色的设定还是由APP的主题所导致的。
protected ViewGroup generateLayout(DecorView decor) {
// Apply data from current theme.
/*......*/
if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
decor.setSystemUiVisibility(
decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
/*......*/
}
/**
* 设置StatusBar字体颜色
* <p>
* 参数true表示StatusBar风格为Light,字体颜色为黑色
* 参数false表示StatusBar风格不是Light,字体颜色为白色
* <p>
* <item name="android:windowLightStatusBar">true</item>
* 在theme或style中使用这个属性改变StatusBar的字体颜色,这种形式相对不灵活
*/
public void setStatusBarTextColor(Window window, boolean lightStatusBar) {
if (window == null) return;
View decor = window.getDecorView();
int ui = decor.getSystemUiVisibility();
if (lightStatusBar) {
ui |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else {
ui &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
decor.setSystemUiVisibility(ui);
}
二 Systemui接收到StatusBarManagerService对状态栏的状态的update,以及对状态栏的更新。
(待续)。