ディスプレイ固有の領域に対する更新内容は次のとおりです。
Android 10 は、デフォルト以外のディスプレイで実行されるアプリのソフトウェア キーボードをサポートしています。
デフォルト以外のディスプレイで実行されるアプリ
インプット メソッド エディタ(IME)のソフトウェア キーボードを表示するディスプレイには、さまざまなモードがあります。ソフトウェア キーボードは次のディスプレイに表示されます。
- フォーカスされているアプリが表示されているのと同じディスプレイ。
- フォーカスされているアプリがデフォルト以外のディスプレイで実行されているときのデフォルトのディスプレイ。
- ディスプレイがまったく表示されない。
使用するモードは、フォーカスされているアプリが表示されているディスプレイの設定に応じて決まります。詳しくは、以下をご覧ください。
WindowManager#setDisplayImePolicy()
WindowManager#getDisplayImePolicy()
図 1. ターゲット アプリと同じセカンダリ ディスプレイに表示された IME ソフトウェア キーボード
システムで使用される IME は 1 つですが、ユーザー フォーカスに合わせてディスプレイを切り替えることができます。Android 10 では、Google とサードパーティのすべての IME が自動的にレイアウトを修正し、作成された新しいディスプレイ サイズに合わせてサイズ変更する必要があります。
ディスプレイ A にアクティブな接続があり、ディスプレイ B の入力欄に入力フォーカスが必要な場合、次のフローが発生します。
- 新しい入力接続がディスプレイ B の入力欄から行われる。
- 接続が承認されるかどうかを
InputMethodManagerService
が確認する。 - IME のディスプレイが選択される。ディスプレイ B が IME の表示をサポートしており、IME を表示できる場合は、B が使用される。これに該当しない場合は、プライマリ デバイスのディスプレイが選択される。
- 選択されたディスプレイがディスプレイ A ではない場合は、接続が再確立される。
InputMethodService
が破棄されて再作成される。
セキュリティ制限
システムが所有していない仮想ディスプレイには IME は表示されません。これは、セキュリティ上の懸念として、悪意のあるアプリがシステム デコレーション サポートを有効にした仮想ディスプレイを作成し、サーフェスからユーザー機密情報(入力予測やカスタム背景など)を読み取る可能性があるためです。
実装
画面上の入力方法で説明されているように、Android 9 以前ではデフォルトの画面でのみ IME を使用できました。Android 10 以降では、フォーカスを切り替えて IME ウィンドウをセカンダリ ディスプレイに移動させることで、別のディスプレイの入力テキスト欄に切り替えることができます。
WindowManager
の実装では、入力方法ウィンドウ(ソフト キーボードが表示される IME ウィンドウ)と入力方法ターゲット(IME 入力が行われるウィンドウ)をトラッキングして IME の状態を管理します。
InputMethodManagerService
(IMMS)については、フォーカスを別のディスプレイに移動したときにディスプレイの変更を InputMethodService
(IMS)に反映して、ランタイムにキーボード レイアウトを再構成できる組み込みメカニズムは他にありません。
ディスプレイ間で IME ウィンドウを切り替えられるように、Android 10 には以下が実装されています。
- IME と入力ターゲット ウィンドウが、
DisplayContent#mInputMethodWindow
とDisplayContent#mInputMethodTarget
でディスプレイごとにトラッキングされるため、WindowManager(WM)は各ディスプレイの IME フォーカス状態を個別に管理できるようになりました。 - IMMS 側では、外部ディスプレイから
ViewRootImpl#handleWindowFocusChanged -> InputMethodManager#onPostWindowFocus -> IMMS#startInputOrWindowGainedFocus
経由でアプリ クライアントのフォーカス リクエストを受け取ると、最初に現在の入力方法サービスをバインド解除し、次にサービスを再バインドして、onServiceConnected()
の外部ディスプレイ用に新しい IME ウィンドウ トークンを再度割り当てます。 - IMS 側では、
IMS#attachToken
を受け取った後、次のフローが発生します。InputMethodService#attachToken()
のサービス コンテキストの表示を更新するために、ContextImpl#updateDisplay
が呼び出されます。これによって呼び出されたViewGroup#addView()
が、現在のコンテキストを確認し、キーボードのレイアウトを修正してターゲット ディスプレイに合わせて調整します。DisplayContent#setInputMethodWindowLocked()
が呼び出された後、実装はWindowProcessController
を使用してプロセスレベルのディスプレイ構成の変更を IME プロセスに送信し、リソースとディスプレイの指標をオーバーライドします。InputMethodService
クライアントは、onConfigurationChanged()
とViewGroup#addView()
の呼び出し後に、正しい構成と正しいディスプレイの指標を取得して入力ビューを再初期化します。