已关闭
feat(render_service): add delayed cleanup for render nodes after process death #30729
feat(render_service): add delayed cleanup for render nodes after process death #30729
已关闭
huaixu-y创建于 6月15日关闭于 7月14日
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);
chuchengcheng
chuchengchengchuchengcheng6月22日

还支持传false?

likedislike
huaixu-y
huaixu-y
6月22日 评论:
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);
chuchengcheng
chuchengchengchuchengcheng6月22日

注意看下这个容器会不会产生泄露

likedislike
huaixu-y
huaixu-y
6月22日 评论:
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+ 
902bool RSMainThread::GetMaxGpuBufferSize(uint32_t& maxWidth, uint32_t& maxHeight)968bool 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#endif870#endif
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#ifdef RS_ENABLE_GPU879#ifdef RS_ENABLE_GPU
868 RSDrawFrame drawFrame_;880 RSDrawFrame drawFrame_;
869#endif881#endif
@@ -2061,6 +2061,11 @@ ErrCode RSRenderPipelineAgent::RepaintEverything()
2061}2061}
2062 2062 
2063void RSRenderPipelineAgent::Clean(pid_t pid, bool forRefresh)2063void 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- pipeline2077+ 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+ 
2094ErrCode RSRenderPipelineAgent::SetColorFollow(const std::string& nodeIdStr, bool isColorFollow)2168ErrCode 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#include "pipeline/rs_canvas_drawing_render_node.h"60#include "pipeline/rs_canvas_drawing_render_node.h"
61#include "pipeline/rs_render_node_map.h"61#include "pipeline/rs_render_node_map.h"
62#include "pipeline/main_thread/rs_render_service_listener.h"62#include "pipeline/main_thread/rs_render_service_listener.h"
63-#include "pipeline/main_thread/rs_main_thread.h"
64#include "pipeline/rs_surface_buffer_callback_manager.h"63#include "pipeline/rs_surface_buffer_callback_manager.h"
65#include "pipeline/rs_surface_render_node.h"64#include "pipeline/rs_surface_render_node.h"
66#include "pipeline/rs_task_dispatcher.h"65#include "pipeline/rs_task_dispatcher.h"
@@ -103,6 +102,7 @@ constexpr uint32_t MEM_BYTE_TO_MB = 1024 * 1024;
103constexpr uint32_t PIDLIST_SIZE_MAX = 128;102constexpr uint32_t PIDLIST_SIZE_MAX = 128;
104constexpr uint64_t MAX_TIME_OUT_NS = 1e9;103constexpr uint64_t MAX_TIME_OUT_NS = 1e9;
105constexpr int64_t MAX_FREEZE_SCREEN_TIME = 3000;104constexpr int64_t MAX_FREEZE_SCREEN_TIME = 3000;
105+constexpr int64_t DELAY_CLEANUP_MS = 10000;
106const std::string UNFREEZE_SCREEN_TASK_NAME = "UNFREEZE_SCREEN_TASK";106const std::string UNFREEZE_SCREEN_TASK_NAME = "UNFREEZE_SCREEN_TASK";
107}107}
108const std::string RSClientToRenderConnection::GPU_FREQ_PREF = "GPU_FREQ_PREF";108const 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#ifndef RENDER_SERVICE_PIPELINE_RS_CLIENT_TO_RENDER_CONNECTION_H16#ifndef RENDER_SERVICE_PIPELINE_RS_CLIENT_TO_RENDER_CONNECTION_H
17#define RENDER_SERVICE_PIPELINE_RS_CLIENT_TO_RENDER_CONNECTION_H17#define RENDER_SERVICE_PIPELINE_RS_CLIENT_TO_RENDER_CONNECTION_H
18 18 
19+#include <atomic>
19#include <mutex>20#include <mutex>
20#include <unordered_set>21#include <unordered_set>
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 }
@@ -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 Rosen379} // namespace Rosen
370} // namespace OHOS380} // 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 
144private:146private:
@@ -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 Rosen155} // 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 Rosen97} // 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 Rosen2024} // namespace Rosen
1979} // namespace OHOS2025} // 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 
140private:142private:
@@ -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 Rosen633} // namespace Rosen
550} // namespace OHOS634} // namespace OHOS
@@ -19,6 +19,7 @@
19#include <event_handler.h>19#include <event_handler.h>
20#include <functional>20#include <functional>
21#include <map>21#include <map>
22+#include <unordered_map>
22#include <unordered_set>23#include <unordered_set>
23#include <vector>24#include <vector>
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 Rosen121} // namespace Rosen
95} // namespace OHOS122} // 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+ 
82private:89private:
83 RSRenderService& renderService_;90 RSRenderService& renderService_;
84 HgmProcessCallback hgmProcessCallback_ = nullptr;91 HgmProcessCallback hgmProcessCallback_ = nullptr;
@@ -68,7 +68,6 @@
68#include "feature/hyper_graphic_manager/rs_render_frame_rate_linker_map.h"68#include "feature/hyper_graphic_manager/rs_render_frame_rate_linker_map.h"
69#include "pipeline/rs_render_node_map.h"69#include "pipeline/rs_render_node_map.h"
70#include "pipeline/main_thread/rs_render_service_listener.h"70#include "pipeline/main_thread/rs_render_service_listener.h"
71-#include "pipeline/main_thread/rs_main_thread.h"
72#include "pipeline/rs_surface_buffer_callback_manager.h"71#include "pipeline/rs_surface_buffer_callback_manager.h"
73#include "pipeline/rs_surface_render_node.h"72#include "pipeline/rs_surface_render_node.h"
74#include "pipeline/rs_task_dispatcher.h"73#include "pipeline/rs_task_dispatcher.h"
@@ -111,6 +110,7 @@ constexpr uint32_t MEM_BYTE_TO_MB = 1024 * 1024;
111constexpr uint32_t PIDLIST_SIZE_MAX = 128;110constexpr uint32_t PIDLIST_SIZE_MAX = 128;
112constexpr uint64_t MAX_TIME_OUT_NS = 1e9;111constexpr uint64_t MAX_TIME_OUT_NS = 1e9;
113constexpr int64_t MAX_FREEZE_SCREEN_TIME = 3000;112constexpr int64_t MAX_FREEZE_SCREEN_TIME = 3000;
113+constexpr int64_t DELAY_CLEANUP_MS = 10000;
114const std::string UNFREEZE_SCREEN_TASK_NAME = "UNFREEZE_SCREEN_TASK";114const std::string UNFREEZE_SCREEN_TASK_NAME = "UNFREEZE_SCREEN_TASK";
115}115}
116const std::string RSClientToServiceConnection::GPU_FREQ_PREF = "GPU_FREQ_PREF";116const 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+ 
184void RSClientToServiceConnection::CleanForRefresh() noexcept198void 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#endif2670#endif
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);
chuchengcheng
chuchengchengchuchengcheng6月26日

