OpenHarmony 窗口创建与管理分析

基于 foundation/window/window_manager/ 源码

目录

术语

缩写 全称 说明
WMS WindowManagerService 窗口管理服务(服务端核心)
WM WindowManager 窗口管理器(客户端 API)
WindowNode 服务端窗口节点,对应一个窗口实例
WindowNodeContainer 每显示器的窗口节点容器,管理 Z-order 树
Session SceneBoard 架构中的窗口会话,替代 WindowNode
SceneBoard OHOS 桌面窗口管理器(类似 Android Launcher 的窗口管理扩展)
StartingWindow 启动窗口(应用冷启动时的占位窗口)
AvoidArea 安全区域(状态栏、导航栏等占据的区域)
RS Render Service 渲染服务,窗口的渲染 surface 由其管理
ZOrder Z-Order 窗口在 Z 轴上的堆叠顺序
Ability OHOS 应用/功能的基本运行单元
SceneSession SceneBoard 管理的场景会话
HDI Hardware Display Interface 显示硬件抽象层

1. 概述

OpenHarmony 的窗口管理子系统(foundation/window/window_manager/)是系统 UI 的核心基础设施,负责所有窗口的创建、销毁、布局、Z-Order 管理、焦点分发、输入事件路由以及安全区域计算。

整体架构一句话: 应用进程通过 libwm(客户端 SDK)向 WindowManagerService(服务端)请求窗口创建/管理,服务端维护以 WindowNode(经典架构)或 Session(SceneBoard 架构)为节点的窗口树,通过 Z-Order 策略和布局策略控制窗口在屏幕上的呈现。

窗口分类:

分类 类型范围 典型窗口 创建方
应用主窗口 WINDOW_TYPE_APP_MAIN_WINDOW 应用主界面 应用 Ability
应用子窗口 WINDOW_TYPE_APP_SUB_WINDOW 弹窗、浮层 应用
系统窗口(应用层以下) WINDOW_TYPE_WALLPAPER / DESKTOP 壁纸、桌面 系统
系统窗口(应用层以上) STATUS_BAR / NAV_BAR / KEYGUARD / FLOAT / PIP / DIALOG / TOAST / LAUNCHER / SCENE_BOARD 等 状态栏、导航栏、锁屏、悬浮窗、画中画、对话框 系统
系统子窗口 SYSTEM_SUB_WINDOW / SCB_SUB_WINDOW 系统场景子窗口 系统
UIExtension WINDOW_TYPE_UI_EXTENSION 安全浮层(如密码输入框) 应用/系统

核心能力一览:

能力 实现组件 说明
窗口创建/销毁 WindowImpl::Create / WindowRoot::Destroy 客户端请求 → 服务端创建节点
Z-Order 管理 WindowZorderPolicy 根据窗口类型和优先级分配 Z 轴顺序
布局策略 WindowLayoutPolicy (Cascade / Tile) 窗口尺寸、位置、分屏管理
焦点管理 WindowNodeContainer::SetFocusWindow 输入焦点切换
安全区域 AvoidAreaController 计算系统栏、凹口等区域
启动窗口 StartingWindow 冷启动/热启动占位界面
窗口动画 RemoteAnimation 窗口切换动画
渲染绑定 RSSurfaceNode 每个窗口绑定一个 RS 渲染节点

2. 目录结构

foundation/window/window_manager/
├── wm/                                ← 客户端 SDK(libwm,供应用使用)
│   ├── include/
│   │   ├── window.h / window_impl.h   ← 窗口接口 / 实现(旧架构)
│   │   ├── window_session_impl.h      ← Session 架构窗口实现
│   │   ├── window_manager.h           ← 窗口管理器客户端 API
│   │   ├── window_option.h            ← 窗口创建参数
│   │   ├── window_adapter.h           ← IPC 桥接(连接 WMS)
│   │   ├── window_agent.h             ← 窗口代理(服务端回调窗口)
│   │   ├── window_scene.h             ← 场景窗口
│   │   ├── root_scene.h               ← 根场景
│   │   └── zidl/                      ← IPC 接口定义
│   └── src/
│       ├── window_impl.cpp            ← 窗口创建/销毁/属性管理
│       ├── window_session_impl.cpp    ← Session 架构窗口实现
│       ├── window_manager.cpp         ← WindowManager 单例实现
│       ├── window_adapter.cpp         ← IPC 调用 WMS 服务
│       ├── window_option.cpp          ← 窗口选项
│       └── ...
├── wmserver/                          ← 服务端 SDK(libsms)
│   ├── include/
│   │   ├── window_manager_service.h   ← WMS 主服务
│   │   ├── window_controller.h        ← 窗口操作控制器
│   │   ├── window_root.h              ← 窗口根(管理每显示器的窗口树)
│   │   ├── window_node.h              ← 服务端窗口节点
│   │   ├── window_node_container.h    ← 窗口节点容器(每显示器)
│   │   ├── window_layout_policy.h     ← 窗口布局策略
│   │   ├── window_zorder_policy.h     ← Z-Order 分配策略
│   │   ├── avoid_area_controller.h    ← 安全区域控制
│   │   ├── starting_window.h          ← 启动窗口
│   │   └── zidl/                      ← IPC 接口定义
│   └── src/
│       ├── window_manager_service.cpp ← 服务入口
│       ├── window_controller.cpp      ← 创建/销毁窗口
│       ├── window_root.cpp            ← 窗口树管理
│       ├── window_layout_policy.cpp   ← 布局算法
│       └── ...
├── window_scene/                      ← SceneBoard 会话管理
│   ├── session/                       ← Session 核心实现
│   │   ├── host/
│   │   │   ├── session.h/cpp         ← Session 基类
│   │   │   ├── scene_session.h/cpp   ← 场景会话
│   │   │   ├── main_session.h/cpp    ← 主窗口会话
│   │   │   ├── sub_session.h/cpp     ← 子窗口会话
│   │   │   ├── system_session.h/cpp  ← 系统窗口会话
│   │   │   ├── keyboard_session.h/cpp ← 键盘会话
│   │   │   └── root_scene_session.h/cpp ← 根场景会话
│   │   └── container/
│   │       └── window_event_channel.h/cpp ← 窗口事件通道
│   ├── session_manager/               ← 会话管理器
│   ├── session_manager_service/       ← 会话管理器服务
│   ├── screen_session_manager/        ← 屏幕会话管理
│   └── screen_session_manager_client/ ← 屏幕会话客户端
├── extension/                         ← UIExtension 窗口扩展
├── interfaces/                        ← 对外接口定义
│   ├── innerkits/wm/                  ← C++ SDK 接口头文件
│   └── kits/                          ← JS/N-API 接口
├── dm/ / dm_lite/                     ← 显示管理器
└── test/ / previewer/                 ← 测试/预览器

