@ohos-graphics/stability-code-review 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +169 -0
  2. package/SKILL.md +518 -0
  3. package/bin/install.js +165 -0
  4. package/config/rules.yaml +445 -0
  5. package/config/whitelist.yaml +52 -0
  6. package/package.json +40 -0
  7. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_001.md +275 -0
  8. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_002.md +273 -0
  9. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_003.md +305 -0
  10. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_004.md +350 -0
  11. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_005.md +301 -0
  12. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_006.md +320 -0
  13. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_007.md +432 -0
  14. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_008.md +394 -0
  15. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_009.md +425 -0
  16. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_010.md +472 -0
  17. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_011.md +204 -0
  18. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_012.md +210 -0
  19. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_013.md +226 -0
  20. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_014.md +222 -0
  21. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_015.md +256 -0
  22. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_016.md +269 -0
  23. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_017.md +222 -0
  24. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_018.md +336 -0
  25. package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_001.md +414 -0
  26. package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_002.md +335 -0
  27. package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_003.md +284 -0
  28. package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_004.md +313 -0
  29. package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_005.md +364 -0
  30. package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_001.md +142 -0
  31. package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_002.md +222 -0
  32. package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_003.md +383 -0
  33. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_001.md +258 -0
  34. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_002.md +131 -0
  35. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_003.md +220 -0
  36. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_004.md +224 -0
  37. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_005.md +250 -0
  38. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_006.md +153 -0
  39. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_007.md +169 -0
  40. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_008.md +153 -0
  41. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_009.md +144 -0
  42. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_010.md +152 -0
  43. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_011.md +221 -0
  44. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_012.md +318 -0
  45. package/references/InitializationOrder/StabilityCodeReview_InitializationOrder_001.md +411 -0
  46. package/references/Lifecycle/StabilityCodeReview_Lifecycle_001.md +255 -0
  47. package/references/Lifecycle/StabilityCodeReview_Lifecycle_002.md +177 -0
  48. package/references/MemoryStability/StabilityCodeReview_MemoryStability_001.md +332 -0
  49. package/references/MemoryStability/StabilityCodeReview_MemoryStability_002.md +261 -0
  50. package/references/MemoryStability/StabilityCodeReview_MemoryStability_003.md +428 -0
  51. package/references/MemoryStability/StabilityCodeReview_MemoryStability_004.md +400 -0
  52. package/references/MemoryStability/StabilityCodeReview_MemoryStability_005.md +364 -0
  53. package/references/MemoryStability/StabilityCodeReview_MemoryStability_006.md +359 -0
  54. package/references/MemoryStability/StabilityCodeReview_MemoryStability_007.md +279 -0
  55. package/references/PROBLEM_TEMPLATE.md +65 -0
  56. package/references/PerformanceStability/StabilityCodeReview_PerformanceStability_001.md +380 -0
  57. package/references/PerformanceStability/StabilityCodeReview_PerformanceStability_002.md +437 -0
  58. package/references/REPORT_TEMPLATE.csv +5 -0
  59. package/references/REPORT_TEMPLATE.md +132 -0
  60. package/references/RULE_DEVELOPMENT_GUIDE.md +711 -0
  61. package/references/RULE_INDEX.md +101 -0
  62. package/references/RULE_TEMPLATE.md +192 -0
  63. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_001.md +334 -0
  64. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_002.md +425 -0
  65. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_003.md +420 -0
  66. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_004.md +409 -0
  67. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_005.md +445 -0
  68. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_006.md +384 -0
  69. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_007.md +395 -0
  70. package/scripts/add-rule.py +423 -0
