自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

OpenHarmony系統(tǒng)解決方案 - 配置屏幕方向?qū)е麻_機(jī)動(dòng)畫和Launcher顯示異常

系統(tǒng) OpenHarmony
配置設(shè)備默認(rèn)方向,例如修改為橫屏顯示,修改文件display_manager_config.xml的buildInDefaultOrientation參數(shù)值為2(Orientation::HORIZONTAL)。

想了解更多關(guān)于開源的內(nèi)容,請(qǐng)?jiān)L問(wèn):

51CTO 開源基礎(chǔ)軟件社區(qū)

https://ost.51cto.com

問(wèn)題描述

問(wèn)題環(huán)境

系統(tǒng)版本:OpenHarmony-3.2-Release

問(wèn)題現(xiàn)象

配置設(shè)備默認(rèn)方向,例如修改為橫屏顯示,修改文件display_manager_config.xml的buildInDefaultOrientation參數(shù)值為2(Orientation::HORIZONTAL)。

源碼中文件位于foundation/window/window_manager/resources/config/rk3568/display_manager_config.xml。

系統(tǒng)中文件位于/etc/window/resources/display_manager_config.xml。

系統(tǒng)啟動(dòng)后開機(jī)動(dòng)畫橫豎屏切換,Launcher顯示異常(偶現(xiàn),去掉鎖屏應(yīng)用和鎖屏服務(wù)后大概率出現(xiàn))。

異常效果:

OpenHarmony系統(tǒng)解決方案 - 配置屏幕方向?qū)е麻_機(jī)動(dòng)畫和Launcher顯示異常-開源基礎(chǔ)軟件社區(qū)OpenHarmony系統(tǒng)解決方案 - 配置屏幕方向?qū)е麻_機(jī)動(dòng)畫和Launcher顯示異常-開源基礎(chǔ)軟件社區(qū)

OpenHarmony系統(tǒng)解決方案 - 配置屏幕方向?qū)е麻_機(jī)動(dòng)畫和Launcher顯示異常-開源基礎(chǔ)軟件社區(qū)OpenHarmony系統(tǒng)解決方案 - 配置屏幕方向?qū)е麻_機(jī)動(dòng)畫和Launcher顯示異常-開源基礎(chǔ)軟件社區(qū)

正常效果:

OpenHarmony系統(tǒng)解決方案 - 配置屏幕方向?qū)е麻_機(jī)動(dòng)畫和Launcher顯示異常-開源基礎(chǔ)軟件社區(qū)OpenHarmony系統(tǒng)解決方案 - 配置屏幕方向?qū)е麻_機(jī)動(dòng)畫和Launcher顯示異常-開源基礎(chǔ)軟件社區(qū)

OpenHarmony系統(tǒng)解決方案 - 配置屏幕方向?qū)е麻_機(jī)動(dòng)畫和Launcher顯示異常-開源基礎(chǔ)軟件社區(qū)OpenHarmony系統(tǒng)解決方案 - 配置屏幕方向?qū)е麻_機(jī)動(dòng)畫和Launcher顯示異常-開源基礎(chǔ)軟件社區(qū)

問(wèn)題原因

  • ScreenRotationController初始化會(huì)設(shè)置rotationLockedRotation_屬性初始值,而ScreenRotationController初始化的觸發(fā)點(diǎn)在開機(jī)動(dòng)畫窗口銷毀時(shí),此時(shí)間點(diǎn)在Launcher的Window加載之后。
  • Launcher加載Window時(shí)會(huì)設(shè)置SetScreenRotation(屏幕旋轉(zhuǎn)角度),因?yàn)長(zhǎng)auncher的方向加載配置為AUTO_ROTATION_RESTRICTED(方向隨傳感器旋轉(zhuǎn)),所以SetScreenRotation會(huì)根據(jù)rotationLockedRotation_屬性值設(shè)置旋轉(zhuǎn)角度,而此時(shí)rotationLockedRotation_屬性并未被設(shè)置初始值,所以SetScreenRotation設(shè)置的值取得是默認(rèn)值0(如果配置為Orientation::HORIZONTAL,則應(yīng)旋轉(zhuǎn)90度,取值為1),導(dǎo)致問(wèn)題的產(chǎn)生。

解決方案

調(diào)整ScreenRotationController初始化時(shí)序,使ScreenRotationController在Launcher加載Window時(shí)觸發(fā)。修改源碼文件:foundation/window/window_manager/wmserver/src/window_node_container.cpp

WindowNodeContainer::RemoveWindowNode函數(shù)中,移除以下代碼:

if (node->GetWindowType() == WindowType::WINDOW_TYPE_BOOT_ANIMATION) {
    DisplayManagerServiceInner::GetInstance().SetGravitySensorSubscriptionEnabled();
}

修改后WindowNodeContainer::RemoveWindowNode函數(shù)代碼:

// 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;
}

WindowNodeContainer::AddWindowNode函數(shù)中,在WLOGFD("AddWindowNode windowId: %{public}u end", node->GetWindowId());行代碼前添加以下代碼:

if (node->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) {
    DisplayManagerServiceInner::GetInstance().SetGravitySensorSubscriptionEnabled();
}

修改后WindowNodeContainer::AddWindowNode函數(shù)代碼:

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;
}