3. 两代架构

OHOS 窗口管理经历了从经典 WMS 到 Scene Session 两代架构演变。

3.1 经典 WMS 架构

经典架构是 OHOS 3.x / 4.x 的主要窗口管理方式:

应用进程 (Client)                     render_service 进程
    │                                       │
    ├── WindowImpl                          │
    │   ├── WindowOption (创建参数)          │
    │   ├── WindowProperty (窗口属性)        │
    │   ├── RSSurfaceNode (渲染 Surface)    │
    │   └── WindowAgent (代理回调)           │
    │                                       │
    └── WindowAdapter ── IPC ──→ WindowManagerService
                                     │
                                     ├── WindowController
                                     │   └── 生成 windowId
                                     │   └── 创建 WindowNode
                                     │
                                     ├── WindowRoot
                                     │   └── WindowNodeContainer
                                     │       ├── WindowNode 树
                                     │       ├── ZOrder 排序
                                     │       └── 布局策略
                                     │
                                     └── 通知 WindowManagerAgent
                                          → 上报焦点/可见性/布局变化

核心组件

组件 所在位置 职责
WindowImpl wm/ 客户端窗口对象,管理属性、事件、生命周期
WindowOption wm/ 窗口创建参数(类型、模式、矩形、标志等)
WindowAgent wm/ 窗口代理对象,作为 IPC 回调的接收端
WindowAdapter wm/ 桥接类,封装对 WMS 的 IPC 调用
WindowManagerService wmserver/ 服务端主入口,序列化所有窗口操作
WindowController wmserver/ 窗口操作控制器,协调 WindowRoot 和输入
WindowRoot wmserver/ 窗口树根,管理每显示器的 WindowNodeContainer
WindowNodeContainer wmserver/ 按显示器的窗口容器,维护窗口节点树 + Z-Order
WindowNode wmserver/ 服务端窗口节点,持有属性、Surface、回调

3.2 Scene Session 架构

Scene Session 架构从 OHOS 5.x 开始引入,与 SceneBoard 桌面环境配合使用:

应用进程                              SceneBoard 进程 (桌面)
    │                                       │
    ├── WindowSessionImpl                    │
    │   ├── 通过 ISession 连接 SceneBoard    │
    │   └── WindowEventChannel (事件通道)     │
    │                                       │
    └── IPC ──→ SceneSessionManager
                     │
                     ├── SessionManagerService
                     │
                     └── Session 树
                         ├── RootSceneSession
                         ├── MainSession (应用主窗口)
                         ├── SubSession (应用子窗口)
                         ├── SystemSession (系统窗口)
                         └── KeyboardSession (键盘)

Session 继承体系:

Session (基类)
├── SceneSession
│   ├── MainSession          — 应用主窗口
│   ├── SubSession           — 应用子窗口
│   ├── SystemSession        — 系统窗口
│   ├── KeyboardSession      — 键盘面板
│   └── RootSceneSession     — 根场景
└── ScbSystemSession         — SceneBoard 系统窗口

3.3 两代架构关系

维度 经典 WMS Scene Session
服务端表示 WindowNode Session / SceneSession
客户端实现 WindowImpl WindowSessionImpl
服务入口 WindowManagerService SessionManagerService
树容器 WindowNodeContainer Session 管理树
IPC 通道 WindowAdapter → IWindowManager ISession → SessionStage
桌面环境 传统桌面/无桌面 SceneBoard 桌面
事件通道 InputTransferStation WindowEventChannel
布局策略 WindowLayoutPolicy LayoutController
启动窗口 StartingWindow(独立的窗口节点) Starting window 集成在 Session 中
兼容性 所有窗口类型 主要配合 SceneBoard 使用

两套架构并非替代关系,而是共存——WindowImplWindowSessionImpl 都实现了 Window 接口,通过 WindowOptionSetWindowSessionType() 来区分走哪条路径。

4. 窗口类型体系

窗口类型由 WindowType 枚举定义(interfaces/innerkits/wm/wm_common.h),按数值范围分层:

// wm_common.h:116
enum class WindowType : uint32_t {
    APP_WINDOW_BASE = 1,
    APP_MAIN_WINDOW_BASE = APP_WINDOW_BASE,
    WINDOW_TYPE_APP_MAIN_WINDOW = APP_MAIN_WINDOW_BASE,  // 1
    APP_MAIN_WINDOW_END,

    APP_SUB_WINDOW_BASE = 1000,
    WINDOW_TYPE_MEDIA = APP_SUB_WINDOW_BASE,              // 1000
    WINDOW_TYPE_APP_SUB_WINDOW,                            // 1001
    WINDOW_TYPE_APP_COMPONENT,                             // 1002
    APP_SUB_WINDOW_END,
    APP_WINDOW_END = APP_SUB_WINDOW_END,

    SYSTEM_WINDOW_BASE = 2000,
    // BELOW_APP 层 - 应用窗口之下
    WINDOW_TYPE_WALLPAPER = SYSTEM_WINDOW_BASE,           // 2000
    WINDOW_TYPE_DESKTOP,                                   // 2001
    BELOW_APP_SYSTEM_WINDOW_END,

    // ABOVE_APP 层 - 应用窗口之上
    ABOVE_APP_SYSTEM_WINDOW_BASE = 2100,
    WINDOW_TYPE_APP_LAUNCHING,                             // 2100
    WINDOW_TYPE_DOCK_SLICE,                                // 2101
    WINDOW_TYPE_INCOMING_CALL,                             // 2102
    WINDOW_TYPE_SEARCHING_BAR,                             // 2103
    WINDOW_TYPE_SYSTEM_ALARM_WINDOW,                       // 2104
    WINDOW_TYPE_INPUT_METHOD_FLOAT,                        // 2105
    WINDOW_TYPE_FLOAT,                                     // 2106
    WINDOW_TYPE_TOAST,                                     // 2107
    WINDOW_TYPE_STATUS_BAR,                                // 2108
    WINDOW_TYPE_PANEL,                                     // 2109
    WINDOW_TYPE_KEYGUARD,                                  // 2110
    WINDOW_TYPE_VOLUME_OVERLAY,                            // 2111
    WINDOW_TYPE_NAVIGATION_BAR,                            // 2112
    WINDOW_TYPE_LAUNCHER_RECENT,                           // 2115
    WINDOW_TYPE_SCENE_BOARD,                               // 2122
    WINDOW_TYPE_PIP,                                       // 2118
    WINDOW_TYPE_KEYBOARD_PANEL,                            // 2124
    // ... 更多类型 ...
    ABOVE_APP_SYSTEM_WINDOW_END,

