想了解更多关于开源的决方内容,请访问:
51CTO 开源基础软件社区
https://ost.51cto.com
系统版本:OpenHarmony-3.2-Release。统解
接入多个显示设备后,决方启动系统偶现卡开机Logo。统解
系统卡在开机Logo界面,决方长时间无法显示开机动画,统解并且无法进入系统。决方
OpenHarmony系统解决方案 - 接入多个显示设备卡开机Logo-开源基础软件社区
系统启动成功,统解显示开机动画,决方开机动画结束后显示锁屏界面。统解
OpenHarmony系统解决方案 - 接入多个显示设备卡开机Logo-开源基础软件社区
修改默认屏幕设置条件,解决AbstractDisplayController控制器加载慢于Display通知屏幕连接事件时,造成的无法设置默认屏幕问题。
修改文件:foundation/window/window_manager/dmserver/src/abstract_display_controller.cpp
AbstractDisplayController::OnAbstractScreenConnect函数中,将以下代码:
if (group->combination_ == ScreenCombination::SCREEN_ALONE || group->GetChildCount() == 1) {
替换为:
ScreenId dmsScreenId = abstractScreenController_->GetDefaultAbstractScreenId();sptr<AbstractDisplay> display = GetAbstractDisplayByScreen(dmsScreenId);if (group->combination_ == ScreenCombination::SCREEN_ALONE || group->GetChildCount() == 1 || display == nullptr) {
替换后完整函数代码:
void AbstractDisplayController::OnAbstractScreenConnect(sptr<AbstractScreen> absScreen){ if (absScreen == nullptr) { WLOGFE("absScreen is null"); return; } WLOGI("connect new screen. id:%{ public}" PRIu64"", absScreen->dmsId_); std::lock_guard<std::recursive_mutex> lock(mutex_); sptr<AbstractScreenGroup> group = absScreen->GetGroup(); if (group == nullptr) { WLOGE("the group information of the screen is wrong"); return; } ScreenId dmsScreenId = abstractScreenController_->GetDefaultAbstractScreenId(); sptr<AbstractDisplay> display = GetAbstractDisplayByScreen(dmsScreenId); if (group->combination_ == ScreenCombination::SCREEN_ALONE || group->GetChildCount() == 1 || display == nullptr) { BindAloneScreenLocked(absScreen); } else if (group->combination_ == ScreenCombination::SCREEN_MIRROR) { WLOGI("OnAbstractScreenConnect, ScreenCombination::SCREEN_MIRROR, AddScreenToMirrorLocked"); AddScreenToMirrorLocked(absScreen); } else if (group->combination_ == ScreenCombination::SCREEN_EXPAND) { WLOGI("OnAbstractScreenConnect, ScreenCombination::SCREEN_EXPAND, AddScreenToExpandLocked"); AddScreenToExpandLocked(absScreen); } else { WLOGE("support in future. combination:%{ public}u", group->combination_); }}
落盘异常开机日志,发现Launcher和SystemUI等系统应用在启动过程中报错,无法获取DefaultDisplayInfo。
08-05 17:18:29.046 521 1088 D C04201/AbstractScreenController: <177>GetDefaultAbstractScreenId: GetDefaultAbstractScreenId, screen:008-05 17:18:29.046 521 1088 D C04201/DisplayManagerService: <190>GetDefaultDisplayInfo: GetDefaultDisplayInfo 008-05 17:18:29.046 521 1088 E C04201/AbstractDisplayController: <105>GetAbstractDisplayByScreen: fail to get AbstractDisplay 008-05 17:18:29.047 521 1088 E C04201/DisplayManagerService: <193>GetDefaultDisplayInfo: fail to get displayInfo by id: invalid display08-05 17:18:29.047 240 1090 I C01800/SAMGR: SystemAbilityManagerStub::OnReceived, code = 12, callerPid = 1156, flags= 008-05 17:18:29.047 1156 1156 W C04201/DisplayManagerProxy: <52>GetDefaultDisplayInfo: DisplayManagerProxy::GetDefaultDisplayInfo SendRequest nullptr.08-05 17:18:29.047 1156 1156 D C03f00/ArkCompiler: [ecmascript] Throw error: JsDisplayManager::OnGetDefaultDisplay failed.
查找默认屏幕设置逻辑,追踪Log发现默认屏幕信息从abstractDisplayMap_中获取。
// foundation/window/window_manager/dmserver/src/abstract_display_controller.cppsptr<AbstractDisplay> AbstractDisplayController::GetAbstractDisplayByScreen(ScreenId screenId) const{ if (screenId == SCREEN_ID_INVALID) { WLOGFE("screen id is invalid."); return nullptr; } std::lock_guard<std::recursive_mutex> lock(mutex_); for (auto iter : abstractDisplayMap_) { sptr<AbstractDisplay> display = iter.second; if (display->GetAbstractScreenId() == screenId) { return display; } } WLOGFE("fail to get AbstractDisplay %{ public}" PRIu64"", screenId); return nullptr;}
abstractDisplayMap_对象会在两个位置被insert数据,BindAloneScreenLocked函数和AddScreenToExpandLocked函数。而两个函数拥有同一个入口函数AbstractDisplayController::OnAbstractScreenConnect。
// foundation/window/window_manager/dmserver/src/abstract_display_controller.cppvoid AbstractDisplayController::OnAbstractScreenConnect(sptr<AbstractScreen> absScreen){ if (absScreen == nullptr) { WLOGFE("absScreen is null"); return; } WLOGI("connect new screen. id:%{ public}" PRIu64"", absScreen->dmsId_); std::lock_guard<std::recursive_mutex> lock(mutex_); sptr<AbstractScreenGroup> group = absScreen->GetGroup(); if (group == nullptr) { WLOGE("the group information of the screen is wrong"); return; } if (group->combination_ == ScreenCombination::SCREEN_ALONE || group->GetChildCount() == 1) { BindAloneScreenLocked(absScreen); } else if (group->combination_ == ScreenCombination::SCREEN_MIRROR) { WLOGI("OnAbstractScreenConnect, ScreenCombination::SCREEN_MIRROR, AddScreenToMirrorLocked"); AddScreenToMirrorLocked(absScreen); } else if (group->combination_ == ScreenCombination::SCREEN_EXPAND) { WLOGI("OnAbstractScreenConnect, ScreenCombination::SCREEN_EXPAND, AddScreenToExpandLocked"); AddScreenToExpandLocked(absScreen); } else { WLOGE("support in future. combination:%{ public}u", group->combination_); }}
查看源码对应Log,发现异常情况下屏幕OnAbstractScreenConnect函数的执行操作是一起完成的,此时ScrrenID为0的屏幕ScreenCombination属性为ScreenCombination::SCREEN_MIRROR。而在正常情况下OnAbstractScreenConnect函数是分开执行的。
异常Log:
08-05 17:18:26.923 521 923 I C04201/AbstractDisplayController: <152>connect new screen. id:008-05 17:18:26.923 521 923 I C04201/AbstractDisplayController: <162>OnAbstractScreenConnect, ScreenCombination::SCREEN_MIRROR, AddScreenToMirrorLocked08-05 17:18:26.923 521 656 I C04201/AbstractScreenController: <1161>operator(): screenId:2, trigger:[foundation]08-05 17:18:26.923 332 430 I C01799/MemMgr: MultiAccountManager::Init The manager initial succeed, accountCount = 0.08-05 17:18:26.923 521 923 I C04201/AbstractDisplayController: <558>bind display to mirror. screen:008-05 17:18:26.923 521 656 I C04200/ClientAgentContainer: <98>GetAgentsByType: no such type of agent registered! type:208-05 17:18:26.923 521 923 I C04201/AbstractScreenController: <203>RegisterAbstractScreenCallback: dmsScreenId :108-05 17:18:26.923 521 923 I C04201/AbstractDisplayController: <152>connect new screen. id:108-05 17:18:26.923 521 923 E C04201/AbstractScreenController: <159>did not find screen:1844674407370955161508-05 17:18:26.923 521 923 E C04201/AbstractDisplayController: <156>the group information of the screen is wrong08-05 17:18:26.923 521 923 I C04201/AbstractScreenController: <203>RegisterAbstractScreenCallback: dmsScreenId :208-05 17:18:26.923 521 923 I C04201/AbstractDisplayController: <152>connect new screen. id:208-05 17:18:26.923 521 923 I C04201/AbstractDisplayController: <162>OnAbstractScreenConnect, ScreenCombination::SCREEN_MIRROR, AddScreenToMirrorLocked08-05 17:18:26.923 521 923 I C04201/AbstractDisplayController: <558>bind display to mirror. screen:2
正常Log:
08-05 17:23:07.081 547 770 I C04201/AbstractDisplayController: <152>connect new screen. id:008-05 17:23:07.081 547 770 D C04201/AbstractScreenController: <177>GetDefaultAbstractScreenId: GetDefaultAbstractScreenId, screen:008-05 17:23:07.088 547 770 I C04201/AbstractDisplayController: <152>connect new screen. id:208-05 17:23:07.088 547 770 I C04201/AbstractDisplayController: <162>OnAbstractScreenConnect, ScreenCombination::SCREEN_MIRROR, AddScreenToMirrorLocked08-05 17:23:07.088 547 770 I C04201/AbstractDisplayController: <558>bind display to mirror. screen:2
查看OnAbstractScreenConnect的触发逻辑有两种。
第一种,AbstractDisplayController初始化时注册屏幕事件回调,注册后遍历dmsScreenMap_调用AbstractDisplayController::OnAbstractScreenConnect初始化在回调注册前记录的屏幕数据。
// foundation/window/window_manager/dmserver/src/abstract_screen_controller.cppvoid AbstractDisplayController::Init(sptr<AbstractScreenController> abstractScreenController){ WLOGFD("display controller init"); displayCount_ = 0; abstractScreenController_ = abstractScreenController; abstractScreenCallback_ = new(std::nothrow) AbstractScreenController::AbstractScreenCallback(); if (abstractScreenCallback_ == nullptr) { WLOGFE("abstractScreenCallback init failed"); return; } abstractScreenCallback_->onConnect_ = std::bind(&AbstractDisplayController::OnAbstractScreenConnect, this, std::placeholders::_1); abstractScreenCallback_->onDisconnect_ = std::bind(&AbstractDisplayController::OnAbstractScreenDisconnect, this, std::placeholders::_1); abstractScreenCallback_->onChange_ = std::bind(&AbstractDisplayController::OnAbstractScreenChange, this, std::placeholders::_1, std::placeholders::_2); abstractScreenController->RegisterAbstractScreenCallback(abstractScreenCallback_);}void AbstractScreenController::RegisterAbstractScreenCallback(sptr<AbstractScreenCallback> cb){ std::lock_guard<std::recursive_mutex> lock(mutex_); abstractScreenCallback_ = cb; for (auto& iter : dmsScreenMap_) { if (iter.second != nullptr && abstractScreenCallback_ != nullptr) { WLOGFI("dmsScreenId :%{ public}" PRIu64"", iter.first); abstractScreenCallback_->onConnect_(iter.second); } }}
第二种,当窗口子系统触发OnRsScreenConnectionChange回调时,会调用ProcessScreenConnected函数。如果abstractScreenCallback_回调函数注册则执行AbstractDisplayController::OnAbstractScreenConnect。
// foundation/window/window_manager/dmserver/src/abstract_screen_controller.cppvoid AbstractScreenController::OnRsScreenConnectionChange(ScreenId rsScreenId, ScreenEvent screenEvent){ WLOGFI("rs screen event. id:%{ public}, event:%{ public}u", rsScreenId, static_cast<uint32_t>(screenEvent)); if (screenEvent == ScreenEvent::CONNECTED) { auto task = [this, rsScreenId] { ProcessScreenConnected(rsScreenId); }; controllerHandler_->PostTask(task, AppExecFwk::EventQueue::Priority::HIGH); } ···}void AbstractScreenController::ProcessScreenConnected(ScreenId rsScreenId){ std::lock_guard<std::recursive_mutex> lock(mutex_); if (screenIdManager_.HasRsScreenId(rsScreenId)) { WLOGE("reconnect screen, screenId=%{ public}" PRIu64"", rsScreenId); return; } WLOGFD("connect new screen"); auto absScreen = InitAndGetScreen(rsScreenId); if (absScreen == nullptr) { return; } sptr<AbstractScreenGroup> screenGroup = AddToGroupLocked(absScreen); if (screenGroup == nullptr) { return; } ··· if (abstractScreenCallback_ != nullptr) { abstractScreenCallback_->onConnect_(absScreen); } ···}
如果OnAbstractScreenConnect在第二种情况执行,加载第一个屏幕时,则在group->GetChildCount() == 1时进入判断,执行BindAloneScreenLocked(absScreen);函数,系统正常运行。
如果OnAbstractScreenConnect在第一种情况执行,加载第一个屏幕时,会创建screenGroup。创建的group也会insert进dmsScreenMap_,此操作会导致异常Log中ScreenId为1的屏幕绑定异常。
// foundation/window/window_manager/dmserver/src/abstract_screen_controller.cppsptr<AbstractScreenGroup> AbstractScreenController::AddToGroupLocked(sptr<AbstractScreen> newScreen){ sptr<AbstractScreenGroup> res; if (dmsScreenGroupMap_.empty()) { WLOGI("connect the first screen"); // 第一块显示设备连接时进入 res = AddAsFirstScreenLocked(newScreen); } else { // 后续显示设备连接时进入 res = AddAsSuccedentScreenLocked(newScreen); } return res;}sptr<AbstractScreenGroup> AbstractScreenController::AddAsFirstScreenLocked(sptr<AbstractScreen> newScreen){ ScreenId dmsGroupScreenId = screenIdManager_.CreateAndGetNewScreenId(SCREEN_ID_INVALID); ··· dmsScreenGroupMap_.insert(std::make_pair(dmsGroupScreenId, screenGroup)); dmsScreenMap_.insert(std::make_pair(dmsGroupScreenId, screenGroup)); ···}
当第二块显示设备连接时,寻找第一块设备创建的group,并把自己添加进group中。
// foundation/window/window_manager/dmserver/src/abstract_screen_controller.cppsptr<AbstractScreenGroup> AbstractScreenController::AddAsSuccedentScreenLocked(sptr<AbstractScreen> newScreen){ ScreenId defaultScreenId = GetDefaultAbstractScreenId(); auto iter = dmsScreenMap_.find(defaultScreenId); if (iter == dmsScreenMap_.end()) { WLOGE("AddAsSuccedentScreenLocked. defaultScreenId:%{ public}" PRIu64" is not in dmsScreenMap_.", defaultScreenId); return nullptr; } auto screen = iter->second; auto screenGroupIter = dmsScreenGroupMap_.find(screen->groupDmsId_); if (screenGroupIter == dmsScreenGroupMap_.end()) { WLOGE("AddAsSuccedentScreenLocked. groupDmsId:%{ public}" PRIu64" is not in dmsScreenGroupMap_.", screen->groupDmsId_); return nullptr; } auto screenGroup = screenGroupIter->second; Point point; if (screenGroup->combination_ == ScreenCombination::SCREEN_EXPAND) { point = { screen->GetActiveScreenMode()->width_, 0}; } screenGroup->AddChild(newScreen, point); return screenGroup;}
当OnAbstractScreenConnect被执行时,获取到ScreenID为0的Group,此时Group内的屏幕数为2,所以无法进入BindAloneScreenLocked函数所在的判断,造成异常。
// foundation/window/window_manager/dmserver/src/abstract_display_controller.cppvoid AbstractDisplayController::OnAbstractScreenConnect(sptr<AbstractScreen> absScreen){ if (absScreen == nullptr) { WLOGFE("absScreen is null"); return; } WLOGI("connect new screen. id:%{ public}" PRIu64"", absScreen->dmsId_); std::lock_guard<std::recursive_mutex> lock(mutex_); sptr<AbstractScreenGroup> group = absScreen->GetGroup(); if (group == nullptr) { WLOGE("the group information of the screen is wrong"); return; } if (group->combination_ == ScreenCombination::SCREEN_ALONE || group->GetChildCount() == 1) { BindAloneScreenLocked(absScreen); } else if (group->combination_ == ScreenCombination::SCREEN_MIRROR) { WLOGI("OnAbstractScreenConnect, ScreenCombination::SCREEN_MIRROR, AddScreenToMirrorLocked"); AddScreenToMirrorLocked(absScreen); } else if (group->combination_ == ScreenCombination::SCREEN_EXPAND) { WLOGI("OnAbstractScreenConnect, ScreenCombination::SCREEN_EXPAND, AddScreenToExpandLocked"); AddScreenToExpandLocked(absScreen); } else { WLOGE("support in future. combination:%{ public}u", group->combination_); }}
想了解更多关于开源的内容,请访问:
51CTO 开源基础软件社区
https://ost.51cto.com
责任编辑:jianghua 来源: 51CTO 开源基础软件社区 开机Logo鸿蒙(责任编辑:百科)
ST步森(002569.SZ)公布消息:终止收购微动天下100%的股权
2020年全年CPI同比上涨2.5% 部分国际大宗商品价格持续攀升
强化私募姓“私” 引导行业回归本源 业内:严监管将推动行业高质量发展
皇朝家居(01198.HK)发布公告:年度归母净利同比下降89.2%
1台币等于多少人民币 一台币兑换多少人民币(2020年9月1日)
1台币等于多少人民币 一台币兑换多少人民币(2020年9月1日)