Supports the separate display for the input window.
Bug: 136039906 Test: Test manually with the uncommented example config in hawk_md. Change-Id: I404cc2ce137563ced8e2180dd0539bd98524ff57
This commit is contained in:
35
samples/MultiClientInputMethod/res/values/config.xml
Normal file
35
samples/MultiClientInputMethod/res/values/config.xml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
** Copyright 2019, The Android Open Source Project
|
||||||
|
**
|
||||||
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
** you may not use this file except in compliance with the License.
|
||||||
|
** You may obtain a copy of the License at
|
||||||
|
**
|
||||||
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
**
|
||||||
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
** See the License for the specific language governing permissions and
|
||||||
|
** limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<string-array name="config_inputDisplayToImeDisplay">
|
||||||
|
<!--
|
||||||
|
The MultiClientInputMethod will use the same display for the IME window by default.
|
||||||
|
But, if you want to use the separate display for the IME window, consider to define item of
|
||||||
|
'config_inputDisplayToImeDisplay'. The each item is a comma-separated pair of the uniqueId of
|
||||||
|
the displays. The first is the uniqueId of the display where the input happens and the second
|
||||||
|
is the unqiueId of the display where the IME window will be shown.
|
||||||
|
FYI, you can find the uniqueId of displays in "dumpsys display".
|
||||||
|
|
||||||
|
E.g. If you have two displays 19261083906282752, local:19260422155234049 and you want to use
|
||||||
|
local:19260422155234049 as the IME window for the input at the display local:19261083906282752,
|
||||||
|
then the config item will be:
|
||||||
|
<item>local:19261083906282752,local:19260422155234049</item>
|
||||||
|
-->
|
||||||
|
</string-array>
|
||||||
|
</resources>
|
||||||
@@ -16,7 +16,9 @@
|
|||||||
|
|
||||||
package com.example.android.multiclientinputmethod;
|
package com.example.android.multiclientinputmethod;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.hardware.display.DisplayManager;
|
import android.hardware.display.DisplayManager;
|
||||||
import android.hardware.display.DisplayManager.DisplayListener;
|
import android.hardware.display.DisplayManager.DisplayListener;
|
||||||
@@ -24,6 +26,7 @@ import android.inputmethodservice.MultiClientInputMethodServiceDelegate;
|
|||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
|
import android.view.Display;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link Service} that implements multi-client IME protocol.
|
* A {@link Service} that implements multi-client IME protocol.
|
||||||
@@ -34,6 +37,9 @@ public final class MultiClientInputMethod extends Service implements DisplayList
|
|||||||
|
|
||||||
// last client that had active InputConnection for a given displayId.
|
// last client that had active InputConnection for a given displayId.
|
||||||
final SparseIntArray mDisplayToLastClientId = new SparseIntArray();
|
final SparseIntArray mDisplayToLastClientId = new SparseIntArray();
|
||||||
|
// Mapping table from the display where IME is attached to the display where IME window will be
|
||||||
|
// shown. Assumes that missing display will use the same display for the IME window.
|
||||||
|
SparseIntArray mInputDisplayToImeDisplay;
|
||||||
SoftInputWindowManager mSoftInputWindowManager;
|
SoftInputWindowManager mSoftInputWindowManager;
|
||||||
MultiClientInputMethodServiceDelegate mDelegate;
|
MultiClientInputMethodServiceDelegate mDelegate;
|
||||||
|
|
||||||
@@ -44,6 +50,7 @@ public final class MultiClientInputMethod extends Service implements DisplayList
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.v(TAG, "onCreate");
|
Log.v(TAG, "onCreate");
|
||||||
}
|
}
|
||||||
|
mInputDisplayToImeDisplay = buildInputDisplayToImeDisplay();
|
||||||
mDelegate = MultiClientInputMethodServiceDelegate.create(this,
|
mDelegate = MultiClientInputMethodServiceDelegate.create(this,
|
||||||
new MultiClientInputMethodServiceDelegate.ServiceCallback() {
|
new MultiClientInputMethodServiceDelegate.ServiceCallback() {
|
||||||
@Override
|
@Override
|
||||||
@@ -56,13 +63,17 @@ public final class MultiClientInputMethod extends Service implements DisplayList
|
|||||||
@Override
|
@Override
|
||||||
public void addClient(int clientId, int uid, int pid,
|
public void addClient(int clientId, int uid, int pid,
|
||||||
int selfReportedDisplayId) {
|
int selfReportedDisplayId) {
|
||||||
|
int imeDisplayId = mInputDisplayToImeDisplay.get(selfReportedDisplayId,
|
||||||
|
selfReportedDisplayId);
|
||||||
final ClientCallbackImpl callback = new ClientCallbackImpl(
|
final ClientCallbackImpl callback = new ClientCallbackImpl(
|
||||||
MultiClientInputMethod.this, mDelegate,
|
MultiClientInputMethod.this, mDelegate,
|
||||||
mSoftInputWindowManager, clientId, uid, pid, selfReportedDisplayId);
|
mSoftInputWindowManager, clientId, uid, pid, imeDisplayId);
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.v(TAG, "addClient clientId=" + clientId + " uid=" + uid
|
Log.v(TAG, "addClient clientId=" + clientId + " uid=" + uid
|
||||||
+ " pid=" + pid + " displayId=" + selfReportedDisplayId);
|
+ " pid=" + pid + " displayId=" + selfReportedDisplayId
|
||||||
|
+ " imeDisplayId=" + imeDisplayId);
|
||||||
}
|
}
|
||||||
|
|
||||||
mDelegate.acceptClient(clientId, callback, callback.getDispatcherState(),
|
mDelegate.acceptClient(clientId, callback, callback.getDispatcherState(),
|
||||||
callback.getLooper());
|
callback.getLooper());
|
||||||
}
|
}
|
||||||
@@ -118,4 +129,38 @@ public final class MultiClientInputMethod extends Service implements DisplayList
|
|||||||
}
|
}
|
||||||
mDelegate.onDestroy();
|
mDelegate.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private SparseIntArray buildInputDisplayToImeDisplay() {
|
||||||
|
// TODO: Support the virtual display after b/137375833 is fixed.
|
||||||
|
Context context = getApplicationContext();
|
||||||
|
String config[] = context.getResources().getStringArray(
|
||||||
|
R.array.config_inputDisplayToImeDisplay);
|
||||||
|
|
||||||
|
SparseIntArray inputDisplayToImeDisplay = new SparseIntArray();
|
||||||
|
Display[] displays = context.getSystemService(DisplayManager.class).getDisplays();
|
||||||
|
for (String item: config) {
|
||||||
|
String[] pair = item.split(",");
|
||||||
|
if (pair.length != 2) {
|
||||||
|
Log.w(TAG, "Skip illegal config: " + item);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int inputDisplay = findDisplayId(displays, pair[0]);
|
||||||
|
int imeDisplay = findDisplayId(displays, pair[1]);
|
||||||
|
if (inputDisplay != Display.INVALID_DISPLAY && imeDisplay != Display.INVALID_DISPLAY) {
|
||||||
|
inputDisplayToImeDisplay.put(inputDisplay, imeDisplay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return inputDisplayToImeDisplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int findDisplayId(Display displays[], String uniqueId) {
|
||||||
|
for (Display display: displays) {
|
||||||
|
if (uniqueId.equals(display.getUniqueId())) {
|
||||||
|
return display.getDisplayId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.w(TAG, "Can't find the display of " + uniqueId);
|
||||||
|
return Display.INVALID_DISPLAY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user