    SYSTEM_SUB_WINDOW_BASE = 2500,
    WINDOW_TYPE_SYSTEM_SUB_WINDOW,                         // 2500
    WINDOW_TYPE_SCB_SUB_WINDOW,                            // 2501
    SYSTEM_SUB_WINDOW_END,
    SYSTEM_WINDOW_END = SYSTEM_SUB_WINDOW_END,

    WINDOW_TYPE_UI_EXTENSION = 3000                       // 3000
};

分层示意图:

Z 轴(从下到上)
  │
  ├── UI_EXTENSION (3000)         安全浮层(密码输入等)
  │
  ├── SYSTEM_SUB_WINDOW (2500)    SceneBoard 子窗口
  │
  ├── ABOVE_APP 系统窗口 (2100+)
  │   ├── SCENE_BOARD (2122)      SceneBoard 桌面
  │   ├── LAUNCHER_RECENT (2115)  最近任务
  │   ├── NAVIGATION_BAR (2112)   导航栏
  │   ├── STATUS_BAR (2108)       状态栏
  │   ├── KEYGUARD (2110)         锁屏
  │   ├── VOLUME_OVERLAY (2111)   音量面板
  │   ├── FLOAT (2106)            悬浮窗
  │   ├── TOAST (2107)            Toast 提示
  │   ├── SYSTEM_ALARM (2104)     系统闹钟
  │   ├── INCOMING_CALL (2102)    来电
  │   ├── DOCK_SLICE (2101)       Dock 栏
  │   └── APP_LAUNCHING (2100)    应用启动屏
  │
  ├── 应用窗口 (1 / 1000+)
  │   ├── APP_SUB_WINDOW (1001)   子窗口(对话框等)
  │   ├── APP_COMPONENT (1002)    组件窗口
  │   ├── MEDIA (1000)            媒体窗口
  │   └── APP_MAIN_WINDOW (1)     应用主窗口
  │
  └── BELOW_APP (2000+)
      ├── DESKTOP (2001)          桌面
      └── WALLPAPER (2000)        壁纸

窗口层次规则

位置 Z-order 范围 说明
BELOW_APP 最低 在应用窗口之下(壁纸/桌面)
应用窗口 中间 APP_MAIN / APP_SUB / MEDIA / COMPONENT
ABOVE_APP 较高 系统 UI 元素(状态栏/导航栏/悬浮窗等)
SYSTEM_SUB 接近最高 SceneBoard 系统子窗口
UI_EXTENSION 最高 安全上下文窗口,独立层次

5. 应用窗口创建流程

5.1 客户端:WindowImpl::Create

应用通过 Window::Create() 创建窗口时,最终进入 WindowImpl::Create()wm/src/window_impl.cpp:1541):

// window_impl.cpp:1541
WMError WindowImpl::Create(uint32_t parentId,
    const std::shared_ptr<AbilityRuntime::Context>& context)
{
    // 1. 参数校验
    WMError ret = WindowCreateCheck(parentId);
    if (ret != WMError::WM_OK) return ret;

    // 2. 初始化显示和上下文
    SetDefaultDisplayIdIfNeed();
    context_ = context;

    // 3. 创建窗口代理(服务端回调用)
    sptr<IWindow> windowAgent(new WindowAgent(window));

    // 4. 获取 Ability token(用于关联启动窗口)
    sptr<IRemoteObject> token = context_ ? context_->GetToken() : nullptr;

    // 5. 调整属性(根据 API 版本、窗口类型)
    ChangePropertyByApiVersion();
    InitAbilityInfo();
    SetSystemConfig();

    // 6. 通过 WindowAdapter 发起 IPC 创建请求
    ret = SingletonContainer::Get<WindowAdapter>()
        .CreateWindow(windowAgent, property_, surfaceNode_, windowId, token);

    // 7. 注册窗口到全局映射表
    {
        std::unique_lock<std::shared_mutex> lock(windowMapMutex_);
        windowMap_.insert({name_, {windowId, self}});
    }
    // 子窗口关联到父窗口
    if (parentId != INVALID_WINDOW_ID) {
        subWindowMap_[property_->GetParentId()].push_back(window);
    }

    // 8. 注册输入通道
    InputTransferStation::GetInstance().AddInputWindow(self);

    state_ = WindowState::STATE_CREATED;
    return ret;
}

创建流程分步说明:

步骤 操作 关键代码
1 检查窗口创建合法性(父窗口是否存在、类型是否合法) WindowCreateCheck(parentId)
2 设置默认 DisplayId、绑定上下文 SetDefaultDisplayIdIfNeed()
3 创建 WindowAgent(IPC 回调代理) new WindowAgent(window)
4 获取 Ability token context_->GetToken()
5 调整属性(API 版本兼容、类型默认值) ChangePropertyByApiVersion()
6 核心:通过 IPC 请求服务端创建窗口 WindowAdapter::CreateWindow()
7 注册到本地窗口映射表 windowMap_.insert()
8 注册输入事件通道 AddInputWindow()

5.2 IPC 桥接:WindowAdapter

WindowAdapter 是客户端与服务端之间的 IPC 桥接层。CreateWindow() 将创建参数序列化后通过 Binder 发送到 WMS:

// WindowAdapter 封装了对 IWindowManager 的 IPC 调用
class WindowAdapter : public RefBase {
    WMError CreateWindow(sptr<IWindow>& window, sptr<WindowProperty>& property,
        std::shared_ptr<RSSurfaceNode> surfaceNode,
        uint32_t& windowId, const sptr<IRemoteObject>& token);
    // ...
};

IPC 接口定义在 zidl/ 目录:

  • IWindowManager — 客户端→服务端(创建/销毁/更新窗口)
  • IWindow — 服务端→客户端(通知窗口事件)
  • IWindowManagerAgent — 服务端→客户端(广播窗口状态变化)

5.3 服务端:WindowManagerService

服务端的 WindowManagerService::CreateWindow()wmserver/src/window_manager_service.cpp:958)在 WMS 线程中处理:

// window_manager_service.cpp:958
WMError WindowManagerService::CreateWindow(sptr<IWindow>& window,
    sptr<WindowProperty>& property,
    const std::shared_ptr<RSSurfaceNode>& surfaceNode,
    uint32_t& windowId, sptr<IRemoteObject> token)
{
    // 1. 安全检查(系统窗口权限)
    // 2. 设置调用者信息
    property->isSystemCalling_ = Permission::IsSystemCalling();
    // 3. 通过 PostSyncTask 投递到 WMS 主线程执行
    auto task = [this, pid, uid, &window, &property, &surfaceNode,
                  &windowId, &token]() {
        return windowController_->CreateWindow(window, property,
            surfaceNode, windowId, token, pid, uid);
    };
    WMError ret = PostSyncTask(task, "CreateWindow");
    // 4. 记录调用者 access token
    accessTokenIdMaps_.insert({windowId, IPCSkeleton::GetCallingTokenID()});
    return ret;
}

