赞
踩
系统版本:OpenHarmony-3.2-Release
1. 配置设备默认方向,例如修改为横屏显示,修改文件display_manager_config.xml的buildInDefaultOrientation参数值为2(Orientation::HORIZONTAL)。
源码中文件位于foundation/window/window_manager/resources/config/rk3568/display_manager_config.xml。
系统中文件位于/etc/window/resources/display_manager_config.xml。
2. 系统启动后开机动画横竖屏切换,Launcher显示异常(偶现,去掉锁屏应用和锁屏服务后大概率出现)。
调整ScreenRotationController初始化时序,使ScreenRotationController在Launcher加载Window时触发。修改源码文件:foundation/window/window_manager/wmserver/src/window_node_container.cpp
1. WindowNodeContainer::RemoveWindowNode函数中,移除以下代码:
- if (node->GetWindowType() == WindowType::WINDOW_TYPE_BOOT_ANIMATION) {
- DisplayManagerServiceInner::GetInstance().SetGravitySensorSubscriptionEnabled();
- }
修改后WindowNodeContainer::RemoveWindowNode函数代码:
- // foundation/window/window_manager/wmserver/src/window_node_container.cpp
- WMError WindowNodeContainer::RemoveWindowNode(sptr<WindowNode>& node, bool fromAnimation)
- {
- ···
- NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_REMOVE);
- DumpScreenWindowTree();
- UpdateCameraFloatWindowStatus(node, false);
- if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) {
- isScreenLocked_ = false;
- SetBelowScreenlockVisible(node, true);
- }
- WLOGFD("RemoveWindowNode windowId: %{public}u end", node->GetWindowId());
- RSInterfaces::GetInstance().SetAppWindowNum(GetAppWindowNum());
- return WMError::WM_OK;
- }
2. WindowNodeContainer::AddWindowNode函数中,在WLOGFD("AddWindowNode windowId: %{public}u end", node->GetWindowId());行代码前添加以下代码:
- if (node->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) {
- DisplayManagerServiceInner::GetInstance().SetGravitySensorSubscriptionEnabled();
- }
修改后WindowNodeContainer::AddWindowNode函数代码:
- WMError WindowNodeContainer::AddWindowNode(sptr<WindowNode>& node, sptr<WindowNode>& parentNode, bool afterAnimation)
- {
- ···
- if (node->GetWindowType() == WindowType::WINDOW_TYPE_WALLPAPER) {
- RemoteAnimation::NotifyAnimationUpdateWallpaper(node);
- }
- if (node->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) {
- DisplayManagerServiceInner::GetInstance().SetGravitySensorSubscriptionEnabled();
- }
- WLOGFD("AddWindowNode windowId: %{public}u end", node->GetWindowId());
- RSInterfaces::GetInstance().SetAppWindowNum(GetAppWindowNum());
- return WMError::WM_OK;
- }
1. 落盘异常开机日志,查找SetRotation相关日志,发现系统启动过程中横竖屏被设置两次。
- 08-05 18:39:55.002 622 811 I C04201/AbstractScreenController: <722>SetRotation: Enter SetRotation, screenId: 0, rotation: 1, isFromWindow: 1
- 08-05 18:39:58.487 622 811 I C04201/AbstractScreenController: <722>SetRotation: Enter SetRotation, screenId: 0, rotation: 0, isFromWindow: 1
2. 查找对应源码发现rotation代表含义。在系统启动时已成功设置旋转90度(水平),但又被设置为旋转0度(垂直),导致异常。
- // foundation/window/window_manager/interfaces/innerkits/dm/dm_common.h
- enum class Rotation : uint32_t {
- ROTATION_0, // 不旋转,垂直
- ROTATION_90, // 旋转90度,水平
- ROTATION_180,
- ROTATION_270,
- };
- // foundation/window/window_manager/dmserver/src/abstract_screen_controller.cpp
- bool AbstractScreenController::SetRotation(ScreenId screenId, Rotation rotationAfter, bool isFromWindow)
- {
- WLOGFI("Enter SetRotation, screenId: %{public}" PRIu64 ", rotation: %{public}u, isFromWindow: %{public}u",
- screenId, rotationAfter, isFromWindow);
- ···
- }
3. 追踪设置旋转0度(垂直)操作日志。发现set orientation时,orientation被设置为8,对应源码含义为AUTO_ROTATION_RESTRICTED。
- 08-05 18:39:58.487 622 811 D C04201/AbstractScreenController: <627>set orientation. screen 0 orientation 8
- 08-05 18:39:58.487 622 811 D C04201/AbstractScreenController: <144>GetAbstractScreen: screenId: 0
- 08-05 18:39:58.487 622 811 D C04201/AbstractScreenController: <177>GetDefaultAbstractScreenId: GetDefaultAbstractScreenId, screen:0
- 08-05 18:39:58.487 622 811 D C04201/DisplayManagerService: <190>GetDefaultDisplayInfo: GetDefaultDisplayInfo 0
- 08-05 18:39:58.487 622 811 D C04201/AbstractScreenController: <177>GetDefaultAbstractScreenId: GetDefaultAbstractScreenId, screen:0
- 08-05 18:39:58.487 622 811 D C04201/DisplayManagerService: <190>GetDefaultDisplayInfo: GetDefaultDisplayInfo 0
- 08-05 18:39:58.487 622 811 I C04201/AbstractScreenController: <722>SetRotation: Enter SetRotation, screenId: 0, rotation: 0, isFromWindow: 1
- // foundation/window/window_manager/dmserver/src/abstract_screen_controller.cpp
- bool AbstractScreenController::SetOrientation(ScreenId screenId, Orientation newOrientation, bool isFromWindow)
- {
- WLOGD("set orientation. screen %{public}" PRIu64" orientation %{public}u", screenId, newOrientation);
- ···
- }
- // foundation/window/window_manager/interfaces/innerkits/dm/dm_common.h
- enum class Orientation : uint32_t {
- BEGIN = 0,
- UNSPECIFIED = BEGIN,
- VERTICAL = 1,
- HORIZONTAL = 2,
- REVERSE_VERTICAL = 3,
- REVERSE_HORIZONTAL = 4,
- SENSOR = 5,
- SENSOR_VERTICAL = 6,
- SENSOR_HORIZONTAL = 7,
- AUTO_ROTATION_RESTRICTED = 8,
- AUTO_ROTATION_PORTRAIT_RESTRICTED = 9,
- AUTO_ROTATION_LANDSCAPE_RESTRICTED = 10,
- LOCKED = 11,
- END = LOCKED,
- };
4. Launcher在创建window时会把PreferredOrientation设置为Window.Orientation.AUTO_ROTATION_RESTRICTED。
- // common/src/main/ets/default/manager/WindowManager.ts
- createWindow(context: ServiceExtensionContext, name: string, windowType: number, loadContent: string,
- isShow: boolean, callback?: Function) {
- Window.create(context, name, windowType).then((win) => {
- void win.setPreferredOrientation(Window.Orientation.AUTO_ROTATION_RESTRICTED);
- ···
- }, (error) => {
- Log.showError(TAG, `createWindow, create error: ${JSON.stringify(error)}`);
- });
- }
5. 当Launcher显示窗口时执行SetOrientation,isFromWindow参数为true。
- // foundation/window/window_manager/dmserver/src/abstract_screen_controller.cpp
- bool AbstractScreenController::SetOrientation(ScreenId screenId, Orientation newOrientation, bool isFromWindow)
- {
- WLOGD("set orientation. screen %{public}" PRIu64" orientation %{public}u", screenId, newOrientation);
- auto screen = GetAbstractScreen(screenId);
- ···
- if (isFromWindow) {
- ScreenRotationController::ProcessOrientationSwitch(newOrientation); // 执行方向选择
- } else {
- Rotation rotationAfter = screen->CalcRotation(newOrientation);
- SetRotation(screenId, rotationAfter, false);
- screen->rotation_ = rotationAfter;
- }
- if (!screen->SetOrientation(newOrientation)) {
- WLOGE("fail to set rotation, screen %{public}" PRIu64"", screenId);
- return false;
- }
- ···
- return true;
- }
6. 因orientation为AUTO_ROTATION_RESTRICTED,会执行ProcessSwitchToSensorRelatedOrientation函数。
- // foundation/window/window_manager/dmserver/src/screen_rotation_controller.cpp
- void ScreenRotationController::ProcessOrientationSwitch(Orientation orientation)
- {
- if (!IsSensorRelatedOrientation(orientation)) {
- ProcessSwitchToSensorUnrelatedOrientation(orientation);
- } else {
- ProcessSwitchToSensorRelatedOrientation(orientation, lastSensorRotationConverted_);
- }
- }
- bool ScreenRotationController::IsSensorRelatedOrientation(Orientation orientation)
- {
- if ((orientation >= Orientation::UNSPECIFIED && orientation <= Orientation::REVERSE_HORIZONTAL) ||
- orientation == Orientation::LOCKED) {
- return false;
- }
- // AUTO_ROTATION_RESTRICTED 返回 true
- return true;
- }
7. 当rotationLockedRotation_与GetCurrentDisplayRotation()不一致时会切换旋转角度。在此处增加日志打印rotationLockedRotation_和GetCurrentDisplayRotation()的值,发现在开机触发Launcher设置屏幕旋转角度时GetCurrentDisplayRotation()函数获取的当前屏幕旋转角度为1(水平)是正确的。而rotationLockedRotation_为0(垂直)。
- // foundation/window/window_manager/dmserver/src/screen_rotation_controller.cpp
- void ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(
- Orientation orientation, DeviceRotation sensorRotationConverted){
- lastOrientationType_ = orientation;
- switch (orientation) {
- case Orientation::AUTO_ROTATION_RESTRICTED: {
- if (isScreenRotationLocked_) {
- SetScreenRotation(rotationLockedRotation_);
- return;
- }
- [[fallthrough]];
- }
- ···
- }
- }
- void ScreenRotationController::SetScreenRotation(Rotation targetRotation){
- if (targetRotation == GetCurrentDisplayRotation()) {
- return;
- }
- DisplayManagerServiceInner::GetInstance().GetDefaultDisplay()->SetRotation(targetRotation);
- DisplayManagerServiceInner::GetInstance().SetRotationFromWindow(defaultDisplayId_, targetRotation);
- WLOGFI("dms: Set screen rotation: %{public}u", targetRotation);
- }
8. 查看rotationLockedRotation_被设置的场景。分别增加日志,发现开机启动时SetScreenRotationLocked函数不会被触发,而Init函数则是在Launcher启动后被触发,此时Launcher已经把屏幕旋转角度设置为0(垂直),rotationLockedRotation_的初始化值则会变成Launcher设置后的参数0(垂直)。而在Launcher触发SetScreenRotation时,rotationLockedRotation_还未被设置,此时取默认值0(垂直),导致异常的产生。
- // foundation/window/window_manager/dmserver/src/screen_rotation_controller.cpp
- void ScreenRotationController::Init()
- {
- ProcessRotationMapping();
- currentDisplayRotation_ = GetCurrentDisplayRotation();
- lastSensorDecidedRotation_ = currentDisplayRotation_;
- rotationLockedRotation_ = currentDisplayRotation_;
- }
- void ScreenRotationController::SetScreenRotationLocked(bool isLocked)
- {
- if (isLocked) {
- rotationLockedRotation_ = GetCurrentDisplayRotation();
- }
- isScreenRotationLocked_ = isLocked;
- }
9. ScreenRotationController::Init()的触发时机是在系统检测到启动完成后,关闭开机动画窗口时触发。如果此操作在Launcher加载Window之后,则会导致问题。改变ScreenRotationController::Init()的初始化时序,在Launcher的window加载时初始化可以修复此问题。
- // foundation/window/window_manager/wmserver/src/window_node_container.cpp
- WMError WindowNodeContainer::RemoveWindowNode(sptr<WindowNode>& node, bool fromAnimation)
- {
- ···
- if (node->GetWindowType() == WindowType::WINDOW_TYPE_BOOT_ANIMATION) {
- DisplayManagerServiceInner::GetInstance().SetGravitySensorSubscriptionEnabled();
- }
- ···
- return WMError::WM_OK;
- }
-
- // foundation/window/window_manager/dmserver/src/display_manager_service.cpp
- void DisplayManagerService::SetGravitySensorSubscriptionEnabled()
- {
- ···
- SensorConnector::SubscribeRotationSensor();
- }
-
- // foundation/window/window_manager/dmserver/src/sensor_connector.cpp
- void SensorConnector::SubscribeRotationSensor()
- {
- WLOGFI("dms: subscribe rotation-related sensor");
- ScreenRotationController::Init();
- ···
- }
如果应用的方向需要随系统切换,可以在module.json5的ability中配置orientation为auto_rotation_restricted。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。