輸入法編輯器支持

下面提供了對這些特定於顯示的區域所做的更新:

Android 10 支持在非默認顯示器上運行的應用程序的軟件鍵盤

在非默認顯示器上運行的應用程序

至於顯示輸入法編輯器 (IME) 的軟件鍵盤的顯示器,有兩種不同的模式。軟鍵盤顯示在:

  • 顯示焦點應用程序的同一顯示器。
  • 焦點應用在非默認顯示器上運行時的默認顯示。

系統根據顯示焦點應用程序的顯示器設置確定使用哪種模式。有關更多詳細信息,請參閱:

  • DisplayWindowSettings#shouldShowImeLocked()
  • DisplayWindowSettings#setShouldShowImeLocked()

圖 1. IME 軟件鍵盤顯示在輔助顯示屏上,包括目標應用程序

該系統使用單個 IME,但可以在顯示之間切換以跟隨用戶焦點。 Android 10 自動要求所有第一方和第三方 IME 在創建時根據新的顯示尺寸修改佈局和調整大小。

如果顯示 A 上存在活動連接,並且輸入字段請求顯示 B 上的輸入焦點,則會發生以下流程:

  1. 新的輸入連接來自顯示器 B 上的輸入字段。
  2. InputMethodManagerService檢查連接是否應該被批准。
  3. 為 IME 選擇了一個顯示器。如果顯示器 B 支持顯示 IME 並被允許顯示,則使用 B。否則,將選擇主設備顯示器。
  4. 如果所選顯示器不是來自顯示器 A,則重新建立連接。 InputMethodService被銷毀,然後再次創建。

安全限制

系統不會在不屬於系統的虛擬顯示器上顯示 IME。這是出於安全考慮,惡意應用程序可能會創建啟用了系統裝飾支持的虛擬顯示器,並從表面讀取用戶敏感信息,例如鍵入預測和自定義背景。

執行

在 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接收到來自外顯的 App 客戶端的焦點請求時,它首先解綁當前輸入法服務,然後重新綁定該服務以重新附加新的 IME onServiceConnected()中外部顯示的窗口標記。
  • 在IMS側,接收到IMS#attachToken後,會出現如下流程:
    • 調用ContextImpl#updateDisplay來更新InputMethodService#attachToken()中服務上下文的顯示。這會調用ViewGroup#addView()來修改鍵盤佈局並適應目標顯示器檢查當前上下文。
    • 調用DisplayContent#setInputMethodWindowLocked()後,實現使用WindowProcessController將進程級顯示配置更改發送到 IME 進程以覆蓋資源和顯示指標。
    • InputMethodService客戶端在onConfigurationChanged()ViewGroup#addView()調用以重新初始化輸入視圖之後獲得具有正確顯示指標的正確配置。

多會話輸入法編輯器支持

具有預期由多個用戶同時使用以提供適當輸入源的多個顯示器的設備實現可以被配置為同時顯示多個輸入法編輯器 (IME),每個顯示器最多一個。以下兩個圖顯示了兩個顯示器上的示例多會話 IME:

圖 2.多會話 IME 示例

圖 3.多會話 IME 示例

支持Per-display 焦點是此功能的先決條件。如果沒有,則無法啟用此功能。由於安全限制,每個顯示器的焦點限制將此功能限制為一小部分設備。

在 Android 10 中,對多會話 IME 的支持是通過具有不同 API 集和縮減功能的單獨系統服務實現的。多會話 IME 與現有 IME 不兼容。可以使用多會話或單會話服務,但不能同時使用。

無法使用基於InputMethodService類構建的現有 Android IME,因為在 Android 1.5 中引入 Android IME API 之前,假設單個 IME 客戶端可以同時聚焦,並且InputMethodService中的許多公共 API 已經已經嚴重依賴這個假設。但是,更新InputMethodService類以支持多客戶端方案具有挑戰性,因為:

  1. 這樣做會給InputMethodService帶來無法接受的複雜性,而這已經很難維護。
  2. IME 開發人員仍然需要更新他們的實現,以便能夠支持來自多個重點 IME 客戶端的並行請求,這可能需要對他們進行重大的重新設計(例如輸入解碼器和打字歷史數據庫)。
  3. 多 IME 客戶端的實際用例預計會迅速發展,因此新協議不穩定,還沒有準備好作為公共 API 公開。

與單會話(常規)IME 一樣,使用DisplayWindowSettings控制在單個顯示器上顯示 IME。

development/samples/MultiClientInputMethod有一個示例多會話 IME。

要測試多會話 IME:

  1. config_perDisplayFocusEnabled設置為true
  2. 運行這些命令:
    1. $ make -j MultiClientInputMethod
    2. $ adb install -r $OUT/system/priv-app/MultiClientInputMethod/MultiClientInputMethod.apk
    3. $ adb root
    4. $ adb shell setprop persist.debug.multi_client_ime \
      com.example.android.multiclientinputmethod/.MultiClientInputMethod
    5. $ adb reboot
  3. 嘗試多種文本輸入方案。

執行

有關實現細節,請參閱MultiClientInputMethodManagerService