WindowController::CreateWindow()wmserver/src/window_controller.cpp)执行实际的创建逻辑:

// window_controller.cpp
WMError WindowController::CreateWindow(sptr<IWindow>& window,
    sptr<WindowProperty>& property,
    const std::shared_ptr<RSSurfaceNode>& surfaceNode,
    uint32_t& windowId, sptr<IRemoteObject> token,
    int32_t pid, int32_t uid)
{
    // 1. 生成窗口 ID
    windowId = GenWindowId();

    // 2. 创建 WindowNode(服务端窗口节点)
    sptr<WindowNode> node = new WindowNode(property, window, surfaceNode, pid, uid);

    // 3. 绑定屏幕和 DisplayId
    sptr<DisplayInfo> displayInfo = ...;
    node->SetDisplayId(displayInfo->GetId());

    // 4. 添加到窗口树
    WMError ret = windowRoot_->SaveWindow(node);
    if (ret != WMError::WM_OK) return ret;

    // 5. 注册死亡通知
    windowRoot_->AddDeathRecipient(node);

    // 6. 将节点插入窗口树
    return windowRoot_->AddWindowNode(parentId, node);
}

5.4 窗口节点树:WindowRoot

WindowRoot 管理每个屏幕的窗口节点容器 WindowNodeContainer

WindowRoot (单例)
├── 屏幕 0 (built-in)
│   └── WindowNodeContainer
│       ├── Below 层
│       │   ├── WindowNode (壁纸, type=2000)
│       │   └── WindowNode (桌面, type=2001)
│       ├── App 层
│       │   ├── WindowNode (应用 A, type=1)
│       │   ├── WindowNode (应用 A 子窗口, type=1001)
│       │   └── WindowNode (应用 B, type=1)
│       └── Above 层
│           ├── WindowNode (状态栏, type=2108)
│           ├── WindowNode (导航栏, type=2112)
│           ├── WindowNode (悬浮窗, type=2106)
│           └── WindowNode (Toast, type=2107)
│
└── 屏幕 1 (外接)
    └── WindowNodeContainer
        └── ...

WindowNode 结构:wmserver/include/window_node.h

属性 类型 说明
property_ sptr<WindowProperty> 窗口属性(类型/模式/矩形/透明度等)
windowToken_ sptr<IWindow> 窗口的 IPC 回调接口(服务端→客户端)
surfaceNode_ shared_ptr<RSSurfaceNode> RS 渲染节点(绑定到渲染管线)
children_ std::vector<sptr<WindowNode>> 子窗口列表
callingPid_/callingUid_ int32_t 调用者进程/用户 ID
displayId_ DisplayId 所属显示器

添加到窗口树的流程:

// WindowNodeContainer::AddWindowNode
// 1. 根据窗口类型确定父容器层(Below/App/Above)
// 2. 调用 AssignZOrder() 分配 Z-Order
//    → WindowZorderPolicy 基于窗口类型和优先级计算
// 3. 将节点插入对应层的链表
// 4. 触发布局重新计算(LayoutPolicy)
// 5. 通知窗口代理(IWindow::UpdateWindowRect)
// 6. 通知其他监听器(焦点、可见性、安全区域变化)

5.5 窗口与 Display 的关系

窗口通过 DisplayId 关联到物理显示器,这个关联贯穿客户端和服务端:

客户端侧的 Display 分配:

// window_impl.cpp:1529
void WindowImpl::SetDefaultDisplayIdIfNeed()
{
    auto displayId = property_->GetDisplayId();
    if (displayId == DISPLAY_ID_INVALID) {
        auto defaultDisplayId = SingletonContainer::IsDestroyed() ? DISPLAY_ID_INVALID :
            SingletonContainer::Get<DisplayManager>().GetDefaultDisplayId();
        property_->SetDisplayId(defaultDisplayId);
    }
}

服务端侧的 Display 分配:

// window_root.cpp:814
WMError WindowRoot::AddWindowNode(uint32_t parentId, sptr<WindowNode>& node, bool fromStartingWin)
{
    // 根据节点的 displayId 获取或创建对应显示器的容器
    auto container = GetOrCreateWindowNodeContainer(node->GetDisplayId());
    if (container == nullptr) {
        return WMError::WM_ERROR_INVALID_DISPLAY;
    }
    // ...
    return container->AddWindowNode(node, parentNode);
}

窗口与 Display 的一对多映射:

WindowRoot (全局单例)
├── displayId=0 (内置屏)
│   └── WindowNodeContainer
│       ├── WindowNode A (displayId=0)
│       ├── WindowNode B (displayId=0)
│       └── ...
│
├── displayId=1 (外接屏)
│   └── WindowNodeContainer
│       ├── WindowNode C (displayId=1)
│       └── ...
│
└── displayId=999 (折叠副屏)
    └── WindowNodeContainer
        └── ...

核心规则:

规则 说明
一个窗口只属于一个显示器 WindowProperty::displayId_ 标识
默认分配到主屏 SetDefaultDisplayIdIfNeed()DisplayManager::GetDefaultDisplayId()
创建时可指定 WindowOption::SetDisplayId(displayId)
跨屏展示 WindowNode::SetShowingDisplays() 记录窗口内容可见于哪些显示器(如折叠屏展开时可见于两个屏)
容器隔离 每个 WindowNodeContainer 独立管理 Z-Order、布局策略和焦点
焦点独立 每个显示器的 WindowNodeContainer 有独立的 SetFocusWindow()

DisplayId 的后续影响:

  • 渲染:RSSurfaceNode 的绘制输出路由到对应 Display 的合成队列
  • 输入:触摸/鼠标事件的坐标转换基于窗口所在的 Display 坐标系
  • 安全区域:AvoidAreaController 按 Display 计算状态栏/导航栏/挖孔区域
  • 帧率:HGM 按 Display 独立管理刷新率策略

6. 系统窗口创建与管理

6.1 系统窗口类型

系统窗口分为三个子层次,基值从 2000 开始:

层次 枚举范围 包含类型 典型位置
BELOW_APP 2000~2001 WALLPAPER, DESKTOP 应用窗口之下
ABOVE_APP 2100~2199 STATUS_BAR, NAVIGATION_BAR, KEYGUARD, FLOAT, TOAST, PANEL, DIALOG, SCENE_BOARD, PIP, SCREENSHOT, VOLUME_OVERLAY 等约 30 种 应用窗口之上
SYSTEM_SUB 2500~2501 SYSTEM_SUB_WINDOW, SCB_SUB_WINDOW 系统子窗口(最高层)

6.2 系统窗口创建

系统窗口的创建流程与应用窗口类似,关键区别:

