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 服务”,指明了更小的责任范围(仅对用户输入活动而不是整个系统活动),从而在一些产品中实现新功能,同时减少另一些产品的技术债务。
利益相关方
教员:
leannogasawara@google.com
审核者:
- 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 Input 团队讨论了此 RFC,申请了隐私权和安全性方面的审核。
设计
activity 状态
活动是指最近发生的用户输入与设备互动。
“近期”是指某个产品配置的时间阈值,例如 15 分钟。
如果设备最近未收到任何活动,会被视为处于空闲状态。
用户输入交互受限于下列初始实现用例。
要求
以下用户互动必须使服务进入或续订活跃状态:
- 用户轻触了屏幕。
- 用户与鼠标或键盘进行了互动。
- 用户按了媒体按钮,例如音量调高或音量调低。
以下用户互动应导致服务进入或续订活跃状态:
- 用户启用或停用了屏幕阅读器。如果用户使用上述某种输入法执行此操作,系统会隐式捕获该操作。 或者,如果通过对 SetUI 进行更改来实现,建议将其视为与打开设备机盖类似。
- 用户打开了设备机盖。
- 用户开启了设备。
由于以下互动的相应理由以内嵌方式提供,因此以下互动不会被视为活跃的用户输入 activity。因此,它们不得导致服务进入活跃状态:
- 用户正在观看视频或收听音频文件:应使用
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 的客户端报告称,他们认为自己有用户输入活动的证据,我们会按这种方式处理他们的信息。因此,只能通过功能路由访问树内组件。如需了解详情,请参阅安全注意事项。
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 协议。它也不会发送时间戳。
盖子传感器
界面 Activity 服务可以使用 fuchsia.hardware.input
FIDL 监控盖子传感器驱动程序报告,并在收到打开盖子的报告时转换为活动状态。
与输入流水线集成
聊天室注意事项
在输入管道 (IP) 组件中实现界面 activity 服务 (A)(而不是作为自己的组件)可以节省约 172 KB 的磁盘空间,具体取决于产品和板级配置。对于空间受限的产品,缩减大小可为系统中的其他改进释放空间。
Build | A | IP | IP + 两个 FIDL |
---|---|---|---|
工作站_专业.Chromebook-x64 | 196 KB | 1,364 KB | 1,388 KB |
core.astro | 184 KB | 688 KB | 700 KB |
其他注意事项
在输入流水线中集成界面 Activity 服务包括以下内容:
- 服务应该是单线程的,因为此时进行多线程没有必要或有益。此外,输入流水线是单线程的,转换库以支持多线程方法会带来不必要的复杂性。
- 该服务应在 Rust 中实现,以避免引入在一个库中管理多种语言所需的复杂性。
- 该服务在恢复模式下不可用,因为恢复模式不使用输入流水线或场景管理器。恢复模式缺少 activity 服务并不是问题,因为从设计上,恢复模式使用单个高度集成的组件,以最大限度减少依赖项。
- 服务不应通过以下方法来处理
InputReport
:将事件标记为已处理或将事件发送到其他组件,因为这会让服务意识到并负责获得更多确定最近是否发生 activity 所必需的信息。 - 服务不应了解有关输入事件来源的特殊信息(因为应通过
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 状态- 当系统转换为活跃状态时,
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 服务不得增加系统中处理输入事件的延迟时间。
虽然提议的协议没有引入异步或计算密集型逻辑,但我们可能需要对高频输入事件引入节流功能。例如,鼠标每秒发送约 1,000 个事件很常见,因此可能需要限制从 MouseInjectorHandler
到 activity 服务的 FIDL 调用的速率限制。
我们可以监控现有的性能测试(如输入延迟时间测试),以判断更改是否会导致性能下降。
安全注意事项
界面 Activity 服务的主要滥用矢量是,通过使用 fuchsia.input.interaction.observation.Aggregator
虚假地报告 Activity 来使系统保持唤醒状态。例如,恶意应用可能会定期报告活动,以使系统保持唤醒状态。鉴于 fuchsia.input.interaction.observation.Aggregator
仅在树内可用,未在 SDK 中提供,并且只能由界面领域的组件使用,因此风险较低。
此类服务都存在以下风险:延迟软件更新、使屏幕保持解锁状态、耗尽电池电量,以及可能会拒绝向设备上的其他应用提供服务。委托数据访问是一种此 RFC 未解决的风险。在使用此服务时,依赖于空闲状态来实现上述功能的客户端应实现自己的活动上限(如果相关),例如在用户活跃 24 小时后强制执行系统 OTA 强制更新。
由于此功能必须通过 CFV2 路由,因此请注意,平台仅授予向输入流水线报告活动的权限,可能还需要在平台级别向 A11y Manager 报告活动,并且相应产品可以进一步路由到可信组件。
隐私注意事项
虽然界面活动服务不会公开有关用户活动性质的任何信息,但它会通过 fuchsia.input.interaction.Notifier
显示最近是否在预设时间阈值内发生了活动。
如果有人在特定时间在家或使用其设备,这会对隐私产生影响并产生敏感信息,因此我们不希望不受信任的组件访问这些内容。由于此功能必须通过 CFV2 路由,因此请注意,平台应仅授予观察平台级别上可信活动的权限,并且相应产品可以进一步路由到可信组件。
具体而言,时间戳不会向订阅者提供。
测试
我们的测试策略包括
- 单元测试
- 使用现有工具进行集成测试
文档
该服务将包含 README 概览,并且新的 FIDL 协议将附带内联注释。
缺点
输入流水线失败
如果输入流水线出现紧急错误或死锁,界面 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
协议必须迁移到提议的挂起模式。- 在没有具体用例或意图公开的情况下,
WatchState
协议会不必要地释放我们不希望客户端依赖的时间戳。
纳入其他活动信号
在某些用户流中,某些信号可能会被视作活动,而在另一些用户流中则不会。 因此,如何解读信号的正确性取决于给定外形规格或服务的需求。
建议使用 fuchsia.input.interaction.Notifier
协议来使用界面 activity 状态,并可与其他形式的 activity(例如通过音频、麦克风或摄像头)结合使用来引用该协议,以便根据具体情况确定相关的某个最终用户或系统状态。例如,屏保功能可能仅查询用户输入 activity,而锁定屏幕功能可能同时查询用户输入 activity 和用户身份验证状态。
支持配置一部分要考虑的活动类型
将来,某些服务可能希望跟踪由一部分用户输入模式确定的 activity 状态,例如最近轻触而不是最近按键。这会在可能的输入模式之间引入指数组合。
鉴于目前人们对更复杂的特征不感兴趣,我们决定不提前引入这种复杂性。
与 Fuchsia 系统身份验证集成
系统身份验证和界面 Activity 服务都关注用户行为的一些概念,但几乎没有实际重叠。例如,系统身份验证关注一组更精细的用户在线状态,包括用户与设备的距离以及用户是否为帐号所有者。
虽然可以通过对这两种用例都适用的方式跟踪用户活动,但在没有驾驶用例的情况下,可能没有必要主动集成这两个系统。
后续工作
允许订阅者配置空闲时间阈值
将来,某些服务可能希望确定它们自己的用户输入互动的新近度阈值。虽然此 RFC 未提出解决方案,但为了简化初始实现,我们省略了此功能。不过,当出现具体用例时,可以扩展提议的协议以添加支持。
早期技术和参考资料
- chrome.idle API 支持“活动”“空闲”和“已锁定”状态。
- Root Presenter 中 Fuchsia 的活动通知程序因闲置而被移除。