多屏 - 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;
     }
相关推荐
元争栈道31 分钟前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
居居飒1 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
思忖小下1 小时前
梳理你的思路(从OOP到架构设计)_简介设计模式
设计模式·架构·eit
Henry_He4 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗5 小时前
Android笔试面试题AI答之Android基础(1)
android
qq_397562316 小时前
android studio更改应用图片,和应用名字。
android·ide·android studio
峥嵘life6 小时前
Android Studio版本升级那些事
android·ide·android studio
新手上路狂踩坑6 小时前
Android Studio的笔记--BusyBox相关
android·linux·笔记·android studio·busybox
一个儒雅随和的男子8 小时前
微服务详细教程之nacos和sentinel实战
微服务·架构·sentinel
腾讯云开发者8 小时前
AI时代,需要怎样的架构师?腾讯云架构师峰会来了!
架构