- 应用窗口:由应用 Ability 通过 WindowManager::CreateWindow 创建
+ 系统窗口:由系统服务(SystemUI / System Ability)调用 WindowManager 接口创建

系统窗口的 WindowOption 配置:

// 系统窗口创建示例
sptr<WindowOption> option = new WindowOption();
option->SetWindowType(WindowType::WINDOW_TYPE_STATUS_BAR);
option->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN);
option->SetWindowRect({0, 0, screenWidth, statusBarHeight});
option->SetFocusable(false);
option->SetTouchable(true);
// ... 创建窗口

6.3 系统窗口权限控制

系统窗口有严格的权限检查(WindowManagerService::CreateWindow 中执行):

CreateWindow() 中:
  1. 如果是 SYSTEM_WINDOW 类型
  2. 检查调用者是否系统级进程(isSystemCalling_)
  3. 非系统进程尝试创建系统窗口 → 返回 WMError::WM_ERROR_INVALID_TYPE

这种检查确保普通应用无法随意创建系统级窗口,防止恶意覆盖系统 UI。

7. 窗口生命周期管理

7.1 状态机

每个 WindowNode 通过 WindowNodeStateMachine 管理生命周期状态:

                  创建
                    │
                    ▼
              ┌────────────┐
              │   CREATED  │
              └─────┬──────┘
                    │ Show
                    ▼
              ┌────────────┐
              │   SHOWN    │◄────── Show
              └─────┬──────┘
                    │ Hide
                    ▼
              ┌────────────┐
              │   HIDDEN   │──► Destroy ──► DESTROYED
              └────────────┘
状态 含义 触发操作
CREATED 窗口节点已创建,但未显示 CreateWindow()
SHOWN 窗口显示在屏幕上 Show() / NotifyWindowTransition()
HIDDEN 窗口被隐藏(仍在树中) Hide() / 后台化
DESTROYED 窗口被销毁 DestroyWindow()

7.2 焦点管理

焦点管理通过 WindowNodeContainer::SetFocusWindow() 实现:

// window_node_container.cpp
WMError WindowNodeContainer::SetFocusWindow(uint32_t windowId)
{
    // 1. 解焦当前焦点窗口
    sptr<WindowNode> curFocusedNode = ...;
    curFocusedNode->SetFocusFlag(false);

    // 2. 设置新焦点
    sptr<WindowNode> newFocusedNode = FindNode(windowId);
    newFocusedNode->SetFocusFlag(true);

    // 3. 广播焦点变化
    NotifyFocusChange(newFocusedNode, curFocusedNode);

    // 4. 更新输入通道焦点
    inputWindowMonitor_->UpdateFocus(windowId);
}

焦点分配规则:

规则 说明
仅 SHOWN 状态的窗口可获焦 隐藏/销毁窗口不能获取焦点
仅 focusable 的窗口可获焦 状态栏/导航栏通常不可焦点
应用窗口按点击顺序获焦 用户点击的窗口获取焦点
系统弹出窗口(Dialog/Float)可获焦 但有限制:需要对应权限
焦点切换触发回调 通过 IFocusChangedListener 通知客户端

7.3 Z-Order 管理

Z-Order 由 WindowZorderPolicy 管理,在每次添加窗口节点时重新分配:

// window_zorder_policy.cpp — 简化的分配逻辑
void WindowZorderPolicy::AssignZOrder(sptr<WindowNode>& node,
    sptr<WindowNodeContainer>& container)
{
    // 1. 确定窗口层次层(Below / App / Above)
    WindowLayer layer = GetWindowLayer(node->GetWindowType());

    // 2. 在层内按类型优先级计算 Z-order
    int zOrder = CalculateTypePriority(node->GetWindowType());

    // 3. 同类型窗口按创建顺序排列
    zOrder += container->GetWindowCountByType(node->GetWindowType());

    node->SetZOrder(zOrder);
}

Z-Order 分层优先级:

优先级顺序(从低到高) 窗口类型
1 (最低) WALLPAPER
2 DESKTOP
3~n 应用主窗口 + 子窗口
n+1 SCENE_BOARD
n+2 LAUNCHER_RECENT, SEARCHING_BAR
n+3 STATUS_BAR, PANEL
n+4 DOCK_SLICE, NAVIGATION_BAR
n+5 KEYGUARD, INCOMING_CALL, SYSTEM_ALARM
n+6 FLOAT, DIALOG, TOAST, PIP
n+7 SYSTEM_SUB_WINDOW, SCB_SUB_WINDOW
max UI_EXTENSION

7.4 布局策略

WindowLayoutPolicy 提供两种布局模式,用于管理分屏和悬浮窗口:

布局模式 策略类 说明
级联 (Cascade) WindowLayoutPolicyCascade 窗口层叠排列,可拖动/缩放
平铺 (Tile) WindowLayoutPolicyTile 窗口分屏/网格排列(Split Screen)

布局策略在每个显示器的 WindowNodeContainer 中生效,在窗口添加/删除/大小变化时触发重排。布局策略负责:

  • 计算窗口可用空间
  • 设置窗口显示位置和大小
  • 处理分屏切换(从 Tile 到 Cascade 或反之)
  • 管理悬浮窗口的默认位置

8. Scene Session 架构详解

8.1 Session 继承体系

Session 架构是 OHOS 5.x+ 引入的新一代窗口管理模型,与 SceneBoard 桌面环境深度集成:

Session (基类)                    ← `window_scene/session/host/include/session.h`
  ├── 属性:persistentId, sessionInfo, windowSessionProperty
  ├── 方法:Show(), Hide(), Disconnect(), ProcessBackEvent()
  ├── 回调:SessionStage(客户端窗口阶段)
  │
  ├── SceneSession                 ← `scene_session.h`
  │   ├── 场景窗口通用实现
  │   ├── 管理 RSSurfaceNode + WindowEventChannel
  │   │
  │   ├── MainSession              ← `main_session.h`
  │   │   ├── 应用主窗口(对应 APP_MAIN_WINDOW)
  │   │   ├── 管理布局控制器 LayoutController
  │   │   └── 处理分屏/悬浮/全屏模式切换
  │   │
  │   ├── SubSession               ← `sub_session.h`
  │   │   ├── 应用子窗口(对应 APP_SUB_WINDOW)
  │   │   └── 跟随父窗口生命周期
  │   │
  │   ├── SystemSession            ← `system_session.h`
  │   │   ├── 系统窗口(状态栏/导航栏/音量面板等)
  │   │   ├── 权限校验(只有系统进程可创建)
  │   │   └── 悬浮球窗口管理(Floating Ball)
  │   │
  │   ├── KeyboardSession          ← `keyboard_session.h`
  │   │   └── 输入法键盘面板
  │   │
  │   └── RootSceneSession         ← `root_scene_session.h`
  │       └── 根场景会话(SceneBoard 的顶层容器)
  │
  └── ScbSystemSession             ← `scb_system_session.h`
      └── SceneBoard 系统窗口(SystemUI 内部使用)

