472 lines
18 KiB
Markdown
472 lines
18 KiB
Markdown
# DevicePlugin 阶段二任务分解文档 — ScreenPlugin 功能迁移
|
||
|
||
## 项目背景
|
||
根据 CEO 陈逸飞指示,DevicePlugin 阶段一(基础框架)已完成并通过 73/73 测试。现进入阶段二:将 ScreenPlugin 的核心功能迁移到 DevicePlugin,实现统一设备管理架构。
|
||
|
||
## 阶段一成果回顾
|
||
- ✅ Message enum 扩展(DeviceCommand/DeviceResponse/DeviceEvent)
|
||
- ✅ DevicePlugin 骨架与 Backend trait 定义
|
||
- ✅ LinuxArm64Backend 实现(Display + SleepInhibit + Backlight)
|
||
- ✅ 单元测试与文档完善(73/73 测试通过)
|
||
|
||
## 阶段二总体目标
|
||
1. 将 ScreenPlugin 的 systemd-inhibit(防息屏)和 unclutter(光标隐藏)功能迁移到 DevicePlugin
|
||
2. ScreenPlugin 改为通过 DeviceCommand 调用 DevicePlugin(thin wrapper)
|
||
3. 确保现有功能不丢失,保持向后兼容
|
||
4. 为未来完全移除 ScreenPlugin 做准备
|
||
|
||
## 当前状态分析
|
||
|
||
### ScreenPlugin 现有功能(src/plugins/screen/mod.rs)
|
||
1. **防息屏(systemd-inhibit)**:
|
||
- `start_wake_lock()` — 启动 systemd-inhibit 子进程(已在 DevicePlugin 实现)
|
||
- `stop_wake_lock()` — 停止 systemd-inhibit 子进程(已在 DevicePlugin 实现)
|
||
- 处理 `Message::ScreenLockRequest(bool)` 消息
|
||
|
||
2. **光标隐藏(unclutter)**:
|
||
- `set_cursor_hidden(bool)` — 启动/停止 unclutter 进程(**需要迁移**)
|
||
- 处理 `Message::CursorVisibility(bool)` 消息
|
||
|
||
3. **配置驱动**:
|
||
- 从 `ctx.config.display.prevent_screen_lock` 读取配置
|
||
- 在 `start()` 时自动启动防息屏和隐藏光标
|
||
|
||
### DevicePlugin 现有能力(src/plugins/device/linux_arm64.rs)
|
||
- ✅ `SetSleepInhibit(bool)` — 已实现 systemd-inhibit
|
||
- ✅ `SetBacklight(bool)` — 已实现背光控制
|
||
- ✅ `GetDisplayInfo` — 已实现显示信息查询
|
||
- ❌ **光标隐藏功能缺失** — 需要新增
|
||
|
||
## 任务列表与执行顺序
|
||
|
||
---
|
||
|
||
### Task 1: DeviceCommand 扩展 — 添加光标控制命令
|
||
**负责人建议**: 张明远(内核工程师,负责阶段一 Message enum 扩展)
|
||
|
||
**优先级**: P0(阻塞后续所有任务)
|
||
|
||
**输入文件**:
|
||
- `src/core/message.rs` — 现有 DeviceCommand 定义
|
||
- `src/plugins/screen/mod.rs` — ScreenPlugin 光标隐藏实现(参考)
|
||
|
||
**任务描述**:
|
||
1. 在 `DeviceCommand` enum 中添加新变体:
|
||
```rust
|
||
/// 设置光标可见性
|
||
/// - true: 显示光标
|
||
/// - false: 隐藏光标(通过 unclutter 或平台特定方式)
|
||
SetCursorVisible(bool),
|
||
```
|
||
2. 在 `DeviceCapability` enum 中添加新能力:
|
||
```rust
|
||
/// 光标控制能力
|
||
Cursor,
|
||
```
|
||
3. 确保新变体派生 `Debug, Clone, Serialize, Deserialize`
|
||
4. 添加文档注释说明用途和平台差异
|
||
|
||
**输出文件**:
|
||
- `src/core/message.rs` — 更新后的消息定义
|
||
|
||
**验收标准**:
|
||
- [ ] `cargo check --workspace` 零 warning
|
||
- [ ] `SetCursorVisible` 变体正确派生 serde traits
|
||
- [ ] 文档注释清晰说明 Linux/Android/Embedded 平台的实现差异
|
||
- [ ] `DeviceCapability::Cursor` 已添加
|
||
|
||
**预计工时**: 0.5 小时
|
||
|
||
---
|
||
|
||
### Task 2: LinuxArm64Backend 扩展 — 实现光标控制
|
||
**负责人建议**: 赵雨薇(屏幕工程师,ScreenPlugin 原作者,熟悉 unclutter)
|
||
|
||
**优先级**: P0(依赖 Task 1)
|
||
|
||
**依赖**: Task 1 必须完成(DeviceCommand 已扩展)
|
||
|
||
**输入文件**:
|
||
- `src/plugins/device/linux_arm64.rs` — 现有 Backend 实现
|
||
- `src/plugins/screen/mod.rs` — ScreenPlugin 光标隐藏实现(参考 set_cursor_hidden)
|
||
|
||
**任务描述**:
|
||
1. 在 `LinuxArm64Backend` 结构体中添加字段:
|
||
```rust
|
||
/// unclutter 子进程(用于隐藏光标)
|
||
cursor_child: Option<Child>,
|
||
/// 光标可见性状态
|
||
cursor_visible: bool,
|
||
```
|
||
2. 在 `capabilities()` 方法中添加 `DeviceCapability::Cursor`
|
||
3. 在 `handle_command()` 中实现 `SetCursorVisible` 命令:
|
||
- `SetCursorVisible(false)` → 启动 unclutter 进程:
|
||
```bash
|
||
pkill -f unclutter # 先清理旧进程
|
||
unclutter -idle 0 -root # 立即隐藏光标
|
||
```
|
||
- `SetCursorVisible(true)` → 停止 unclutter 进程:
|
||
```bash
|
||
pkill -f unclutter
|
||
```
|
||
- 参考 ScreenPlugin::set_cursor_hidden 的实现(src/plugins/screen/mod.rs:64-101)
|
||
4. 在 `shutdown()` 方法中清理 cursor_child 进程
|
||
5. 添加错误处理:unclutter 不可用时记录警告但不阻塞
|
||
|
||
**输出文件**:
|
||
- `src/plugins/device/linux_arm64.rs` — 更新后的 Backend 实现
|
||
|
||
**验收标准**:
|
||
- [ ] `cargo check --workspace` 零 warning
|
||
- [ ] `SetCursorVisible(false)` 能成功启动 unclutter 进程
|
||
- [ ] `SetCursorVisible(true)` 能成功停止 unclutter 进程
|
||
- [ ] 重复调用相同命令不会产生多个 unclutter 进程
|
||
- [ ] shutdown 正确清理 cursor_child 资源
|
||
- [ ] unclutter 不可用时不阻塞插件启动
|
||
|
||
**预计工时**: 2 小时
|
||
|
||
---
|
||
|
||
### Task 3: ScreenPlugin 重构 — 改为 DevicePlugin 的 thin wrapper
|
||
**负责人建议**: 赵雨薇(ScreenPlugin 原作者,熟悉现有实现和消息流)
|
||
|
||
**优先级**: P0(依赖 Task 2)
|
||
|
||
**依赖**: Task 2 必须完成(DevicePlugin 已支持光标控制)
|
||
|
||
**输入文件**:
|
||
- `src/plugins/screen/mod.rs` — 现有 ScreenPlugin 实现
|
||
- `src/plugins/device/mod.rs` — DevicePlugin 实现
|
||
- `src/core/message.rs` — 消息定义
|
||
|
||
**任务描述**:
|
||
1. 重构 `ScreenPlugin` 结构体,移除直接硬件操作字段:
|
||
```rust
|
||
pub struct ScreenPlugin {
|
||
ctx: Option<PluginContext>,
|
||
// 移除 wake_lock_child: Option<Child>
|
||
// 移除 cursor_hidden: bool
|
||
}
|
||
```
|
||
2. 重构 `start_wake_lock()` 方法:
|
||
```rust
|
||
fn start_wake_lock(&self) {
|
||
if let Some(ctx) = &self.ctx {
|
||
let envelope = Envelope {
|
||
from: self.id().to_string(),
|
||
to: Destination::Plugin("device".to_string()),
|
||
message: Message::DeviceCommand(DeviceCommand::SetSleepInhibit(true)),
|
||
};
|
||
let _ = ctx.tx.send(envelope);
|
||
}
|
||
}
|
||
```
|
||
3. 重构 `stop_wake_lock()` 方法(类似,发送 `SetSleepInhibit(false)`)
|
||
4. 重构 `set_cursor_hidden()` 方法:
|
||
```rust
|
||
fn set_cursor_hidden(&self, hidden: bool) {
|
||
if let Some(ctx) = &self.ctx {
|
||
let envelope = Envelope {
|
||
from: self.id().to_string(),
|
||
to: Destination::Plugin("device".to_string()),
|
||
message: Message::DeviceCommand(DeviceCommand::SetCursorVisible(!hidden)),
|
||
};
|
||
let _ = ctx.tx.send(envelope);
|
||
}
|
||
}
|
||
```
|
||
5. 保持 `handle_message()` 的消息接口不变:
|
||
- `Message::ScreenLockRequest(bool)` → 调用 start/stop_wake_lock
|
||
- `Message::CursorVisibility(bool)` → 调用 set_cursor_hidden
|
||
6. 移除所有 `#[cfg(target_os = "linux")]` 条件编译(平台适配由 DevicePlugin 负责)
|
||
7. 在文件顶部添加注释说明 ScreenPlugin 现在是 DevicePlugin 的 thin wrapper
|
||
|
||
**输出文件**:
|
||
- `src/plugins/screen/mod.rs` — 重构后的 ScreenPlugin 实现
|
||
|
||
**验收标准**:
|
||
- [ ] `cargo check --workspace` 零 warning
|
||
- [ ] ScreenPlugin 不再直接调用 systemd-inhibit 或 unclutter
|
||
- [ ] 所有功能通过 DeviceCommand 消息实现
|
||
- [ ] `Message::ScreenLockRequest` 和 `Message::CursorVisibility` 接口保持不变
|
||
- [ ] 移除了所有平台特定的条件编译代码
|
||
- [ ] 代码行数减少至少 50%
|
||
|
||
**预计工时**: 2 小时
|
||
|
||
---
|
||
|
||
### Task 4: 集成测试 — 验证 ScreenPlugin + DevicePlugin 协作
|
||
**负责人建议**: 李思琪(视频引擎工程师,负责阶段一测试,熟悉消息流测试)
|
||
|
||
**优先级**: P1(依赖 Task 3)
|
||
|
||
**依赖**: Task 3 必须完成(ScreenPlugin 重构完成)
|
||
|
||
**输入文件**:
|
||
- `src/plugins/screen/mod.rs` — 重构后的 ScreenPlugin
|
||
- `src/plugins/device/` — DevicePlugin 实现
|
||
- `src/plugins/device/tests.rs` — 现有测试(参考)
|
||
|
||
**任务描述**:
|
||
1. 在 `src/plugins/device/tests.rs` 中添加光标控制测试:
|
||
```rust
|
||
#[test]
|
||
fn test_set_cursor_visible() {
|
||
// 测试 SetCursorVisible 命令的序列化/反序列化
|
||
}
|
||
|
||
#[test]
|
||
fn test_cursor_capability() {
|
||
// 测试 LinuxArm64Backend 报告 Cursor 能力
|
||
}
|
||
```
|
||
2. 创建 `src/plugins/screen/tests.rs`:
|
||
```rust
|
||
#[test]
|
||
fn test_screen_lock_request_sends_device_command() {
|
||
// 测试 ScreenLockRequest 消息转换为 DeviceCommand::SetSleepInhibit
|
||
}
|
||
|
||
#[test]
|
||
fn test_cursor_visibility_sends_device_command() {
|
||
// 测试 CursorVisibility 消息转换为 DeviceCommand::SetCursorVisible
|
||
}
|
||
```
|
||
3. 在 `src/plugins/screen/mod.rs` 中添加 `#[cfg(test)] mod tests;`
|
||
4. 编写集成测试文档 `docs/DEVICE_PLUGIN_INTEGRATION_TEST.md`:
|
||
- 说明 ScreenPlugin 和 DevicePlugin 的消息流
|
||
- 提供手动测试步骤(如何验证防息屏和光标隐藏)
|
||
- 列出测试覆盖的场景
|
||
|
||
**输出文件**:
|
||
- `src/plugins/device/tests.rs` — 更新后的测试
|
||
- `src/plugins/screen/tests.rs` — 新增测试
|
||
- `docs/DEVICE_PLUGIN_INTEGRATION_TEST.md` — 集成测试文档
|
||
|
||
**验收标准**:
|
||
- [ ] `cargo check --workspace --all-targets` 零 warning
|
||
- [ ] `cargo test --workspace` 全部通过
|
||
- [ ] 至少新增 4 个测试用例(2 个 device + 2 个 screen)
|
||
- [ ] 集成测试文档包含清晰的消息流图和手动测试步骤
|
||
- [ ] 测试覆盖 ScreenPlugin → DevicePlugin 的消息转换
|
||
|
||
**预计工时**: 2.5 小时
|
||
|
||
---
|
||
|
||
### Task 5: 文档更新与迁移总结
|
||
**负责人建议**: 李思琪(负责阶段一文档,熟悉项目文档结构)
|
||
|
||
**优先级**: P1(依赖 Task 4)
|
||
|
||
**依赖**: Task 4 必须完成(测试通过)
|
||
|
||
**输入文件**:
|
||
- `docs/DEVICE_PLUGIN_DESIGN.md` — 设计文档
|
||
- `.showen/DEVICE_PLUGIN_TASKS.md` — 阶段一任务文档
|
||
- `src/plugins/screen/mod.rs` — 重构后的 ScreenPlugin
|
||
- `src/plugins/device/README.md` — DevicePlugin 文档
|
||
|
||
**任务描述**:
|
||
1. 更新 `docs/DEVICE_PLUGIN_DESIGN.md`:
|
||
- 在第 6 节"实施计划"中标记阶段二已完成
|
||
- 在第 8 节"验收标准"中勾选 ScreenPlugin 迁移项
|
||
- 添加"阶段二成果"章节,说明 ScreenPlugin 迁移细节
|
||
2. 更新 `src/plugins/device/README.md`:
|
||
- 在"支持的能力"中添加 Cursor 控制
|
||
- 添加"与 ScreenPlugin 的关系"章节,说明迁移历史
|
||
3. 更新 `src/plugins/screen/mod.rs` 文件头注释:
|
||
```rust
|
||
//! ScreenPlugin — 屏幕管理(Thin Wrapper)
|
||
//!
|
||
//! 本插件现在是 DevicePlugin 的 thin wrapper,通过 DeviceCommand 消息
|
||
//! 调用 DevicePlugin 实现防息屏和光标隐藏功能。
|
||
//!
|
||
//! 历史:v0.1.0 直接调用 systemd-inhibit 和 unclutter
|
||
//! v0.2.0 迁移到 DevicePlugin(2026-03-13)
|
||
```
|
||
4. 创建迁移总结文档 `docs/SCREEN_PLUGIN_MIGRATION_SUMMARY.md`:
|
||
- 迁移前后架构对比图
|
||
- 代码行数对比(迁移前 vs 迁移后)
|
||
- 性能影响分析(消息传递开销)
|
||
- 未来计划(是否完全移除 ScreenPlugin)
|
||
|
||
**输出文件**:
|
||
- `docs/DEVICE_PLUGIN_DESIGN.md` — 更新设计文档
|
||
- `src/plugins/device/README.md` — 更新 DevicePlugin 文档
|
||
- `src/plugins/screen/mod.rs` — 更新文件头注释
|
||
- `docs/SCREEN_PLUGIN_MIGRATION_SUMMARY.md` — 迁移总结文档
|
||
|
||
**验收标准**:
|
||
- [ ] 所有文档更新完整,反映阶段二成果
|
||
- [ ] 迁移总结文档包含清晰的架构对比图
|
||
- [ ] ScreenPlugin 文件头注释说明其 thin wrapper 角色
|
||
- [ ] 设计文档验收标准已更新
|
||
|
||
**预计工时**: 1.5 小时
|
||
|
||
---
|
||
|
||
### Task 6: 示例插件完善 — 展示 DeviceCommand 使用(可选)
|
||
**负责人建议**: 王浩然(网络工程师,可参与示例开发)
|
||
|
||
**优先级**: P2(依赖 Task 5,可延后)
|
||
|
||
**依赖**: Task 5 必须完成(文档更新完成)
|
||
|
||
**输入文件**:
|
||
- `examples/` — 现有示例代码
|
||
- `src/plugins/device/README.md` — DevicePlugin 文档
|
||
|
||
**任务描述**:
|
||
1. 创建 `examples/device_demo.rs`:
|
||
- 演示如何发送 `DeviceCommand::GetDisplayInfo`
|
||
- 演示如何发送 `DeviceCommand::SetSleepInhibit`
|
||
- 演示如何发送 `DeviceCommand::SetCursorVisible`
|
||
- 演示如何接收 `DeviceResponse`
|
||
2. 在 `Cargo.toml` 中添加示例配置:
|
||
```toml
|
||
[[example]]
|
||
name = "device_demo"
|
||
path = "examples/device_demo.rs"
|
||
```
|
||
3. 添加示例运行说明到 `src/plugins/device/README.md`
|
||
|
||
**输出文件**:
|
||
- `examples/device_demo.rs` — 示例代码
|
||
- `Cargo.toml` — 更新示例配置
|
||
- `src/plugins/device/README.md` — 更新运行说明
|
||
|
||
**验收标准**:
|
||
- [ ] `cargo check --examples` 零 warning
|
||
- [ ] `cargo run --example device_demo` 能成功运行
|
||
- [ ] 示例代码包含清晰的注释说明每个步骤
|
||
- [ ] README 包含示例运行说明
|
||
|
||
**预计工时**: 2 小时
|
||
|
||
---
|
||
|
||
## 任务依赖关系图
|
||
|
||
```
|
||
Task 1 (DeviceCommand 扩展 — 光标控制)
|
||
↓
|
||
Task 2 (LinuxArm64Backend 扩展 — 实现光标控制)
|
||
↓
|
||
Task 3 (ScreenPlugin 重构 — thin wrapper)
|
||
↓
|
||
Task 4 (集成测试 — 验证协作)
|
||
↓
|
||
Task 5 (文档更新与迁移总结)
|
||
↓
|
||
Task 6 (示例插件完善,可选)
|
||
```
|
||
|
||
## 团队成员分工建议
|
||
|
||
| 成员 | 角色 | 负责任务 | 理由 |
|
||
|----------|----------------|---------------|-----------------------------------------------|
|
||
| 张明远 | 内核工程师 | Task 1 | 负责阶段一 Message enum 扩展,熟悉类型系统 |
|
||
| 赵雨薇 | 屏幕工程师 | Task 2, 3 | ScreenPlugin 原作者,熟悉 unclutter 和消息流 |
|
||
| 李思琪 | 视频引擎工程师 | Task 4, 5 | 负责阶段一测试和文档,熟悉测试框架 |
|
||
| 王浩然 | 网络工程师 | Task 6(可选)| 可参与示例开发,学习 DevicePlugin 使用 |
|
||
|
||
**核心团队**: 张明远、赵雨薇、李思琪(3 人)
|
||
**执行模式**: 串行交付(Task 1 → Task 2 → Task 3 → Task 4 → Task 5)
|
||
|
||
## 关键风险与应对
|
||
|
||
### 风险 1: unclutter 在某些 Linux 发行版不可用
|
||
**影响**: 中
|
||
**应对**: Task 2 中添加错误处理,unclutter 失败时记录警告但不阻塞插件启动,光标控制功能降级为 no-op
|
||
|
||
### 风险 2: ScreenPlugin 重构后消息传递延迟
|
||
**影响**: 低
|
||
**应对**: Task 4 中添加性能测试,测量消息传递开销(预计 < 1ms),如果延迟明显则考虑优化
|
||
|
||
### 风险 3: 现有依赖 ScreenPlugin 的代码可能受影响
|
||
**影响**: 低
|
||
**应对**: Task 3 保持 ScreenPlugin 的消息接口不变(ScreenLockRequest/CursorVisibility),确保向后兼容
|
||
|
||
### 风险 4: DevicePlugin 未启动时 ScreenPlugin 功能失效
|
||
**影响**: 中
|
||
**应对**: Task 3 中添加错误处理,DevicePlugin 不可用时记录警告,Task 4 中添加测试验证降级行为
|
||
|
||
## 时间估算
|
||
|
||
| 任务 | 预计工时 | 依赖关系 | 负责人 |
|
||
|--------|----------|----------|--------|
|
||
| Task 1 | 0.5h | 无 | 张明远 |
|
||
| Task 2 | 2h | Task 1 | 赵雨薇 |
|
||
| Task 3 | 2h | Task 2 | 赵雨薇 |
|
||
| Task 4 | 2.5h | Task 3 | 李思琪 |
|
||
| Task 5 | 1.5h | Task 4 | 李思琪 |
|
||
| Task 6 | 2h | Task 5 | 王浩然(可选)|
|
||
|
||
**总计**: 8.5 小时(必需任务),10.5 小时(含可选任务)
|
||
**预计完成时间**: 1-1.5 个工作日(假设单人串行)
|
||
|
||
**优化方案**:
|
||
- Task 1 完成后,赵雨薇可以立即开始 Task 2(无等待)
|
||
- Task 4 和 Task 5 可以部分并行(李思琪先写测试,再写文档)
|
||
- Task 6 可以与 Task 5 并行(王浩然独立开发示例)
|
||
|
||
## 验收总清单
|
||
|
||
阶段二完成的标志:
|
||
|
||
- [ ] `cargo check --workspace --all-targets` 零 warning
|
||
- [ ] `cargo test --workspace` 全部通过(包括新增的 4+ 个测试)
|
||
- [ ] DevicePlugin 支持 Cursor 控制能力
|
||
- [ ] ScreenPlugin 重构为 thin wrapper,代码行数减少 50%+
|
||
- [ ] ScreenPlugin 和 DevicePlugin 协作正常,消息流测试通过
|
||
- [ ] 文档完整更新(设计文档 + README + 迁移总结)
|
||
- [ ] 手动测试验证:防息屏和光标隐藏功能正常工作
|
||
- [ ] 性能测试:消息传递延迟 < 1ms
|
||
|
||
## 与阶段一的对比
|
||
|
||
| 维度 | 阶段一(基础框架) | 阶段二(ScreenPlugin 迁移) |
|
||
|----------------|-----------------------------------|-----------------------------------|
|
||
| 任务数量 | 5 个任务(4 必需 + 1 可选) | 6 个任务(5 必需 + 1 可选) |
|
||
| 总工时 | 12-14 小时 | 8.5-10.5 小时 |
|
||
| 核心团队 | 4 人(张明远/王思远/赵雨薇/李思琪)| 3 人(张明远/赵雨薇/李思琪) |
|
||
| 关键挑战 | 从零搭建架构 | 重构现有插件,保持兼容性 |
|
||
| 测试新增 | 5+ 个单元测试 | 4+ 个单元测试 + 集成测试 |
|
||
| 文档新增 | 设计文档 + README | 迁移总结 + 集成测试文档 |
|
||
|
||
## 后续规划(阶段三预告)
|
||
|
||
阶段二完成后,可以考虑:
|
||
|
||
1. **完全移除 ScreenPlugin**(如果 thin wrapper 无存在价值)
|
||
2. **扩展 DevicePlugin 能力**:
|
||
- 触摸/按钮输入事件
|
||
- 传感器数据读取
|
||
- 音频播放
|
||
3. **添加其他平台后端**:
|
||
- Android Backend
|
||
- Embedded (bare-metal) Backend
|
||
4. **VideoPlugin 迁移**:
|
||
- 将 framebuffer 写入迁移到 DevicePlugin.WriteFramebuffer
|
||
|
||
## 汇报要求
|
||
|
||
每个任务完成后,负责人需要:
|
||
1. 运行 `export PATH="/home/showen/.rustup/toolchains/stable-aarch64-unknown-linux-gnu/bin:$PATH" && cargo check --workspace --all-targets` 验证编译
|
||
2. 运行 `export PATH="/home/showen/.rustup/toolchains/stable-aarch64-unknown-linux-gnu/bin:$PATH" && cargo test --workspace` 验证测试
|
||
3. 更新自己的 soul 文件,记录本次任务经验
|
||
4. 在 `.showen/TEAM_CHAT.md` 中汇报任务完成情况
|
||
|
||
全部任务完成后,PM 刘建国向 CEO 汇报到 `.showen/inbox/ceo.md`。
|
||
|
||
---
|
||
|
||
**文档创建时间**: 2026-03-13
|
||
**文档创建人**: PM 刘建国
|
||
**文档版本**: v1.0
|
||
**基于**: DevicePlugin 阶段一成果(73/73 测试通过)
|