多屏 - 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;
     }
相关推荐
Reese_Cool1 小时前
【C语言二级考试】循环结构设计
android·java·c语言·开发语言
平凡シンプル2 小时前
安卓 uniapp跨端开发
android·uni-app
elina80132 小时前
安卓实现导入Excel文件
android·excel
严文文-Chris2 小时前
【设计模式-享元】
android·java·设计模式
趋势大仙2 小时前
SQLiteDatabase insert or replace数据不生效
android·数据库
DS小龙哥2 小时前
QT For Android开发-打开PPT文件
android·qt·powerpoint
伯牙碎琴3 小时前
十一、SOA(SOA的具体设计模式)
架构
试行3 小时前
Android实现自定义下拉列表绑定数据
android·java
Dingdangr8 小时前
Android中的Intent的作用
android
技术无疆8 小时前
快速开发与维护:探索 AndroidAnnotations
android·java·android studio·android-studio·androidx·代码注入