8.2 SceneBoard 窗口管理

SceneBoard 是一个系统级桌面进程(类似 Android Launcher + WindowManager 的部分能力),它通过 SessionManager 管理所有窗口:

SceneBoard 进程
    │
    ├── SceneSessionManager
    │   ├── 注册所有 Session
    │   ├── 管理 Session 生命周期
    │   └── 协调 Z-Order 和焦点
    │
    ├── SessionManagerService(IPC 服务)
    │   ├── 接收来自应用的 Session 请求
    │   └── 分发给 SceneSessionManager
    │
    └── ScreenSessionManager
        ├── 管理屏幕会话
        └── 处理多屏/折叠屏事件

8.3 窗口与 Session 的绑定

WindowSessionImpl 是客户端 Window 接口的 Session 架构实现。当 WindowSessionType 设置为 Session 模式时,窗口不是直接通过 WMS 创建,而是绑定到一个已有的 Session:

// window_session_impl.h:101
class WindowSessionImpl : public Window {
    WMError Create(const std::shared_ptr<AbilityRuntime::Context>& context,
        const sptr<Rosen::ISession>& iSession,  // 来自 SceneBoard 的 Session 接口
        const std::string& identityToken = "",
        bool isModuleAbilityHookEnd = false,
        bool isBlockSubwindow = false);
};

Session 创建的典型流程:

1. 应用启动(Ability 启动)
   → Ability Runner 请求 SceneBoard 创建 Session

2. SceneBoard 创建 MainSession
   → 分配 persistentId
   → 创建 RSSurfaceNode(渲染 surface)
   → 返回 ISession 接口给应用

3. 应用创建 WindowSessionImpl
   → 绑定 ISession → WindowEventChannel
   → 通过 Session 通信(非 WMS)

4. 窗口显示
   → 应用调用 Show()
   → SessionManager 通知 SceneBoard
   → SceneBoard 更新窗口布局和可见性

Session 架构的关键优势:

优势 说明
生命周期解耦 窗口的生命周期由 SceneBoard 统一管理,而非每个应用的 WMS 请求
灵活布局 SceneBoard 可以自由控制窗口位置/大小/动画,无需 WMS 参与
跨进程协作 Session 接口天然支持多进程交互
动画同步 窗口切换动画在 SceneBoard 侧协调,避免闪现
扩展性好 新窗口类型只需添加新的 Session 子类

9. 窗口与 VSync 信号的关系

VSync(垂直同步信号)是渲染的触发源,窗口通过 VsyncStation 实现逐窗口粒度的 VSync 订阅、帧率控制和生命周期管理。

9.1 VsyncStation:窗口级的 VSync 订阅器

每个窗口在创建时生成一个 VsyncStation 实例,绑定到窗口的 RSSurfaceNode

// window_impl.cpp:131(WindowImpl 构造函数)
WindowImpl::WindowImpl(const sptr<WindowOption>& option) {
    // ...
    surfaceNode_ = CreateSurfaceNode(property_->GetWindowName(), option->GetWindowType());
    if (surfaceNode_ != nullptr) {
        vsyncStation_ = std::make_shared<VsyncStation>(surfaceNode_->GetId());
        //                          ↑ 以渲染节点 ID 作为 VSync 订阅的唯一标识
    }
}

VsyncStation(定义在 utils/include/vsync_station.h)封装了 VSync 的完整生命周期:

class VsyncStation {
    void RequestVsync(const std::shared_ptr<VsyncCallback>& vsyncCallback);
    bool IsVsyncReceiverCreated();
    void RunOnceOnNextVsync(OnCallback&& callback);
    void RunOnceAfterNVsyncs(uint32_t delayVsyncCount, OnCallback&& callback);
    int64_t GetVSyncPeriod();
    std::optional<uint32_t> GetFps();
    void Destroy();  // 窗口销毁时调用
};

9.2 VSync 请求的全链路

窗口需要渲染下一帧
    │
    ├── WindowImpl::RequestVsync(callback)        ← Window 接口
    │   └── vsyncStation_->RequestVsync(callback)
    │
    ├── 或 SceneSession::RunOnNextVsync(callback) ← SceneBoard 接口
    │   └── vsyncStation_->RunOnceOnNextVsync(callback)
    │         ↓
    │   VsyncStation::RequestVsync()
    │       ↓
    │   GetOrCreateVsyncReceiver()      ← 懒创建,首次使用才初始化
    │       ↓
    │   RSInterfaces::CreateVSyncReceiver(
    │       name,                    ← "WM_" + pid(进程唯一标识)
    │       frameRateLinkerId,       ← 帧率链接器(逐窗口帧率控制)
    │       vsyncHandler,            ← 事件处理器(回调线程)
    │       nodeId=surfaceNode_->GetId() ← 窗口的渲染节点 ID
    │   )
    │       ↓
    │   向 render_service 的 appVSyncDistributor 注册
    │       ↓
    │   VSync 信号到达 → 回调触发 → 窗口开始新一帧的渲染

关键实现细节vsync_station.cpp):

// vsync_station.cpp:90
std::shared_ptr<VSyncReceiver> VsyncStation::GetOrCreateVsyncReceiverLocked()
{
    if (receiver_ == nullptr) {
        auto& rsClient = RSInterfaces::GetInstance();
        // 通过 RS 接口创建 VSyncReceiver,传入 nodeId_ 作为窗口标识
        auto receiver = rsClient.CreateVSyncReceiver(
            "WM_" + std::to_string(::getprocpid()),
            frameRateLinker_->GetId(),
            vsyncHandler_, nodeId_);
        receiver_ = receiver;
    }
    return receiver_;
}

9.3 窗口级帧率控制

VsyncStation 内部通过 RSFrameRateLinker 绑定到 surfaceNodeId,允许逐窗口设定帧率

窗口 A (前台动画 60fps)    窗口 B (后台暂停)        窗口 C (视频 24fps)
    │                          │                         │
    │ RequestVsync(every frame)│ (no request)             │ RequestVsync(24fps)
    ▼                          ▼                         ▼
appVSyncDistributor       (不注册)                  (帧率链接器限制)
    │                          │                         │
 VSync 每帧到达            零功耗                    VSync 1/24s 到达
    │                          │                         │
 开始渲染                  不渲染                    按视频帧率更新

9.4 窗口生命周期与 VSync 的联动

窗口进入后台时停止 VSync 请求,前台时恢复:

// window_impl.cpp:1456
WMError WindowImpl::WindowCreateCheck(uint32_t parentId)
{
    if (vsyncStation_ == nullptr || !vsyncStation_->IsVsyncReceiverCreated()) {
        return WMError::WM_ERROR_NULLPTR;
    }
    // ...
}

