已关闭
feat(render_service): add delayed cleanup for render nodes after process death #30729
huaixu-y创建于 6月15日关闭于 7月14日
feat(render_service): add delayed cleanup for render nodes after process death #30729
已关闭
共 33 个文件变更+1313-40
| @@ -33,6 +33,7 @@ | |||
| 33 | | --- | --- | --- | --- | | 33 | | --- | --- | --- | --- | |
| 34 | | RS 进程入口 | `rs-process-entry.md` | `render_service/main/`, `core/system/`, `RenderService` | RS 单测 | | 34 | | RS 进程入口 | `rs-process-entry.md` | `render_service/main/`, `core/system/`, `RenderService` | RS 单测 | |
| 35 | | RS 主线程/连接 | `rs-main-thread.md` | `render_service/core/pipeline/main_thread/`, `RSMainThread` | pipeline | | 35 | | RS 主线程/连接 | `rs-main-thread.md` | `render_service/core/pipeline/main_thread/`, `RSMainThread` | pipeline | |
| 36 | +| 进程死亡延迟清理 | `design-delayed-cleanup.md` | `RSMainThread::delayCleanup*`, `CleanAll`, `TriggerImmediateCleanup` | pipeline | | ||
| 36 | | RS 渲染线程 | `rs-render-thread.md` | `render_thread/`, `RSUniRender` | render_thread | | 37 | | RS 渲染线程 | `rs-render-thread.md` | `render_thread/`, `RSUniRender` | render_thread | |
| 37 | | 并行渲染/SLR | `rs-parallel-render.md` | `parallel_render/`, `slr_scale/`, `parallel` | pipeline | | 38 | | 并行渲染/SLR | `rs-parallel-render.md` | `parallel_render/`, `slr_scale/`, `parallel` | pipeline | |
| 38 | | 客户端 UI 节点 | `rs-client-ui-node.md` | `render_service_client/core/ui/`, `RSNode`, `RSSurfaceNode` | UI/fuzz | | 39 | | 客户端 UI 节点 | `rs-client-ui-node.md` | `render_service_client/core/ui/`, `RSNode`, `RSSurfaceNode` | UI/fuzz | |
| @@ -0,0 +1,584 @@ | |||
| 1 | +# 进程死亡后延迟清理渲染节点设计文档 | ||
| 2 | + | ||
| 3 | +## 1. 背景与目标 | ||
| 4 | + | ||
| 5 | +### 1.1 背景 | ||
| 6 | + | ||
| 7 | +在 OpenHarmony 图形栈中,应用进程终止时,RenderService 会立即销毁该进程的所有渲染节点。当应用进程快速重启时,用户会观察到窗口瞬间消失再重新出现,体验不佳。 | ||
| 8 | + | ||
| 9 | +### 1.2 目标 | ||
| 10 | + | ||
| 11 | +为已启用延迟清理的进程提供死亡后延迟清理机制: | ||
| 12 | +- 进程死亡后,渲染相关数据(节点、transaction、caches 等)延迟固定时间后清理(当前 `constexpr DELAY_CLEANUP_MS = 10000`) | ||
| 13 | +- 新进程可通过接口立即清理旧进程资源 | ||
| 14 | +- 同时支持单进程模式和多进程模式(Service 主进程 + Render 子进程) | ||
| 15 | + | ||
| 16 | +--- | ||
| 17 | + | ||
| 18 | +## 2. 架构设计 | ||
| 19 | + | ||
| 20 | +### 2.1 整体架构 | ||
| 21 | + | ||
| 22 | +```mermaid | ||
| 23 | +flowchart TB | ||
| 24 | + subgraph Client["应用进程 (Client)"] | ||
| 25 | + C_RSInterfaces["RSInterfaces"] | ||
| 26 | + C_RSRenderServiceClient["RSRenderServiceClient<br/>(OHOS/Darwin/Win)"] | ||
| 27 | + end | ||
| 28 | + | ||
| 29 | + subgraph Service["Service 主进程 (Service)"] | ||
| 30 | + S_RSClientToServiceConnection["RSClientToServiceConnection"] | ||
| 31 | + S_RSMainThread["RSMainThread"] | ||
| 32 | + S_RSRenderProcessManagerAgent["RSRenderProcessManagerAgent"] | ||
| 33 | + end | ||
| 34 | + | ||
| 35 | + subgraph Render["Render 子进程 (Render)"] | ||
| 36 | + R_RSServiceToRenderConnection["RSServiceToRenderConnection"] | ||
| 37 | + R_RSClientToRenderConnection["RSClientToRenderConnection"] | ||
| 38 | + R_RSMainThread["RSMainThread"] | ||
| 39 | + R_RSRenderPipelineAgent["RSRenderPipelineAgent"] | ||
| 40 | + end | ||
| 41 | + | ||
| 42 | + C_RSInterfaces -->|"SetDelayedCleanupEnabled()<br/>TriggerImmediateCleanup()"| C_RSRenderServiceClient | ||
| 43 | + C_RSRenderServiceClient -->|"IPC: RSIClientToServiceConnection"| S_RSClientToServiceConnection | ||
| 44 | + | ||
| 45 | + S_RSClientToServiceConnection -->|"SetDelayedCleanupEnabled(pid, enabled)"| S_RSMainThread | ||
| 46 | + S_RSClientToServiceConnection -->|"BroadcastDelayedCleanupEnabled(pid, enabled)"| S_RSRenderProcessManagerAgent | ||
| 47 | + S_RSRenderProcessManagerAgent -->|"IPC: RSIServiceToRenderConnection"| R_RSServiceToRenderConnection | ||
| 48 | + R_RSServiceToRenderConnection -->|"SetDelayedCleanupEnabled(pid, enabled)"| R_RSRenderPipelineAgent | ||
| 49 | + R_RSRenderPipelineAgent -->|"SetDelayedCleanupEnabled(pid, enabled)"| R_RSMainThread | ||
| 50 | + | ||
| 51 | + S_RSClientToServiceConnection -->|"CleanAll() → DoCleanAll()"| S_RSMainThread | ||
| 52 | + R_RSClientToRenderConnection -->|"CleanAll() → ExecuteCleanup()"| R_RSMainThread | ||
| 53 | +``` | ||
| 54 | + | ||
| 55 | +### 2.2 关键设计决策 | ||
| 56 | + | ||
| 57 | +| 决策 | 方案 | 理由 | | ||
| 58 | +|------|------|------| | ||
| 59 | +| 客户端接口位置 | `RSInterfaces`(Service 路径) | 延迟清理是全系统协调行为,非单个 Render 连接私有行为;消除 `ClientToRenderConnection` 反向引用 `ClientToServiceConnection` 的耦合 | | ||
| 60 | +| 延迟状态存储 | `RSMainThread::delayCleanupPids_` | 进程级单例,Service 和 Render 端各自管理 | | ||
| 61 | +| 延迟任务调度 | `RSMainThread::PostTask(taskName, delayMs)` | 利用现有主线程任务队列,延迟一定时间后执行 | | ||
| 62 | +| 多进程广播 | `ClientToServiceConnection::Broadcast...()` | Service 端持有 `renderProcessManagerAgent_`,天然适合协调所有 Render 子进程 | | ||
| 63 | +| 防重复清理 | `RSMainThread::Register/UnregisterDelayCleanupTask` | 按 pid 管理任务列表,`TriggerImmediateCleanup` 时取消并立即执行 | | ||
| 64 | +| 连接保活 | `wptr<RSClientTo*Connection>` 捕获 | 延迟 lambda 中 `promote()` 校验,防止连接已析构时悬空访问 | | ||
| 65 | + | ||
| 66 | +### 2.3 设计约束 | ||
| 67 | + | ||
| 68 | +| 约束 | 说明 | 实现 | | ||
| 69 | +|------|------|------| | ||
| 70 | +| 状态同步 | Render 进程必须与 Service 进程同时启用/禁用延迟清理 | 通过 `BroadcastDelayedCleanupEnabled` + `RSMainThread` 单例保证;`RSIServiceToRenderConnection` 接口不替换为 `rs_render_interface.h`,避免 Render 反向访问 Service 的私有接口 | | ||
| 71 | +| 延迟时间固定 | 首版不引入额外配置耦合,延迟时间使用 `constexpr DELAY_CLEANUP_MS = 10000` 硬编码;后续如需动态调整,可迁移到配置中心 | Service 与 Render 共用同一常量 | | ||
| 72 | +| 正确性优先 | 为简化同步与生命周期管理,清理任务在主线程串行执行 | 后续若 profiling 发现掉帧,再考虑拆出 IPC 调用或任务分片 | | ||
| 73 | + | ||
| 74 | +--- | ||
| 75 | + | ||
| 76 | +## 3. 核心组件 | ||
| 77 | + | ||
| 78 | +### 3.1 类图 | ||
| 79 | + | ||
| 80 | +```mermaid | ||
| 81 | +classDiagram | ||
| 82 | + class RSInterfaces { | ||
| 83 | + +SetDelayedCleanupEnabled(bool enabled) void | ||
| 84 | + +TriggerImmediateCleanup(pid_t pid) void | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + class RSRenderServiceClient { | ||
| 88 | + +SetDelayedCleanupEnabled(bool enabled) void | ||
| 89 | + +TriggerImmediateCleanup(pid_t pid) void | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + class RSIClientToServiceConnection { | ||
| 93 | + <<interface>> | ||
| 94 | + +SetDelayedCleanupEnabled(bool enabled) ErrCode | ||
| 95 | + +TriggerImmediateCleanup(pid_t pid) ErrCode | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + class RSClientToServiceConnection { | ||
| 99 | + -sptr~RSRenderProcessManagerAgent~ renderProcessManagerAgent_ | ||
| 100 | + +SetDelayedCleanupEnabled(bool enabled) ErrCode | ||
| 101 | + +TriggerImmediateCleanup(pid_t pid) ErrCode | ||
| 102 | + +BroadcastDelayedCleanupEnabled(pid_t pid, bool enabled) | ||
| 103 | + +BroadcastImmediateCleanup(pid_t pid) | ||
| 104 | + +CleanAll(bool toDelete) | ||
| 105 | + -DoCleanAll(bool toDelete) | ||
| 106 | + -DoCleanForRefresh() | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + class RSMainThread { | ||
| 110 | + -unordered_set~pid_t~ delayCleanupPids_ | ||
| 111 | + -unordered_map~pid_t, vector~DelayCleanupInfo~~ delayCleanupTasks_ | ||
| 112 | + +SetDelayedCleanupEnabled(pid_t pid, bool enabled) | ||
| 113 | + +IsDelayCleanupEnabled(pid_t pid) bool | ||
| 114 | + +TriggerImmediateCleanup(pid_t pid) | ||
| 115 | + +RegisterDelayCleanupTask(pid_t pid, string taskName, function~void()~ cleanupFunc) | ||
| 116 | + +UnregisterDelayCleanupTask(string taskName) | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + class RSIServiceToRenderConnection { | ||
| 120 | + <<interface>> | ||
| 121 | + +SetDelayedCleanupEnabled(pid_t pid, bool enabled) | ||
| 122 | + +TriggerImmediateCleanup(pid_t pid) | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + class RSServiceToRenderConnection { | ||
| 126 | + -sptr~RSRenderPipelineAgent~ renderPipelineAgent_ | ||
| 127 | + +SetDelayedCleanupEnabled(pid_t pid, bool enabled) | ||
| 128 | + +TriggerImmediateCleanup(pid_t pid) | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + class RSClientToRenderConnection { | ||
| 132 | + -sptr~RSRenderPipelineAgent~ renderPipelineAgent_ | ||
| 133 | + +CleanAll(bool toDelete) | ||
| 134 | + -DoCleanAll(bool toDelete) | ||
| 135 | + -ExecuteCleanup(bool toDelete) | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + class RSRenderPipelineAgent { | ||
| 139 | + +DoClean(pid_t pid, bool forRefresh, bool sync) | ||
| 140 | + +SetDelayedCleanupEnabled(uint32_t pid, bool enabled) | ||
| 141 | + +TriggerImmediateCleanup(pid_t pid) | ||
| 142 | + +HasRenderPipeline() bool | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + RSInterfaces --> RSRenderServiceClient | ||
| 146 | + RSRenderServiceClient --> RSIClientToServiceConnection | ||
| 147 | + RSIClientToServiceConnection <|-- RSClientToServiceConnection | ||
| 148 | + RSClientToServiceConnection --> RSMainThread | ||
| 149 | + RSClientToServiceConnection --> RSIServiceToRenderConnection : 多进程广播 | ||
| 150 | + RSIServiceToRenderConnection <|-- RSServiceToRenderConnection | ||
| 151 | + RSServiceToRenderConnection --> RSRenderPipelineAgent | ||
| 152 | + RSServiceToRenderConnection --> RSMainThread | ||
| 153 | + RSClientToRenderConnection --> RSMainThread | ||
| 154 | + RSClientToRenderConnection --> RSRenderPipelineAgent | ||
| 155 | +``` | ||
| 156 | + | ||
| 157 | +### 3.2 RSMainThread(延迟清理状态中心) | ||
| 158 | + | ||
| 159 | +```mermaid | ||
| 160 | +classDiagram | ||
| 161 | + class RSMainThread { | ||
| 162 | + -struct DelayCleanupInfo | ||
| 163 | + -mutable mutex delayCleanupMutex_ | ||
| 164 | + -unordered_set~pid_t~ delayCleanupPids_ | ||
| 165 | + -unordered_map~pid_t, vector~DelayCleanupInfo~~ delayCleanupTasks_ | ||
| 166 | + +SetDelayedCleanupEnabled(pid_t pid, bool enabled) | ||
| 167 | + +IsDelayCleanupEnabled(pid_t pid) bool | ||
| 168 | + +TriggerImmediateCleanup(pid_t pid) | ||
| 169 | + +RegisterDelayCleanupTask(pid_t pid, string taskName, function~void()~) | ||
| 170 | + +UnregisterDelayCleanupTask(string taskName) | ||
| 171 | + } | ||
| 172 | +``` | ||
| 173 | + | ||
| 174 | +**关键行为**: | ||
| 175 | +- `TriggerImmediateCleanup(pid)`:获取该 pid 的所有 `DelayCleanupInfo`,逐个 `RemoveTask` 并执行 `cleanupFunc`;无论是否存在延迟任务,最后都从 `delayCleanupPids_` 移除该 pid | ||
| 176 | + | ||
| 177 | +--- | ||
| 178 | + | ||
| 179 | +## 4. 关键流程 | ||
| 180 | + | ||
| 181 | +### 4.1 启用延迟清理 | ||
| 182 | + | ||
| 183 | +```mermaid | ||
| 184 | +sequenceDiagram | ||
| 185 | + participant App as 应用进程 | ||
| 186 | + participant C_RSInterfaces as RSInterfaces | ||
| 187 | + participant C_RSRenderServiceClient as RSRenderServiceClient | ||
| 188 | + participant S_Proxy as RSIClientToServiceConnection Proxy | ||
| 189 | + participant S_Stub as RSIClientToServiceConnection Stub | ||
| 190 | + participant S_ClientToService as RSClientToServiceConnection | ||
| 191 | + participant S_RSMainThread as RSMainThread(Service) | ||
| 192 | + participant S_RSRenderProcessManagerAgent as RSRenderProcessManagerAgent | ||
| 193 | + participant R_Proxy as RSIServiceToRenderConnection Proxy | ||
| 194 | + participant R_Stub as RSIServiceToRenderConnection Stub | ||
| 195 | + participant R_ClientToRender as RSClientToRenderConnection | ||
| 196 | + participant R_RSMainThread as RSMainThread(Render) | ||
| 197 | + | ||
| 198 | + App->>C_RSInterfaces: SetDelayedCleanupEnabled(true) | ||
| 199 | + C_RSInterfaces->>C_RSRenderServiceClient: SetDelayedCleanupEnabled(true) | ||
| 200 | + C_RSRenderServiceClient->>S_Proxy: IPC: SetDelayedCleanupEnabled(true) | ||
| 201 | + S_Proxy->>S_Stub: SendRequest(0x014005) | ||
| 202 | + S_Stub->>S_ClientToService: SetDelayedCleanupEnabled(true) | ||
| 203 | + | ||
| 204 | + S_ClientToService->>S_RSMainThread: SetDelayedCleanupEnabled(remotePid_, true) | ||
| 205 | + S_RSMainThread->>S_RSMainThread: delayCleanupPids_.insert(remotePid_) | ||
| 206 | + | ||
| 207 | + S_ClientToService->>S_RSRenderProcessManagerAgent: BroadcastDelayedCleanupEnabled(remotePid_, true) | ||
| 208 | + loop 遍历所有 Render 子进程 | ||
| 209 | + S_RSRenderProcessManagerAgent->>R_Proxy: IPC: SetDelayedCleanupEnabled(remotePid_, true) | ||
| 210 | + R_Proxy->>R_Stub: SendRequest(0x00F015) | ||
| 211 | + R_Stub->>R_ClientToRender: SetDelayedCleanupEnabled(remotePid_, true) | ||
| 212 | + R_ClientToRender->>R_RSMainThread: SetDelayedCleanupEnabled(remotePid_, true) | ||
| 213 | + R_RSMainThread->>R_RSMainThread: delayCleanupPids_.insert(remotePid_) | ||
| 214 | + end | ||
| 215 | +``` | ||
| 216 | + | ||
| 217 | +### 4.2 应用进程死亡(延迟清理) | ||
| 218 | + | ||
| 219 | +```mermaid | ||
| 220 | +sequenceDiagram | ||
| 221 | + participant App as 应用进程 | ||
| 222 | + participant S_ClientToService as RSClientToServiceConnection | ||
| 223 | + participant S_RSMainThread as RSMainThread(Service) | ||
| 224 | + participant R_ClientToRender as RSClientToRenderConnection | ||
| 225 | + participant R_RSMainThread as RSMainThread(Render) | ||
| 226 | + | ||
| 227 | + App->>App: [进程死亡] | ||
| 228 | + App--xS_ClientToService: binder 断开 → CleanAll() | ||
| 229 | + App--xR_ClientToRender: binder 断开 → CleanAll() | ||
| 230 | + | ||
| 231 | + S_ClientToService->>S_RSMainThread: IsDelayCleanupEnabled(remotePid_) | ||
| 232 | + S_RSMainThread-->>S_ClientToService: true | ||
| 233 | + S_ClientToService->>S_RSMainThread: PostTask(DoCleanAll, delayMs) | ||
| 234 | + S_ClientToService->>S_RSMainThread: RegisterDelayCleanupTask(remotePid_, taskName, cleanupFunc) | ||
| 235 | + | ||
| 236 | + R_ClientToRender->>R_RSMainThread: IsDelayCleanupEnabled(remotePid_) | ||
| 237 | + R_RSMainThread-->>R_ClientToRender: true | ||
| 238 | + R_ClientToRender->>R_RSMainThread: PostTask(DoCleanAll, delayMs) | ||
| 239 | + R_ClientToRender->>R_RSMainThread: RegisterDelayCleanupTask(remotePid_, taskName, cleanupFunc) | ||
| 240 | + | ||
| 241 | + Note over S_RSMainThread,R_RSMainThread: [after DELAY_CLEANUP_MS] | ||
| 242 | + S_RSMainThread->>S_ClientToService: DoCleanAll() | ||
| 243 | + R_RSMainThread->>R_ClientToRender: DoCleanAll() | ||
| 244 | +``` | ||
| 245 | + | ||
| 246 | +### 4.3 新进程立即清理旧资源 | ||
| 247 | + | ||
| 248 | +```mermaid | ||
| 249 | +sequenceDiagram | ||
| 250 | + participant NewApp as 新应用进程 | ||
| 251 | + participant C_RSInterfaces as RSInterfaces | ||
| 252 | + participant C_RSRenderServiceClient as RSRenderServiceClient | ||
| 253 | + participant S_Proxy as RSIClientToServiceConnection Proxy | ||
| 254 | + participant S_Stub as RSIClientToServiceConnection Stub | ||
| 255 | + participant S_ClientToService as RSClientToServiceConnection | ||
| 256 | + participant S_RSMainThread as RSMainThread(Service) | ||
| 257 | + participant S_RSRenderProcessManagerAgent as RSRenderProcessManagerAgent | ||
| 258 | + participant R_Proxy as RSIServiceToRenderConnection Proxy | ||
| 259 | + participant R_Stub as RSIServiceToRenderConnection Stub | ||
| 260 | + participant R_ClientToRender as RSClientToRenderConnection | ||
| 261 | + participant R_RSMainThread as RSMainThread(Render) | ||
| 262 | + | ||
| 263 | + NewApp->>C_RSInterfaces: TriggerImmediateCleanup(oldPid) | ||
| 264 | + C_RSInterfaces->>C_RSRenderServiceClient: TriggerImmediateCleanup(oldPid) | ||
| 265 | + C_RSRenderServiceClient->>S_Proxy: IPC: TriggerImmediateCleanup(oldPid) | ||
| 266 | + S_Proxy->>S_Stub: SendRequest(0x014006) | ||
| 267 | + S_Stub->>S_ClientToService: TriggerImmediateCleanup(oldPid) | ||
| 268 | + | ||
| 269 | + S_ClientToService->>S_RSMainThread: TriggerImmediateCleanup(oldPid) | ||
| 270 | + S_RSMainThread->>S_RSMainThread: delayCleanupTasks_[oldPid] → infos | ||
| 271 | + loop 遍历所有 DelayCleanupInfo | ||
| 272 | + S_RSMainThread->>S_RSMainThread: RemoveTask(info.taskName) | ||
| 273 | + S_RSMainThread->>S_ClientToService: info.cleanupFunc() → DoCleanAll() | ||
| 274 | + end | ||
| 275 | + S_RSMainThread->>S_RSMainThread: delayCleanupPids_.erase(oldPid) | ||
| 276 | + | ||
| 277 | + S_ClientToService->>S_RSRenderProcessManagerAgent: BroadcastImmediateCleanup(oldPid) | ||
| 278 | + loop 遍历所有 Render 子进程 | ||
| 279 | + S_RSRenderProcessManagerAgent->>R_Proxy: IPC: TriggerImmediateCleanup(oldPid) | ||
| 280 | + R_Proxy->>R_Stub: SendRequest(0x00F016) | ||
| 281 | + R_Stub->>R_ClientToRender: TriggerImmediateCleanup(oldPid) | ||
| 282 | + R_ClientToRender->>R_RSMainThread: TriggerImmediateCleanup(oldPid) | ||
| 283 | + R_RSMainThread->>R_RSMainThread: 执行同上的立即清理逻辑 | ||
| 284 | + end | ||
| 285 | +``` | ||
| 286 | + | ||
| 287 | +--- | ||
| 288 | + | ||
| 289 | +## 5. 单进程 vs 多进程差异 | ||
| 290 | + | ||
| 291 | +```mermaid | ||
| 292 | +flowchart LR | ||
| 293 | + subgraph Single["单进程模式"] | ||
| 294 | + direction TB | ||
| 295 | + S1["Service 端广播"] | ||
| 296 | + S2["GetServiceToRenderConns() 为空"] | ||
| 297 | + S3["广播循环不执行"] | ||
| 298 | + S4["Render 端 DoClean()"] | ||
| 299 | + S5["rsRenderPipeline_ 有效"] | ||
| 300 | + S6["直接操作 RSMainThread"] | ||
| 301 | + S1 --> S2 --> S3 | ||
| 302 | + S4 --> S5 --> S6 | ||
| 303 | + end | ||
| 304 | + | ||
| 305 | + subgraph Multi["多进程模式"] | ||
| 306 | + direction TB | ||
| 307 | + M1["Service 端广播"] | ||
| 308 | + M2["GetServiceToRenderConns() 非空"] | ||
| 309 | + M3["遍历所有 Render 子进程"] | ||
| 310 | + M4["通过 IPC 通知"] | ||
| 311 | + M5["Render 端 DoClean()"] | ||
| 312 | + M6["rsRenderPipeline_ == nullptr"] | ||
| 313 | + M7["直接返回(空操作)"] | ||
| 314 | + M1 --> M2 --> M3 --> M4 | ||
| 315 | + M5 --> M6 --> M7 | ||
| 316 | + end | ||
| 317 | +``` | ||
| 318 | + | ||
| 319 | +| 场景 | Service 端 `ClientToServiceConnection` | Render 端 `ClientToRenderConnection` | | ||
| 320 | +|------|----------------------------------------|--------------------------------------| | ||
| 321 | +| **单进程模式** | `renderProcessManagerAgent_->GetServiceToRenderConns()` 为空,广播循环不执行;`RSMainThread::SetDelayedCleanupEnabled` 直接生效 | `renderPipelineAgent_->DoClean()` 通过 `rsRenderPipeline_->GetMainThread()` 直接操作 | | ||
| 322 | +| **多进程模式** | `BroadcastDelayedCleanupEnabled` 遍历所有 Render 子进程,通过 `RSIServiceToRenderConnection` IPC 通知 | 1. `Set/TriggerDelayedCleanupEnabled` 检测到 `rsRenderPipeline_ == nullptr`,fallback 调用 `RSMainThread::Instance()` 设置/触发 Render 子进程状态;<br>2. `CleanAll` 检查 `RSMainThread::IsDelayCleanupEnabled()`,与 Service 端一致 post 延迟任务;<br>3. `DoClean()` 因 `rsRenderPipeline_ == nullptr` 直接返回,不执行核心清理;<br>4. `toDelete` 相关的 `RemoveConnection` / `UnRegisterApplicationAgent` / `RemoveDeathRecipient` 仍延迟执行;<br>5. 为减少无意义任务,multi-process 且 `toDelete == false` 的析构路径不 post 延迟任务;<br>6. 延迟清理由 Service 端 `ClientToServiceConnection` 的 `CleanAll` 驱动 | | ||
| 323 | + | ||
| 324 | +**注意**: | ||
| 325 | +- 多进程模式下,Service 端执行核心清理(节点、caches、token 等),Render 端执行连接级清理(`RemoveConnection`、`UnRegisterApplicationAgent`、`RemoveDeathRecipient`)。两端状态同步、延迟时间一致,执行行为一致。 | ||
| 326 | +- 为优化性能,`ExecuteCleanup` 仅在 `HasRenderPipeline()` 为 true 时调用 `DoClean()`,multi-process 下跳过该空转;`CleanAll` 在 multi-process 且 `toDelete == false` 时不 post 无意义延迟任务。 | ||
| 327 | + | ||
| 328 | +--- | ||
| 329 | + | ||
| 330 | +## 6. 避免主线程阻塞策略 | ||
| 331 | + | ||
| 332 | +延迟清理的核心挑战是在保证清理正确性的同时,避免阻塞 RenderService 主线程。以下策略确保主线程始终可响应: | ||
| 333 | + | ||
| 334 | +| 策略 | 说明 | | ||
| 335 | +|------|------| | ||
| 336 | +| **异步任务调度** | 延迟路径使用 `PostTask(taskName, delayMs)` 将清理任务投递到主线程任务队列,不阻塞当前 binder 死亡回调线程 | | ||
| 337 | +| **DoClean 的 sync 参数拆分** | `RSRenderPipelineAgent::DoClean(pid, forRefresh, sync)` 中,延迟路径传入 `sync=false`,直接调用 `mainThread->CleanResources()`,不执行 `.wait()`,避免 lambda 在主线程执行时因等待自身而死锁 | | ||
| 338 | +| **Service 端内联执行** | `RSClientToServiceConnection` 的延迟 cleanup lambda 直接调用 `DoCleanForRefresh()`,内联执行 `CleanVirtualScreens`、`hgmContext_->CleanAllWhenServiceConnectionDie`、`RemoveToken` 等,不嵌套 `ScheduleMainThreadTask(...).wait()` | | ||
| 339 | +| **IPC 广播非阻塞** | `BroadcastDelayedCleanupEnabled` / `BroadcastImmediateCleanup` 遍历 Render 子进程时,IPC 请求使用 `TF_ASYNC` 标志,不阻塞调用方等待各 Render 子进程响应 | | ||
| 340 | + | ||
| 341 | +**阻塞风险对比**: | ||
| 342 | + | ||
| 343 | +```mermaid | ||
| 344 | +flowchart LR | ||
| 345 | + subgraph Risk["潜在阻塞场景"] | ||
| 346 | + R1["PostTask(...).wait()"] | ||
| 347 | + R2["ScheduleTask(...).wait() 嵌套"] | ||
| 348 | + R3["同步 IPC 广播"] | ||
| 349 | + end | ||
| 350 | + | ||
| 351 | + subgraph Safe["实际安全方案"] | ||
| 352 | + S1["PostTask(taskName, delayMs) 不 wait"] | ||
| 353 | + S2["DoClean sync=false 直接调用"] | ||
| 354 | + S3["TF_ASYNC 异步 IPC"] | ||
| 355 | + end | ||
| 356 | + | ||
| 357 | + R1 --> S1 | ||
| 358 | + R2 --> S2 | ||
| 359 | + R3 --> S3 | ||
| 360 | +``` | ||
| 361 | + | ||
| 362 | +### 6.1 性能影响与阻塞风险 | ||
| 363 | + | ||
| 364 | +#### 主线程开销 | ||
| 365 | + | ||
| 366 | +当前方案把清理任务整体 post 到 `RSMainThread`,任务中既包含内存操作,也包含同步 IPC 调用: | ||
| 367 | + | ||
| 368 | +| 端 | 清理操作 | 执行位置 | 是否可能阻塞 | | ||
| 369 | +|---|---|---|---| | ||
| 370 | +| Service | `CleanVirtualScreens()` | 主线程 | 低(本地 map/锁遍历) | | ||
| 371 | +| Service | `hgmContext_->CleanAllWhenServiceConnectionDie()` | 主线程 | **是(等待 HgmTaskHandleThread)** | | ||
| 372 | +| Service | `RSTypefaceCache::RemoveDrawingTypefacesByPid()` | 主线程 | 低(本地 cache) | | ||
| 373 | +| Service | `pidToBundleName_.clear()` | 主线程 | 否 | | ||
| 374 | +| Service | `renderServiceAgent_->RemoveToken()` | 主线程 | 否(本地 `connections_` map erase) | | ||
| 375 | +| Render | `renderPipelineAgent_->DoClean(..., false)` | 主线程 | **是(等待 uni render thread)** | | ||
| 376 | +| Render | `RemoveConnection()` / `UnRegisterApplicationAgent()` / `RemoveDeathRecipient()` | 主线程 | 否(本地 map + binder driver 本地操作) | | ||
| 377 | + | ||
| 378 | +#### 丢帧/冻结风险场景 | ||
| 379 | + | ||
| 380 | +| 场景 | 风险等级 | 说明 | | ||
| 381 | +|---|---|---|---| | ||
| 382 | +| 单次进程死亡,负载正常 | 低 | 单个 delay cleanup 任务通常 <5ms,对下一帧影响有限 | | ||
| 383 | +| HgmTaskHandleThread / uni render thread 繁忙 | 中 | `CleanAllWhenServiceConnectionDie` / `DoClean` 会同步等待,可能阻塞 16ms+ | | ||
| 384 | +| 渲染线程被 GPU/合成阻塞 | 高 | `PostUniRenderThreadSyncTask` 会让主线程一直等到渲染帧完成,可能数十 ms,导致 freeze | | ||
| 385 | +| 多个进程同时死亡 | 高 | 多个 delay cleanup 任务串行排队,累计阻塞主线程 | | ||
| 386 | +| 主线程高负载时延迟任务被积压 | 中 | 任务以 `Priority::IDLE` 投递,忙时可能延迟执行;一旦开始执行又会占用主线程 | | ||
| 387 | + | ||
| 388 | +#### 与原始方案的对比 | ||
| 389 | + | ||
| 390 | +| 方案 | 阻塞影响范围 | 说明 | | ||
| 391 | +|---|---|---| | ||
| 392 | +| 原始方案(立即清理) | binder 死亡回调线程 | `CleanAll` 中的同步等待在 binder 线程执行,不占用主线程;但死亡发生瞬间仍可能阻塞 binder 池 | | ||
| 393 | +| 当前方案(延迟清理) | `RSMainThread` | 清理逻辑在主线程执行,若内部同步等待其他线程/GPU,会直接影响 VSync 和帧率 | | ||
| 394 | + | ||
| 395 | +> 结论:当前方案把阻塞从 binder 线程转移到了 `RSMainThread`。**正常单次死亡不会明显丢帧**;但渲染线程繁忙或大量进程同时死亡时,存在 **freeze/jank 风险**。 | ||
| 396 | + | ||
| 397 | +#### 设计权衡 | ||
| 398 | + | ||
| 399 | +| 选择 | 优点 | 缺点 | | ||
| 400 | +|---|---|---| | ||
| 401 | +| 在主线程执行全部清理 | 顺序确定、线程安全、实现简单 | IPC 阻塞可能掉帧 | | ||
| 402 | +| 把 IPC 拆到后台线程 | 不阻塞主线程 | 顺序难保证、需要额外同步、连接可能在后台线程和主线程间析构 | | ||
| 403 | + | ||
| 404 | +当前实现选择了**正确性优先于性能**的折中,原因包括: | ||
| 405 | +1. 进程死亡是低频事件 | ||
| 406 | +2. 延迟到固定延时时间后执行,通常不是用户交互高峰期 | ||
| 407 | +3. 为保证清理顺序和线程安全,接受有限的主线程开销 | ||
| 408 | + | ||
| 409 | +#### 后续优化方向(可选) | ||
| 410 | + | ||
| 411 | +如果后续 profiling 证明清理导致掉帧,可考虑: | ||
| 412 | + | ||
| 413 | +1. **把 IPC 调用拆到后台线程** | ||
| 414 | + ```cpp | ||
| 415 | + RSMainThread::Instance()->PostTask([weakConn]() { | ||
| 416 | + // 主线程执行必须在主线程的清理 | ||
| 417 | + conn->CleanVirtualScreens(); | ||
| 418 | + conn->hgmContext_->CleanAllWhenServiceConnectionDie(pid); | ||
| 419 | + // ... | ||
| 420 | + // 把 IPC 调用 post 到后台线程 | ||
| 421 | + BackgroundThread::PostTask([weakConn]() { conn->renderServiceAgent_->RemoveToken(token); }); | ||
| 422 | + }); | ||
| 423 | + ``` | ||
| 424 | + | ||
| 425 | +2. **把同步 IPC 改为异步** | ||
| 426 | + 如果 `renderServiceAgent_` 支持异步 IPC,使用 `TF_ASYNC` 标志不等待响应。 | ||
| 427 | + | ||
| 428 | +3. **把延迟任务拆成多个小任务** | ||
| 429 | + 把 `doCleanup` 拆成多个小任务分多次 post 到 main thread,让主线程有机会处理 VSync。 | ||
| 430 | + | ||
| 431 | +--- | ||
| 432 | + | ||
| 433 | +## 7. 异常与边界处理 | ||
| 434 | + | ||
| 435 | +```mermaid | ||
| 436 | +flowchart TD | ||
| 437 | + A[边界场景] --> B[同一 pid 多次建立连接] | ||
| 438 | + A --> C[延迟任务执行前连接已析构] | ||
| 439 | + A --> D[TriggerImmediateCleanup 时 pid 无延迟任务] | ||
| 440 | + A --> E[renderPipelineAgent_ == nullptr] | ||
| 441 | + A --> F[renderProcessManagerAgent_ == nullptr] | ||
| 442 | + A --> G[clientToService == nullptr] | ||
| 443 | + | ||
| 444 | + B --> B1[AddConnection 替换旧连接] | ||
| 445 | + B --> B2[旧连接 cleanDone_ = true] | ||
| 446 | + B --> B3[防止重复清理] | ||
| 447 | + | ||
| 448 | + C --> C1[wptr.promote 失败] | ||
| 449 | + C --> C2[lambda 直接返回] | ||
| 450 | + | ||
| 451 | + D --> D1[delayCleanupTasks_.find 失败] | ||
| 452 | + D --> D2[delayCleanupPids_.erase(pid)] | ||
| 453 | + | ||
| 454 | + E --> E1[DoClean 直接返回] | ||
| 455 | + E --> E2[不崩溃] | ||
| 456 | + | ||
| 457 | + F --> F1[Broadcast... 直接返回] | ||
| 458 | + F --> F2[不崩溃] | ||
| 459 | + | ||
| 460 | + G --> G1[返回 ERR_INVALID_DATA] | ||
| 461 | +``` | ||
| 462 | + | ||
| 463 | +| 场景 | 处理 | | ||
| 464 | +|------|------| | ||
| 465 | +| 同一 pid 多次建立连接 | `AddConnection` 替换旧连接;旧连接 `cleanDone_ = true` 防止重复清理 | | ||
| 466 | +| 延迟任务执行前连接已析构 | `wptr.promote()` 失败,lambda 直接返回 | | ||
| 467 | +| `TriggerImmediateCleanup` 时 pid 无延迟任务 | `delayCleanupTasks_.find(pid)` 失败,无任务可执行,但仍从 `delayCleanupPids_` 移除该 pid | | ||
| 468 | +| `renderPipelineAgent_ == nullptr`(多进程) | `DoClean()` 直接返回,不崩溃 | | ||
| 469 | +| `renderProcessManagerAgent_ == nullptr` | `Broadcast...()` 直接返回,不崩溃 | | ||
| 470 | +| `clientToService == nullptr`(客户端) | 返回 `ERR_INVALID_DATA` | | ||
| 471 | + | ||
| 472 | +--- | ||
| 473 | + | ||
| 474 | +## 8. 接口清单 | ||
| 475 | + | ||
| 476 | +### 8.1 客户端公开接口 | ||
| 477 | + | ||
| 478 | +```cpp | ||
| 479 | +class RSInterfaces { | ||
| 480 | +public: | ||
| 481 | + /// @brief 为当前进程启用/禁用延迟清理 | ||
| 482 | + /// @param enabled true 启用,false 禁用 | ||
| 483 | + /// @return true 成功,false 失败 | ||
| 484 | + bool SetDelayedCleanupEnabled(bool enabled); | ||
| 485 | + | ||
| 486 | + /// @brief 立即清理指定 pid 的延迟资源 | ||
| 487 | + /// @param pid 旧进程 pid | ||
| 488 | + /// @return true 成功,false 失败 | ||
| 489 | + bool TriggerImmediateCleanup(pid_t pid); | ||
| 490 | +}; | ||
| 491 | +``` | ||
| 492 | + | ||
| 493 | +### 8.2 Service 端 IPC 接口 | ||
| 494 | + | ||
| 495 | +```cpp | ||
| 496 | +class RSIClientToServiceConnection : public IRemoteBroker { | ||
| 497 | +public: | ||
| 498 | + virtual ErrCode SetDelayedCleanupEnabled(bool enabled) = 0; | ||
| 499 | + virtual ErrCode TriggerImmediateCleanup(pid_t pid) = 0; | ||
| 500 | +}; | ||
| 501 | +``` | ||
| 502 | + | ||
| 503 | +### 8.3 Service→Render IPC 接口(多进程广播) | ||
| 504 | + | ||
| 505 | +```cpp | ||
| 506 | +class RSIServiceToRenderConnection { | ||
| 507 | +public: | ||
| 508 | + virtual void SetDelayedCleanupEnabled(pid_t pid, bool enabled) = 0; | ||
| 509 | + virtual void TriggerImmediateCleanup(pid_t pid) = 0; | ||
| 510 | +}; | ||
| 511 | +``` | ||
| 512 | + | ||
| 513 | +--- | ||
| 514 | + | ||
| 515 | +## 9. 修改文件清单 | ||
| 516 | + | ||
| 517 | +### 9.1 核心延迟逻辑(4 个文件) | ||
| 518 | + | ||
| 519 | +| 文件 | 修改内容 | | ||
| 520 | +|------|----------| | ||
| 521 | +| `rs_main_thread.h/.cpp` | 新增 `Set/Is/TriggerDelayedCleanupEnabled`、`Register/UnregisterDelayCleanupTask`、`DelayCleanupInfo` | | ||
| 522 | +| `rs_render_pipeline_agent.h/.cpp` | 新增 `DoClean(pid, forRefresh, sync)`、`Set/TriggerDelayedCleanupEnabled`、`HasRenderPipeline()`;多进程下 `rsRenderPipeline_ == nullptr` 时 fallback 到 `RSMainThread::Instance()` | | ||
| 523 | + | ||
| 524 | +### 9.2 Service 端接口与实现(7 个文件) | ||
| 525 | + | ||
| 526 | +| 文件 | 修改内容 | | ||
| 527 | +|------|----------| | ||
| 528 | +| `rs_iclient_to_service_connection.h` | 新增两个纯虚接口(返回 `ErrCode`) | | ||
| 529 | +| `rs_iclient_to_service_connection_ipc_interface_code.h` | 新增枚举值 `0x014005`、`0x014006` | | ||
| 530 | +| `rs_client_to_service_connection_proxy.h/.cpp` | 新增 Proxy 实现 | | ||
| 531 | +| `rs_client_to_service_connection_stub.cpp` | 新增 Stub 分发 | | ||
| 532 | +| `rs_client_to_service_connection.h/.cpp` | 新增实现(本地 + 广播);`CleanForRefresh` 拆分为 `DoCleanForRefresh()`,供延迟清理路径直接调用 | | ||
| 533 | + | ||
| 534 | +### 9.3 Render 端连接调整(3 个文件) | ||
| 535 | + | ||
| 536 | +| 文件 | 修改内容 | | ||
| 537 | +|------|----------| | ||
| 538 | +| `rs_client_to_render_connection.h/.cpp` | `CleanAll` 改为查询 `RSMainThread::IsDelayCleanupEnabled` 并 post 延迟任务;多进程下 `DoClean()` 因 `rsRenderPipeline_ == nullptr` 不执行核心清理,但仍延迟执行 `RemoveConnection` / `UnRegisterApplicationAgent`;`ExecuteCleanup` 通过 `HasRenderPipeline()` 跳过空转;`CleanAll` 在 multi-process 且 `toDelete == false` 时不 post 无意义延迟任务;移除 `SetDelayedCleanupEnabled`/`TriggerImmediateCleanup`/`renderService_` | | ||
| 539 | +| `rs_render_service.h` | 移除 `friend class RSClientToRenderConnection` | | ||
| 540 | + | ||
| 541 | +### 9.4 多进程广播 IPC(7 个文件) | ||
| 542 | + | ||
| 543 | +| 文件 | 修改内容 | | ||
| 544 | +|------|----------| | ||
| 545 | +| `rs_iservice_to_render_connection.h` | 新增两个纯虚接口 | | ||
| 546 | +| `rs_iservice_to_render_connection_ipc_interface_code.h` | 新增枚举值 `0x00F015`、`0x00F016` | | ||
| 547 | +| `rs_service_to_render_connection_proxy.h/.cpp` | 新增 Proxy 实现 | | ||
| 548 | +| `rs_service_to_render_connection_stub.cpp` | 新增 Stub 分发 | | ||
| 549 | +| `rs_service_to_render_connection.h/.cpp` | 新增转发实现 | | ||
| 550 | + | ||
| 551 | +### 9.5 客户端接口调整(6 个文件) | ||
| 552 | + | ||
| 553 | +| 文件 | 修改内容 | | ||
| 554 | +|------|----------| | ||
| 555 | +| `rs_interfaces.h/.cpp` | 新增 `Set/TriggerDelayedCleanupEnabled`(`RSInterfaces` 返回 `bool`) | | ||
| 556 | +| `rs_render_service_client.h` | 新增两个纯虚方法声明(返回 `ErrCode`) | | ||
| 557 | +| `rs_render_service_client.cpp` (OHOS/Darwin/Windows) | 新增实现 | | ||
| 558 | + | ||
| 559 | +### 9.6 权限校验(1 个文件) | ||
| 560 | + | ||
| 561 | +| 文件 | 修改内容 | | ||
| 562 | +|------|----------| | ||
| 563 | +| `rs_iclient_to_service_connection_ipc_interface_code_access_verifier.cpp` | 新增 `SET_DELAYED_CLEANUP_ENABLED`/`TRIGGER_IMMEDIATE_CLEANUP` case,限制为 `IsSystemCalling` | | ||
| 564 | + | ||
| 565 | +--- | ||
| 566 | + | ||
| 567 | +## 10. 附录 | ||
| 568 | + | ||
| 569 | +### 10.1 枚举值分配 | ||
| 570 | + | ||
| 571 | +**Service 端(`RSIClientToServiceConnectionInterfaceCode`)**: | ||
| 572 | +- `SET_DELAYED_CLEANUP_ENABLED = 0x014005` | ||
| 573 | +- `TRIGGER_IMMEDIATE_CLEANUP = 0x014006` | ||
| 574 | + | ||
| 575 | +**Service→Render(`RSIServiceToRenderConnectionInterfaceCode`)**: | ||
| 576 | +- `SET_DELAYED_CLEANUP_ENABLED = 0x00F015` | ||
| 577 | +- `TRIGGER_IMMEDIATE_CLEANUP = 0x00F016` | ||
| 578 | + | ||
| 579 | +### 10.2 线程安全说明 | ||
| 580 | + | ||
| 581 | +- `RSMainThread::delayCleanupMutex_` 保护 `delayCleanupPids_` 和 `delayCleanupTasks_` | ||
| 582 | +- `RSClientTo*Connection::mutex_` 保护 `cleanDone_` | ||
| 583 | +- `RSClientToServiceConnection::pidToBundleMutex_` 保护 `pidToBundleName_` | ||
| 584 | +- `RSScreenManagerAgent::mutex_` 保护 `virtualScreenIds_` | ||
| @@ -899,6 +899,72 @@ void RSMainThread::CleanResources(pid_t pid, bool forRefresh) | |||
| 899 | } | 899 | } |
| 900 | } | 900 | } |
| 901 | 901 | ||
| 902 | +void RSMainThread::SetDelayedCleanupEnabled(pid_t pid, bool enabled) | ||
| 903 | +{ | ||
| 904 | + std::lock_guard<std::mutex> lock(delayCleanupMutex_); | ||
| 905 | + if (enabled) { | ||
| 906 | + delayCleanupPids_.insert(pid); | ||
| 907 | + } else { | ||
| 908 | + delayCleanupPids_.erase(pid); | ||
| 909 | + } | ||
| 910 | +} | ||
| 911 | + | ||
| 912 | +bool RSMainThread::IsDelayCleanupEnabled(pid_t pid) | ||
| 913 | +{ | ||
| 914 | + std::lock_guard<std::mutex> lock(delayCleanupMutex_); | ||
| 915 | + return delayCleanupPids_.find(pid) != delayCleanupPids_.end(); | ||
| 916 | +} | ||
| 917 | + | ||
| 918 | +void RSMainThread::TriggerImmediateCleanup(pid_t pid) | ||
| 919 | +{ | ||
| 920 | + std::vector<DelayCleanupInfo> infos; | ||
| 921 | + { | ||
| 922 | + std::lock_guard<std::mutex> lock(delayCleanupMutex_); | ||
| 923 | + auto it = delayCleanupTasks_.find(pid); | ||
| 924 | + if (it != delayCleanupTasks_.end()) { | ||
| 925 | + infos = std::move(it->second); | ||
| 926 | + delayCleanupTasks_.erase(it); | ||
| 927 | + } | ||
| 928 | + } | ||
| 929 | + for (const auto& info : infos) { | ||
| 930 | + RemoveTask(info.taskName); | ||
| 931 | + if (info.cleanupFunc) { | ||
| 932 | + info.cleanupFunc(); | ||
| 933 | + } | ||
| 934 | + } | ||
| 935 | + { | ||
| 936 | + std::lock_guard<std::mutex> lock(delayCleanupMutex_); | ||
| 937 | + delayCleanupPids_.erase(pid); | ||
注意看下这个容器会不会产生泄露 ![]() ![]() | |||
| 938 | + } | ||
| 939 | +} | ||
| 940 | + | ||
| 941 | +void RSMainThread::RegisterDelayCleanupTask(pid_t pid, const std::string& taskName, std::function<void()> cleanupFunc) | ||
| 942 | +{ | ||
| 943 | + std::lock_guard<std::mutex> lock(delayCleanupMutex_); | ||
| 944 | + delayCleanupTasks_[pid].push_back({taskName, std::move(cleanupFunc)}); | ||
| 945 | +} | ||
| 946 | + | ||
| 947 | +void RSMainThread::UnregisterDelayCleanupTask(const std::string& taskName) | ||
| 948 | +{ | ||
| 949 | + std::lock_guard<std::mutex> lock(delayCleanupMutex_); | ||
| 950 | + pid_t pidToErase = -1; | ||
| 951 | + for (auto& [pid, infos] : delayCleanupTasks_) { | ||
| 952 | + auto it = std::find_if(infos.begin(), infos.end(), | ||
| 953 | + [&taskName](const auto& info) { return info.taskName == taskName; }); | ||
| 954 | + if (it != infos.end()) { | ||
| 955 | + infos.erase(it); | ||
| 956 | + if (infos.empty()) { | ||
| 957 | + pidToErase = pid; | ||
| 958 | + } | ||
| 959 | + break; | ||
| 960 | + } | ||
| 961 | + } | ||
| 962 | + if (pidToErase != -1) { | ||
| 963 | + delayCleanupTasks_.erase(pidToErase); | ||
| 964 | + delayCleanupPids_.erase(pidToErase); | ||
| 965 | + } | ||
| 966 | +} | ||
| 967 | + | ||
| 902 | bool RSMainThread::GetMaxGpuBufferSize(uint32_t& maxWidth, uint32_t& maxHeight) | 968 | bool RSMainThread::GetMaxGpuBufferSize(uint32_t& maxWidth, uint32_t& maxHeight) |
| 903 | { | 969 | { |
| 904 | RS_LOGI("GetMaxGpuBufferSize: start query GPU buffer size limits"); | 970 | RS_LOGI("GetMaxGpuBufferSize: start query GPU buffer size limits"); |
| @@ -469,6 +469,11 @@ public: | |||
| 469 | bool TransitionDataMutexLockIfNoCommands(); | 469 | bool TransitionDataMutexLockIfNoCommands(); |
| 470 | void TransitionDataMutexUnlock(); | 470 | void TransitionDataMutexUnlock(); |
| 471 | void CleanResources(pid_t pid, bool forRefresh = false); | 471 | void CleanResources(pid_t pid, bool forRefresh = false); |
| 472 | + void SetDelayedCleanupEnabled(pid_t pid, bool enabled); | ||
| 473 | + bool IsDelayCleanupEnabled(pid_t pid); | ||
| 474 | + void TriggerImmediateCleanup(pid_t pid); | ||
| 475 | + void RegisterDelayCleanupTask(pid_t pid, const std::string& taskName, std::function<void()> cleanupFunc); | ||
| 476 | + void UnregisterDelayCleanupTask(const std::string& taskName); | ||
| 472 | bool GetMaxGpuBufferSize(uint32_t& maxWidth, uint32_t& maxHeight); | 477 | bool GetMaxGpuBufferSize(uint32_t& maxWidth, uint32_t& maxHeight); |
| 473 | 478 | ||
| 474 | const std::shared_ptr<RSHwcContext>& GetHwcContext() const { return hwcContext_; } | 479 | const std::shared_ptr<RSHwcContext>& GetHwcContext() const { return hwcContext_; } |
| @@ -864,6 +869,13 @@ private: | |||
| 864 | friend class RSProfiler; | 869 | friend class RSProfiler; |
| 865 | 870 | ||
| 866 | std::set<pid_t> exitedPidSet_; | 871 | std::set<pid_t> exitedPidSet_; |
| 872 | + struct DelayCleanupInfo { | ||
| 873 | + std::string taskName; | ||
| 874 | + std::function<void()> cleanupFunc; | ||
| 875 | + }; | ||
| 876 | + mutable std::mutex delayCleanupMutex_; | ||
| 877 | + std::unordered_set<pid_t> delayCleanupPids_; | ||
| 878 | + std::unordered_map<pid_t, std::vector<DelayCleanupInfo>> delayCleanupTasks_; | ||
| 867 | 879 | ||
| 868 | RSDrawFrame drawFrame_; | 880 | RSDrawFrame drawFrame_; |
| 869 | 881 | ||
| @@ -2061,6 +2061,11 @@ ErrCode RSRenderPipelineAgent::RepaintEverything() | |||
| 2061 | } | 2061 | } |
| 2062 | 2062 | ||
| 2063 | void RSRenderPipelineAgent::Clean(pid_t pid, bool forRefresh) | 2063 | void RSRenderPipelineAgent::Clean(pid_t pid, bool forRefresh) |
| 2064 | +{ | ||
| 2065 | + DoClean(pid, forRefresh, true); | ||
| 2066 | +} | ||
| 2067 | + | ||
| 2068 | +void RSRenderPipelineAgent::DoClean(pid_t pid, bool forRefresh, bool sync) | ||
| 2064 | { | 2069 | { |
| 2065 | auto pipeline = rsRenderPipeline_.lock(); | 2070 | auto pipeline = rsRenderPipeline_.lock(); |
| 2066 | if (!pipeline) { | 2071 | if (!pipeline) { |
| @@ -2069,13 +2074,20 @@ void RSRenderPipelineAgent::Clean(pid_t pid, bool forRefresh) | |||
| 2069 | RS_LOGD("Clean() start, remotePid: %{public}s, forRefresh: %{public}d", std::to_string(pid).c_str(), forRefresh); | 2074 | RS_LOGD("Clean() start, remotePid: %{public}s, forRefresh: %{public}d", std::to_string(pid).c_str(), forRefresh); |
| 2070 | RS_TRACE_NAME("RSRenderPipelineAgent::Clean begin, remotePid: " + std::to_string(pid)); | 2075 | RS_TRACE_NAME("RSRenderPipelineAgent::Clean begin, remotePid: " + std::to_string(pid)); |
| 2071 | RsCommandVerifyHelper::GetInstance().RemoveCntWithPid(pid); | 2076 | RsCommandVerifyHelper::GetInstance().RemoveCntWithPid(pid); |
| 2072 | - pipeline | 2077 | + if (sync) { |
| 2073 | - ->ScheduleMainThreadTask([mainThread = pipeline->GetMainThread(), pid, forRefresh]() { | 2078 | + pipeline |
| 2074 | - if (mainThread == nullptr) { | 2079 | + ->ScheduleMainThreadTask([mainThread = pipeline->GetMainThread(), pid, forRefresh]() { |
| 2075 | - return; | 2080 | + if (mainThread == nullptr) { |
| 2076 | - } | 2081 | + return; |
| 2082 | + } | ||
| 2083 | + mainThread->CleanResources(pid, forRefresh); | ||
| 2084 | + }).wait(); | ||
| 2085 | + } else { | ||
| 2086 | + auto mainThread = pipeline->GetMainThread(); | ||
| 2087 | + if (mainThread != nullptr) { | ||
| 2077 | mainThread->CleanResources(pid, forRefresh); | 2088 | mainThread->CleanResources(pid, forRefresh); |
| 2078 | - }).wait(); | 2089 | + } |
| 2090 | + } | ||
| 2079 | RSSurfaceBufferCallbackManager::Instance().UnregisterSurfaceBufferCallback(pid); | 2091 | RSSurfaceBufferCallbackManager::Instance().UnregisterSurfaceBufferCallback(pid); |
| 2080 | RSTypefaceCache::Instance().RemoveDrawingTypefacesByPid(pid); | 2092 | RSTypefaceCache::Instance().RemoveDrawingTypefacesByPid(pid); |
| 2081 | { | 2093 | { |
| @@ -2091,6 +2103,68 @@ void RSRenderPipelineAgent::Clean(pid_t pid, bool forRefresh) | |||
| 2091 | RS_TRACE_NAME("RSRenderPipelineAgent::Clean end, remotePid: " + std::to_string(pid)); | 2103 | RS_TRACE_NAME("RSRenderPipelineAgent::Clean end, remotePid: " + std::to_string(pid)); |
| 2092 | } | 2104 | } |
| 2093 | 2105 | ||
| 2106 | +void RSRenderPipelineAgent::SetDelayedCleanupEnabled(pid_t pid, bool enabled) | ||
| 2107 | +{ | ||
| 2108 | + auto renderPipeline = rsRenderPipeline_.lock(); | ||
| 2109 | + if (renderPipeline == nullptr) { | ||
| 2110 | + return; | ||
| 2111 | + } | ||
| 2112 | + renderPipeline->ScheduleMainThreadTask( | ||
| 2113 | + [mainThread = renderPipeline->GetMainThread(), pid, enabled]() { | ||
| 2114 | + mainThread->SetDelayedCleanupEnabled(pid, enabled); | ||
| 2115 | + }).wait(); | ||
| 2116 | +} | ||
| 2117 | + | ||
| 2118 | +void RSRenderPipelineAgent::TriggerImmediateCleanup(pid_t pid) | ||
| 2119 | +{ | ||
| 2120 | + auto renderPipeline = rsRenderPipeline_.lock(); | ||
| 2121 | + if (renderPipeline == nullptr) { | ||
| 2122 | + return; | ||
| 2123 | + } | ||
| 2124 | + renderPipeline->ScheduleMainThreadTask( | ||
| 2125 | + [mainThread = renderPipeline->GetMainThread(), pid]() { | ||
| 2126 | + mainThread->TriggerImmediateCleanup(pid); | ||
| 2127 | + }).wait(); | ||
| 2128 | +} | ||
| 2129 | + | ||
| 2130 | +bool RSRenderPipelineAgent::IsDelayCleanupEnabled(pid_t pid) | ||
| 2131 | +{ | ||
| 2132 | + auto renderPipeline = rsRenderPipeline_.lock(); | ||
| 2133 | + if (renderPipeline == nullptr) { | ||
| 2134 | + return false; | ||
| 2135 | + } | ||
| 2136 | + return renderPipeline->GetMainThread()->IsDelayCleanupEnabled(pid); | ||
| 2137 | +} | ||
| 2138 | + | ||
| 2139 | +void RSRenderPipelineAgent::PostDelayCleanupTask(pid_t pid, const std::string& taskName, | ||
| 2140 | + std::function<void()> cleanupFunc, uint32_t delayMs) | ||
| 2141 | +{ | ||
| 2142 | + auto renderPipeline = rsRenderPipeline_.lock(); | ||
| 2143 | + if (renderPipeline == nullptr) { | ||
| 2144 | + return; | ||
| 2145 | + } | ||
| 2146 | + auto mainThread = renderPipeline->GetMainThread(); | ||
| 2147 | + mainThread->RegisterDelayCleanupTask(pid, taskName, cleanupFunc); | ||
| 2148 | + mainThread->PostTask( | ||
| 2149 | + [mainThread, cleanupFunc, taskName]() { | ||
| 2150 | + cleanupFunc(); | ||
| 2151 | + mainThread->UnregisterDelayCleanupTask(taskName); | ||
| 2152 | + }, taskName, delayMs); | ||
| 2153 | +} | ||
| 2154 | + | ||
| 2155 | +sptr<IApplicationAgent> RSRenderPipelineAgent::UnRegisterApplicationAgentOnMainThread(pid_t pid) | ||
| 2156 | +{ | ||
| 2157 | + auto renderPipeline = rsRenderPipeline_.lock(); | ||
| 2158 | + if (renderPipeline != nullptr) { | ||
| 2159 | + auto mainThread = renderPipeline->GetMainThread(); | ||
| 2160 | + if (mainThread == nullptr) { | ||
| 2161 | + return nullptr; | ||
| 2162 | + } | ||
| 2163 | + return mainThread->UnRegisterApplicationAgent(pid); | ||
| 2164 | + } | ||
| 2165 | + return RSMainThread::Instance()->UnRegisterApplicationAgent(pid); | ||
| 2166 | +} | ||
| 2167 | + | ||
| 2094 | ErrCode RSRenderPipelineAgent::SetColorFollow(const std::string& nodeIdStr, bool isColorFollow) | 2168 | ErrCode RSRenderPipelineAgent::SetColorFollow(const std::string& nodeIdStr, bool isColorFollow) |
| 2095 | { | 2169 | { |
| 2096 | auto pipeline = rsRenderPipeline_.lock(); | 2170 | auto pipeline = rsRenderPipeline_.lock(); |
| @@ -181,6 +181,8 @@ public: | |||
| 181 | ErrCode RepaintEverything(); | 181 | ErrCode RepaintEverything(); |
| 182 | ErrCode SetColorFollow(const std::string &nodeIdStr, bool isColorFollow); | 182 | ErrCode SetColorFollow(const std::string &nodeIdStr, bool isColorFollow); |
| 183 | void Clean(pid_t pid, bool forRefresh = false); | 183 | void Clean(pid_t pid, bool forRefresh = false); |
| 184 | + void DoClean(pid_t pid, bool forRefresh, bool sync); | ||
| 185 | + bool HasRenderPipeline() const { return rsRenderPipeline_.lock() != nullptr; } | ||
| 184 | void SetFreeMultiWindowStatus(bool enable); | 186 | void SetFreeMultiWindowStatus(bool enable); |
| 185 | int32_t RegisterSelfDrawingNodeRectChangeCallback( | 187 | int32_t RegisterSelfDrawingNodeRectChangeCallback( |
| 186 | pid_t remotePid, const RectConstraint& constraint, sptr<RSISelfDrawingNodeRectChangeCallback> callback); | 188 | pid_t remotePid, const RectConstraint& constraint, sptr<RSISelfDrawingNodeRectChangeCallback> callback); |
| @@ -208,6 +210,12 @@ public: | |||
| 208 | void ClearSurfaceWatermarkForNodes(pid_t pid, const std::string& name, | 210 | void ClearSurfaceWatermarkForNodes(pid_t pid, const std::string& name, |
| 209 | const std::vector<NodeId>& nodeIdList, bool isSystemCalling); | 211 | const std::vector<NodeId>& nodeIdList, bool isSystemCalling); |
| 210 | void ForceRefreshOneFrameWithNextVSync(); | 212 | void ForceRefreshOneFrameWithNextVSync(); |
| 213 | + void SetDelayedCleanupEnabled(pid_t pid, bool enabled); | ||
| 214 | + void TriggerImmediateCleanup(pid_t pid); | ||
| 215 | + bool IsDelayCleanupEnabled(pid_t pid); | ||
| 216 | + void PostDelayCleanupTask(pid_t pid, const std::string& taskName, | ||
| 217 | + std::function<void()> cleanupFunc, uint32_t delayMs); | ||
| 218 | + sptr<IApplicationAgent> UnRegisterApplicationAgentOnMainThread(pid_t pid); | ||
| 211 | std::string GetBundleName(pid_t pid); | 219 | std::string GetBundleName(pid_t pid); |
| 212 | void UnRegisterApplicationAgent(sptr<IApplicationAgent> app); | 220 | void UnRegisterApplicationAgent(sptr<IApplicationAgent> app); |
| 213 | sptr<IApplicationAgent> UnRegisterApplicationAgent(uint32_t pid); | 221 | sptr<IApplicationAgent> UnRegisterApplicationAgent(uint32_t pid); |
| @@ -60,7 +60,6 @@ | |||
| 60 | 60 | ||
| 61 | 61 | ||
| 62 | 62 | ||
| 63 | - | ||
| 64 | 63 | ||
| 65 | 64 | ||
| 66 | 65 | ||
| @@ -103,6 +102,7 @@ constexpr uint32_t MEM_BYTE_TO_MB = 1024 * 1024; | |||
| 103 | constexpr uint32_t PIDLIST_SIZE_MAX = 128; | 102 | constexpr uint32_t PIDLIST_SIZE_MAX = 128; |
| 104 | constexpr uint64_t MAX_TIME_OUT_NS = 1e9; | 103 | constexpr uint64_t MAX_TIME_OUT_NS = 1e9; |
| 105 | constexpr int64_t MAX_FREEZE_SCREEN_TIME = 3000; | 104 | constexpr int64_t MAX_FREEZE_SCREEN_TIME = 3000; |
| 105 | +constexpr int64_t DELAY_CLEANUP_MS = 10000; | ||
| 106 | const std::string UNFREEZE_SCREEN_TASK_NAME = "UNFREEZE_SCREEN_TASK"; | 106 | const std::string UNFREEZE_SCREEN_TASK_NAME = "UNFREEZE_SCREEN_TASK"; |
| 107 | } | 107 | } |
| 108 | const std::string RSClientToRenderConnection::GPU_FREQ_PREF = "GPU_FREQ_PREF"; | 108 | const std::string RSClientToRenderConnection::GPU_FREQ_PREF = "GPU_FREQ_PREF"; |
| @@ -162,26 +162,76 @@ void RSClientToRenderConnection::CleanAll(bool toDelete) noexcept | |||
| 162 | if (cleanDone_) { | 162 | if (cleanDone_) { |
| 163 | return; | 163 | return; |
| 164 | } | 164 | } |
| 165 | - } | ||
| 166 | - | ||
| 167 | - if (renderPipelineAgent_ == nullptr) { | ||
| 168 | - return; | ||
| 169 | - } | ||
| 170 | - | ||
| 171 | - renderPipelineAgent_->Clean(remotePid_, false); | ||
| 172 | - { | ||
| 173 | - std::lock_guard<std::mutex> lock(mutex_); | ||
| 174 | cleanDone_ = true; | 165 | cleanDone_ = true; |
| 175 | } | 166 | } |
| 176 | 167 | ||
| 177 | - if (toDelete) { | 168 | + if (renderPipelineAgent_ != nullptr && renderPipelineAgent_->IsDelayCleanupEnabled(remotePid_)) { |
| 178 | - auto token = iface_cast<RSIConnectionToken>(GetToken()); | 169 | + bool delayedTaskHasEffect = toDelete || renderPipelineAgent_->HasRenderPipeline(); |
| 179 | - renderPipelineAgent_->RemoveConnection(remotePid_, token); | 170 | + if (!delayedTaskHasEffect) { |
| 171 | + DoCleanAll(toDelete); | ||
| 172 | + return; | ||
| 173 | + } | ||
| 174 | + std::string taskName = "DelayClean_Render_" + std::to_string(remotePid_); | ||
| 175 | + renderPipelineAgent_->PostDelayCleanupTask(remotePid_, taskName, | ||
| 176 | + [weakConn = wptr<RSClientToRenderConnection>(this), toDelete]() { | ||
| 177 | + auto conn = weakConn.promote(); | ||
| 178 | + if (conn == nullptr) { | ||
| 179 | + return; | ||
| 180 | + } | ||
| 181 | + conn->ExecuteCleanup(toDelete); | ||
| 182 | + }, DELAY_CLEANUP_MS); | ||
| 183 | + } else { | ||
| 184 | + DoCleanAll(toDelete); | ||
| 185 | + } | ||
| 186 | +} | ||
| 180 | 187 | ||
| 188 | +void RSClientToRenderConnection::DoCleanAll(bool toDelete) | ||
| 189 | +{ | ||
| 190 | + if (renderPipelineAgent_ == nullptr) { | ||
| 191 | + return; | ||
| 192 | + } | ||
| 193 | + renderPipelineAgent_->Clean(remotePid_, false); | ||
| 194 | + if (toDelete) { | ||
| 181 | auto appToken = renderPipelineAgent_->UnRegisterApplicationAgent(remotePid_); | 195 | auto appToken = renderPipelineAgent_->UnRegisterApplicationAgent(remotePid_); |
| 182 | if (appToken && appToken->AsObject() && applicationDeathRecipient_) { | 196 | if (appToken && appToken->AsObject() && applicationDeathRecipient_) { |
| 183 | appToken->AsObject()->RemoveDeathRecipient(applicationDeathRecipient_); | 197 | appToken->AsObject()->RemoveDeathRecipient(applicationDeathRecipient_); |
| 184 | } | 198 | } |
| 199 | + | ||
| 200 | + if (renderPipelineAgent_->HasRenderPipeline()) { | ||
| 201 | + auto token = iface_cast<RSIConnectionToken>(GetToken()); | ||
| 202 | + if (token != nullptr) { | ||
| 203 | + renderPipelineAgent_->RemoveConnection(remotePid_, token); | ||
| 204 | + } | ||
| 205 | + } | ||
| 206 | + } | ||
| 207 | +} | ||
| 208 | + | ||
| 209 | +void RSClientToRenderConnection::ExecuteCleanup(bool toDelete) | ||
| 210 | +{ | ||
| 211 | + if (renderPipelineAgent_ == nullptr) { | ||
| 212 | + return; | ||
| 213 | + } | ||
| 214 | + bool expected = false; | ||
| 215 | + if (!delayCleanupExecuted_.compare_exchange_strong(expected, true)) { | ||
| 216 | + return; | ||
| 217 | + } | ||
| 218 | + if (renderPipelineAgent_->HasRenderPipeline()) { | ||
| 219 | + renderPipelineAgent_->DoClean(remotePid_, false, false); | ||
| 220 | + } | ||
| 221 | + if (toDelete) { | ||
| 222 | + // ExecuteCleanup runs on RSMainThread, call UnRegisterApplicationAgentOnMainThread | ||
| 223 | + // to avoid renderPipelineAgent_->UnRegisterApplicationAgent deadlock. | ||
| 224 | + auto appToken = renderPipelineAgent_->UnRegisterApplicationAgentOnMainThread(remotePid_); | ||
| 225 | + if (appToken && appToken->AsObject() && applicationDeathRecipient_) { | ||
| 226 | + appToken->AsObject()->RemoveDeathRecipient(applicationDeathRecipient_); | ||
| 227 | + } | ||
| 228 | + | ||
| 229 | + if (renderPipelineAgent_->HasRenderPipeline()) { | ||
| 230 | + auto token = iface_cast<RSIConnectionToken>(GetToken()); | ||
| 231 | + if (token != nullptr) { | ||
| 232 | + renderPipelineAgent_->RemoveConnection(remotePid_, token); | ||
| 233 | + } | ||
| 234 | + } | ||
| 185 | } | 235 | } |
| 186 | } | 236 | } |
| 187 | 237 | ||
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| @@ -249,8 +250,12 @@ private: | |||
| 249 | friend class RSApplicationRenderThreadDeathRecipient; | 250 | friend class RSApplicationRenderThreadDeathRecipient; |
| 250 | sptr<RSApplicationRenderThreadDeathRecipient> applicationDeathRecipient_ = nullptr; | 251 | sptr<RSApplicationRenderThreadDeathRecipient> applicationDeathRecipient_ = nullptr; |
| 251 | 252 | ||
| 253 | + void DoCleanAll(bool toDelete); | ||
| 254 | + void ExecuteCleanup(bool toDelete); | ||
| 255 | + | ||
| 252 | mutable std::mutex mutex_; | 256 | mutable std::mutex mutex_; |
| 253 | bool cleanDone_ = false; | 257 | bool cleanDone_ = false; |
| 258 | + std::atomic<bool> delayCleanupExecuted_ { false }; | ||
| 254 | bool needRefresh_ = true; | 259 | bool needRefresh_ = true; |
| 255 | const std::string VOTER_SCENE_BLUR = "VOTER_SCENE_BLUR"; | 260 | const std::string VOTER_SCENE_BLUR = "VOTER_SCENE_BLUR"; |
| 256 | const std::string VOTER_SCENE_GPU = "VOTER_SCENE_GPU"; | 261 | const std::string VOTER_SCENE_GPU = "VOTER_SCENE_GPU"; |
| @@ -592,6 +592,14 @@ bool RSIClientToServiceConnectionInterfaceCodeAccessVerifier::IsExclusiveVerific | |||
| 592 | hasPermission = IsSystemCalling(codeEnumTypeName_ + "::SET_APS_CONFIG_PARAMS"); | 592 | hasPermission = IsSystemCalling(codeEnumTypeName_ + "::SET_APS_CONFIG_PARAMS"); |
| 593 | break; | 593 | break; |
| 594 | } | 594 | } |
| 595 | + case static_cast<CodeUnderlyingType>(CodeEnumType::SET_DELAYED_CLEANUP_ENABLED): { | ||
| 596 | + hasPermission = IsSystemCalling(codeEnumTypeName_ + "::SET_DELAYED_CLEANUP_ENABLED"); | ||
| 597 | + break; | ||
| 598 | + } | ||
| 599 | + case static_cast<CodeUnderlyingType>(CodeEnumType::TRIGGER_IMMEDIATE_CLEANUP): { | ||
| 600 | + hasPermission = IsSystemCalling(codeEnumTypeName_ + "::TRIGGER_IMMEDIATE_CLEANUP"); | ||
| 601 | + break; | ||
| 602 | + } | ||
| 595 | default: { | 603 | default: { |
| 596 | break; | 604 | break; |
| 597 | } | 605 | } |
Mrosen/modules/render_service/main/render_process/transaction/rs_service_to_render_connection.cpp+10-0
| @@ -366,5 +366,15 @@ void RSServiceToRenderConnection::SetCacheEnabledForRotation(bool enabled) | |||
| 366 | { | 366 | { |
| 367 | renderPipelineAgent_->SetCacheEnabledForRotation(enabled); | 367 | renderPipelineAgent_->SetCacheEnabledForRotation(enabled); |
| 368 | } | 368 | } |
| 369 | + | ||
| 370 | +void RSServiceToRenderConnection::SetDelayedCleanupEnabled(pid_t pid, bool enabled) | ||
| 371 | +{ | ||
| 372 | + renderPipelineAgent_->SetDelayedCleanupEnabled(pid, enabled); | ||
| 373 | +} | ||
| 374 | + | ||
| 375 | +void RSServiceToRenderConnection::TriggerImmediateCleanup(pid_t pid) | ||
| 376 | +{ | ||
| 377 | + renderPipelineAgent_->TriggerImmediateCleanup(pid); | ||
| 378 | +} | ||
| 369 | } // namespace Rosen | 379 | } // namespace Rosen |
| 370 | } // namespace OHOS | 380 | } // namespace OHOS |
| @@ -139,6 +139,8 @@ public: | |||
| 139 | int32_t RegisterUIExtensionCallback(pid_t pid, uint64_t userId, sptr<RSIUIExtensionCallback> callback, | 139 | int32_t RegisterUIExtensionCallback(pid_t pid, uint64_t userId, sptr<RSIUIExtensionCallback> callback, |
| 140 | bool unobscured = false) override; | 140 | bool unobscured = false) override; |
| 141 | void SetCacheEnabledForRotation(bool enabled) override; | 141 | void SetCacheEnabledForRotation(bool enabled) override; |
| 142 | + void SetDelayedCleanupEnabled(pid_t pid, bool enabled) override; | ||
| 143 | + void TriggerImmediateCleanup(pid_t pid) override; | ||
| 142 | void SetVmaCacheStatus(bool flag) override; | 144 | void SetVmaCacheStatus(bool flag) override; |
| 143 | 145 | ||
| 144 | private: | 146 | private: |
Mrosen/modules/render_service/main/render_process/transaction/zidl/rs_iservice_to_render_connection.h+2-0
| @@ -148,6 +148,8 @@ public: | |||
| 148 | bool unobscured = false) = 0; | 148 | bool unobscured = false) = 0; |
| 149 | virtual void ForceRefreshOneFrameWithNextVSync() = 0; | 149 | virtual void ForceRefreshOneFrameWithNextVSync() = 0; |
| 150 | virtual void SetCacheEnabledForRotation(bool enabled) = 0; | 150 | virtual void SetCacheEnabledForRotation(bool enabled) = 0; |
| 151 | + virtual void SetDelayedCleanupEnabled(pid_t pid, bool enabled) = 0; | ||
| 152 | + virtual void TriggerImmediateCleanup(pid_t pid) = 0; | ||
| 151 | }; | 153 | }; |
| 152 | 154 | ||
| 153 | } // namespace Rosen | 155 | } // namespace Rosen |
| @@ -90,6 +90,8 @@ enum class RSIServiceToRenderConnectionInterfaceCode : CodeUnderlyingType { | |||
| 90 | SET_CACHE_ENABLED_FOR_ROTATION = 0x00F013, | 90 | SET_CACHE_ENABLED_FOR_ROTATION = 0x00F013, |
| 91 | SET_HDR_FORCE_HWC_ENABLED = 0X00F014, | 91 | SET_HDR_FORCE_HWC_ENABLED = 0X00F014, |
| 92 | SET_APS_CONFIG_PARAMS = 0X00F016, | 92 | SET_APS_CONFIG_PARAMS = 0X00F016, |
| 93 | + SET_DELAYED_CLEANUP_ENABLED = 0x00F017, | ||
| 94 | + TRIGGER_IMMEDIATE_CLEANUP = 0x00F018, | ||
| 93 | }; | 95 | }; |
| 94 | 96 | ||
| 95 | } // namespace Rosen | 97 | } // namespace Rosen |
| @@ -1975,5 +1975,51 @@ void RSServiceToRenderConnectionProxy::SetCacheEnabledForRotation(bool enabled) | |||
| 1975 | RS_LOGE("%{public}s: SendRequest failed, err is %{public}d", __func__, err); | 1975 | RS_LOGE("%{public}s: SendRequest failed, err is %{public}d", __func__, err); |
| 1976 | } | 1976 | } |
| 1977 | } | 1977 | } |
| 1978 | + | ||
| 1979 | +void RSServiceToRenderConnectionProxy::SetDelayedCleanupEnabled(pid_t pid, bool enabled) | ||
| 1980 | +{ | ||
| 1981 | + MessageParcel data; | ||
| 1982 | + MessageParcel reply; | ||
| 1983 | + MessageOption option; | ||
| 1984 | + option.SetFlags(MessageOption::TF_ASYNC); | ||
| 1985 | + if (!data.WriteInterfaceToken(RSIServiceToRenderConnection::GetDescriptor())) { | ||
| 1986 | + RS_LOGE("%{public}s: WriteInterfaceToken failed", __func__); | ||
| 1987 | + return; | ||
| 1988 | + } | ||
| 1989 | + if (!data.WriteInt32(pid)) { | ||
| 1990 | + RS_LOGE("%{public}s: WriteInt32 pid failed", __func__); | ||
| 1991 | + return; | ||
| 1992 | + } | ||
| 1993 | + if (!data.WriteBool(enabled)) { | ||
| 1994 | + RS_LOGE("%{public}s: WriteBool enabled failed", __func__); | ||
| 1995 | + return; | ||
| 1996 | + } | ||
| 1997 | + uint32_t code = static_cast<uint32_t>(RSIServiceToRenderConnectionInterfaceCode::SET_DELAYED_CLEANUP_ENABLED); | ||
| 1998 | + int32_t err = Remote()->SendRequest(code, data, reply, option); | ||
| 1999 | + if (err != NO_ERROR) { | ||
| 2000 | + RS_LOGE("%{public}s: SendRequest failed, err is %{public}d", __func__, err); | ||
| 2001 | + } | ||
| 2002 | +} | ||
| 2003 | + | ||
| 2004 | +void RSServiceToRenderConnectionProxy::TriggerImmediateCleanup(pid_t pid) | ||
| 2005 | +{ | ||
| 2006 | + MessageParcel data; | ||
| 2007 | + MessageParcel reply; | ||
| 2008 | + MessageOption option; | ||
| 2009 | + option.SetFlags(MessageOption::TF_ASYNC); | ||
| 2010 | + if (!data.WriteInterfaceToken(RSIServiceToRenderConnection::GetDescriptor())) { | ||
| 2011 | + RS_LOGE("%{public}s: WriteInterfaceToken failed", __func__); | ||
| 2012 | + return; | ||
| 2013 | + } | ||
| 2014 | + if (!data.WriteInt32(pid)) { | ||
| 2015 | + RS_LOGE("%{public}s: WriteInt32 pid failed", __func__); | ||
| 2016 | + return; | ||
| 2017 | + } | ||
| 2018 | + uint32_t code = static_cast<uint32_t>(RSIServiceToRenderConnectionInterfaceCode::TRIGGER_IMMEDIATE_CLEANUP); | ||
| 2019 | + int32_t err = Remote()->SendRequest(code, data, reply, option); | ||
| 2020 | + if (err != NO_ERROR) { | ||
| 2021 | + RS_LOGE("%{public}s: SendRequest failed, err is %{public}d", __func__, err); | ||
| 2022 | + } | ||
| 2023 | +} | ||
| 1978 | } // namespace Rosen | 2024 | } // namespace Rosen |
| 1979 | } // namespace OHOS | 2025 | } // namespace OHOS |
| @@ -135,6 +135,8 @@ public: | |||
| 135 | int32_t RegisterUIExtensionCallback(pid_t pid, uint64_t userId, sptr<RSIUIExtensionCallback> callback, | 135 | int32_t RegisterUIExtensionCallback(pid_t pid, uint64_t userId, sptr<RSIUIExtensionCallback> callback, |
| 136 | bool unobscured = false) override; | 136 | bool unobscured = false) override; |
| 137 | void SetCacheEnabledForRotation(bool enabled) override; | 137 | void SetCacheEnabledForRotation(bool enabled) override; |
| 138 | + void SetDelayedCleanupEnabled(pid_t pid, bool enabled) override; | ||
| 139 | + void TriggerImmediateCleanup(pid_t pid) override; | ||
| 138 | void SetVmaCacheStatus(bool flag) override; | 140 | void SetVmaCacheStatus(bool flag) override; |
| 139 | 141 | ||
| 140 | private: | 142 | private: |
| @@ -1142,6 +1142,32 @@ int RSServiceToRenderConnectionStub::OnRemoteRequest( | |||
| 1142 | SetApsConfigParams(event, params); | 1142 | SetApsConfigParams(event, params); |
| 1143 | break; | 1143 | break; |
| 1144 | } | 1144 | } |
| 1145 | + case static_cast<uint32_t>(RSIServiceToRenderConnectionInterfaceCode::SET_DELAYED_CLEANUP_ENABLED): { | ||
| 1146 | + pid_t pid = 0; | ||
| 1147 | + if (!data.ReadInt32(pid)) { | ||
| 1148 | + RS_LOGE("%{public}s: ReadInt32 pid failed", __func__); | ||
| 1149 | + ret = ERR_INVALID_DATA; | ||
| 1150 | + break; | ||
| 1151 | + } | ||
| 1152 | + bool enabled = false; | ||
| 1153 | + if (!data.ReadBool(enabled)) { | ||
| 1154 | + RS_LOGE("%{public}s: ReadBool enabled failed", __func__); | ||
| 1155 | + ret = ERR_INVALID_DATA; | ||
| 1156 | + break; | ||
| 1157 | + } | ||
| 1158 | + SetDelayedCleanupEnabled(pid, enabled); | ||
| 1159 | + break; | ||
| 1160 | + } | ||
| 1161 | + case static_cast<uint32_t>(RSIServiceToRenderConnectionInterfaceCode::TRIGGER_IMMEDIATE_CLEANUP): { | ||
| 1162 | + pid_t pid = 0; | ||
| 1163 | + if (!data.ReadInt32(pid)) { | ||
| 1164 | + RS_LOGE("%{public}s: ReadInt32 pid failed", __func__); | ||
| 1165 | + ret = ERR_INVALID_DATA; | ||
| 1166 | + break; | ||
| 1167 | + } | ||
| 1168 | + TriggerImmediateCleanup(pid); | ||
| 1169 | + break; | ||
| 1170 | + } | ||
| 1145 | default: | 1171 | default: |
| 1146 | return IPCObjectStub::OnRemoteRequest(code, data, reply, option); | 1172 | return IPCObjectStub::OnRemoteRequest(code, data, reply, option); |
| 1147 | } | 1173 | } |
| @@ -546,5 +546,89 @@ void RSRenderService::ScreenManagerListener::OnProcessDisconnected(ScreenId scre | |||
| 546 | } | 546 | } |
| 547 | renderService_.vsyncManager_->OnScreenDisconnected(screenId, renderService_.handler_); | 547 | renderService_.vsyncManager_->OnScreenDisconnected(screenId, renderService_.handler_); |
| 548 | } | 548 | } |
| 549 | + | ||
| 550 | +void RSRenderService::SetDelayedCleanupEnabled(pid_t pid, bool enabled) | ||
| 551 | +{ | ||
| 552 | + std::lock_guard<std::mutex> lock(delayCleanupMutex_); | ||
| 553 | + if (enabled) { | ||
| 554 | + delayCleanupPids_.insert(pid); | ||
| 555 | + } else { | ||
| 556 | + delayCleanupPids_.erase(pid); | ||
| 557 | + } | ||
| 558 | +} | ||
| 559 | + | ||
| 560 | +bool RSRenderService::IsDelayCleanupEnabled(pid_t pid) | ||
| 561 | +{ | ||
| 562 | + std::lock_guard<std::mutex> lock(delayCleanupMutex_); | ||
| 563 | + return delayCleanupPids_.find(pid) != delayCleanupPids_.end(); | ||
| 564 | +} | ||
| 565 | + | ||
| 566 | +void RSRenderService::TriggerImmediateCleanup(pid_t pid) | ||
| 567 | +{ | ||
| 568 | + std::vector<DelayCleanupInfo> infos; | ||
| 569 | + { | ||
| 570 | + std::lock_guard<std::mutex> lock(delayCleanupMutex_); | ||
| 571 | + auto it = delayCleanupTasks_.find(pid); | ||
| 572 | + if (it != delayCleanupTasks_.end()) { | ||
| 573 | + infos = std::move(it->second); | ||
| 574 | + delayCleanupTasks_.erase(it); | ||
| 575 | + } | ||
| 576 | + } | ||
| 577 | + for (const auto& info : infos) { | ||
| 578 | + if (handler_) { | ||
| 579 | + handler_->RemoveTask(info.taskName); | ||
| 580 | + } | ||
| 581 | + if (info.cleanupFunc) { | ||
| 582 | + info.cleanupFunc(); | ||
| 583 | + } | ||
| 584 | + } | ||
| 585 | + { | ||
| 586 | + std::lock_guard<std::mutex> lock(delayCleanupMutex_); | ||
| 587 | + delayCleanupPids_.erase(pid); | ||
| 588 | + } | ||
| 589 | +} | ||
| 590 | + | ||
| 591 | +void RSRenderService::RegisterDelayCleanupTask(pid_t pid, const std::string& taskName, | ||
| 592 | + std::function<void()> cleanupFunc) | ||
| 593 | +{ | ||
| 594 | + std::lock_guard<std::mutex> lock(delayCleanupMutex_); | ||
| 595 | + delayCleanupTasks_[pid].push_back({taskName, std::move(cleanupFunc)}); | ||
| 596 | +} | ||
| 597 | + | ||
| 598 | +void RSRenderService::UnregisterDelayCleanupTask(const std::string& taskName) | ||
| 599 | +{ | ||
| 600 | + std::lock_guard<std::mutex> lock(delayCleanupMutex_); | ||
| 601 | + pid_t pidToErase = -1; | ||
| 602 | + for (auto it = delayCleanupTasks_.begin(); it != delayCleanupTasks_.end(); ++it) { | ||
| 603 | + auto& infos = it->second; | ||
| 604 | + for (auto infoIt = infos.begin(); infoIt != infos.end();) { | ||
| 605 | + if (infoIt->taskName == taskName) { | ||
| 606 | + infoIt = infos.erase(infoIt); | ||
| 607 | + } else { | ||
| 608 | + ++infoIt; | ||
| 609 | + } | ||
| 610 | + } | ||
| 611 | + if (infos.empty()) { | ||
| 612 | + pidToErase = it->first; | ||
| 613 | + } | ||
| 614 | + } | ||
| 615 | + if (pidToErase != -1) { | ||
| 616 | + delayCleanupTasks_.erase(pidToErase); | ||
| 617 | + delayCleanupPids_.erase(pidToErase); | ||
| 618 | + } | ||
| 619 | +} | ||
| 620 | + | ||
| 621 | +void RSRenderService::PostDelayCleanupTask(pid_t pid, const std::string& taskName, | ||
| 622 | + std::function<void()> cleanupFunc, uint32_t delayMs) | ||
| 623 | +{ | ||
| 624 | + RegisterDelayCleanupTask(pid, taskName, cleanupFunc); | ||
| 625 | + if (handler_) { | ||
| 626 | + handler_->PostTask( | ||
| 627 | + [this, cleanupFunc, taskName]() { | ||
| 628 | + cleanupFunc(); | ||
| 629 | + UnregisterDelayCleanupTask(taskName); | ||
| 630 | + }, taskName, delayMs); | ||
| 631 | + } | ||
| 632 | +} | ||
| 549 | } // namespace Rosen | 633 | } // namespace Rosen |
| 550 | } // namespace OHOS | 634 | } // namespace OHOS |
| @@ -19,6 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | + | ||
| 22 | 23 | ||
| 23 | 24 | ||
| 24 | 25 | ||
| @@ -135,6 +136,22 @@ private: | |||
| 135 | std::map<sptr<IRemoteObject>, | 136 | std::map<sptr<IRemoteObject>, |
| 136 | std::pair<sptr<RSIClientToServiceConnection>, sptr<RSIClientToRenderConnection>>> connections_; | 137 | std::pair<sptr<RSIClientToServiceConnection>, sptr<RSIClientToRenderConnection>>> connections_; |
| 137 | 138 | ||
| 139 | + struct DelayCleanupInfo { | ||
| 140 | + std::string taskName; | ||
| 141 | + std::function<void()> cleanupFunc; | ||
| 142 | + }; | ||
| 143 | + mutable std::mutex delayCleanupMutex_; | ||
| 144 | + std::unordered_set<pid_t> delayCleanupPids_; | ||
| 145 | + std::unordered_map<pid_t, std::vector<DelayCleanupInfo>> delayCleanupTasks_; | ||
| 146 | + | ||
| 147 | + void SetDelayedCleanupEnabled(pid_t pid, bool enabled); | ||
| 148 | + bool IsDelayCleanupEnabled(pid_t pid); | ||
| 149 | + void TriggerImmediateCleanup(pid_t pid); | ||
| 150 | + void RegisterDelayCleanupTask(pid_t pid, const std::string& taskName, std::function<void()> cleanupFunc); | ||
| 151 | + void UnregisterDelayCleanupTask(const std::string& taskName); | ||
| 152 | + void PostDelayCleanupTask(pid_t pid, const std::string& taskName, | ||
| 153 | + std::function<void()> cleanupFunc, uint32_t delayMs); | ||
| 154 | + | ||
| 138 | sptr<RsGameFrameHandler> rsGameFrameHandler_ = nullptr; | 155 | sptr<RsGameFrameHandler> rsGameFrameHandler_ = nullptr; |
| 139 | 156 | ||
| 140 | friend class RSRenderServiceAgent; | 157 | friend class RSRenderServiceAgent; |
| @@ -91,5 +91,32 @@ void RSRenderServiceAgent::HandleGameSceneChanged() const | |||
| 91 | handler->HandleGameSceneChanged(); | 91 | handler->HandleGameSceneChanged(); |
| 92 | } | 92 | } |
| 93 | } | 93 | } |
| 94 | + | ||
| 95 | +bool RSRenderServiceAgent::IsDelayCleanupEnabled(pid_t pid) | ||
| 96 | +{ | ||
| 97 | + return renderService_.IsDelayCleanupEnabled(pid); | ||
| 98 | +} | ||
| 99 | + | ||
| 100 | +void RSRenderServiceAgent::SetDelayedCleanupEnabled(pid_t pid, bool enabled) | ||
| 101 | +{ | ||
| 102 | + renderService_.SetDelayedCleanupEnabled(pid, enabled); | ||
| 103 | +} | ||
| 104 | + | ||
| 105 | +void RSRenderServiceAgent::PostDelayCleanupTask(pid_t pid, const std::string& taskName, | ||
| 106 | + std::function<void()> cleanupFunc, uint32_t delayMs) | ||
| 107 | +{ | ||
| 108 | + renderService_.PostDelayCleanupTask(pid, taskName, std::move(cleanupFunc), delayMs); | ||
| 109 | +} | ||
| 110 | + | ||
| 111 | +void RSRenderServiceAgent::TriggerImmediateCleanup(pid_t pid) | ||
| 112 | +{ | ||
| 113 | + if (renderService_.handler_ == nullptr) { | ||
| 114 | + return; | ||
| 115 | + } | ||
| 116 | + renderService_.handler_->PostTask( | ||
| 117 | + [&renderService = renderService_, pid]() { | ||
| 118 | + renderService.TriggerImmediateCleanup(pid); | ||
| 119 | + }); | ||
| 120 | +} | ||
| 94 | } // namespace Rosen | 121 | } // namespace Rosen |
| 95 | } // namespace OHOS | 122 | } // namespace OHOS |
| @@ -79,6 +79,13 @@ public: | |||
| 79 | HgmProcessCallback& GetHgmProcessCallback() { return hgmProcessCallback_; } | 79 | HgmProcessCallback& GetHgmProcessCallback() { return hgmProcessCallback_; } |
| 80 | void RegisterHgmProcessCallback(HgmProcessCallback hgmProcessCallback); | 80 | void RegisterHgmProcessCallback(HgmProcessCallback hgmProcessCallback); |
| 81 | 81 | ||
| 82 | + // Delayed cleanup helpers, to avoid RSMainThread singleton in Connection classes. | ||
| 83 | + bool IsDelayCleanupEnabled(pid_t pid); | ||
| 84 | + void SetDelayedCleanupEnabled(pid_t pid, bool enabled); | ||
| 85 | + void PostDelayCleanupTask(pid_t pid, const std::string& taskName, | ||
| 86 | + std::function<void()> cleanupFunc, uint32_t delayMs); | ||
| 87 | + void TriggerImmediateCleanup(pid_t pid); | ||
| 88 | + | ||
| 82 | private: | 89 | private: |
| 83 | RSRenderService& renderService_; | 90 | RSRenderService& renderService_; |
| 84 | HgmProcessCallback hgmProcessCallback_ = nullptr; | 91 | HgmProcessCallback hgmProcessCallback_ = nullptr; |
Mrosen/modules/render_service/main/render_server/transaction/rs_client_to_service_connection.cpp+102-20
| @@ -68,7 +68,6 @@ | |||
| 68 | 68 | ||
| 69 | 69 | ||
| 70 | 70 | ||
| 71 | - | ||
| 72 | 71 | ||
| 73 | 72 | ||
| 74 | 73 | ||
| @@ -111,6 +110,7 @@ constexpr uint32_t MEM_BYTE_TO_MB = 1024 * 1024; | |||
| 111 | constexpr uint32_t PIDLIST_SIZE_MAX = 128; | 110 | constexpr uint32_t PIDLIST_SIZE_MAX = 128; |
| 112 | constexpr uint64_t MAX_TIME_OUT_NS = 1e9; | 111 | constexpr uint64_t MAX_TIME_OUT_NS = 1e9; |
| 113 | constexpr int64_t MAX_FREEZE_SCREEN_TIME = 3000; | 112 | constexpr int64_t MAX_FREEZE_SCREEN_TIME = 3000; |
| 113 | +constexpr int64_t DELAY_CLEANUP_MS = 10000; | ||
| 114 | const std::string UNFREEZE_SCREEN_TASK_NAME = "UNFREEZE_SCREEN_TASK"; | 114 | const std::string UNFREEZE_SCREEN_TASK_NAME = "UNFREEZE_SCREEN_TASK"; |
| 115 | } | 115 | } |
| 116 | const std::string RSClientToServiceConnection::GPU_FREQ_PREF = "GPU_FREQ_PREF"; | 116 | const std::string RSClientToServiceConnection::GPU_FREQ_PREF = "GPU_FREQ_PREF"; |
| @@ -181,6 +181,20 @@ void RSClientToServiceConnection::CleanVirtualScreens() noexcept | |||
| 181 | screenManagerAgent_->CleanVirtualScreens(); | 181 | screenManagerAgent_->CleanVirtualScreens(); |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | +void RSClientToServiceConnection::DoCleanForRefresh() noexcept | ||
| 185 | +{ | ||
| 186 | + RS_TRACE_NAME_FMT("CleanVirtualScreens %d", remotePid_); | ||
| 187 | + CleanVirtualScreens(); | ||
| 188 | + if (hgmContext_ != nullptr) { | ||
| 189 | + hgmContext_->CleanAllWhenServiceConnectionDie(remotePid_); | ||
| 190 | + } | ||
| 191 | + RSTypefaceCache::Instance().RemoveDrawingTypefacesByPid(remotePid_); | ||
| 192 | + { | ||
| 193 | + std::lock_guard<std::mutex> lock(pidToBundleMutex_); | ||
| 194 | + pidToBundleName_.clear(); | ||
| 195 | + } | ||
| 196 | +} | ||
| 197 | + | ||
| 184 | void RSClientToServiceConnection::CleanForRefresh() noexcept | 198 | void RSClientToServiceConnection::CleanForRefresh() noexcept |
| 185 | { | 199 | { |
| 186 | if (!renderServiceAgent_) { | 200 | if (!renderServiceAgent_) { |
| @@ -194,19 +208,8 @@ void RSClientToServiceConnection::CleanForRefresh() noexcept | |||
| 194 | if (!connection) { | 208 | if (!connection) { |
| 195 | return; | 209 | return; |
| 196 | } | 210 | } |
| 197 | - RS_TRACE_NAME_FMT("CleanVirtualScreens %d", connection->remotePid_); | 211 | + connection->DoCleanForRefresh(); |
| 198 | - connection->CleanVirtualScreens(); | ||
| 199 | }).wait(); | 212 | }).wait(); |
| 200 | - | ||
| 201 | - if (hgmContext_ != nullptr) { | ||
| 202 | - hgmContext_->CleanAllWhenServiceConnectionDie(remotePid_); | ||
| 203 | - } | ||
| 204 | - RSTypefaceCache::Instance().RemoveDrawingTypefacesByPid(remotePid_); | ||
| 205 | - | ||
| 206 | - { | ||
| 207 | - std::lock_guard<std::mutex> lock(pidToBundleMutex_); | ||
| 208 | - pidToBundleName_.clear(); | ||
| 209 | - } | ||
| 210 | RS_LOGD("CleanForRefresh() end."); | 213 | RS_LOGD("CleanForRefresh() end."); |
| 211 | RS_TRACE_NAME("RSClientToServiceConnection CleanForRefresh end, remotePid: " + std::to_string(remotePid_)); | 214 | RS_TRACE_NAME("RSClientToServiceConnection CleanForRefresh end, remotePid: " + std::to_string(remotePid_)); |
| 212 | } | 215 | } |
| @@ -218,24 +221,55 @@ void RSClientToServiceConnection::CleanAll(bool toDelete) noexcept | |||
| 218 | if (cleanDone_) { | 221 | if (cleanDone_) { |
| 219 | return; | 222 | return; |
| 220 | } | 223 | } |
| 224 | + cleanDone_ = true; | ||
| 221 | } | 225 | } |
| 226 | + | ||
| 227 | + bool shouldDelay = renderServiceAgent_ != nullptr && | ||
| 228 | + renderServiceAgent_->IsDelayCleanupEnabled(remotePid_); | ||
| 229 | + if (shouldDelay) { | ||
| 230 | + std::string taskName = "DelayClean_Service_" + std::to_string(remotePid_); | ||
| 231 | + auto doCleanup = [weakConn = wptr<RSClientToServiceConnection>(this), toDelete]() { | ||
| 232 | + auto conn = weakConn.promote(); | ||
| 233 | + if (conn == nullptr) { | ||
| 234 | + return; | ||
| 235 | + } | ||
| 236 | + bool expected = false; | ||
| 237 | + if (!conn->delayCleanupExecuted_.compare_exchange_strong(expected, true)) { | ||
| 238 | + return; | ||
| 239 | + } | ||
| 240 | + RS_LOGD("CleanAll() start."); | ||
| 241 | + RS_TRACE_NAME("RSClientToServiceConnection CleanAll begin, remotePid: " + std::to_string(conn->remotePid_)); | ||
| 242 | + conn->DoCleanForRefresh(); | ||
| 243 | + if (toDelete) { | ||
| 244 | + auto token = iface_cast<RSIConnectionToken>(conn->GetToken()); | ||
| 245 | + if (token != nullptr && conn->renderServiceAgent_ != nullptr) { | ||
| 246 | + conn->renderServiceAgent_->RemoveToken(token); | ||
| 247 | + } | ||
| 248 | + } | ||
| 249 | + RS_LOGD("CleanAll() end."); | ||
| 250 | + RS_TRACE_NAME("RSClientToServiceConnection CleanAll end, remotePid: " + std::to_string(conn->remotePid_)); | ||
| 251 | + }; | ||
| 252 | + renderServiceAgent_->PostDelayCleanupTask(remotePid_, taskName, doCleanup, DELAY_CLEANUP_MS); | ||
| 253 | + } else { | ||
| 254 | + DoCleanAll(toDelete); | ||
| 255 | + } | ||
| 256 | +} | ||
| 257 | + | ||
| 258 | +void RSClientToServiceConnection::DoCleanAll(bool toDelete) | ||
| 259 | +{ | ||
| 222 | if (!renderServiceAgent_) { | 260 | if (!renderServiceAgent_) { |
| 223 | return; | 261 | return; |
| 224 | } | 262 | } |
| 225 | - | ||
| 226 | RS_LOGD("CleanAll() start."); | 263 | RS_LOGD("CleanAll() start."); |
| 227 | RS_TRACE_NAME("RSClientToServiceConnection CleanAll begin, remotePid: " + std::to_string(remotePid_)); | 264 | RS_TRACE_NAME("RSClientToServiceConnection CleanAll begin, remotePid: " + std::to_string(remotePid_)); |
| 228 | 265 | ||
| 229 | CleanForRefresh(); | 266 | CleanForRefresh(); |
| 230 | 267 | ||
| 231 | - { | ||
| 232 | - std::lock_guard<std::mutex> lock(mutex_); | ||
| 233 | - cleanDone_ = true; | ||
| 234 | - } | ||
| 235 | - | ||
| 236 | if (toDelete) { | 268 | if (toDelete) { |
| 237 | auto token = iface_cast<RSIConnectionToken>(GetToken()); | 269 | auto token = iface_cast<RSIConnectionToken>(GetToken()); |
| 238 | - renderServiceAgent_->RemoveToken(token); | 270 | + if (token != nullptr) { |
| 271 | + renderServiceAgent_->RemoveToken(token); | ||
| 272 | + } | ||
| 239 | } | 273 | } |
| 240 | 274 | ||
| 241 | RS_LOGD("CleanAll() end."); | 275 | RS_LOGD("CleanAll() end."); |
| @@ -2636,5 +2670,53 @@ bool RSClientToServiceConnection::ProfilerIsSecureScreen() | |||
| 2636 | 2670 | ||
| 2637 | } | 2671 | } |
| 2638 | 2672 | ||
| 2673 | +void RSClientToServiceConnection::BroadcastDelayedCleanupEnabled(pid_t pid, bool enabled) | ||
| 2674 | +{ | ||
| 2675 | + if (renderProcessManagerAgent_ == nullptr) { | ||
| 2676 | + return; | ||
| 2677 | + } | ||
| 2678 | + auto serviceToRenderConns = renderProcessManagerAgent_->GetServiceToRenderConns(); | ||
| 2679 | + for (auto& conn : serviceToRenderConns) { | ||
| 2680 | + if (conn != nullptr) { | ||
| 2681 | + conn->SetDelayedCleanupEnabled(pid, enabled); | ||
| 2682 | + } | ||
| 2683 | + } | ||
| 2684 | +} | ||
| 2685 | + | ||
| 2686 | +void RSClientToServiceConnection::BroadcastImmediateCleanup(pid_t pid) | ||
| 2687 | +{ | ||
| 2688 | + if (renderProcessManagerAgent_ == nullptr) { | ||
| 2689 | + return; | ||
| 2690 | + } | ||
| 2691 | + auto serviceToRenderConns = renderProcessManagerAgent_->GetServiceToRenderConns(); | ||
| 2692 | + for (auto& conn : serviceToRenderConns) { | ||
| 2693 | + if (conn != nullptr) { | ||
| 2694 | + conn->TriggerImmediateCleanup(pid); | ||
| 2695 | + } | ||
| 2696 | + } | ||
| 2697 | +} | ||
| 2698 | + | ||
| 2699 | +ErrCode RSClientToServiceConnection::SetDelayedCleanupEnabled(bool enabled) | ||
| 2700 | +{ | ||
| 2701 | + if (renderServiceAgent_ == nullptr) { | ||
| 2702 | + RS_LOGE("RSClientToServiceConnection::SetDelayedCleanupEnabled renderServiceAgent_ is nullptr"); | ||
| 2703 | + return ERR_INVALID_VALUE; | ||
| 2704 | + } | ||
| 2705 | + renderServiceAgent_->SetDelayedCleanupEnabled(remotePid_, enabled); | ||
| 2706 | + BroadcastDelayedCleanupEnabled(remotePid_, enabled); | ||
这里如果存在多个RP时,会往多个RP中插入RemotePid,但是RemotePid清理不掉,可能存在内存泄露 ![]() ![]() | |||
| 2707 | + return ERR_OK; | ||
| 2708 | +} | ||
| 2709 | + | ||
| 2710 | +ErrCode RSClientToServiceConnection::TriggerImmediateCleanup(pid_t pid) | ||
| 2711 | +{ | ||
| 2712 | + if (renderServiceAgent_ == nullptr) { | ||
| 2713 | + RS_LOGE("RSClientToServiceConnection::TriggerImmediateCleanup renderServiceAgent_ is nullptr"); | ||
| 2714 | + return ERR_INVALID_VALUE; | ||
| 2715 | + } | ||
| 2716 | + renderServiceAgent_->TriggerImmediateCleanup(pid); | ||
| 2717 | + BroadcastImmediateCleanup(pid); | ||
| 2718 | + return ERR_OK; | ||
| 2719 | +} | ||
| 2720 | + | ||
| 2639 | } // namespace Rosen | 2721 | } // namespace Rosen |
| 2640 | } // namespace OHOS | 2722 | } // namespace OHOS |
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| @@ -63,11 +64,19 @@ public: | |||
| 63 | 64 | ||
| 64 | void RegisterRemoteRefreshCallback() override; | 65 | void RegisterRemoteRefreshCallback() override; |
| 65 | 66 | ||
| 67 | + void BroadcastDelayedCleanupEnabled(pid_t pid, bool enabled); | ||
| 68 | + void BroadcastImmediateCleanup(pid_t pid); | ||
| 69 | + | ||
| 70 | + ErrCode SetDelayedCleanupEnabled(bool enabled) override; | ||
| 71 | + ErrCode TriggerImmediateCleanup(pid_t pid) override; | ||
| 72 | + | ||
| 66 | private: | 73 | private: |
| 67 | void CleanVirtualScreens() noexcept; | 74 | void CleanVirtualScreens() noexcept; |
| 68 | 75 | ||
| 69 | void CleanForRefresh() noexcept; | 76 | void CleanForRefresh() noexcept; |
| 70 | 77 | ||
| 78 | + void DoCleanForRefresh() noexcept; | ||
| 79 | + | ||
| 71 | void CleanAll(bool toDelete = false) noexcept; | 80 | void CleanAll(bool toDelete = false) noexcept; |
| 72 | 81 | ||
| 73 | int32_t RegisterVariationTypeface(Drawing::SharedTypeface& sharedTypeface, int32_t& needUpdate); | 82 | int32_t RegisterVariationTypeface(Drawing::SharedTypeface& sharedTypeface, int32_t& needUpdate); |
| @@ -459,8 +468,11 @@ private: | |||
| 459 | friend class RSConnectionRefreshRecipient; | 468 | friend class RSConnectionRefreshRecipient; |
| 460 | sptr<RSConnectionRefreshRecipient> connRefreshRecipient_; | 469 | sptr<RSConnectionRefreshRecipient> connRefreshRecipient_; |
| 461 | 470 | ||
| 471 | + void DoCleanAll(bool toDelete); | ||
| 472 | + | ||
| 462 | mutable std::mutex mutex_; | 473 | mutable std::mutex mutex_; |
| 463 | bool cleanDone_ = false; | 474 | bool cleanDone_ = false; |
| 475 | + std::atomic<bool> delayCleanupExecuted_ { false }; | ||
| 464 | const std::string VOTER_SCENE_BLUR = "VOTER_SCENE_BLUR"; | 476 | const std::string VOTER_SCENE_BLUR = "VOTER_SCENE_BLUR"; |
| 465 | const std::string VOTER_SCENE_GPU = "VOTER_SCENE_GPU"; | 477 | const std::string VOTER_SCENE_GPU = "VOTER_SCENE_GPU"; |
| 466 | const std::string VIDEO_TUNNEL = "VIDEO_TUNNEL"; | 478 | const std::string VIDEO_TUNNEL = "VIDEO_TUNNEL"; |
| @@ -222,6 +222,8 @@ static constexpr std::array descriptorCheckList = { | |||
| 222 | static_cast<uint32_t>(RSIClientToServiceConnectionInterfaceCode::CREATE_VSYNC_CONNECTION), | 222 | static_cast<uint32_t>(RSIClientToServiceConnectionInterfaceCode::CREATE_VSYNC_CONNECTION), |
| 223 | static_cast<uint32_t>(RSIClientToServiceConnectionInterfaceCode::GET_PIXELMAP_BY_PROCESSID), | 223 | static_cast<uint32_t>(RSIClientToServiceConnectionInterfaceCode::GET_PIXELMAP_BY_PROCESSID), |
| 224 | static_cast<uint32_t>(RSIClientToServiceConnectionInterfaceCode::SET_APS_CONFIG_PARAMS), | 224 | static_cast<uint32_t>(RSIClientToServiceConnectionInterfaceCode::SET_APS_CONFIG_PARAMS), |
| 225 | + static_cast<uint32_t>(RSIClientToServiceConnectionInterfaceCode::SET_DELAYED_CLEANUP_ENABLED), | ||
| 226 | + static_cast<uint32_t>(RSIClientToServiceConnectionInterfaceCode::TRIGGER_IMMEDIATE_CLEANUP), | ||
| 225 | static_cast<uint32_t>(RSIClientToServiceConnectionInterfaceCode::SET_UIFIRST_SCALE), | 227 | static_cast<uint32_t>(RSIClientToServiceConnectionInterfaceCode::SET_UIFIRST_SCALE), |
| 226 | }; | 228 | }; |
| 227 | 229 | ||
| @@ -3486,6 +3488,26 @@ int RSClientToServiceConnectionStub::OnRemoteRequest( | |||
| 3486 | reply.WriteBool(retValue); | 3488 | reply.WriteBool(retValue); |
| 3487 | break; | 3489 | break; |
| 3488 | } | 3490 | } |
| 3491 | + case static_cast<uint32_t>(RSIClientToServiceConnectionInterfaceCode::SET_DELAYED_CLEANUP_ENABLED): { | ||
| 3492 | + bool enabled = false; | ||
| 3493 | + if (!data.ReadBool(enabled)) { | ||
| 3494 | + RS_LOGE("RSClientToServiceConnectionStub::OnRemoteRequest ReadBool enabled failed"); | ||
| 3495 | + ret = ERR_INVALID_DATA; | ||
| 3496 | + break; | ||
| 3497 | + } | ||
| 3498 | + ret = SetDelayedCleanupEnabled(enabled); | ||
| 3499 | + break; | ||
| 3500 | + } | ||
| 3501 | + case static_cast<uint32_t>(RSIClientToServiceConnectionInterfaceCode::TRIGGER_IMMEDIATE_CLEANUP): { | ||
| 3502 | + pid_t pid = 0; | ||
| 3503 | + if (!data.ReadInt32(pid)) { | ||
| 3504 | + RS_LOGE("RSClientToServiceConnectionStub::OnRemoteRequest ReadInt32 pid failed"); | ||
| 3505 | + ret = ERR_INVALID_DATA; | ||
| 3506 | + break; | ||
| 3507 | + } | ||
| 3508 | + ret = TriggerImmediateCleanup(pid); | ||
| 3509 | + break; | ||
| 3510 | + } | ||
| 3489 | default: { | 3511 | default: { |
| 3490 | return IPCObjectStub::OnRemoteRequest(code, data, reply, option); | 3512 | return IPCObjectStub::OnRemoteRequest(code, data, reply, option); |
| 3491 | } | 3513 | } |
| @@ -203,6 +203,8 @@ enum class RSIClientToServiceConnectionInterfaceCode : CodeUnderlyingType { | |||
| 203 | 203 | ||
| 204 | GET_SCREEN_VCP_FEATURE = 0x014003, | 204 | GET_SCREEN_VCP_FEATURE = 0x014003, |
| 205 | SET_SCREEN_VCP_FEATURE = 0x014004, | 205 | SET_SCREEN_VCP_FEATURE = 0x014004, |
| 206 | + SET_DELAYED_CLEANUP_ENABLED = 0x014005, | ||
| 207 | + TRIGGER_IMMEDIATE_CLEANUP = 0x014006, | ||
| 206 | 208 | ||
| 207 | // Special invocation. Do not change it. | 209 | // Special invocation. Do not change it. |
| 208 | NOTIFY_LIGHT_FACTOR_STATUS = 1000, | 210 | NOTIFY_LIGHT_FACTOR_STATUS = 1000, |
| @@ -432,6 +432,10 @@ public: | |||
| 432 | virtual void RemoveToken() = 0; | 432 | virtual void RemoveToken() = 0; |
| 433 | 433 | ||
| 434 | virtual void RegisterRemoteRefreshCallback() = 0; | 434 | virtual void RegisterRemoteRefreshCallback() = 0; |
| 435 | + | ||
| 436 | + virtual ErrCode SetDelayedCleanupEnabled(bool enabled) = 0; | ||
| 437 | + | ||
| 438 | + virtual ErrCode TriggerImmediateCleanup(pid_t pid) = 0; | ||
| 435 | 439 | ||
| 436 | }; | 440 | }; |
| 437 | } // namespace Rosen | 441 | } // namespace Rosen |
| @@ -449,6 +449,10 @@ public: | |||
| 449 | bool AvcodecVideoGetRecent(); | 449 | bool AvcodecVideoGetRecent(); |
| 450 | 450 | ||
| 451 | void TriggerOnFinish(const FinishCallbackRet& ret) const; | 451 | void TriggerOnFinish(const FinishCallbackRet& ret) const; |
| 452 | + | ||
| 453 | + void SetDelayedCleanupEnabled(bool enabled); | ||
| 454 | + | ||
| 455 | + void TriggerImmediateCleanup(pid_t pid); | ||
| 452 | 456 | ||
| 453 | private: | 457 | private: |
| 454 | 458 | ||
| @@ -777,5 +777,13 @@ bool RSRenderServiceClient::AvcodecVideoGetRecent() | |||
| 777 | { | 777 | { |
| 778 | return false; | 778 | return false; |
| 779 | } | 779 | } |
| 780 | + | ||
| 781 | +void RSRenderServiceClient::SetDelayedCleanupEnabled(bool enabled) | ||
| 782 | +{ | ||
| 783 | +} | ||
| 784 | + | ||
| 785 | +void RSRenderServiceClient::TriggerImmediateCleanup(pid_t pid) | ||
| 786 | +{ | ||
| 787 | +} | ||
| 780 | } // namespace Rosen | 788 | } // namespace Rosen |
| 781 | } // namespace OHOS | 789 | } // namespace OHOS |
| @@ -2150,6 +2150,26 @@ bool RSRenderServiceClient::AvcodecVideoGetRecent() | |||
| 2150 | } | 2150 | } |
| 2151 | return true; | 2151 | return true; |
| 2152 | } | 2152 | } |
| 2153 | + | ||
| 2154 | +void RSRenderServiceClient::SetDelayedCleanupEnabled(bool enabled) | ||
| 2155 | +{ | ||
| 2156 | + auto clientToService = RSConnectHub::GetClientToServiceConnection(); | ||
| 2157 | + if (!clientToService) { | ||
| 2158 | + ROSEN_LOGE("RSRenderServiceClient::SetDelayedCleanupEnabled clientToService == nullptr!"); | ||
| 2159 | + return; | ||
| 2160 | + } | ||
| 2161 | + clientToService->SetDelayedCleanupEnabled(enabled); | ||
| 2162 | +} | ||
| 2163 | + | ||
| 2164 | +void RSRenderServiceClient::TriggerImmediateCleanup(pid_t pid) | ||
| 2165 | +{ | ||
| 2166 | + auto clientToService = RSConnectHub::GetClientToServiceConnection(); | ||
| 2167 | + if (!clientToService) { | ||
| 2168 | + ROSEN_LOGE("RSRenderServiceClient::TriggerImmediateCleanup clientToService == nullptr!"); | ||
| 2169 | + return; | ||
| 2170 | + } | ||
| 2171 | + clientToService->TriggerImmediateCleanup(pid); | ||
| 2172 | +} | ||
| 2153 | 2173 | ||
| 2154 | } // namespace Rosen | 2174 | } // namespace Rosen |
| 2155 | } // namespace OHOS | 2175 | } // namespace OHOS |
| @@ -5461,6 +5461,54 @@ ErrCode RSClientToServiceConnectionProxy::SetOptimizeCanvasDirtyPidList(const st | |||
| 5461 | { | 5461 | { |
| 5462 | return ERR_INVALID_VALUE; | 5462 | return ERR_INVALID_VALUE; |
| 5463 | } | 5463 | } |
| 5464 | + | ||
| 5465 | +ErrCode RSClientToServiceConnectionProxy::SetDelayedCleanupEnabled(bool enabled) | ||
| 5466 | +{ | ||
| 5467 | + MessageParcel data; | ||
| 5468 | + MessageParcel reply; | ||
| 5469 | + MessageOption option; | ||
| 5470 | + option.SetFlags(MessageOption::TF_ASYNC); | ||
| 5471 | + if (!data.WriteInterfaceToken(RSIClientToServiceConnection::GetDescriptor())) { | ||
| 5472 | + ROSEN_LOGE("RSClientToServiceConnectionProxy::SetDelayedCleanupEnabled WriteInterfaceToken err."); | ||
| 5473 | + return ERR_INVALID_DATA; | ||
| 5474 | + } | ||
| 5475 | + if (!data.WriteBool(enabled)) { | ||
| 5476 | + ROSEN_LOGE("RSClientToServiceConnectionProxy::SetDelayedCleanupEnabled WriteBool err."); | ||
| 5477 | + return ERR_INVALID_DATA; | ||
| 5478 | + } | ||
| 5479 | + uint32_t code = static_cast<uint32_t>( | ||
| 5480 | + RSIClientToServiceConnectionInterfaceCode::SET_DELAYED_CLEANUP_ENABLED); | ||
| 5481 | + int32_t err = SendRequest(code, data, reply, option); | ||
| 5482 | + if (err != NO_ERROR) { | ||
| 5483 | + ROSEN_LOGE("RSClientToServiceConnectionProxy::SetDelayedCleanupEnabled SendRequest err."); | ||
| 5484 | + return ERR_INVALID_DATA; | ||
| 5485 | + } | ||
| 5486 | + return ERR_OK; | ||
| 5487 | +} | ||
| 5488 | + | ||
| 5489 | +ErrCode RSClientToServiceConnectionProxy::TriggerImmediateCleanup(pid_t pid) | ||
| 5490 | +{ | ||
| 5491 | + MessageParcel data; | ||
| 5492 | + MessageParcel reply; | ||
| 5493 | + MessageOption option; | ||
| 5494 | + option.SetFlags(MessageOption::TF_ASYNC); | ||
| 5495 | + if (!data.WriteInterfaceToken(RSIClientToServiceConnection::GetDescriptor())) { | ||
| 5496 | + ROSEN_LOGE("RSClientToServiceConnectionProxy::TriggerImmediateCleanup WriteInterfaceToken err."); | ||
| 5497 | + return ERR_INVALID_DATA; | ||
| 5498 | + } | ||
| 5499 | + if (!data.WriteInt32(pid)) { | ||
| 5500 | + ROSEN_LOGE("RSClientToServiceConnectionProxy::TriggerImmediateCleanup WriteInt32 err."); | ||
| 5501 | + return ERR_INVALID_DATA; | ||
| 5502 | + } | ||
| 5503 | + uint32_t code = static_cast<uint32_t>( | ||
| 5504 | + RSIClientToServiceConnectionInterfaceCode::TRIGGER_IMMEDIATE_CLEANUP); | ||
| 5505 | + int32_t err = SendRequest(code, data, reply, option); | ||
| 5506 | + if (err != NO_ERROR) { | ||
| 5507 | + ROSEN_LOGE("RSClientToServiceConnectionProxy::TriggerImmediateCleanup SendRequest err."); | ||
| 5508 | + return ERR_INVALID_DATA; | ||
| 5509 | + } | ||
| 5510 | + return ERR_OK; | ||
| 5511 | +} | ||
| 5464 | 5512 | ||
| 5465 | } // namespace Rosen | 5513 | } // namespace Rosen |
| 5466 | } // namespace OHOS | 5514 | } // namespace OHOS |
| @@ -361,6 +361,10 @@ public: | |||
| 361 | 361 | ||
| 362 | ErrCode SetOptimizeCanvasDirtyPidList(const std::vector<int32_t>& pidList) override; | 362 | ErrCode SetOptimizeCanvasDirtyPidList(const std::vector<int32_t>& pidList) override; |
| 363 | 363 | ||
| 364 | + ErrCode SetDelayedCleanupEnabled(bool enabled) override; | ||
| 365 | + | ||
| 366 | + ErrCode TriggerImmediateCleanup(pid_t pid) override; | ||
| 367 | + | ||
| 364 | bool WriteSurfaceCaptureConfig(const RSSurfaceCaptureConfig& captureConfig, MessageParcel& data); | 368 | bool WriteSurfaceCaptureConfig(const RSSurfaceCaptureConfig& captureConfig, MessageParcel& data); |
| 365 | 369 | ||
| 366 | bool WriteSurfaceCaptureBlurParam(const RSSurfaceCaptureBlurParam& blurParam, MessageParcel& data); | 370 | bool WriteSurfaceCaptureBlurParam(const RSSurfaceCaptureBlurParam& blurParam, MessageParcel& data); |
| @@ -784,5 +784,13 @@ bool RSRenderServiceClient::AvcodecVideoGetRecent() | |||
| 784 | { | 784 | { |
| 785 | return false; | 785 | return false; |
| 786 | } | 786 | } |
| 787 | + | ||
| 788 | +void RSRenderServiceClient::SetDelayedCleanupEnabled(bool enabled) | ||
| 789 | +{ | ||
| 790 | +} | ||
| 791 | + | ||
| 792 | +void RSRenderServiceClient::TriggerImmediateCleanup(pid_t pid) | ||
| 793 | +{ | ||
| 794 | +} | ||
| 787 | } // namespace Rosen | 795 | } // namespace Rosen |
| 788 | } // namespace OHOS | 796 | } // namespace OHOS |
| @@ -1261,5 +1261,15 @@ int32_t RSInterfaces::SetLogicalCameraRotationCorrection(ScreenId id, ScreenRota | |||
| 1261 | { | 1261 | { |
| 1262 | return 0; | 1262 | return 0; |
| 1263 | } | 1263 | } |
| 1264 | + | ||
| 1265 | +void RSInterfaces::SetDelayedCleanupEnabled(bool enabled) | ||
| 1266 | +{ | ||
| 1267 | + renderServiceClient_->SetDelayedCleanupEnabled(enabled); | ||
| 1268 | +} | ||
| 1269 | + | ||
| 1270 | +void RSInterfaces::TriggerImmediateCleanup(pid_t pid) | ||
| 1271 | +{ | ||
| 1272 | + renderServiceClient_->TriggerImmediateCleanup(pid); | ||
| 1273 | +} | ||
| 1264 | } // namespace Rosen | 1274 | } // namespace Rosen |
| 1265 | } // namespace OHOS | 1275 | } // namespace OHOS |
| @@ -1540,6 +1540,22 @@ public: | |||
| 1540 | */ | 1540 | */ |
| 1541 | int32_t GetFrameStabilityResult(const FrameStabilityTarget& target, bool& result); | 1541 | int32_t GetFrameStabilityResult(const FrameStabilityTarget& target, bool& result); |
| 1542 | 1542 | ||
| 1543 | + /** | ||
| 1544 | + * @brief Set delayed cleanup enabled for current process. | ||
| 1545 | + * When enabled, RenderService will delay cleaning up render nodes | ||
| 1546 | + * for a fixed duration (DELAY_CLEANUP_MS) after this process dies. | ||
| 1547 | + * @param enabled true to enable delayed cleanup, false to disable. | ||
| 1548 | + */ | ||
| 1549 | + void SetDelayedCleanupEnabled(bool enabled); | ||
| 1550 | + | ||
| 1551 | + /** | ||
| 1552 | + * @brief Trigger immediate cleanup for a specified process. | ||
| 1553 | + * Used when a new process restarts to clean up leftover | ||
| 1554 | + * delayed cleanup data from the old process. | ||
| 1555 | + * @param pid The pid of the old process to clean up immediately. | ||
| 1556 | + */ | ||
| 1557 | + void TriggerImmediateCleanup(pid_t pid); | ||
| 1558 | + | ||
| 1543 | private: | 1559 | private: |
| 1544 | RSInterfaces(); | 1560 | RSInterfaces(); |
| 1545 | ~RSInterfaces() noexcept; | 1561 | ~RSInterfaces() noexcept; |
| @@ -1560,4 +1576,4 @@ private: | |||
| 1560 | } // namespace Rosen | 1576 | } // namespace Rosen |
| 1561 | } // namespace OHOS | 1577 | } // namespace OHOS |
| 1562 | 1578 | ||
| 1563 | -#endif // RENDER_SERVICE_CLIENT_CORE_TRANSACTION_RS_INTERFACES_H | 1579 | +#endif // RENDER_SERVICE_CLIENT_CORE_TRANSACTION_RS_INTERFACES_H |


还支持传false?