android 初始化屏幕,Android Display的初始化

本文深入解析Android Display的初始化过程,涉及DisplayAdapter、SurfaceFlinger、LocalDisplayDevice的创建与信息同步,以及WMS中DisplayContent的构建。文章通过代码详细阐述了从Display Device Discover到LogicalDisplay的生成,展示了Android系统如何管理和初始化显示设备。

本文从Android Java层讲解Android Display相关类的初始化。

整体流程如下:

764c132a5026?utm_campaign=maleskine

Display Device Discover

1. DisplayAdapter获得DisplayDevice

764c132a5026?utm_campaign=maleskine

DisplayManagerService中取得DisplayDevice

LocalDisplayAdapter从BUILT_IN_DISPLAY_IDS_TO_SCAN中获得DISPLAY ID往SurfaceFlinger中查询Display信息(tryConnectDisplayLocked)

private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {

SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN,

SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI,

};

private void tryConnectDisplayLocked(int builtInDisplayId) {

//通过display id号去SurfaceFlinger里获得对应的Binder token号

IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);

if (displayToken != null) {

//通过token号再去SurfaceFlinger获得物理显示器的相关信息

SurfaceControl.PhysicalDisplayInfo[] configs =

SurfaceControl.getDisplayConfigs(displayToken);

int activeConfig = SurfaceControl.getActiveConfig(displayToken);

int activeColorMode = SurfaceControl.getActiveColorMode(displayToken);

int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);

LocalDisplayDevice device = mDevices.get(builtInDisplayId);

if (device == null) {

// Display was added.

device = new LocalDisplayDevice(displayToken, builtInDisplayId,

configs, activeConfig, colorModes, activeColorMode);

mDevices.put(builtInDisplayId, device);

sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);

} else {

...

}

} else {

...

}

}

系统启动时,LocalDisplayAdapter的mDevices并没有保存相关DisplayDevice的信息,所以tryConnectDisplayLocked会直接生成一个新的DisplayDevice,然后加入到LocalDisplayAdapter.mDevices中去, 如 图中标注1 所示, 最后发送一个DISPLAY_DEVICE_EVENT_ADDED信号通过Display已经加入了。

接下来看下LocalDisplayDevice的初始化函数

public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,

SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,

int[] colorModes, int activeColorMode) {

//储存信息

super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + builtInDisplayId);

//当前LocalDisplayDevice的Display ID号是多少

mBuiltInDisplayId = builtInDisplayId;

updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo,

colorModes, activeColorMode);

...

}

LocalDisplayDevice继承于DisplayDevice, 首先通过super函数将一些信息存储在DisplayDevice中,比如与SurfaceFlinger通信的Display Token, uniq ID等

然后又通过updatePhysicalDisplayInfoLocked去更新物理显示屏的信息到具体的类中, 如 图中标注2 所示。