// window_impl.cpp:1764
void WindowImpl::ClearVsyncStation()
{
    if (vsyncStation_ != nullptr) {
        vsyncStation_->Destroy();  // 窗口销毁,取消 VSync 注册
    }
}

9.5 Session 架构中的 VSync

Session 架构有等价的机制,通过 SceneSession 暴露 VSync 能力:

// scene_session.cpp:10659
void SceneSession::SetVsyncStation(const std::shared_ptr<VsyncStation>& vsyncStation)
{
    vsyncStation_ = vsyncStation;
}

void SceneSession::RunOnNextVsync(OnCallback&& callback)
{
    RETURN_IF_NULL(vsyncStation_);
    vsyncStation_->RunOnceOnNextVsync(std::move(callback));
}

std::optional<uint32_t> SceneSession::GetFpsFromVsync() const
{
    RETURN_IF_NULL(vsyncStation_, std::nullopt);
    return vsyncStation_->GetFps();
}

9.6 完整的窗口 → 渲染通路

            ┌─────────────────────────────────┐
            │  WindowImpl                      │
            │  ├── surfaceNode_  (渲染出口)     │
            │  │     ↓ RSSurfaceNode           │
            │  │     → BufferQueue → render_svc│
            │  └── vsyncStation_ (VSync入口)    │
            │        ↓ VsyncStation            │
            │        → VSyncReceiver           │
            │        → appVSyncDistributor     │
            └──────────┬──────────────────────┘
                       │
          ┌────────────┴────────────┐
          │                         │
    RequestVsync()             BufferQueue (像素)
          │                         │
          ▼                         ▼
    appVSyncDistributor      render_service 主线程
          │                    ConsumeBuffer
    VSync 回调触发                  │
          │                    Prepare/Process
    窗口开始新帧                    │
    (UI树→布局→Canvas)         Render Thread
          │                    GPU/HWC Compo
    提交 Transaction                │
    + QueueBuffer              HDI→Display

关键结论:

维度 说明
VSync 是全局的还是窗口级别的? render_service 的 VSync 硬件信号是全局的,但 订阅是窗口级别的
每个窗口是否都收到同一个 VSync? 不是。只有 主动 RequestVsync 的窗口 会收到信号,后台窗口收不到
VSync 频率可以逐窗口不同? 可以。通过 RSFrameRateLinker + VsyncStation 实现逐窗口帧率控制
窗口如何关联 VSync? 窗口的 surfaceNode_->GetId() 作为 VSyncReceiver 的识别 ID
窗口销毁时? ClearVsyncStation()vsyncStation_->Destroy() → 取消 VSync 注册

10. 与 Android 对比

维度 OHOS (Rosen WindowManager) Android (WindowManager + WMS + SF)
服务端 WindowManagerService(单进程中处理所有窗口操作) WindowManagerService(SystemServer 中的一个服务)
客户端 API Window::Create() / WindowManager WindowManager.addView() / WindowManagerGlobal
窗口节点 WindowNode + WindowProperty WindowState + WindowManager.LayoutParams
窗口树 WindowNodeContainer(每显示器一个) DisplayContent(每显示器一个,管理 WindowToken→WindowState)
窗口类型 枚举值分三段(BELOW_APP/ABOVE_APP/SUB) TYPE_APPLICATION / TYPE_SYSTEM / TYPE_SUB 等
Z-Order WindowZorderPolicy(类型优先级+创建顺序) WindowManagerPolicy(窗口类型层级 + Z-order 计算)
焦点 WindowNodeContainer::SetFocusWindow DisplayContent::setFocusedApp / WindowState 焦点链
分屏布局 WindowLayoutPolicy (Cascade / Tile) SplitScreenTaskOrganizer / TaskOrganizer
安全区域 AvoidAreaController(状态栏/导航栏/挖孔屏) InsetsController / SystemInsets
启动窗口 StartingWindow(专用 WindowNode) StartingWindow(窗口令牌关联)
桌面集成 SceneBoard → Session 架构(可选) Launcher(独立进程,非窗口管理核心)
渲染绑定 RSSurfaceNode(Render Service Client) SurfaceControl(SurfaceFlinger)
IPC 协议 自定义 MessageParcel / Binder Binder(IWindowManager.aidl)
输入法窗口 KeyboardSession(Session 架构) InputMethodManager + InputWindow
多屏支持 WindowRoot 管理多显示器的 WindowNodeContainer DisplayManagerService + DisplayContent
动画框架 RemoteAnimation 控制器 WindowAnimationSpec / RemoteAnimation

架构差异总结:

核心差异 OHOS Android
窗口树管理 WindowRoot → WindowNodeContainer → WindowNode 三层 DisplayContent → WindowToken → WindowState 三层
渲染层耦合 WMS 直接持有 RSSurfaceNode(与 RenderService 紧耦合) WMS 通过 SurfaceControl 间接操作,SurfaceFlinger 独立管理
窗口类型体系 数值分段法(每段留扩展空间) 属性枚举法(不同类型的 FLAG 和 TYPE 组合)
桌面窗口管理 可选方案:经典 WMS 或 SceneBoard Session 固定方案(Launcher 作为普通应用)
安全区域 通过 AvoidAreaController 计算 通过 InsetsController + WindowInsets 计算
窗口生命周期 WindowNodeStateMachine 严格状态机 WindowState 内部状态更简化

11. 关键技术点

11.1 窗口 ID 生成

WindowController::GenWindowId() 使用原子递增计数器生成唯一窗口 ID,确保同一进程中每个窗口的 ID 唯一。

11.2 窗口属性序列化

WindowProperty 实现 Parcelable 接口,通过 Marshalling/Unmarshalling 在客户端和服务端之间通过 IPC 传递窗口属性。

11.3 窗口死亡通知

WindowRoot 通过 AddDeathRecipient() 注册 DeathRecipient 监控窗口的 IPC 连接。当窗口所在进程异常退出时,自动触发 WindowRoot::DestroyWindow() 清理对应的窗口节点。

11.4 两种 WindowSessionType

WindowOption::SetWindowSessionType() 允许客户端选择使用经典 WMS 模式还是 Session 模式:

SessionType 含义 适用场景
TYPE_DEFAULT 经典 WMS 模式 传统应用 / 无 SceneBoard 环境
TYPE_SCENE_BOARD SceneBoard Session 模式 SceneBoard 桌面环境

11.5 窗口 flag 系统

WindowFlag 枚举提供窗口行为控制:

Flag 含义
WINDOW_FLAG_NEED_AVOID_AREA 需要计算安全区域
WINDOW_FLAG_PARENT_LIMIT 限制在父窗口范围内
WINDOW_FLAG_SHOW_WHEN_LOCKED 锁屏时仍然显示
WINDOW_FLAG_WATER_MARK 水印窗口
WINDOW_FLAG_HANDWRITE 手写窗口

