RFC-0172:界面 activity 服务 | |
---|---|
状态 | 已接受 |
区域 |
|
说明 | 提出了一项服务,用于确定用户输入的活动或空闲状态并通知客户端。 |
问题 | |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2022-06-02 |
审核日期(年-月-日) | 2022-06-30 |
摘要
此 RFC 引入了新的界面 activity 服务,该服务会取代现有版本并缩小其职责范围。
所提议的服务添加了两个新的 FIDL 协议:
- 一个私有 FIDL 协议
fuchsia.input.interaction.observation.Aggregator
,用于收集用户输入活动的证据, - 合作伙伴 FIDL 协议
fuchsia.input.interaction.Notifier
,用于通知客户端用户输入 activity 状态的变化。
设计初衷
我们希望提供一项服务,用于通知系统的其他部分是否最近发生了用户输入活动。此服务非常有用,可用于通知其他系统服务(例如节能协议或屏幕保护程序功能)。
系统中有一个预先存在的“Activity 服务”,它将自身确立为系统中用户空闲状态的真相来源。此提案不同于当前方法,它引入了新的“界面 activity 服务”,以指明责任范围更窄(仅限于用户输入 activity,而非整个系统 activity),从而支持某些产品中的新功能,同时减少其他产品中的技术债务。
利益相关方
教员:
leannogasawara@google.com
Reviewers:
- jsankey@google.com
- neelsa@google.com
- sanjayc@google.com
- quiche@google.com
- wittrock@google.com
咨询了:
- anwilson@google.com
- comfoltey@google.com
- fmil@google.com
- kpozin@google.com
- palmer@google.com
- yaar@google.com
社交:
在文档审核期间,我们与 Fuchsia 输入团队讨论了此 RFC,并请求对其进行隐私和安全审核。
设计
activity 状态
活动是指用户最近与设备进行的输入互动。
“最近”是指产品配置的时间阈值(例如 15 分钟)。
如果设备近期未收到任何活动,则被视为处于空闲状态。
用户输入互动在初始实现阶段仅限于下面列出的用例。
要求
以下用户互动必须会导致服务进入或续订有效状态:
- 用户触摸了屏幕。
- 用户与鼠标或键盘互动。
- 用户按下了媒体按钮,例如音量调高或音量调低按钮。
以下用户互动应会导致服务进入或恢复活跃状态:
- 用户启用或停用了屏幕阅读器。如果用户使用上述某种输入模式执行此操作,系统会隐式捕获该操作。或者,如果是通过对 SetUI 的更改来执行此操作,建议将其视为类似于打开设备盖子。
- 用户已打开设备盖子。
- 用户开启了设备。
以下互动不会被视为活跃用户输入活动,原因如下文所述。因此,它们不得导致服务进入active 状态:
- 用户正在观看视频或聆听音频文件:应使用
fuchsia.media.ActivityReporter
,而不是本 RFC 中所述的 activity 服务。
协议和服务
我们向合作伙伴 SDK 引入了新的内部 FIDL 协议 fuchsia.input.interaction.observation.Aggregator
和新的 FIDL 协议 fuchsia.input.interaction.Notifier
。这些协议将由 Input Pipeline 组件中的新 Activity
类实现和公开。
fuchsia.input.interaction.observation.Aggregator
此 API 的客户报告说,他们认为自己有用户输入活动的证据,我们会将其信息视为如此。因此,系统会通过 capability 路由将访问权限限制为仅限树内组件。如需了解详情,请参阅安全注意事项。
library fuchsia.input.interaction.observation;
using zx;
/// The Aggregator protocol collects evidence of user activity and uses this
/// evidence to set the system's activity state.
@discoverable
protocol Aggregator {
/// Reports a discrete activity such as a keystroke.
ReportDiscreteActivity(struct {
activity DiscreteActivity;
event_time zx.time;
}) -> ();
};
与其前身收集离散事件和持续事件(即具有开始时间和结束时间的活动)不同,此 RFC 定义的此协议的初始版本仅收集“离散”活动。收集正在进行的事件的功能最初是为了支持媒体播放而引入的,这明确不属于此 RFC 的用例。
fuchsia.input.interaction.Notifier
此 API 的客户端应希望订阅用户互动“活跃”和“空闲”状态之间的变化,就像 fuchsia.ui.activity.State
中定义的那样。此 RFC 计划在 fuchsia.input.interaction
库中创建一个类似的枚举,以便在将来需要扩展时使用 flexible
。无需限制访问权限,请参阅隐私权注意事项。例如:
- 树内:当设备进入空闲状态时,无障碍功能管理器会让屏幕阅读器停止对屏幕上的更改进行口述(例如,如果显示了时钟,则每分钟一次)。
- 非树内:当设备进入空闲状态时,客户端会返回主屏幕。
library fuchsia.input.interaction;
/// The Notifier protocol offers a subscription interface through
/// which clients can watch for changes in the system's activity state.
@discoverable
protocol Notifier {
/// Subscribe to changes in the system's state.
/// The server will always respond immediately with the initial state,
/// and after that whenever the system's state changes.
WatchState(table {}) -> (resource struct {
state State;
});
};
拟议的协议将与现有的 fuchsia.ui.activity.Notifier.WatchState
协议不同,因为它将使用挂起 get 模式,完全无需 Listener 协议。它也不会发送时间戳。
盖子传感器
界面活动服务可以使用 fuchsia.hardware.input
FIDL 监控盖子传感器驱动程序报告,并在收到盖子打开报告后转换为活动状态。
与输入流水线集成
空间注意事项
在输入流水线 (IP) 组件中实现界面 activity 服务 (A) 而不是作为自己的组件实现,可以节省约 172 KB 的磁盘空间,具体取决于产品和开发板配置。对于受空间限制的产品,减小大小可为系统中的其他改进腾出空间。
构建 | A | IP | IP + 两个 FIDL |
---|---|---|---|
workstation_pro.chromebook-x64 | 196 KB | 1364 KB | 1388 KB |
core.astro | 184 KB | 688 KB | 700 KB |
其他注意事项
在输入流水线中集成界面 activity 服务包括以下步骤:
- 此服务应采用单线程设计,因为目前不需要也不利于采用多线程设计。此外,输入流水线是单线程的,将库转换为支持多线程方法会引入不必要的复杂性。
- 应使用 Rust 实现该服务,以避免引入在一个库中管理多种语言所需的复杂性。
- 该服务在恢复模式下不可用,因为恢复模式不使用输入流水线或场景管理器。恢复模式没有 activity 服务并不是问题,因为恢复模式的设计就是使用单个高度集成的组件来尽量减少依赖项。
- 服务不应通过标记已处理的事件或将其发送到其他组件来处理
InputReport
,因为这会导致服务知晓并负责处理超出确定近期是否发生了活动所需的信息。 - 该服务不应对输入事件的来源有特殊的了解(因为这些事件应通过
fuchsia.input.interaction.observation.Aggregator
报告)。 - 因此,不应将该服务实现为
InputHandler
。
可配置的空闲阈值
闲置阈值是指自上次用户活动以来系统进入闲置状态所经过的时间。您可以在产品级别的输入流水线或场景管理器组件中使用结构化配置进行设置,当前产品的设置为 15 分钟。
实现
服务将按如下方式实现:
- 定义新的
fuchsia.input.interaction.observation.Aggregator
和fuchsia.input.interaction.Notifier
FIDL 协议。 - 实现并单元测试一个新的
Activity
服务,该服务在输入流水线中进行初始化,以便同时处理这两种协议。 - 通过
fuchsia.input.interaction.observation.Aggregator
报告相关的InputHandlers
活动。注意:最好在此阶段(而不是在绑定阶段)报告活动,因为InputHandlers
负责将信息从InputEvents
分派到其他组件或服务。 受影响的处理脚本包括:
- MediaButtonsHandler
- MouseInjectorHandler
- TouchInjectorHandler
- KeypressHandler(新)
- 为以下情况添加集成测试:
fuchsia.input.interaction.observation.Aggregator
用于通知 activity 状态- 当系统转换为“Active”时,系统会通知
fuchsia.input.interaction.Notifier
- 当系统转换为空闲状态时,
fuchsia.input.interaction.Notifier
会收到通知
=== fuchsia.input.interaction.Notifier
目前可供客户使用 ===
- 废弃并移除了
fuchsia.ui.activity.Tracker
、fuchsia.ui.activity.Provider
和fuchsia.ui.activity.control.Control
- 将 FIDL 协议标记为已废弃,并附上使用新协议的说明
- 将
fuchsia.ui.activity.Provider
的现有用法迁移到fuchsia.input.interaction.Notifier
[在 Cobalt、Omaha 和 PowerManager 中] - 移除了
fuchsia.ui.activity.Tracker
的使用(无效) - 删除
//src/sys/activity
性能
界面 activity 服务不得增加系统中输入事件的处理延迟时间。
虽然所提议的协议不会引入异步或计算密集的逻辑,但我们可能需要对高频率输入事件引入节流。例如,鼠标通常会每秒发送大约 1000 个事件,因此可能需要对从 MouseInjectorHandler
到 activity 服务的 FIDL 调用进行速率限制。
我们可以监控现有的性能测试(例如输入延迟时间测试),以确定更改是否会导致性能下降。
安全注意事项
界面 activity 服务的主要滥用途径是通过使用 fuchsia.input.interaction.observation.Aggregator
虚假报告 activity 来让系统保持唤醒状态。例如,恶意应用可能会定期报告活动以保持系统处于唤醒状态。由于 fuchsia.input.interaction.observation.Aggregator
仅在树中提供,而不是在 SDK 中提供,并且仅供界面领域中的组件使用,因此这被认为风险较低。
任何此类服务都可能会导致软件更新延迟、屏幕保持解锁状态、耗尽电池电量,并且可能会导致设备上的其他应用无法正常运行。委托数据访问是本 RFC 未解决的一个风险。依赖于空闲状态来使用上述功能的客户端在使用此服务时应实现自己的活动上限(如果适用),例如在用户活跃 24 小时后强制执行系统 OTA。
由于此功能必须通过 CFV2 路由,因此请注意,平台仅授予在平台级别向输入流水线和可能的无障碍功能管理器报告活动的权限,并且产品可以进一步路由到可信组件。
隐私注意事项
虽然界面活动服务不会公开与用户活动性质相关的任何信息,但它会通过 fuchsia.input.interaction.Notifier
分享最近是否在预设时间阈值内发生了活动。
用户是否在特定时间在家或使用设备,这对隐私有影响且非常敏感,因此我们不希望不可信的组件有权访问此类信息。由于此功能必须通过 CFV2 路由,因此请注意,平台应仅授予在平台级别可信的活动的观察权限,并且产品可以进一步路由到可信组件。
订阅者将无法看到时间戳。
测试
我们的测试策略包括
- 单元测试
- 使用现有工具进行集成测试
文档
该服务将包含 README 概览,新的 FIDL 协议将附带内嵌注释。
缺点
输入流水线故障
如果输入流水线 panic 或发生死锁,界面 activity 服务也会失败。在这种情况下,空闲状态变化的订阅者可能希望默认采用活动状态行为,而不是空闲状态行为,并且应采取其他缓解措施(例如活动超时上限),以确保关键进程仍能正常运行。如果输入数据流无法接收或回复输入报告,则可能表示系统存在更广泛的问题。
替代方案
使用现有的 fuchsia.ui.activity.Tracker
协议
这种方法更倾向于创建新的 fuchsia.input.interaction.observation.Aggregator
协议。
- 当前协议位于合作伙伴 SDK 中,不能仅限于私有 SDK 使用。包含合作伙伴 SDK 需要满足额外的 CTS 测试要求。
- 汇总器更明确地指明了协议的操作。
- 目前的一组用例不需要使用
StartOngoingActivity
或EndOngoingActivity
,未来可能需要重新评估当前模式。
修改现有 fuchsia.ui.activity.Provider
协议
这种方法更倾向于创建新的 fuchsia.input.interaction.Notifier
协议。
- 当前协议可由
fuchsia.ui.activity.control.Control
协议控制。 WatchState
协议必须迁移到提议的挂起 get 模式。WatchState
协议会不必要地发布时间戳,我们不希望客户端在没有具体用例或公开时间戳的意图的情况下依赖于该时间戳。
纳入其他活动信号
某些信号在某些用户体验流程中可能被视为活动,但在其他用户体验流程中可能不会。因此,信号解读方式的正确性会因给定外形规格或服务的需求而异。
建议使用 fuchsia.input.interaction.Notifier
协议来使用界面 activity 状态,并且可以与其他形式的 activity(例如来自音频、麦克风或摄像头的 activity)结合引用,以便根据具体情况确定一些最终用户或系统状态。例如,屏保功能可能只会查询用户输入活动,而锁屏功能可能同时查询用户输入活动和用户身份验证状态。
支持配置要考虑的一组活动类型
将来,某些服务可能希望遵循由部分用户输入模式(例如最近的轻触,但不是最近的按键操作)决定的 activity 状态。这会在可能的输入模式之间引入指数级组合。
鉴于用户目前对更精细的功能不感兴趣,我们决定不急于引入这种复杂性。
与 Fuchsia 的系统身份验证集成
系统身份验证和界面 activity 服务都关注某种用户行为,但在实际应用中重叠很少。例如,系统身份验证会关注更精细的一组用户在线状态,包括用户与设备的距离以及用户是否为账号所有者。
虽然您或许可以以适合这两种用例的方式跟踪用户活动,但如果没有明确的应用场景,就没有必要主动集成这两种系统。
后续工作
允许订阅者配置空闲时间阈值
未来,某些服务可能希望自行确定用户输入互动的新近性阈值。虽然本 RFC 未提出解决方案,而是出于简化初始实现的目的而忽略了此功能,但在出现具体用例时,可以扩展所提议的协议以添加支持。
在先技术和参考文档
- chrome.idle API 支持“active”“idle”和“locked”状态。
- 由于未使用,Root Presenter 中的 Fuchsia activity 通知器已被移除。