定位過(guò)程

落盤異常開機(jī)日志,查找SetRotation相關(guān)日志,發(fā)現(xiàn)系統(tǒng)啟動(dòng)過(guò)程中橫豎屏被設(shè)置兩次。

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

查找對(duì)應(yīng)源碼發(fā)現(xiàn)rotation代表含義。在系統(tǒng)啟動(dòng)時(shí)已成功設(shè)置旋轉(zhuǎn)90度(水平),但又被設(shè)置為旋轉(zhuǎn)0度(垂直),導(dǎo)致異常。

// foundation/window/window_manager/interfaces/innerkits/dm/dm_common.h
enum class Rotation : uint32_t {
    ROTATION_0,          // 不旋轉(zhuǎn),垂直
    ROTATION_90,        // 旋轉(zhuǎn)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);
    ···
}

追蹤設(shè)置旋轉(zhuǎn)0度(垂直)操作日志。發(fā)現(xiàn)set orientation時(shí),orientation被設(shè)置為8,對(duì)應(yīng)源碼含義為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,
};

Launcher在創(chuàng)建window時(shí)會(huì)把PreferredOrientation設(shè)置為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)}`);
    });
}

當(dāng)Launcher顯示窗口時(shí)執(zhí)行SetOrientation,isFromWindow參數(shù)為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); // 執(zhí)行方向選擇
    } 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;
}

因orientation為AUTO_ROTATION_RESTRICTED,會(huì)執(zhí)行ProcessSwitchToSensorRelatedOrientation函數(shù)。

// 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;
}

當(dāng)rotationLockedRotation_與GetCurrentDisplayRotation()不一致時(shí)會(huì)切換旋轉(zhuǎn)角度。在此處增加日志打印rotationLockedRotation_和GetCurrentDisplayRotation()的值,發(fā)現(xiàn)在開機(jī)觸發(fā)Launcher設(shè)置屏幕旋轉(zhuǎn)角度時(shí)GetCurrentDisplayRotation()函數(shù)獲取的當(dāng)前屏幕旋轉(zhuǎn)角度為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);
}

查看rotationLockedRotation_被設(shè)置的場(chǎng)景。分別增加日志,發(fā)現(xiàn)開機(jī)啟動(dòng)時(shí)SetScreenRotationLocked函數(shù)不會(huì)被觸發(fā),而Init函數(shù)則是在Launcher啟動(dòng)后被觸發(fā),此時(shí)Launcher已經(jīng)把屏幕旋轉(zhuǎn)角度設(shè)置為0(垂直),rotationLockedRotation_的初始化值則會(huì)變成Launcher設(shè)置后的參數(shù)0(垂直)。而在Launcher觸發(fā)SetScreenRotation時(shí),rotationLockedRotation_還未被設(shè)置,此時(shí)取默認(rèn)值0(垂直),導(dǎo)致異常的產(chǎn)生。

// 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;
}

ScreenRotationController::Init()的觸發(fā)時(shí)機(jī)是在系統(tǒng)檢測(cè)到啟動(dòng)完成后,關(guān)閉開機(jī)動(dòng)畫窗口時(shí)觸發(fā)。如果此操作在Launcher加載Window之后,則會(huì)導(dǎo)致問(wèn)題。改變ScreenRotationController::Init()的初始化時(shí)序,在Launcher的window加載時(shí)初始化可以修復(fù)此問(wèn)題。

// 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();
    ···
}

知識(shí)分享

如果應(yīng)用的方向需要隨系統(tǒng)切換,可以在module.json5的ability中配置orientation為auto_rotation_restricted。

想了解更多關(guān)于開源的內(nèi)容,請(qǐng)?jiān)L問(wèn):

51CTO 開源基礎(chǔ)軟件社區(qū)

https://ost.51cto.com

責(zé)任編輯:jianghua 來(lái)源: 51CTO 開源基礎(chǔ)軟件社區(qū)
相關(guān)推薦

2023-07-10 16:06:50

鴻蒙檢測(cè)鎖屏應(yīng)用

2022-03-18 16:07:04

Graphic子系統(tǒng)鴻蒙

2022-10-12 15:14:08

開機(jī)動(dòng)畫鴻蒙

2023-07-27 14:42:16

開機(jī)Logo鴻蒙

2011-09-09 14:49:31

Windows7開機(jī)動(dòng)畫

2018-09-14 16:20:37

2017-06-01 11:17:57

Python異常重試解決方案

2016-03-13 18:06:47

2010-02-24 14:05:08

WCF openati

2020-09-04 13:50:35

前端異常監(jiān)控代碼

2018-04-10 15:44:31

Gradle依賴關(guān)系異常

2016-03-13 17:35:18

2022-08-08 12:47:26

云服務(wù)商解決方案電信產(chǎn)業(yè)

2010-02-26 15:46:48

Silverlight

2009-11-06 15:25:25

WCF異常

2009-06-17 11:47:21

Hibernate 刪

2011-12-09 11:13:17

2010-05-31 12:38:48

Nagios中文

2009-12-23 21:06:47

統(tǒng)一通信多媒體聯(lián)絡(luò)中心平臺(tái)華為

2013-05-14 15:47:27

MySQL監(jiān)控錯(cuò)誤日志
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)