4. 跨设备共享作用域设计:CrossDeviceScope 与统一标识

在多设备连接场景中,依赖注入的生命周期管理必须跨越单设备的边界。传统 @Singleton 或 @ActivityScoped 作用域无法处理设备间的实例共享与隔离。本章定义 CrossDeviceScope 作为跨设备共享作用域,并引入 统一标识 作为设备间依赖定位的唯一依据。

4.1 作用域边界定义

CrossDeviceScope 是一个逻辑作用域,其中的依赖实例生命周期与一组已配对的物理设备会话绑定。作用域边界由以下三个要素共同划定:

  • 设备集合:当前会话中参与的所有设备唯一标识(DeviceId)组成的集合。
  • 统一标识:由跨设备会话名称或哈希值生成的不可变标识(CrossDeviceId),用于在 DI 容器中定位作用域实例。
  • 会话活跃性:当集合中任一设备主动离开或心跳超时,作用域标记为可回收。
关键决策:CrossDeviceScope 不依赖单一设备进程存活,而是基于外部协调服务(如协程 SupervisorJob 或持久化存储中的会话记录)维持边界。

4.2 模块分层

为实现跨设备作用域的可管理性,按如下层级组织模块:

层级模块名称职责
L1设备抽象层提供设备发现、连接状态监听、DeviceId 分配
L2会话管理模块维护设备集合,计算/更新 CrossDeviceId
L3统一标识服务生成、校验、缓存 CrossDeviceId
L4信任链路模块签名认证,防止标识伪造
L5作用域容器持有 CrossDeviceScope 实例,执行注入与销毁

4.3 组件职责

  • CrossDeviceScopeManager:单例组件,管理所有活跃的跨设备作用域集合。提供 getScope(crossDeviceId) 与 destroyScope(crossDeviceId) 接口。
  • 统一标识服务:根据设备列表与自定义命名策略生成标识。标识接口定义如下:
// 统一标识服务接口定义(非代码,仅示意)
interface CrossDeviceIdGenerator {
    suspend fun generateId(deviceIds: Set, sessionName: String): String
    suspend fun validateId(candidateId: String, proof: String): Boolean
}
  • 设备注册表:记录每个 CrossDeviceScope 下的设备状态,支持增删查。
  • 会话令牌持有者:持有签名后的统一标识,用于跨进程/跨设备传递认证。

4.4 数据流与控制流

  1. 设备 A 上线 → 设备抽象层生成 DeviceId_A。
  2. 会话管理模块收到配对成功事件 → 收集全部 DeviceId 集合 → 调用统一标识服务生成 CrossDeviceId_X。
  3. 信任链路模块对 CrossDeviceId_X 签名,分发到各设备。
  4. 各设备通过 CrossDeviceScopeManager.getScope(CrossDeviceId_X) 获取或创建作用域。
  5. 作用域内注入的依赖(如共享数据通道、同步锁)在所有设备中保持单例。
  6. 任一设备离线 → 会话管理模块通知作用域容器 → 标记为“待回收”→ 待所有依赖释放后销毁。
数据流特点:控制流采用事件驱动,数据流在作用域内存中共享;统一标识作为路由键,确保不同会话的依赖完全隔离。

4.5 信任链路

统一标识必须防篡改、防重放。信任链路采用双层签名:

  • 设备级签名:每个 DeviceId 由设备私钥签名,校验方用设备公钥验证。
  • 会话级签名:CrossDeviceId 由会话发起设备签名,其他设备在加入时验证签名链。
层次签名方式验证方
设备身份ECDSA 签名协调服务 / 其他设备
统一标识HMAC + 会话密钥每台设备本地校验
风险点:若设备离线后仍持有旧签名,可能尝试重放已被销毁的作用域标识。应在信任链路中加入时间戳与作用域序号(Epoch)。

4.6 选型权衡

决策方案 A方案 B推荐场景
标识生成UUID v4命名空间哈希(如 SHA‑256(设备列表+时间))需要确定性标识时选 B
作用域存储进程内 Map持久化 SQLite设备频繁重连时选 B
跨设备同步广播 + 本地复制集中协调服务设备数量 ≤ 5 选 A

4.7 风险点

  • 标识冲突:不同会话巧合产生相同 CrossDeviceId → 解决:在标识前附加会话发起设备公钥指纹。
  • 作用域泄漏:设备离线后作用域未被及时销毁 → 设置心跳超时强制回收。
  • 状态不一致:设备 A 已离开,设备 B 仍在向作用域写入 → 引入写前校验(Write-Ahead Check)机制。

4.8 落地步骤

  1. 定义统一标识格式(前缀 + 设备列表哈希 + 会话序号)。
  2. 实现 CrossDeviceIdGenerator 接口并注入为 @Singleton。
  3. 创建 @CrossDeviceScope 注解,标注其在 Hilt 模块中的定义。
  4. 在 Application 级别初始化 CrossDeviceScopeManager。
  5. 在设备配对成功后调用 manager.getOrCreate(crossDeviceId)。
  6. 集成信任链路模块,单元测试签名与验证流程。

4.9 验收标准

编号验收要求验证方式
AC‑01同一设备集合在不同时间生成的 CrossDeviceId 相同自动化重复测试
AC‑02设备 A 注入的依赖实例与设备 B 通过同一 ID 获取的实例是同一个 Java 对象对象引用比较(需可序列化验证)
AC‑03设备离线后 30 s 内作用域被销毁,再次上线需创建新作用域日志 + 依赖计数检查
AC‑04伪造的 CrossDeviceId 被信任链路拒绝,注入失败注入异常验证
实践建议:在验收阶段使用 @Inject 注入一个 Counter 对象,在设备 A 中递增,检查设备 B 中读取的值是否同步变化,以此验证跨设备作用域单例。
CrossDeviceScope 架构图 设备节点 作用域容器 统一标识服务 设备 A DeviceId_A 设备 B DeviceId_B 设备 C DeviceId_C 统一标识服务 CrossDeviceId 生成/校验 信任链路模块 签名 & 验证 CrossDeviceScope 容器 作用域 Map<CrossDeviceId, Map<Key, Any>> 共享依赖 (单例实例) 统一标识生成过程 hash(DeviceId_A + DeviceIdB + ...) + epoch 经 HMAC 签名后分发给所有设备 作用域生命周期 创建 → 注入 → 同步 → 任一设备离线 → 标记“待回收”→ 依赖归零后销毁