,

下面提供了對這些特定於顯示的區域所做的更新:

Android 10 支持在非默認顯示器上運行的應用程序的軟件鍵盤

在非默認顯示器上運行的應用程序

至於顯示輸入法編輯器 (IME) 的軟件鍵盤的顯示器,有兩種不同的模式。軟鍵盤顯示在:

  • 顯示焦點應用程序的同一顯示器。
  • 焦點應用在非默認顯示器上運行時的默認顯示。

系統根據顯示焦點應用程序的顯示器設置確定使用哪種模式。有關更多詳細信息,請參閱:

  • DisplayWindowSettings#shouldShowImeLocked()
  • DisplayWindowSettings#setShouldShowImeLocked()

圖 1. IME 軟件鍵盤顯示在輔助顯示屏上,包括目標應用程序

該系統使用單個 IME,但可以在顯示之間切換以跟隨用戶焦點。 Android 10 自動要求所有第一方和第三方 IME 在創建時根據新的顯示尺寸修改佈局和調整大小。

如果顯示 A 上存在活動連接,並且輸入字段請求顯示 B 上的輸入焦點,則會發生以下流程:

  1. 新的輸入連接來自顯示器 B 上的輸入字段。
  2. InputMethodManagerService檢查連接是否應該被批准。
  3. 為 IME 選擇了一個顯示器。如果顯示器 B 支持顯示 IME 並被允許顯示,則使用 B。否則,將選擇主設備顯示器。
  4. 如果所選顯示器不是來自顯示器 A,則重新建立連接。 InputMethodService被銷毀,然後再次創建。

安全限制

系統不會在不屬於系統的虛擬顯示器上顯示 IME。這是出於安全考慮,惡意應用程序可能會創建啟用了系統裝飾支持的虛擬顯示器,並從表面讀取用戶敏感信息,例如鍵入預測和自定義背景。

執行

在 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接收到來自外顯的 App 客戶端的焦點請求時,它首先解綁當前輸入法服務,然後重新綁定該服務以重新附加新的 IME onServiceConnected()中外部顯示的窗口標記。
  • 在IMS側,接收到IMS#attachToken後,會出現如下流程:
    • 調用ContextImpl#updateDisplay來更新InputMethodService#attachToken()中服務上下文的顯示。這會調用ViewGroup#addView()來修改鍵盤佈局並適應目標顯示器檢查當前上下文。
    • 調用DisplayContent#setInputMethodWindowLocked()後,實現使用WindowProcessController將進程級顯示配置更改發送到 IME 進程以覆蓋資源和顯示指標。
    • InputMethodService客戶端在onConfigurationChanged()ViewGroup#addView()調用以重新初始化輸入視圖之後獲得具有正確顯示指標的正確配置。

多會話輸入法編輯器支持

具有預期由多個用戶同時使用以提供適當輸入源的多個顯示器的設備實現可以被配置為同時顯示多個輸入法編輯器 (IME),每個顯示器最多一個。以下兩個圖顯示了兩個顯示器上的示例多會話 IME:

圖 2.多會話 IME 示例

圖 3.多會話 IME 示例

支持Per-display 焦點是此功能的先決條件。如果沒有,則無法啟用此功能。由於安全限制,每個顯示器的焦點限制將此功能限制為一小部分設備。

在 Android 10 中,對多會話 IME 的支持是通過具有不同 API 集和縮減功能的單獨系統服務實現的。多會話 IME 與現有 IME 不兼容。可以使用多會話或單會話服務,但不能同時使用。

無法使用基於InputMethodService類構建的現有 Android IME,因為在 Android 1.5 中引入 Android IME API 之前,假設單個 IME 客戶端可以同時聚焦,並且InputMethodService中的許多公共 API 已經已經嚴重依賴這個假設。但是,更新InputMethodService類以支持多客戶端方案具有挑戰性,因為:

  1. 這樣做會給InputMethodService帶來無法接受的複雜性,而這已經很難維護。
  2. IME 開發人員仍然需要更新他們的實現,以便能夠支持來自多個重點 IME 客戶端的並行請求,這可能需要對他們進行重大的重新設計(例如輸入解碼器和打字歷史數據庫)。
  3. 多 IME 客戶端的實際用例預計會迅速發展,因此新協議不穩定,還沒有準備好作為公共 API 公開。

與單會話(常規)IME 一樣,使用DisplayWindowSettings控制在單個顯示器上顯示 IME。

development/samples/MultiClientInputMethod有一個示例多會話 IME。

要測試多會話 IME:

  1. config_perDisplayFocusEnabled設置為true
  2. 運行這些命令:
    1. $ make -j MultiClientInputMethod
    2. $ adb install -r $OUT/system/priv-app/MultiClientInputMethod/MultiClientInputMethod.apk
    3. $ adb root
    4. $ adb shell setprop persist.debug.multi_client_ime \
      com.example.android.multiclientinputmethod/.MultiClientInputMethod
    5. $ adb reboot
  3. 嘗試多種文本輸入方案。

執行

有關實現細節,請參閱MultiClientInputMethodManagerService