11.6 窗口与 Node 的两层关系

OHOS 中有两层 Node,分别属于渲染系统和窗口管理系统,容易混淆:

层一:RSSurfaceNode(渲染节点)— 每个窗口一个

WindowImpl 构造函数 → surfaceNode_ = CreateSurfaceNode(name, type)
    ↓
CreateSurfaceNode() (window_impl.cpp:192)
    ├── 根据 WindowType 选择 RSSurfaceNodeType
    │   ├── APP_MAIN_WINDOW     → APP_WINDOW_NODE
    │   ├── BOOT_ANIMATION      → SELF_DRAWING_WINDOW_NODE
    │   ├── PIP / MEDIA         → APP_WINDOW_NODE
    │   └── 其他                → DEFAULT
    │
    └── RSSurfaceNode::Create(config, rsSurfaceNodeType)
        → 创建渲染表面(render_service 可见的渲染实体)

RSSurfaceNode 与窗口的 1:1 关系

  • 窗口位置变化 → surfaceNode_->SetBounds()
  • 窗口可见性变化 → surfaceNode_->SetVisible()
  • 窗口 Canvas 绘制 → 通过 surfaceNode 的 BufferQueue 传输像素
  • surfaceNode_->GetId() 可反向查找到 WindowNode

层二:WindowNode(服务端窗口节点)— WMS 端的逻辑节点

WindowController::CreateWindow()
    │
    ├── node = new WindowNode(property, window, surfaceNode, pid, uid)
    │    ├── surfaceNode_    → 客户端的 RSSurfaceNode(同一指针)
    │    ├── windowToken_    → 客户端 IWindow 回调接口
    │    ├── property_       → 窗口属性(类型/模式/矩形)
    │    └── abilityToken_   → Ability 令牌(关联启动窗口)
    │
    ├── windowRoot_->SaveWindow(node)
    │   └── surfaceIdWindowNodeMap_[surfaceNode->GetId()] = node
    │       → 可通过 RS 节点 ID 反向查找到 WindowNode
    │
    └── windowRoot_->AddWindowNode(parentId, node)
        → 插入 WindowNodeContainer 的 Z-order 树

三层 Node 的全链路关系:

渲染管线 (Rosen)          窗口管理 (WMS)            显示
RSSurfaceNode (渲染)  ←→  WindowNode (逻辑)  →  WindowNodeContainer → Display
      ↑                         ↑
      │ surfaceNodeId 映射       │ displayId
      │                          │
  surfaceIdWindowNodeMap_   WindowProperty::displayId

数量关系:
  Display 1 个          → WindowNodeContainer 1 个
  WindowNodeContainer 1 个 → WindowNode N 个
  WindowNode 1 个       → RSSurfaceNode 1 个(1:1)
  WindowImpl 1 个       → RSSurfaceNode 1 个(1:1)
  RSSurfaceNode 1 个    → render_service 中 1 个渲染表面

Node 类型汇总:

维度 RSSurfaceNode WindowNode
所属系统 Render Service (Rosen) Window Manager (WMS)
创建时机 WindowImpl 构造时 WMS::CreateWindow() 时
职责 渲染表面、BufferQueue、VSync 绑定 窗口逻辑(属性/焦点/Z-Order/生命周期)
跨进程 同一指针跨进程引用 服务端独有
销毁 WindowImpl 析构 WMS::DestroyWindow()

11.7 窗口的渲染绑定

每个 WindowImpl 创建时自动创建 RSSurfaceNode(Render Service 渲染节点):

// WindowImpl 构造函数(window_impl.cpp:131)
WindowImpl::WindowImpl(const sptr<WindowOption>& option) {
    // 创建 RS 渲染 Surface
    struct RSSurfaceNodeConfig config;
    config.SurfaceNodeName = name_;
    surfaceNode_ = RSSurfaceNode::Create(config, RSSurfaceNodeType::DEFAULT);
    // 设置窗口 ID 到渲染节点
    surfaceNode_->SetWindowId(property_->GetWindowId());
}

RSSurfaceNode 是 OHOS 渲染管线(Rosen)中的基础节点,绑定到窗口后:

  • 窗口的位置/大小变化 → 对应 RSSurfaceNode 的 bounds 变化
  • 窗口可见性变化 → RSSurfaceNode 的 visible 标志变化
  • 窗口的 Canvas 绘制结果 → 通过 BufferQueue 传递到 render_service

11.8 启动窗口(StartingWindow)

StartingWindow 是应用冷启动/热启动时显示的临时窗口,由 WMS 在应用准备好之前创建:

// starting_window.h
class StartingWindow {
    void Show(sptr<WindowTransitionInfo> info,
        std::shared_ptr<Media::PixelMap> pixelMap,
        uint32_t bkgColor, bool isColdStart);
    void Cancel(sptr<IRemoteObject> abilityToken);
};
启动类型 触发条件 处理方式
冷启动 应用进程未运行 显示像素图/背景色类型的 StartingWindow
热启动 应用进程已运行但窗口不可见 可能复用已有的窗口快照
应用闪屏 应用自定义启动页 StartingWindow 显示后,应用接管界面

StartingWindow 通过 WindowController::StartingWindow() 创建并添加为临时窗口节点,在应用实际窗口准备好后被 CancelStartingWindow() 移除。

11.9 窗口创建权限检查

WindowManagerService::CreateWindow() 在创建窗口前执行两重权限检查:

// 1. 系统窗口权限检查
if (WindowHelper::IsSystemWindow(property->GetWindowType())) {
    if (!Permission::IsSystemCalling()) {
        return WMError::WM_ERROR_INVALID_TYPE;
    }
}

// 2. 录音/悬浮窗权限检查(特定类型需要额外权限)
if (property->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT) {
    if (!Permission::IsSystemSetting()) {
        return WMError::WM_ERROR_NOT_SYSTEM_APP;
    }
}

11.10 VsyncStation:窗口级 VSync 机制

VsyncStation 是连接窗口管理子系统和渲染子系统的关键桥梁,已在第 9 章详细展开。此处总结其核心机制:

机制 说明
创建时机 WindowImpl 构造时,绑定到 surfaceNode_->GetId()
懒加载 VSyncReceiver 在首次 RequestVsync() 时创建
帧率控制 通过 RSFrameRateLinker 实现逐窗口帧率设定
生命周期 窗口销毁时 ClearVsyncStation()Destroy() 取消注册
Session 等价 SceneSession::SetVsyncStation() + RunOnNextVsync()
posted @ 2026-05-28 12:00  getmoon  阅读(58)  评论(0)    收藏  举报