diff --git a/samples/MultiClientInputMethod/Android.bp b/samples/MultiClientInputMethod/Android.bp
deleted file mode 100644
index 32c6ae006..000000000
--- a/samples/MultiClientInputMethod/Android.bp
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright (C) 2018 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.
-//
-
-package {
- // See: http://go/android-license-faq
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_app {
- name: "MultiClientInputMethod",
- srcs: ["**/*.java"],
- platform_apis: true,
- certificate: "platform",
- privileged: true,
- dex_preopt: {
- enabled: false,
- },
-}
diff --git a/samples/MultiClientInputMethod/AndroidManifest.xml b/samples/MultiClientInputMethod/AndroidManifest.xml
deleted file mode 100755
index 54087769b..000000000
--- a/samples/MultiClientInputMethod/AndroidManifest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/MultiClientInputMethod/res/drawable/sym_keyboard_delete.png b/samples/MultiClientInputMethod/res/drawable/sym_keyboard_delete.png
deleted file mode 100755
index 5139c7179..000000000
Binary files a/samples/MultiClientInputMethod/res/drawable/sym_keyboard_delete.png and /dev/null differ
diff --git a/samples/MultiClientInputMethod/res/drawable/sym_keyboard_done.png b/samples/MultiClientInputMethod/res/drawable/sym_keyboard_done.png
deleted file mode 100755
index 471c5021b..000000000
Binary files a/samples/MultiClientInputMethod/res/drawable/sym_keyboard_done.png and /dev/null differ
diff --git a/samples/MultiClientInputMethod/res/drawable/sym_keyboard_return.png b/samples/MultiClientInputMethod/res/drawable/sym_keyboard_return.png
deleted file mode 100755
index 5a5670c32..000000000
Binary files a/samples/MultiClientInputMethod/res/drawable/sym_keyboard_return.png and /dev/null differ
diff --git a/samples/MultiClientInputMethod/res/drawable/sym_keyboard_search.png b/samples/MultiClientInputMethod/res/drawable/sym_keyboard_search.png
deleted file mode 100755
index e72cde3bb..000000000
Binary files a/samples/MultiClientInputMethod/res/drawable/sym_keyboard_search.png and /dev/null differ
diff --git a/samples/MultiClientInputMethod/res/drawable/sym_keyboard_shift.png b/samples/MultiClientInputMethod/res/drawable/sym_keyboard_shift.png
deleted file mode 100755
index 275769618..000000000
Binary files a/samples/MultiClientInputMethod/res/drawable/sym_keyboard_shift.png and /dev/null differ
diff --git a/samples/MultiClientInputMethod/res/drawable/sym_keyboard_space.png b/samples/MultiClientInputMethod/res/drawable/sym_keyboard_space.png
deleted file mode 100755
index cef2daa5d..000000000
Binary files a/samples/MultiClientInputMethod/res/drawable/sym_keyboard_space.png and /dev/null differ
diff --git a/samples/MultiClientInputMethod/res/layout/input.xml b/samples/MultiClientInputMethod/res/layout/input.xml
deleted file mode 100755
index 528a15361..000000000
--- a/samples/MultiClientInputMethod/res/layout/input.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
diff --git a/samples/MultiClientInputMethod/res/values/config.xml b/samples/MultiClientInputMethod/res/values/config.xml
deleted file mode 100644
index 133b73e67..000000000
--- a/samples/MultiClientInputMethod/res/values/config.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/samples/MultiClientInputMethod/res/xml/method.xml b/samples/MultiClientInputMethod/res/xml/method.xml
deleted file mode 100644
index abac23b5a..000000000
--- a/samples/MultiClientInputMethod/res/xml/method.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
diff --git a/samples/MultiClientInputMethod/res/xml/qwerty.xml b/samples/MultiClientInputMethod/res/xml/qwerty.xml
deleted file mode 100755
index 05164d3d2..000000000
--- a/samples/MultiClientInputMethod/res/xml/qwerty.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/MultiClientInputMethod/res/xml/symbols.xml b/samples/MultiClientInputMethod/res/xml/symbols.xml
deleted file mode 100755
index df4692b36..000000000
--- a/samples/MultiClientInputMethod/res/xml/symbols.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/MultiClientInputMethod/res/xml/symbols_shift.xml b/samples/MultiClientInputMethod/res/xml/symbols_shift.xml
deleted file mode 100755
index fe771b408..000000000
--- a/samples/MultiClientInputMethod/res/xml/symbols_shift.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/ClientCallbackImpl.java b/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/ClientCallbackImpl.java
deleted file mode 100644
index 23e2757de..000000000
--- a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/ClientCallbackImpl.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-package com.example.android.multiclientinputmethod;
-
-import android.inputmethodservice.MultiClientInputMethodServiceDelegate;
-import android.os.Bundle;
-import android.os.Looper;
-import android.os.ResultReceiver;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.WindowManager;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.CursorAnchorInfo;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputConnection;
-
-final class ClientCallbackImpl implements MultiClientInputMethodServiceDelegate.ClientCallback {
- private static final String TAG = "ClientCallbackImpl";
- private static final boolean DEBUG = false;
-
- private final MultiClientInputMethodServiceDelegate mDelegate;
- private final SoftInputWindowManager mSoftInputWindowManager;
- private final int mClientId;
- private final int mUid;
- private final int mPid;
- private final int mSelfReportedDisplayId;
- private final KeyEvent.DispatcherState mDispatcherState;
- private final Looper mLooper;
- private final MultiClientInputMethod mInputMethod;
-
- ClientCallbackImpl(MultiClientInputMethod inputMethod,
- MultiClientInputMethodServiceDelegate delegate,
- SoftInputWindowManager softInputWindowManager, int clientId, int uid, int pid,
- int selfReportedDisplayId) {
- mInputMethod = inputMethod;
- mDelegate = delegate;
- mSoftInputWindowManager = softInputWindowManager;
- mClientId = clientId;
- mUid = uid;
- mPid = pid;
- mSelfReportedDisplayId = selfReportedDisplayId;
- mDispatcherState = new KeyEvent.DispatcherState();
- // 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#mDisplayToLastClientId.
- mLooper = Looper.getMainLooper();
- }
-
- KeyEvent.DispatcherState getDispatcherState() {
- return mDispatcherState;
- }
-
- Looper getLooper() {
- return mLooper;
- }
-
- @Override
- public void onAppPrivateCommand(String action, Bundle data) {
- }
-
- @Override
- public void onDisplayCompletions(CompletionInfo[] completions) {
- }
-
- @Override
- public void onFinishSession() {
- if (DEBUG) {
- Log.v(TAG, "onFinishSession clientId=" + mClientId);
- }
- final SoftInputWindow window =
- mSoftInputWindowManager.getSoftInputWindow(mSelfReportedDisplayId);
- if (window == null) {
- return;
- }
- // SoftInputWindow also needs to be cleaned up when this IME client is still associated with
- // it.
- if (mClientId == window.getClientId()) {
- window.onFinishClient();
- }
- }
-
- @Override
- public void onHideSoftInput(int flags, ResultReceiver resultReceiver) {
- if (DEBUG) {
- Log.v(TAG, "onHideSoftInput clientId=" + mClientId + " flags=" + flags);
- }
- final SoftInputWindow window =
- mSoftInputWindowManager.getSoftInputWindow(mSelfReportedDisplayId);
- if (window == null) {
- return;
- }
- // Seems that the Launcher3 has a bug to call onHideSoftInput() too early so we cannot
- // enforce clientId check yet.
- // TODO: Check clientId like we do so for onShowSoftInput().
- window.hide();
- }
-
- @Override
- public void onShowSoftInput(int flags, ResultReceiver resultReceiver) {
- if (DEBUG) {
- Log.v(TAG, "onShowSoftInput clientId=" + mClientId + " flags=" + flags);
- }
- final SoftInputWindow window =
- mSoftInputWindowManager.getSoftInputWindow(mSelfReportedDisplayId);
- if (window == null) {
- return;
- }
- if (mClientId != window.getClientId()) {
- Log.w(TAG, "onShowSoftInput() from a background client is ignored."
- + " windowClientId=" + window.getClientId()
- + " clientId=" + mClientId);
- return;
- }
- window.show();
- }
-
- @Override
- public void onStartInputOrWindowGainedFocus(InputConnection inputConnection,
- EditorInfo editorInfo, int startInputFlags, int softInputMode, int targetWindowHandle) {
- if (DEBUG) {
- Log.v(TAG, "onStartInputOrWindowGainedFocus clientId=" + mClientId
- + " editorInfo=" + editorInfo
- + " startInputFlags="
- + InputMethodDebug.startInputFlagsToString(startInputFlags)
- + " softInputMode=" + InputMethodDebug.softInputModeToString(softInputMode)
- + " targetWindowHandle=" + targetWindowHandle);
- }
-
- final int state = softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE;
- final boolean forwardNavigation =
- (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0;
-
- final SoftInputWindow window =
- mSoftInputWindowManager.getOrCreateSoftInputWindow(mSelfReportedDisplayId);
- if (window == null) {
- return;
- }
-
- if (window.getTargetWindowHandle() != targetWindowHandle) {
- // Target window has changed. Report new IME target window to the system.
- 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) {
- // Placeholder InputConnection case.
- if (window.getClientId() == mClientId) {
- // Special hack for temporary focus changes (e.g. notification shade).
- // If we have already established a connection to this client, and if a placeholder
- // InputConnection is notified, just ignore this event.
- } else {
- window.onDummyStartInput(mClientId, targetWindowHandle);
- }
- } else {
- window.onStartInput(mClientId, targetWindowHandle, inputConnection);
- }
-
- switch (state) {
- case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
- if (forwardNavigation) {
- window.show();
- }
- break;
- case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
- window.show();
- break;
- case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
- if (forwardNavigation) {
- window.hide();
- }
- break;
- case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
- window.hide();
- break;
- }
- mInputMethod.mDisplayToLastClientId.put(mSelfReportedDisplayId, mClientId);
- }
-
- @Override
- public void onUpdateCursorAnchorInfo(CursorAnchorInfo info) {
- }
-
- @Override
- public void onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd,
- int candidatesStart, int candidatesEnd) {
- }
-
- @Override
- public boolean onGenericMotionEvent(MotionEvent event) {
- return false;
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (DEBUG) {
- Log.v(TAG, "onKeyDown clientId=" + mClientId + " keyCode=" + keyCode
- + " event=" + event);
- }
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- final SoftInputWindow window =
- mSoftInputWindowManager.getSoftInputWindow(mSelfReportedDisplayId);
- if (window != null && window.isShowing()) {
- event.startTracking();
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean onKeyLongPress(int keyCode, KeyEvent event) {
- return false;
- }
-
- @Override
- public boolean onKeyMultiple(int keyCode, KeyEvent event) {
- return false;
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (DEBUG) {
- Log.v(TAG, "onKeyUp clientId=" + mClientId + "keyCode=" + keyCode
- + " event=" + event);
- }
- if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking() && !event.isCanceled()) {
- final SoftInputWindow window =
- mSoftInputWindowManager.getSoftInputWindow(mSelfReportedDisplayId);
- if (window != null && window.isShowing()) {
- window.hide();
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean onTrackballEvent(MotionEvent event) {
- return false;
- }
-}
diff --git a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/InputMethodDebug.java b/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/InputMethodDebug.java
deleted file mode 100644
index dd11d212a..000000000
--- a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/InputMethodDebug.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-package com.example.android.multiclientinputmethod;
-
-import android.view.WindowManager;
-
-import com.android.internal.inputmethod.StartInputFlags;
-
-import java.util.StringJoiner;
-
-/**
- * Provides useful methods for debugging.
- */
-final class InputMethodDebug {
-
- /**
- * Not intended to be instantiated.
- */
- private InputMethodDebug() {
- }
-
- /**
- * Converts soft input flags to {@link String} for debug logging.
- *
- * @param softInputMode integer constant for soft input flags.
- * @return {@link String} message corresponds for the given {@code softInputMode}.
- */
- public static String softInputModeToString(int softInputMode) {
- final StringJoiner joiner = new StringJoiner("|");
- final int state = softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE;
- final int adjust = softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
- final boolean isForwardNav =
- (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0;
-
- switch (state) {
- case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
- joiner.add("STATE_UNSPECIFIED");
- break;
- case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
- joiner.add("STATE_UNCHANGED");
- break;
- case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
- joiner.add("STATE_HIDDEN");
- break;
- case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
- joiner.add("STATE_ALWAYS_HIDDEN");
- break;
- case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
- joiner.add("STATE_VISIBLE");
- break;
- case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
- joiner.add("STATE_ALWAYS_VISIBLE");
- break;
- default:
- joiner.add("STATE_UNKNOWN(" + state + ")");
- break;
- }
-
- switch (adjust) {
- case WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED:
- joiner.add("ADJUST_UNSPECIFIED");
- break;
- case WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE:
- joiner.add("ADJUST_RESIZE");
- break;
- case WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN:
- joiner.add("ADJUST_PAN");
- break;
- case WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING:
- joiner.add("ADJUST_NOTHING");
- break;
- default:
- joiner.add("ADJUST_UNKNOWN(" + adjust + ")");
- break;
- }
-
- if (isForwardNav) {
- // This is a special bit that is set by the system only during the window navigation.
- joiner.add("IS_FORWARD_NAVIGATION");
- }
-
- return joiner.setEmptyValue("(none)").toString();
- }
-
- /**
- * Converts start input flags to {@link String} for debug logging.
- *
- * @param startInputFlags integer constant for start input flags.
- * @return {@link String} message corresponds for the given {@code startInputFlags}.
- */
- public static String startInputFlagsToString(int startInputFlags) {
- final StringJoiner joiner = new StringJoiner("|");
- if ((startInputFlags & StartInputFlags.VIEW_HAS_FOCUS) != 0) {
- joiner.add("VIEW_HAS_FOCUS");
- }
- if ((startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0) {
- joiner.add("IS_TEXT_EDITOR");
- }
- if ((startInputFlags & StartInputFlags.INITIAL_CONNECTION) != 0) {
- joiner.add("INITIAL_CONNECTION");
- }
-
- return joiner.setEmptyValue("(none)").toString();
- }
-}
diff --git a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/MultiClientInputMethod.java b/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/MultiClientInputMethod.java
deleted file mode 100644
index a3f9d1b74..000000000
--- a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/MultiClientInputMethod.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-package com.example.android.multiclientinputmethod;
-
-import android.annotation.NonNull;
-import android.app.Service;
-import android.content.Context;
-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;
-import android.view.Display;
-
-/**
- * A {@link Service} that implements multi-client IME protocol.
- */
-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 for a given displayId.
- 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;
- MultiClientInputMethodServiceDelegate mDelegate;
-
- private DisplayManager mDisplayManager;
-
- @Override
- public void onCreate() {
- if (DEBUG) {
- Log.v(TAG, "onCreate");
- }
- mInputDisplayToImeDisplay = buildInputDisplayToImeDisplay();
- mDelegate = MultiClientInputMethodServiceDelegate.create(this,
- new MultiClientInputMethodServiceDelegate.ServiceCallback() {
- @Override
- public void initialized() {
- if (DEBUG) {
- Log.i(TAG, "initialized");
- }
- }
-
- @Override
- public void addClient(int clientId, int uid, int pid,
- int selfReportedDisplayId) {
- int imeDisplayId = mInputDisplayToImeDisplay.get(selfReportedDisplayId,
- selfReportedDisplayId);
- final ClientCallbackImpl callback = new ClientCallbackImpl(
- MultiClientInputMethod.this, mDelegate,
- mSoftInputWindowManager, clientId, uid, pid, imeDisplayId);
- if (DEBUG) {
- Log.v(TAG, "addClient clientId=" + clientId + " uid=" + uid
- + " pid=" + pid + " displayId=" + selfReportedDisplayId
- + " imeDisplayId=" + imeDisplayId);
- }
-
- mDelegate.acceptClient(clientId, callback, callback.getDispatcherState(),
- callback.getLooper());
- }
-
- @Override
- public void removeClient(int clientId) {
- if (DEBUG) {
- Log.v(TAG, "removeClient clientId=" + clientId);
- }
- }
- });
- mSoftInputWindowManager = new SoftInputWindowManager(this, mDelegate);
- }
-
- @Override
- public void onDisplayAdded(int displayId) {
- mInputDisplayToImeDisplay = buildInputDisplayToImeDisplay();
- }
-
- @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);
- }
-
- @Override
- public boolean onUnbind(Intent intent) {
- if (DEBUG) {
- Log.v(TAG, "onUnbind intent=" + intent);
- }
- if (mDisplayManager != null) {
- mDisplayManager.unregisterDisplayListener(this);
- }
- return mDelegate.onUnbind(intent);
- }
-
- @Override
- public void onDestroy() {
- if (DEBUG) {
- Log.v(TAG, "onDestroy");
- }
- mDelegate.onDestroy();
- }
-
- @NonNull
- private SparseIntArray buildInputDisplayToImeDisplay() {
- 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 regexp) {
- for (Display display: displays) {
- if (display.getUniqueId().matches(regexp)) {
- int displayId = display.getDisplayId();
- if (DEBUG) {
- Log.v(TAG, regexp + " matches displayId=" + displayId);
- }
- return displayId;
- }
- }
- Log.w(TAG, "Can't find the display of " + regexp);
- return Display.INVALID_DISPLAY;
- }
-}
diff --git a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/NoopKeyboardActionListener.java b/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/NoopKeyboardActionListener.java
deleted file mode 100644
index 94248ce52..000000000
--- a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/NoopKeyboardActionListener.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-package com.example.android.multiclientinputmethod;
-
-import android.inputmethodservice.KeyboardView;
-
-/**
- * Provides the no-op implementation of {@link KeyboardView.OnKeyboardActionListener}
- */
-class NoopKeyboardActionListener implements KeyboardView.OnKeyboardActionListener {
- @Override
- public void onPress(int primaryCode) {
- }
-
- @Override
- public void onRelease(int primaryCode) {
- }
-
- @Override
- public void onKey(int primaryCode, int[] keyCodes) {
- }
-
- @Override
- public void onText(CharSequence text) {
- }
-
- @Override
- public void swipeLeft() {
- }
-
- @Override
- public void swipeRight() {
- }
-
- @Override
- public void swipeDown() {
- }
-
- @Override
- public void swipeUp() {
- }
-}
diff --git a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/SoftInputWindow.java b/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/SoftInputWindow.java
deleted file mode 100644
index 93e60a7a9..000000000
--- a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/SoftInputWindow.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-package com.example.android.multiclientinputmethod;
-
-import android.app.Dialog;
-import android.content.Context;
-import android.inputmethodservice.Keyboard;
-import android.inputmethodservice.KeyboardView;
-import android.inputmethodservice.MultiClientInputMethodServiceDelegate;
-import android.os.IBinder;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.ViewGroup;
-import android.view.WindowManager.LayoutParams;
-import android.view.inputmethod.InputConnection;
-import android.widget.LinearLayout;
-
-import java.util.Arrays;
-
-final class SoftInputWindow extends Dialog {
- private static final String TAG = "SoftInputWindow";
- private static final boolean DEBUG = false;
-
- private final KeyboardView mKeyboardView;
-
- private final Keyboard mQwertygKeyboard;
- private final Keyboard mSymbolKeyboard;
- private final Keyboard mSymbolShiftKeyboard;
-
- private int mClientId = MultiClientInputMethodServiceDelegate.INVALID_CLIENT_ID;
- private int mTargetWindowHandle = MultiClientInputMethodServiceDelegate.INVALID_WINDOW_HANDLE;
-
- private static final KeyboardView.OnKeyboardActionListener sNoopListener =
- new NoopKeyboardActionListener();
-
- SoftInputWindow(Context context, IBinder token) {
- super(context, android.R.style.Theme_DeviceDefault_InputMethod);
-
- final LayoutParams lp = getWindow().getAttributes();
- lp.type = LayoutParams.TYPE_INPUT_METHOD;
- lp.setTitle("InputMethod");
- lp.gravity = Gravity.BOTTOM;
- lp.width = LayoutParams.MATCH_PARENT;
- lp.height = LayoutParams.WRAP_CONTENT;
- lp.token = token;
- getWindow().setAttributes(lp);
-
- final int windowSetFlags = LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | LayoutParams.FLAG_NOT_FOCUSABLE
- | LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
- final int windowModFlags = LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | LayoutParams.FLAG_NOT_FOCUSABLE
- | LayoutParams.FLAG_DIM_BEHIND
- | LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
- getWindow().setFlags(windowSetFlags, windowModFlags);
-
- final LinearLayout layout = new LinearLayout(context);
- layout.setOrientation(LinearLayout.VERTICAL);
-
- mKeyboardView = (KeyboardView) getLayoutInflater().inflate(R.layout.input, null);
- mQwertygKeyboard = new Keyboard(context, R.xml.qwerty);
- mSymbolKeyboard = new Keyboard(context, R.xml.symbols);
- mSymbolShiftKeyboard = new Keyboard(context, R.xml.symbols_shift);
- mKeyboardView.setKeyboard(mQwertygKeyboard);
- mKeyboardView.setOnKeyboardActionListener(sNoopListener);
-
- // TODO(b/158663354): Disabling keyboard popped preview key since it is currently broken.
- mKeyboardView.setPreviewEnabled(false);
-
- layout.addView(mKeyboardView);
-
- setContentView(layout, new ViewGroup.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
-
- // TODO: Check why we need to call this.
- getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
- }
-
- int getClientId() {
- return mClientId;
- }
-
- int getTargetWindowHandle() {
- return mTargetWindowHandle;
- }
-
- boolean isQwertyKeyboard() {
- return mKeyboardView.getKeyboard() == mQwertygKeyboard;
- }
-
- boolean isSymbolKeyboard() {
- Keyboard keyboard = mKeyboardView.getKeyboard();
- return keyboard == mSymbolKeyboard || keyboard == mSymbolShiftKeyboard;
- }
-
- void onFinishClient() {
- mKeyboardView.setOnKeyboardActionListener(sNoopListener);
- mClientId = MultiClientInputMethodServiceDelegate.INVALID_CLIENT_ID;
- mTargetWindowHandle = MultiClientInputMethodServiceDelegate.INVALID_WINDOW_HANDLE;
- }
-
- void onDummyStartInput(int clientId, int targetWindowHandle) {
- if (DEBUG) {
- Log.v(TAG, "onDummyStartInput clientId=" + clientId
- + " targetWindowHandle=" + targetWindowHandle);
- }
- mKeyboardView.setOnKeyboardActionListener(sNoopListener);
- mClientId = clientId;
- mTargetWindowHandle = targetWindowHandle;
- }
-
- void onStartInput(int clientId, int targetWindowHandle, InputConnection inputConnection) {
- if (DEBUG) {
- Log.v(TAG, "onStartInput clientId=" + clientId
- + " targetWindowHandle=" + targetWindowHandle);
- }
- mClientId = clientId;
- mTargetWindowHandle = targetWindowHandle;
- mKeyboardView.setOnKeyboardActionListener(new NoopKeyboardActionListener() {
- @Override
- public void onKey(int primaryCode, int[] keyCodes) {
- if (DEBUG) {
- Log.v(TAG, "onKey clientId=" + clientId + " primaryCode=" + primaryCode
- + " keyCodes=" + Arrays.toString(keyCodes));
- }
- boolean isShifted = isShifted(); // Store the current state before resetting it.
- resetShift();
- switch (primaryCode) {
- case Keyboard.KEYCODE_CANCEL:
- hide();
- break;
- case Keyboard.KEYCODE_DELETE:
- inputConnection.sendKeyEvent(
- new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
- inputConnection.sendKeyEvent(
- new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
- break;
- case Keyboard.KEYCODE_MODE_CHANGE:
- handleSwitchKeyboard();
- break;
- case Keyboard.KEYCODE_SHIFT:
- handleShift(isShifted);
- break;
- default:
- handleCharacter(inputConnection, primaryCode, isShifted);
- break;
- }
- }
-
- @Override
- public void onText(CharSequence text) {
- if (DEBUG) {
- Log.v(TAG, "onText clientId=" + clientId + " text=" + text);
- }
- if (inputConnection == null) {
- return;
- }
- inputConnection.commitText(text, 0);
- }
- });
- }
-
- void handleSwitchKeyboard() {
- if (isQwertyKeyboard()) {
- mKeyboardView.setKeyboard(mSymbolKeyboard);
- } else {
- mKeyboardView.setKeyboard(mQwertygKeyboard);
- }
-
- }
-
- boolean isShifted() {
- return mKeyboardView.isShifted();
- }
-
- void resetShift() {
- if (isSymbolKeyboard() && isShifted()) {
- mKeyboardView.setKeyboard(mSymbolKeyboard);
- }
- mKeyboardView.setShifted(false);
- }
-
- void handleShift(boolean isShifted) {
- if (isSymbolKeyboard()) {
- mKeyboardView.setKeyboard(isShifted ? mSymbolKeyboard : mSymbolShiftKeyboard);
- }
- mKeyboardView.setShifted(!isShifted);
- }
-
- void handleCharacter(InputConnection inputConnection, int primaryCode, boolean isShifted) {
- if (isQwertyKeyboard() && isShifted) {
- primaryCode = Character.toUpperCase(primaryCode);
- }
- inputConnection.commitText(String.valueOf((char) primaryCode), 1);
- }
-}
diff --git a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/SoftInputWindowManager.java b/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/SoftInputWindowManager.java
deleted file mode 100644
index f97c44980..000000000
--- a/samples/MultiClientInputMethod/src/com/example/android/multiclientinputmethod/SoftInputWindowManager.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-package com.example.android.multiclientinputmethod;
-
-import android.content.Context;
-import android.hardware.display.DisplayManager;
-import android.inputmethodservice.MultiClientInputMethodServiceDelegate;
-import android.os.IBinder;
-import android.util.SparseArray;
-import android.view.Display;
-
-final class SoftInputWindowManager {
- private final Context mContext;
- private final MultiClientInputMethodServiceDelegate mDelegate;
- private final SparseArray mSoftInputWindows = new SparseArray<>();
-
- SoftInputWindowManager(Context context, MultiClientInputMethodServiceDelegate delegate) {
- mContext = context;
- mDelegate = delegate;
- }
-
- SoftInputWindow getOrCreateSoftInputWindow(int displayId) {
- final SoftInputWindow existingWindow = mSoftInputWindows.get(displayId);
- if (existingWindow != null) {
- return existingWindow;
- }
-
- final Display display =
- mContext.getSystemService(DisplayManager.class).getDisplay(displayId);
- if (display == null) {
- return null;
- }
- final IBinder windowToken = mDelegate.createInputMethodWindowToken(displayId);
- if (windowToken == null) {
- return null;
- }
-
- final Context displayContext = mContext.createDisplayContext(display);
- final SoftInputWindow newWindow = new SoftInputWindow(displayContext, windowToken);
- mSoftInputWindows.put(displayId, newWindow);
- return newWindow;
- }
-
- SoftInputWindow getSoftInputWindow(int displayId) {
- return mSoftInputWindows.get(displayId);
- }
-}