这里如果存在多个RP时,会往多个RP中插入RemotePid,但是RemotePid清理不掉,可能存在内存泄露

likedislike
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 Rosen2721} // namespace Rosen
2640} // namespace OHOS2722} // namespace OHOS
@@ -16,6 +16,7 @@
16#ifndef RENDER_SERVICE_PIPELINE_RS_CLIENT_TO_SERVICE_CONNECTION_H16#ifndef RENDER_SERVICE_PIPELINE_RS_CLIENT_TO_SERVICE_CONNECTION_H
17#define RENDER_SERVICE_PIPELINE_RS_CLIENT_TO_SERVICE_CONNECTION_H17#define RENDER_SERVICE_PIPELINE_RS_CLIENT_TO_SERVICE_CONNECTION_H
18 18 
19+#include <atomic>
19#include <functional>20#include <functional>
20#include <mutex>21#include <mutex>
21#include <unordered_set>22#include <unordered_set>
@@ -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+ 
66private:73private:
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#endif439#endif
436};440};
437} // namespace Rosen441} // 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#endif456#endif
453private:457private:
454#ifndef ENABLE_RS_PROXY458#ifndef ENABLE_RS_PROXY
@@ -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 Rosen788} // namespace Rosen
781} // namespace OHOS789} // 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#endif2173#endif
2154} // namespace Rosen2174} // namespace Rosen
2155} // namespace OHOS2175} // 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#endif5512#endif
5465} // namespace Rosen5513} // namespace Rosen
5466} // namespace OHOS5514} // 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 Rosen795} // namespace Rosen
788} // namespace OHOS796} // 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 Rosen1274} // namespace Rosen
1265} // namespace OHOS1275} // 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+ 
1543private:1559private:
1544 RSInterfaces();1560 RSInterfaces();
1545 ~RSInterfaces() noexcept;1561 ~RSInterfaces() noexcept;
@@ -1560,4 +1576,4 @@ private:
1560} // namespace Rosen1576} // namespace Rosen
1561} // namespace OHOS1577} // namespace OHOS
1562 1578 
1563-#endif // RENDER_SERVICE_CLIENT_CORE_TRANSACTION_RS_INTERFACES_H1579+#endif // RENDER_SERVICE_CLIENT_CORE_TRANSACTION_RS_INTERFACES_H