多屏 - SystemUI显示

基于Android R版本分析

在多个屏幕上显示StatusBar和NavigationBar,需要修改两个位置:

  • DisplayPolicy

    • 在DisplayPolicy中有两个变量:mHasStatusBarmHasNavigationBar,该变量用于判断当前屏幕中是否需要显示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;
     }
相关推荐
数据猎手小k1 小时前
AndroidLab:一个系统化的Android代理框架,包含操作环境和可复现的基准测试,支持大型语言模型和多模态模型。
android·人工智能·机器学习·语言模型
你的小102 小时前
JavaWeb项目-----博客系统
android
风和先行2 小时前
adb 命令查看设备存储占用情况
android·adb
AaVictory.3 小时前
Android 开发 Java中 list实现 按照时间格式 yyyy-MM-dd HH:mm 顺序
android·java·list
似霰4 小时前
安卓智能指针sp、wp、RefBase浅析
android·c++·binder
大风起兮云飞扬丶4 小时前
Android——网络请求
android
干一行,爱一行4 小时前
android camera data -> surface 显示
android
断墨先生4 小时前
uniapp—android原生插件开发(3Android真机调试)
android·uni-app
无极程序员6 小时前
PHP常量
android·ide·android studio
58沈剑7 小时前
80后聊架构:架构设计中两个重要指标,延时与吞吐量(Latency vs Throughput) | 架构师之路...
架构