Fix MSIME client's active state

Introduce per-display active client. Also, deactivate previous client
when window loses focus so that connection can be restarted on next
focus gain.

Test: Manually using the steps in bug.
Bug: 131619304
Change-Id: Iefad3f018ef0cc1b3729af4a140afa1b52139ce0
This commit is contained in:
Tarandeep Singh
2019-06-06 16:42:52 -07:00
parent 9faff5f560
commit 0f7a3f791d
2 changed files with 34 additions and 12 deletions

View File

@@ -58,7 +58,7 @@ final class ClientCallbackImpl implements MultiClientInputMethodServiceDelegate.
// For simplicity, we use the main looper for this sample.
// To use other looper thread, make sure that the IME Window also runs on the same looper
// and introduce an appropriate synchronization mechanism instead of directly accessing
// MultiClientInputMethod#mLastClientId.
// MultiClientInputMethod#mDisplayToLastClientId.
mLooper = Looper.getMainLooper();
}
@@ -157,11 +157,13 @@ final class ClientCallbackImpl implements MultiClientInputMethodServiceDelegate.
mDelegate.reportImeWindowTarget(
mClientId, targetWindowHandle, window.getWindow().getAttributes().token);
}
final int lastClientId = mInputMethod.mDisplayToLastClientId.get(mSelfReportedDisplayId);
if (lastClientId != mClientId) {
// deactivate previous client and activate current.
mDelegate.setActive(lastClientId, false /* active */);
mDelegate.setActive(mClientId, true /* active */);
}
if (inputConnection == null || editorInfo == null) {
// deactivate previous client.
if (mInputMethod.mLastClientId != mClientId) {
mDelegate.setActive(mInputMethod.mLastClientId, false /* active */);
}
// Dummy InputConnection case.
if (window.getClientId() == mClientId) {
// Special hack for temporary focus changes (e.g. notification shade).
@@ -171,9 +173,6 @@ final class ClientCallbackImpl implements MultiClientInputMethodServiceDelegate.
window.onDummyStartInput(mClientId, targetWindowHandle);
}
} else {
if (mInputMethod.mLastClientId != mClientId) {
mDelegate.setActive(mClientId, true /* active */);
}
window.onStartInput(mClientId, targetWindowHandle, inputConnection);
}
@@ -195,7 +194,7 @@ final class ClientCallbackImpl implements MultiClientInputMethodServiceDelegate.
window.hide();
break;
}
mInputMethod.mLastClientId = mClientId;
mInputMethod.mDisplayToLastClientId.put(mSelfReportedDisplayId, mClientId);
}
@Override

View File

@@ -18,22 +18,27 @@ package com.example.android.multiclientinputmethod;
import android.app.Service;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.inputmethodservice.MultiClientInputMethodServiceDelegate;
import android.os.IBinder;
import android.util.Log;
import android.util.SparseIntArray;
/**
* A {@link Service} that implements multi-client IME protocol.
*/
public final class MultiClientInputMethod extends Service {
public final class MultiClientInputMethod extends Service implements DisplayListener {
private static final String TAG = "MultiClientInputMethod";
private static final boolean DEBUG = false;
// last client that had active InputConnection.
int mLastClientId = MultiClientInputMethodServiceDelegate.INVALID_CLIENT_ID;
// last client that had active InputConnection for a given displayId.
final SparseIntArray mDisplayToLastClientId = new SparseIntArray();
SoftInputWindowManager mSoftInputWindowManager;
MultiClientInputMethodServiceDelegate mDelegate;
private DisplayManager mDisplayManager;
@Override
public void onCreate() {
if (DEBUG) {
@@ -72,11 +77,26 @@ public final class MultiClientInputMethod extends Service {
mSoftInputWindowManager = new SoftInputWindowManager(this, mDelegate);
}
@Override
public void onDisplayAdded(int displayId) {
}
@Override
public void onDisplayRemoved(int displayId) {
mDisplayToLastClientId.delete(displayId);
}
@Override
public void onDisplayChanged(int displayId) {
}
@Override
public IBinder onBind(Intent intent) {
if (DEBUG) {
Log.v(TAG, "onBind intent=" + intent);
}
mDisplayManager = getApplicationContext().getSystemService(DisplayManager.class);
mDisplayManager.registerDisplayListener(this, getMainThreadHandler());
return mDelegate.onBind(intent);
}
@@ -85,6 +105,9 @@ public final class MultiClientInputMethod extends Service {
if (DEBUG) {
Log.v(TAG, "onUnbind intent=" + intent);
}
if (mDisplayManager != null) {
mDisplayManager.unregisterDisplayListener(this);
}
return mDelegate.onUnbind(intent);
}