@@ -0,0 +1,131 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_GraphicsStability_002"
3
+ name: "VulkanCleanUpHelper与SharedContext引用计数混用"
4
+ category: "图形稳定性"
5
+ severity: "HIGH"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # VulkanCleanUpHelper与SharedContext引用计数混用
11
+
12
+ ## 问题描述
13
+
14
+ VulkanCleanUpHelper与SharedContext分属两套引用计数管理,不能混用。同一资源不能同时使用两种引用计数机制管理,否则会导致引用计数不一致,引发资源泄漏或提前释放。
15
+
16
+ ## 检测示例
17
+
18
+ ### 错误示例
19
+
20
+ ```cpp
21
+ // 错误示例1:同一资源使用两种引用计数管理
22
+ class TextureManager {
23
+ public:
24
+ sk_sp<Surface> CreateSurface(
25
+ GrDirectContext* context,
26
+ const GrBackendTexture& backendTexture,
27
+ VulkanCleanUpHelper* cleanUpHelper,
28
+ SharedContext* sharedContext)
29
+ {
30
+ // 错误:同时使用VulkanCleanUpHelper和SharedContext
31
+ auto surface = Surface::MakeFromBackendTexture(
32
+ context, backendTexture, kTopLeft_GrSurfaceOrigin,
33
+ 1, kRGBA_8888_SkColorType,
34
+ sharedContext->GetSurfaceProps(), // SharedContext引用计数
35
+ cleanUpHelper); // VulkanCleanUpHelper引用计数
36
+ return surface; // 错误:两套引用计数混用
37
+ }
38
+ };
39
+
40
+ // 错误示例2:引用计数操作混用
41
+ class ImageResource {
42
+ public:
43
+ void AddRef() {
44
+ cleanUpHelper_->ref(); // VulkanCleanUpHelper引用
45
+ sharedContext_->AddRef(); // SharedContext引用 // 错误:混用
46
+ }
47
+
48
+ void Release() {
49
+ cleanUpHelper_->unref(); // VulkanCleanUpHelper释放
50
+ sharedContext_->Release(); // SharedContext释放 // 错误:混用
51
+ }
52
+
53
+ private:
54
+ VulkanCleanUpHelper* cleanUpHelper_;
55
+ SharedContext* sharedContext_;
56
+ };
57
+ ```
58
+
59
+ ### 正确示例
60
+
61
+ ```cpp
62
+ // 正确示例1:仅使用VulkanCleanUpHelper管理
63
+ class TextureManager {
64
+ public:
65
+ sk_sp<Surface> CreateSurface(
66
+ GrDirectContext* context,
67
+ const GrBackendTexture& backendTexture,
68
+ VulkanCleanUpHelper* cleanUpHelper)
69
+ {
70
+ auto surface = Surface::MakeFromBackendTexture(
71
+ context, backendTexture, kTopLeft_GrSurfaceOrigin,
72
+ 1, kRGBA_8888_SkColorType, nullptr, cleanUpHelper); // 正确:仅使用一套机制
73
+ return surface;
74
+ }
75
+ };
76
+
77
+ // 正确示例2:仅使用SharedContext管理
78
+ class ImageManager {
79
+ public:
80
+ sk_sp<Image> CreateImage(
81
+ SharedContext* sharedContext,
82
+ const GrBackendTexture& backendTexture)
83
+ {
84
+ auto image = sharedContext->CreateImageFromBackendTexture(backendTexture); // 正确
85
+ return image;
86
+ }
87
+ };
88
+ ```
89
+
90
+ ## 风险流分析(RiskFlow)
91
+
92
+ - **RISK_SOURCE**: VulkanCleanUpHelper与SharedContext引用计数混用
93
+ - **RISK_TYPE**: 引用计数管理冲突
94
+ - **RISK_PATH**: 两套引用计数机制混用 -> 引用计数不一致 -> 资源泄漏或提前释放
95
+ - **IMPACT_POINT**: 内存泄漏、GPU崩溃
96
+
97
+ ## 影响分析(ImpactAnalysis)
98
+
99
+ - **Trigger**: 同一资源使用两种引用计数管理
100
+ - **Propagation**: 引用计数机制冲突,计数不一致
101
+ - **Consequence**: 资源泄漏或提前释放、GPU崩溃、渲染异常
102
+ - **Mitigation**: 选择一种引用计数机制统一管理,不要混用
103
+
104
+ ## 误报排除
105
+
106
+ | 场景 | 识别特征 | 处理方式 |
107
+ |------|----------|----------|
108
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
109
+ | 仅使用一种机制 | 只存在一种引用计数 | 不报 |
110
+ ## 测试用例
111
+
112
+ ### 触发用例(应该报)
113
+
114
+ ```cpp
115
+ // 错误:混用两套引用计数
116
+ void MixedRefCount()
117
+ {
118
+ cleanUpHelper->ref(); // VulkanCleanUpHelper
119
+ sharedContext->AddRef(); // SharedContext // 应该报
120
+ }
121
+ ```
122
+
123
+ ### 安全用例(不应该报)
124
+
125
+ ```cpp
126
+ // 正确:仅使用一套引用计数
127
+ void SingleRefCount()
128
+ {
129
+ cleanUpHelper->ref(); // 仅VulkanCleanUpHelper // 不报
130
+ }
131
+ ```
@@ -0,0 +1,220 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_GraphicsStability_003"
3
+ name: "RS主线程禁止使用RenderNodeDrawable"
4
+ category: "图形稳定性"
5
+ severity: "HIGH"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # RS主线程禁止使用RenderNodeDrawable
11
+
12
+ ## 问题描述
13
+
14
+ RSMainThread类(RS主线程)不能使用RenderNodeDrawable,只能产生RenderNodeDrawable。**RSMainThread类负责渲染的Prepare及以前阶段**,包括处理事务数据、执行动画、计算遮挡、准备渲染数据等,而RenderNodeDrawable的实际绘制操作应在RSUniRenderThread类(Process及以后阶段)执行。如果在RSMainThread类中直接使用RenderNodeDrawable执行绘制,会破坏线程模型,引发渲染异常或崩溃。
15
+
16
+ **渲染流程说明**:
17
+ - RSMainThread类:负责Prepare及以前阶段(OnVsync → ProcessCommand → Animate → Prepare → CalcOcclusion → Sync)
18
+ - RSUniRenderThread类:负责Process及以后阶段(Render → OnDraw → GPU操作 → 资源管理)
19
+
20
+ ## 检测示例
21
+
22
+ ### 错误示例
23
+
24
+ ```cpp
25
+ // 错误示例1:RS主线程直接使用RenderNodeDrawable绘制
26
+ void RSMainThread::OnRender()
27
+ {
28
+ auto drawable = GetRenderNodeDrawable(); // 错误:主线程获取Drawable
29
+
30
+ // 错误:主线程直接执行绘制操作
31
+ drawable->Draw(canvas); // 错误:主线程不应执行绘制
32
+
33
+ // 错误:主线程操作Drawable状态
34
+ drawable->SetVisible(true); // 错误:主线程不应操作Drawable
35
+ }
36
+
37
+ // 错误示例2:主线程回调中使用RenderNodeDrawable
38
+ class MainThreadHandler {
39
+ public:
40
+ void HandleRenderCommand()
41
+ {
42
+ if (IsMainThread()) {
43
+ auto drawable = node->GetDrawable(); // 错误:主线程获取
44
+ drawable->UpdateContent(); // 错误:主线程使用
45
+ }
46
+ }
47
+ };
48
+ ```
49
+
50
+ ### 正确示例
51
+
52
+ ```cpp
53
+ // 正确示例1:RS主线程只产生RenderNodeDrawable
54
+ void RSMainThread::ProcessCommand()
55
+ {
56
+ auto node = CreateRenderNode();
57
+ auto drawable = RenderNodeDrawable::Create(node); // 正确:主线程创建
58
+
59
+ // 正确:提交到渲染线程执行
60
+ SubmitToRenderThread(drawable);
61
+ }
62
+
63
+ // 正确示例2:渲染线程使用RenderNodeDrawable
64
+ void RenderThread::OnRender()
65
+ {
66
+ auto drawable = GetPendingDrawable(); // 正确:渲染线程获取
67
+
68
+ // 正确:渲染线程执行绘制
69
+ drawable->Draw(canvas); // 正确:渲染线程绘制
70
+ }
71
+
72
+ // 正确示例3:主线程通过命令传递
73
+ void RSMainThread::UpdateNode()
74
+ {
75
+ UpdateRenderNodeCommand cmd;
76
+ cmd.nodeId = node->GetId();
77
+ cmd.content = newContent;
78
+
79
+ SubmitCommand(cmd); // 正确:通过命令传递,不直接操作Drawable
80
+ }
81
+ ```
82
+
83
+ ## 风险流分析(RiskFlow)
84
+
85
+ - **RISK_SOURCE**: RSMainThread类使用RenderNodeDrawable
86
+ - **RISK_TYPE**: 线程职责越界
87
+ - **RISK_PATH**: RSMainThread类使用RenderNodeDrawable -> 线程安全风险 -> 渲染异常或崩溃
88
+ - **IMPACT_POINT**: 渲染异常、线程安全问题
89
+
90
+ ## 影响分析(ImpactAnalysis)
91
+
92
+ - **Trigger**: RSMainThread类直接操作RenderNodeDrawable
93
+ - **Propagation**: 破坏渲染线程模型
94
+ - **Consequence**: 渲染异常、界面卡顿、崩溃
95
+ - **Mitigation**: RSMainThread类只产生RenderNodeDrawable,不直接使用
96
+
97
+ ## 误报排除
98
+
99
+ | 场景 | 识别特征 | 处理方式 |
100
+ |------|----------|----------|
101
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
102
+ | 创建操作 | RenderNodeDrawable::Create, OnGenerate | 不报(允许创建)|
103
+ | 渲染线程上下文 | RSUniRenderThread::, RenderThread:: | 不报 |
104
+ | 通过Drawable访问Node | drawable->GetRenderNode() | 不报(允许Get)|
105
+
106
+ ### 创建vs使用的场景区分
107
+
108
+ RSMainThread允许**创建**RenderNodeDrawable,但禁止**使用**(绘制):
109
+
110
+ #### ✅ 允许场景(创建RenderNodeDrawable)
111
+
112
+ ```cpp
113
+ // 正确场景1:创建RenderNodeDrawable
114
+ void RSMainThread::PrepareNode(RSRenderNode& node)
115
+ {
116
+ auto drawable = RenderNodeDrawable::OnGenerate(node); // ✅ 允许创建
117
+ node.SetDrawable(drawable); // ✅ 允许设置
118
+ }
119
+
120
+ // 正确场景2:获取Drawable但不执行绘制
121
+ void RSMainThread::ProcessNode(RSRenderNode& node)
122
+ {
123
+ auto drawable = node.GetDrawable(); // ✅ 允许获取
124
+ if (drawable) {
125
+ drawable->UpdateBounds(node.GetBounds()); // ✅ 允许Prepare阶段的状态更新
126
+ }
127
+ }
128
+
129
+ // 正确场景3:Prepare阶段的状态准备
130
+ void RSMainThread::PrepareRenderNode(RSRenderNode& node)
131
+ {
132
+ auto drawable = RenderNodeDrawable::Create(node); // ✅ 允许创建
133
+ drawable->SetPrepareData(data); // ✅ 允许Prepare数据设置
134
+ }
135
+ ```
136
+
137
+ #### ❌ 禁止场景(使用RenderNodeDrawable执行绘制)
138
+
139
+ ```cpp
140
+ // 错误场景1:主线程执行Draw绘制
141
+ void RSMainThread::RenderFrame()
142
+ {
143
+ auto drawable = GetDrawable();
144
+ drawable->Draw(canvas); // ❌ 禁止:主线程不应绘制
145
+ }
146
+
147
+ // 错误场景2:主线程执行OnDraw
148
+ void RSMainThread::OnRender()
149
+ {
150
+ auto drawable = GetDrawable();
151
+ drawable->OnDraw(canvas); // ❌ 禁止:主线程不应OnDraw
152
+ }
153
+
154
+ // 错误场景3:主线程执行GPU相关绘制命令
155
+ void RSMainThread::RenderNode()
156
+ {
157
+ auto drawable = GetDrawable();
158
+ drawable->RenderContent(); // ❌ 禁止:GPU绘制操作
159
+ }
160
+ ```
161
+
162
+ ### RenderNodeDrawable生命周期
163
+
164
+ 理解RenderNodeDrawable的两个阶段:
165
+
166
+ - **Prepare阶段(RSMainThread)**:
167
+ - 创建RenderNodeDrawable
168
+ - 设置Prepare数据(bounds、content等)
169
+ - 更新Drawable状态(可见性、脏区域等)
170
+ - 不执行实际的绘制操作
171
+
172
+ - **Process阶段(RSUniRenderThread)**:
173
+ - 获取已创建的Drawable
174
+ - 执行Draw/OnDraw绘制
175
+ - 执行GPU相关操作
176
+ - 资源管理和清理
177
+
178
+ ### 检测规则细化
179
+
180
+ **应该报的情况**:
181
+ - RSMainThread中调用`drawable->Draw(canvas)`
182
+ - RSMainThread中调用`drawable->OnDraw(canvas)`
183
+ - RSMainThread中调用`drawable->RenderContent()`
184
+ - RSMainThread中执行GPU绘制命令
185
+
186
+ **不应该报的情况**:
187
+ - RSMainThread中调用`RenderNodeDrawable::Create(node)`
188
+ - RSMainThread中调用`RenderNodeDrawable::OnGenerate(node)`
189
+ - RSMainThread中调用`drawable->GetRenderNode()`
190
+ - RSMainThread中调用`drawable->UpdateBounds(bounds)`(Prepare数据)
191
+ - RSUniRenderThread中的任何Drawable操作
192
+ ## 测试用例
193
+
194
+ ### 触发用例(应该报)
195
+
196
+ ```cpp
197
+ // RSMainThread上下文中使用RenderNodeDrawable
198
+ void RSMainThread::OnRender()
199
+ {
200
+ auto drawable = GetRenderNodeDrawable();
201
+ drawable->Draw(canvas); // 应该报:主线程不应绘制
202
+ }
203
+ ```
204
+
205
+ ### 安全用例(不应该报)
206
+
207
+ ```cpp
208
+ // RSMainThread只创建RenderNodeDrawable
209
+ void RSMainThread::CreateDrawable()
210
+ {
211
+ auto drawable = RenderNodeDrawable::Create(node); // 不报:允许创建
212
+ SubmitToRenderThread(drawable);
213
+ }
214
+
215
+ // 渲染线程使用RenderNodeDrawable
216
+ void RenderThread::OnRender()
217
+ {
218
+ drawable->Draw(canvas); // 不报:渲染线程允许使用
219
+ }
220
+ ```
@@ -0,0 +1,224 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_GraphicsStability_004"
3
+ name: "RSUniRenderThread禁止访问RenderNode"
4
+ category: "图形稳定性"
5
+ severity: "HIGH"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # RSUniRenderThread禁止访问RenderNode
11
+
12
+ ## 问题描述
13
+
14
+ RSUniRenderThread类(统一渲染线程)不能访问RenderNode。**RSUniRenderThread类负责渲染的Process及以后阶段**,包括执行绘制命令、GPU操作、资源管理等。访问RenderNode应在RSMainThread类(Prepare阶段)进行,RSUniRenderThread类通过命令或Drawable间接获取渲染信息。
15
+
16
+ **渲染流程说明**:
17
+ - RSMainThread类:负责Prepare及以前阶段(OnVsync → ProcessCommand → Animate → Prepare → CalcOcclusion → Sync),可以直接访问RenderNode
18
+ - RSUniRenderThread类:负责Process及以后阶段(Render → OnDraw → GPU操作 → 资源管理),不应直接访问RenderNode
19
+
20
+ ## 检测示例
21
+
22
+ ### 错误示例
23
+
24
+ ```cpp
25
+ // 错误示例1:RSUniRenderThread类直接访问RenderNode
26
+ void RSUniRenderThread::RenderFrame()
27
+ {
28
+ auto node = GetRenderNode(id); // 错误:RSUniRenderThread类获取RenderNode
29
+
30
+ // 错误:RSUniRenderThread类直接操作RenderNode
31
+ node->UpdateContent(); // 错误:不应在RSUniRenderThread类访问
32
+
33
+ // 错误:RSUniRenderThread类读取RenderNode状态
34
+ auto bounds = node->GetBounds(); // 错误:不应在RSUniRenderThread类访问
35
+ }
36
+
37
+ // 错误示例2:RSUniRenderThread类回调中访问RenderNode
38
+ class UniRenderCallback {
39
+ public:
40
+ void OnRenderComplete()
41
+ {
42
+ if (IsUniRenderThread()) {
43
+ RenderNode* node = nodeMap_->GetNode(surfaceId); // 错误
44
+ node->SetRenderComplete(); // 错误
45
+ }
46
+ }
47
+ };
48
+ ```
49
+
50
+ ### 正确示例
51
+
52
+ ```cpp
53
+ // 正确示例1:RSUniRenderThread类通过Drawable获取信息
54
+ void RSUniRenderThread::RenderFrame()
55
+ {
56
+ auto drawable = GetDrawableForRender(); // 正确:通过Drawable
57
+
58
+ // 正确:从Drawable获取渲染信息
59
+ drawable->Draw(canvas); // 正确:不直接访问RenderNode
60
+ }
61
+
62
+ // 正确示例2:RSUniRenderThread类通过命令接收数据
63
+ void RSUniRenderThread::ProcessCommand(const RenderCommand& cmd)
64
+ {
65
+ // 正确:从命令中获取需要的信息
66
+ auto bounds = cmd.bounds;
67
+ auto content = cmd.content;
68
+
69
+ RenderInternal(bounds, content); // 正确:使用命令数据
70
+ }
71
+
72
+ // 正确示例3:RSMainThread类管理RenderNode
73
+ void RSMainThread::UpdateRenderNode(NodeId id, const Content& content)
74
+ {
75
+ auto node = GetRenderNode(id); // 正确:RSMainThread类访问
76
+ node->UpdateContent(content); // 正确:RSMainThread类操作
77
+
78
+ // 正确:通知RSUniRenderThread类
79
+ SubmitRenderCommand(id, node->GetBounds());
80
+ }
81
+ ```
82
+
83
+ ## 风险流分析(RiskFlow)
84
+
85
+ - **RISK_SOURCE**: RSUniRenderThread类访问RenderNode
86
+ - **RISK_TYPE**: 线程访问越界
87
+ - **RISK_PATH**: RSUniRenderThread类访问RenderNode -> 线程安全风险 -> 数据竞争
88
+ - **IMPACT_POINT**: 渲染数据不一致、崩溃
89
+
90
+ ## 影响分析(ImpactAnalysis)
91
+
92
+ - **Trigger**: RSUniRenderThread类直接访问RenderNode
93
+ - **Propagation**: 破坏线程模型,引发数据竞争
94
+ - **Consequence**: 渲染异常、数据损坏、崩溃
95
+ - **Mitigation**: RSUniRenderThread类不应直接访问RenderNode
96
+
97
+ ## 误报排除
98
+
99
+ | 场景 | 识别特征 | 处理方式 |
100
+ |------|----------|----------|
101
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
102
+ | 主线程上下文 | RSMainThread:: | 不报 |
103
+ | 通过Drawable间接获取 | drawable->GetRenderNode().lock() | 不报(允许间接获取)|
104
+ | 只读访问 | drawable->GetNodeBounds() | 不报(从Drawable获取数据)|
105
+
106
+ ### 间接获取vs直接访问的场景区分
107
+
108
+ RSUniRenderThread允许通过Drawable**间接获取**RenderNode信息,但禁止**直接访问**RenderNode对象:
109
+
110
+ #### ✅ 允许场景(通过Drawable间接获取)
111
+
112
+ ```cpp
113
+ // 正确场景1:通过Drawable获取Node信息
114
+ void RSUniRenderThread::RenderDrawable(RSRenderNodeDrawable* drawable)
115
+ {
116
+ auto node = drawable->GetRenderNode().lock(); // ✅ 允许:通过Drawable间接获取
117
+ if (!node) {
118
+ return;
119
+ }
120
+ // 使用node的只读信息进行绘制准备
121
+ auto bounds = node->GetBounds(); // ✅ 允许:通过Drawable获取的只读访问
122
+ }
123
+
124
+ // 正确场景2:从Drawable获取渲染数据
125
+ void RSUniRenderThread::DrawContent(RSRenderNodeDrawable* drawable)
126
+ {
127
+ // Drawable已经缓存了必要的渲染数据
128
+ drawable->Draw(canvas); // ✅ 允许:使用Drawable绘制
129
+
130
+ // 不直接访问Node获取数据
131
+ // auto node = nodeMap_->GetNode(id); // ❌ 禁止
132
+ }
133
+
134
+ // 正确场景3:使用Drawable缓存的Prepare数据
135
+ void RSUniRenderThread::ProcessDrawable()
136
+ {
137
+ auto drawable = GetDrawable();
138
+ auto bounds = drawable->GetCachedBounds(); // ✅ 允许:使用Drawable缓存的数据
139
+ auto content = drawable->GetCachedContent(); // ✅ 允许
140
+ }
141
+ ```
142
+
143
+ #### ❌ 禁止场景(直接访问RenderNode)
144
+
145
+ ```cpp
146
+ // 错误场景1:通过NodeMap直接获取RenderNode
147
+ void RSUniRenderThread::RenderFrame()
148
+ {
149
+ auto node = nodeMap_->GetNode(nodeId); // ❌ 禁止:直接访问NodeMap
150
+ node->UpdateContent(); // ❌ 禁止:直接操作RenderNode
151
+ }
152
+
153
+ // 错误场景2:通过全局容器访问RenderNode
154
+ void RSUniRenderThread::ProcessNodes()
155
+ {
156
+ for (auto& node : globalNodeList) { // ❌ 禁止:直接遍历Node容器
157
+ node->Render(); // ❌ 禁止
158
+ }
159
+ }
160
+
161
+ // 错误场景3:通过id直接查询RenderNode
162
+ void RSUniRenderThread::OnRender(NodeId id)
163
+ {
164
+ RSRenderNode* node = RSBaseRenderNode::GetNodeById(id); // ❌ 禁止:直接查询
165
+ auto bounds = node->GetBounds(); // ❌ 禁止
166
+ }
167
+ ```
168
+
169
+ ### RenderNode访问路径说明
170
+
171
+ 理解RenderNode的两种访问路径:
172
+
173
+ - **RSMainThread路径**(允许直接访问):
174
+ - `GetRenderNode(id)` - 直接从NodeMap获取
175
+ - `RSRenderNode::GetNodeById(id)` - 直接查询
176
+ - 可以执行Update、Prepare等操作
177
+
178
+ - **RSUniRenderThread路径**(只能间接访问):
179
+ - `drawable->GetRenderNode().lock()` - 通过Drawable获取weak_ptr
180
+ - `drawable->GetCachedXXX()` - 使用Drawable缓存的数据
181
+ - 只能读取Prepare阶段缓存的数据,不能修改
182
+
183
+ ### 检测规则细化
184
+
185
+ **应该报的情况**:
186
+ - RSUniRenderThread中调用`nodeMap_->GetNode(id)`
187
+ - RSUniRenderThread中调用`RSBaseRenderNode::GetNodeById(id)`
188
+ - RSUniRenderThread中直接操作`RSRenderNode*`指针
189
+ - RSUniRenderThread中遍历`globalNodeList`等Node容器
190
+
191
+ **不应该报的情况**:
192
+ - RSUniRenderThread中调用`drawable->GetRenderNode().lock()`(通过Drawable间接获取)
193
+ - RSUniRenderThread中调用`drawable->GetCachedXXX()`(使用Drawable缓存数据)
194
+ - RSMainThread中的任何RenderNode访问
195
+ - Prepare阶段的RenderNode操作(在RSMainThread中)
196
+ ## 测试用例
197
+
198
+ ### 触发用例(应该报)
199
+
200
+ ```cpp
201
+ // RSUniRenderThread类访问RenderNode
202
+ void RSUniRenderThread::OnRender()
203
+ {
204
+ RenderNode* node = GetRenderNode(id); // 应该报
205
+ node->GetBounds(); // 应该报
206
+ }
207
+ ```
208
+
209
+ ### 安全用例(不应该报)
210
+
211
+ ```cpp
212
+ // RSMainThread类访问RenderNode
213
+ void RSMainThread::UpdateNode()
214
+ {
215
+ RenderNode* node = GetRenderNode(id); // 不报:RSMainThread类允许
216
+ }
217
+
218
+ // RSUniRenderThread类使用Drawable
219
+ void RSUniRenderThread::OnRender()
220
+ {
221
+ auto drawable = GetDrawable(); // 不报
222
+ drawable->Draw(canvas); // 不报
223
+ }
224
+ ```