基于Android R版本分析
在多个屏幕上显示StatusBar和NavigationBar,需要修改两个位置:
-
DisplayPolicy
-
在DisplayPolicy中有两个变量:mHasStatusBar 和mHasNavigationBar,该变量用于判断当前屏幕中是否需要显示StatusBar和NavigationBar;
- mHasStatusBar:默认在DefaultDisplay中显示,在其他非DefaultDisplay中不显示;
- mHasNavigationBar:根据 "qemu.hw.mainkeys" 这个SystemProperties来标识是否需要显示;
-
-
SystemUI进程中:在SystemUI代码中,需要主动的遍历所有的DisplayIds ,为每一个Display配套一组StatusBar和NavigationBar,本质上其实就是为每一个Display创建两个Window窗口用于承载对应的StatusBar和NavigationBar,这个StatusBar和NavigationBar可以和主屏显示相同,也可以定制化副屏的StatusBar和NavigationBar;
DisplayPolicy patch
diff
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 2267bcb3..d6aa613b 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -157,6 +157,7 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.IntArray;
+import android.util.Log;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
@@ -649,18 +650,27 @@ public class DisplayPolicy {
if (mDisplayContent.isDefaultDisplay) {
mHasStatusBar = true;
+ // 在/frameworks/base/core/res/res/values/config.xml中定义的config_showNavigationBar:
+ // <bool name="config_showNavigationBar">false</bool>
mHasNavigationBar = mContext.getResources().getBoolean(R.bool.config_showNavigationBar);
// Allow a system property to override this. Used by the emulator.
// See also hasNavigationBar().
+ // 通过该SystemProperties来控制display是否需要显示navigation bar
String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
+ /**
+ * qemu.hw.mainkeys = 1 //不存在
+ * qemu.hw.mainkeys = 0 //存在
+ */
if ("1".equals(navBarOverride)) {
mHasNavigationBar = false;
} else if ("0".equals(navBarOverride)) {
mHasNavigationBar = true;
}
} else {
- mHasStatusBar = false;
+ // 默认在副屏中,StatusBar不显示,即使在SystemUI中强制使其显示,但是在DisplayPolicy中也不会标记
+ // StatusBar已显示
+ mHasStatusBar = true;
mHasNavigationBar = mDisplayContent.supportsSystemDecorations();
}
@@ -748,6 +758,7 @@ public class DisplayPolicy {
return mDockMode;
}
+ // 在CUX SystemUI中判斷是否需要显示navigation bar就是通过DisplayPolicy中的hasNavigationBar实现的
public boolean hasNavigationBar() {
return mHasNavigationBar;
}
@@ -3033,18 +3044,30 @@ public class DisplayPolicy {
/**
* Called when the configuration has changed, and it's safe to load new values from resources.
+ *
+ * onConfigurationChanged事件并不是只有屏幕方向改变才可以触发,其他的一些系统设置改变也可以触发,比如打开或者隐藏键盘
*/
public void onConfigurationChanged() {
final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation();
final Resources res = getCurrentUserResources();
+ // 这个几个rotation代表了横竖屏设置的参数
+ /**
+ * portrait Rotation:肖像 旋转
+ * landscape Rotation:景观 旋转
+ */
final int portraitRotation = displayRotation.getPortraitRotation();
final int upsideDownRotation = displayRotation.getUpsideDownRotation();
final int landscapeRotation = displayRotation.getLandscapeRotation();
final int seascapeRotation = displayRotation.getSeascapeRotation();
final int uiMode = mService.mPolicy.getUiMode();
+ /**
+ * 判断DisplayContent对应的DisplayPolicy中是否标记了已存在hasStatusBar
+ * 默认在副屏中不存在StatusBar
+ */
if (hasStatusBar()) {
+ // 在判断允许存在StatusBar之后,StatusBarHeight的值就不能为0
mStatusBarHeightForRotation[portraitRotation] =
mStatusBarHeightForRotation[upsideDownRotation] =
res.getDimensionPixelSize(R.dimen.status_bar_height_portrait);
@@ -3244,6 +3267,14 @@ public class DisplayPolicy {
* decorations that could never be removed in Honeycomb. That is, system bar or
* button bar.
*/
+ /**
+ * 应用区域分两种情况:
+ * 1、当导航栏显示的时候,应用区域会减去导航栏的高度
+ * 2、当状态栏显示的时候,应用区域的距离会减去状态栏的高度
+ *
+ * 在原生的逻辑中,只考虑了navigation bar的height和cutout的height,因为statusbar在副屏的height默认为0,
+ * 所以就没有考虑statusBar的height
+ */
public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
DisplayCutout displayCutout) {
int height = fullHeight;
@@ -3288,6 +3319,13 @@ public class DisplayPolicy {
// bar height.
statusBarHeight = Math.max(0, statusBarHeight - displayCutout.getSafeInsetTop());
}
+ // 获取应用区域的高度
+ /**
+ * 应用区域分两种情况:
+ * 1、当导航栏显示的时候,应用区域会减去导航栏的高度
+ * 2、当状态栏显示的时候,应用区域的距离会减去状态栏的高度(StatusBar的height需要手动的进行删除,因为
+ * getNonDecorDisplayHeight方法中没有考虑StatusBar)
+ */
return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayCutout)
- statusBarHeight;
}