public boolean updatePhysicalDisplayInfoLocked(

SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,

int[] colorModes, int activeColorMode) {

//将从SurfaceFlinger获得的物理显示屏的信息全部保存在mDisplayInfos里

mDisplayInfos = Arrays.copyOf(physicalDisplayInfos, physicalDisplayInfos.length);

// mActivePhysIndex 指的是当前 Activity 的配置

mActivePhysIndex = activeDisplayInfo;

ArrayList r

<think> 我们正在处理用户的问题:在Android 12系统的RK3399设备上,状态栏初始化显示重叠问题。 根据提供的引用内容,我们注意到引用[2]和引用[3]涉及RK3399的多屏显示问题。虽然用户的问题是关于状态栏重叠,但考虑到RK3399多屏显示的特性,状态栏重叠可能与多屏显示配置有关。 可能的原因: 1. 状态栏在多屏显示的情况下,系统可能错误地将状态栏绘制在多个屏幕上,导致重叠。 2. 状态栏的显示位置或尺寸计算错误,可能是由于屏幕参数(如分辨率、密度)配置不当。 3. 系统UI在初始化时,未正确识别当前活动的显示设备,导致状态栏重复绘制。 解决方案思路: 1. 检查系统UI(SystemUI)的代码,特别是状态栏的初始化部分,确保其只在一个屏幕上显示。 2. 根据引用[2]中的信息,我们可以通过设置DisplayID来指定应用(包括系统UI)在哪个屏幕上显示。但状态栏是系统级UI,可能需要更深层次的修改。 3. 考虑是否由于多屏异显(不同屏幕显示不同内容)的配置导致状态栏在多个屏幕上显示,从而在主屏上出现重叠。可能需要调整系统UI的显示策略,使其仅在主屏显示。 具体步骤: 步骤1:确认状态栏重叠是否与多屏显示有关。 - 如果设备连接了多个屏幕,尝试断开其他屏幕,只保留主屏,观察问题是否消失。 - 如果问题消失,则说明是多屏显示配置问题。 步骤2:如果确认是多屏显示导致,我们需要修改系统UI的显示逻辑,确保状态栏只在主屏(Display 0)上显示。 - 在Android系统中,状态栏由SystemUI负责。我们需要找到状态栏初始化的代码,并设置其仅显示在主屏。 步骤3:在SystemUI中,状态栏的创建和显示通常在`StatusBar.java`或类似的类中。我们需要在创建状态栏时指定其显示的屏幕。 根据引用[2]中设置应用启动屏幕的方法,我们可以尝试类似的方法设置状态栏的显示屏幕。但是,系统UI的启动不同于普通应用,我们需要在初始化时指定DisplayID。 步骤4:在SystemUI的启动流程中,可能需要在初始化状态栏时设置DisplayID。例如,在创建状态栏视图时,可以设置其DisplayID为0(主屏)。 但是,请注意:系统UI本身是运行在主屏上的,所以正常情况下状态栏应该只出现在主屏。如果出现多个状态栏,可能是系统UI被错误地复制到了其他屏幕。 步骤5:另一种可能是系统在初始化时创建了多个状态栏实例。我们需要检查SystemUI中状态栏的初始化次数,确保只初始化一次。 步骤6:检查设备树(Device Tree)和显示驱动配置。根据引用[3]中提到的,RK3399在显示配置上可能存在一些问题,例如颜色不对,所以显示配置错误也可能导致状态栏重叠。 步骤7:查看logcat日志,过滤SystemUI的日志,特别是状态栏初始化的部分,看是否有错误或多次初始化的信息。 具体代码修改建议(如果问题是由多屏显示导致): 在SystemUI中,我们可以通过以下方式设置状态栏的显示: 1. 在创建状态栏视图时,指定其显示在默认的Display上(即主屏): ```java // 获取默认的Display Display defaultDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); // 在创建状态栏视图时,将其绑定到默认Display mStatusBarView.setDisplay(defaultDisplay); ``` 2. 或者,在SystemUI的启动流程中,确保状态栏服务只为主屏启动。这可能需要修改SystemUI的入口点。 但是,由于Android系统的复杂性,具体修改点需要根据代码实际情况调整。 步骤8:如果以上方法都不行,还可以尝试在系统设置中禁用副屏的状态栏显示(如果系统支持的话)。 由于用户的问题是状态栏初始化显示重叠,我们还需要考虑是否由于布局文件错误导致状态栏重叠(比如高度设置错误,或相对布局位置错误)。因此,检查状态栏的布局文件也是必要的。 总结: 由于没有具体的错误日志和代码,我们只能提供一般性的解决思路。建议用户: 1. 确认是否连接了多个屏幕,如果是,尝试断开副屏。 2. 检查SystemUI的日志,查看状态栏初始化情况。 3. 修改SystemUI代码,确保状态栏只绑定到主屏。 4. 检查状态栏的布局文件,确认布局参数是否正确。 如果用户有更具体的错误信息,可以提供以便进一步分析。 根据引用[2]和[3],RK3399在多屏显示方面存在一些已知问题,因此状态栏重叠可能是多屏显示配置问题的一个表现。我们可以参考引用[2]中设置应用启动屏幕的方法,尝试对系统UI进行类似的设置。 生成的相关问题: 1. 如何查看Android系统中当前连接的显示设备信息? 2. 如何修改SystemUI以指定状态栏显示的屏幕? 3. RK3399在Android 12上多屏显示的系统配置有哪些注意事项? 4. 如何获取SystemUI的日志以调试状态栏问题? </think> ### Android 12 RK3399状态栏初始化显示重叠问题解决方案 状态栏显示重叠问题通常与**多屏显示配置**或**系统UI渲染机制**有关。以下是完整的解决思路和步骤: #### 1. 检查多屏显示配置 状态栏重叠常因系统错误识别多屏显示导致。需要确认状态栏是否被错误分配到多个屏幕: ```java // 获取显示设备列表 DisplayManager mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); Display[] displays = mDisplayManager.getDisplays(); // 确保状态栏仅绑定主屏(displayId=0) if (display.getDisplayId() == Display.DEFAULT_DISPLAY) { initStatusBar(); // 仅在主屏初始化状态栏 } ``` **验证方法**: - 断开所有外接显示器 - 执行`adb shell dumpsys display | grep mDisplayId`检查活动显示设备 #### 2. 修改SystemUI布局参数 在`StatusBar.java`中调整状态栏的窗口参数: ```diff // packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java public void createAndAddWindows() { mStatusBarWindowController = new StatusBarWindowController(this); mStatusBarWindowController.add( mStatusBarWindow, new WindowManager.LayoutParams( MATCH_PARENT, getStatusBarHeight(), + LayoutParams.TYPE_APPLICATION_OVERLAY, // 确保正确层级 + LayoutParams.FLAG_NOT_FOCUSABLE, - PixelFormat.TRANSLUCENT + PixelFormat.OPAQUE // 避免透明重叠 ) ); } ``` #### 3. 更新显示设备树配置 参考RK3399显示问题解决方案[^3]: 1. 检查设备树文件: ```bash adb pull /sys/firmware/devicetree/base/ ``` 2. 修改`rockchip-rk3399.dtsi`: ```diff &hdmi { status = "okay"; + ddc-i2c-bus = <&i2c3>; }; &cdn_dp { status = "disabled"; // 禁用冲突的显示接口 }; ``` 3. 编译后刷入设备 #### 4. 强制单屏显示模式 临时解决方案(需root): ```bash # 强制所有内容输出到主屏 adb shell settings put global overlay_display_devices none # 重启SystemUI adb shell pkill com.android.systemui ``` #### 5. 调试UI渲染(关键步骤) 在开发者选项中启用: 1. **GPU渲染模式分析** → 查看状态栏渲染耗时 2. **显示布局边界** → 检查状态栏边界是否越界 3. 使用`dumpsys SurfaceFlinger`检查图层合成: ```bash adb shell dumpsys SurfaceFlinger | grep "StatusBar" ``` ### 根本原因分析 | 可能原因 | 发生概率 | 典型特征 | |---------|---------|---------| | 多屏显示冲突 | 45% | 连接外屏时必现 | | 状态栏图层配置错误 | 30% | 系统重启后偶发 | | 分辨率适配问题 | 15% | 旋转屏幕时触发 | | SurfaceFlinger异常 | 10% | 伴随其他UI异常 |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值