输入法支持

我们对这些与屏幕相关的部分进行了更新,详情见下文:

对于在非默认屏幕上运行的应用,Android 10 支持使用软件键盘

在非默认屏幕上运行的应用

关于输入法 (IME) 的软件键盘显示在哪个屏幕上,有不同的模式。软件键盘:

  • 显示在目标应用所在的屏幕上。
  • 显示在默认屏幕上(当目标应用在非默认屏幕上运行时)。
  • 不显示在任何屏幕上。

系统会根据目标应用所在屏幕的设置确定要使用的模式。如需了解详情,请参阅:

  • WindowManager#setDisplayImePolicy()
  • WindowManager#getDisplayImePolicy()

图 1. 在辅助屏幕上显示 IME 软件键盘,包括目标应用

系统使用一个 IME,但可以在屏幕之间切换,以跟踪用户焦点。Android 10 默认所有第一方和第三方 IME 在创建时都会根据新屏幕的尺寸调整布局和大小。

如果屏幕 A 上有一个活动连接,并且屏幕 B 上的输入字段请求获得输入焦点,则会触发以下流程:

  1. 屏幕 B 上的输入字段发出一个新的输入连接。
  2. InputMethodManagerService 检查是否应该批准该连接。
  3. 系统为该 IME 选择一个屏幕。如果屏幕 B 支持且允许显示 IME,则使用屏幕 B。否则,将选择设备的主屏幕。
  4. 如果所选屏幕并非来自屏幕 A,则重新建立连接。系统会销毁 InputMethodService,然后重新创建它。

安全限制

系统不会在不属于自己的虚拟屏幕上显示 IME。这是出于安全方面的考虑,因为恶意应用可能会创建启用了系统装饰支持的虚拟屏幕,并从 Surface 读取用户敏感信息(例如输入预测和自定义背景)。

实现

在 Android 9(及更低版本)中,IME 只能在默认屏幕上使用,如屏幕输入法中所述。在 Android 10(及更高版本)中,用户可以通过切换焦点在不同屏幕上的不同输入文本字段之间切换,IME 窗口会移动到辅助屏幕上。

WindowManager 中的实现会跟踪输入法窗口(绘制软件键盘的 IME 窗口)和输入法目标窗口(IME 输入所在的窗口),以管理 IME 状态。

对于 InputMethodManagerService (IMMS),将焦点移至另一个屏幕时,没有其他内置机制可以将屏幕更改传递给 InputMethodService (IMS),并在运行时重新配置键盘布局。

为了实现在屏幕之间切换 IME 窗口,Android 10 实现了以下功能:

  • 现在,可以在 DisplayContent#mInputMethodWindowDisplayContent#mInputMethodTarget 中跟踪每个屏幕的 IME 和输入目标窗口,以便 WindowManager (WM) 可以单独管理每个屏幕的 IME 焦点状态。
  • 在 IMMS 端,当通过 ViewRootImpl#handleWindowFocusChanged -> InputMethodManager#onPostWindowFocus -> IMMS#startInputOrWindowGainedFocus 收到来自外部屏幕的应用客户端焦点请求时,它会先取消绑定当前的输入法服务,然后再重新绑定该服务,以在 onServiceConnected() 中重新附加针对该外部屏幕的新 IME 窗口令牌。
  • 在 IMS 端,收到 IMS#attachToken 后,将触发以下流程:
    • 调用 ContextImpl#updateDisplay,以在 InputMethodService#attachToken() 中更新服务上下文的屏幕。这会调用 ViewGroup#addView() 来调整键盘布局并适应检查当前上下文的目标屏幕。
    • 调用 DisplayContent#setInputMethodWindowLocked() 之后,该实现使用 WindowProcessController 将进程级屏幕配置更改发送给 IME 进程,以替换资源和屏幕指标。
    • 调用 onConfigurationChanged()ViewGroup#addView() 之后,InputMethodService 客户端将获得合适的配置(其中包含正确的屏幕指标)来重新初始化输入视图。