summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Taran Singh <tarandeep@google.com> 2022-08-11 18:32:47 +0000
committer Taran Singh <tarandeep@google.com> 2022-08-24 00:24:04 +0000
commitf092a7cb23aa94d9250948de0e936f155d7ea1cd (patch)
treef0f6889a54c901357520d4d9cc24f725ee7685ee
parentb40e48cd51dc771da422515e23821e60bc67b483 (diff)
Improve handwriting Ink window lifetime
1. When the system removes the last known stylus device and has no other stylus available, remove the Ink window. 2. Create InkWindow only if the device+IME combination supports handwriting and the stylus is being used. Bug: 243571274 Bug: 239121683 Bug: 210039666 Test: atest StylusHandwritingTest Change-Id: Icd3eea91fe144cff7100d3ecf19191c064c0d196
-rw-r--r--core/java/android/inputmethodservice/IInputMethodWrapper.java11
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java54
-rw-r--r--core/java/android/view/inputmethod/InputMethod.java7
-rw-r--r--core/java/com/android/internal/inputmethod/IInputMethod.aidl3
-rw-r--r--services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java13
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodBindingController.java3
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java92
7 files changed, 129 insertions, 54 deletions
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 3d593872757d..05daf63fdd5d 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -81,6 +81,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
private static final int DO_INIT_INK_WINDOW = 120;
private static final int DO_FINISH_STYLUS_HANDWRITING = 130;
private static final int DO_UPDATE_TOOL_TYPE = 140;
+ private static final int DO_REMOVE_STYLUS_HANDWRITING_WINDOW = 150;
final WeakReference<InputMethodServiceInternal> mTarget;
final Context mContext;
@@ -254,6 +255,10 @@ class IInputMethodWrapper extends IInputMethod.Stub
inputMethod.finishStylusHandwriting();
return;
}
+ case DO_REMOVE_STYLUS_HANDWRITING_WINDOW: {
+ inputMethod.removeStylusHandwritingWindow();
+ return;
+ }
}
Log.w(TAG, "Unhandled message code: " + msg.what);
@@ -434,4 +439,10 @@ class IInputMethodWrapper extends IInputMethod.Stub
public void finishStylusHandwriting() {
mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_STYLUS_HANDWRITING));
}
+
+ @BinderThread
+ @Override
+ public void removeStylusHandwritingWindow() {
+ mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_REMOVE_STYLUS_HANDWRITING_WINDOW));
+ }
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index c2027b136f0e..48b9b8869cae 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -621,7 +621,7 @@ public class InputMethodService extends AbstractInputMethodService {
private boolean mDestroyed;
private boolean mOnPreparedStylusHwCalled;
- /** Stylus handwriting Ink window. */
+ /** Stylus handwriting Ink window. */
private InkWindow mInkWindow;
/**
@@ -708,9 +708,6 @@ public class InputMethodService extends AbstractInputMethodService {
mConfigTracker.onInitialize(params.configChanges);
mPrivOps.set(params.privilegedOperations);
InputMethodPrivilegedOperationsRegistry.put(params.token, mPrivOps);
- if (params.stylusHandWritingSupported) {
- mInkWindow = new InkWindow(mWindow.getContext());
- }
mNavigationBarController.onNavButtonFlagsChanged(params.navigationBarFlags);
attachToken(params.token);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
@@ -744,9 +741,6 @@ public class InputMethodService extends AbstractInputMethodService {
attachToWindowToken(token);
mToken = token;
mWindow.setToken(token);
- if (mInkWindow != null) {
- mInkWindow.setToken(token);
- }
}
/**
@@ -785,7 +779,7 @@ public class InputMethodService extends AbstractInputMethodService {
mInputConnection = null;
// free-up cached InkWindow surface on detaching from current client.
if (mInkWindow != null) {
- mInkWindow.hide(true /* remove */);
+ removeHandwritingInkWindow();
}
}
@@ -972,6 +966,7 @@ public class InputMethodService extends AbstractInputMethodService {
Log.d(TAG, "Input should have started before starting Stylus handwriting.");
return;
}
+ maybeCreateInkWindow();
if (!mOnPreparedStylusHwCalled) {
// prepare hasn't been called by Stylus HOVER.
onPrepareStylusHandwriting();
@@ -1031,12 +1026,24 @@ public class InputMethodService extends AbstractInputMethodService {
*/
@Override
public void initInkWindow() {
+ maybeCreateInkWindow();
mInkWindow.initOnly();
onPrepareStylusHandwriting();
mOnPreparedStylusHwCalled = true;
}
/**
+ * Create and attach token to Ink window if it wasn't already created.
+ */
+ private void maybeCreateInkWindow() {
+ if (mInkWindow == null) {
+ mInkWindow = new InkWindow(mWindow.getContext());
+ mInkWindow.setToken(mToken);
+ }
+ // TODO(b/243571274): set an idle-timeout after which InkWindow is removed.
+ }
+
+ /**
* {@inheritDoc}
* @hide
*/
@@ -1047,6 +1054,15 @@ public class InputMethodService extends AbstractInputMethodService {
/**
* {@inheritDoc}
+ * @hide
+ */
+ @Override
+ public void removeStylusHandwritingWindow() {
+ InputMethodService.this.removeStylusHandwritingWindow();
+ }
+
+ /**
+ * {@inheritDoc}
*/
@MainThread
@Override
@@ -2511,6 +2527,7 @@ public class InputMethodService extends AbstractInputMethodService {
mHandwritingEventReceiver.dispose();
mHandwritingEventReceiver = null;
+ // TODO(b/243571274): set an idle-timeout after which InkWindow is removed.
mInkWindow.hide(false /* remove */);
mPrivOps.resetStylusHandwriting(requestId);
@@ -2519,6 +2536,27 @@ public class InputMethodService extends AbstractInputMethodService {
}
/**
+ * Remove Stylus handwriting window.
+ * Typically, this is called when {@link InkWindow} should no longer be holding a surface in
+ * memory.
+ */
+ private void removeStylusHandwritingWindow() {
+ if (mInkWindow != null) {
+ if (mHandwritingRequestId.isPresent()) {
+ // if handwriting session is still ongoing. This shouldn't happen.
+ finishStylusHandwriting();
+ }
+ removeHandwritingInkWindow();
+ }
+ }
+
+ private void removeHandwritingInkWindow() {
+ mInkWindow.hide(true /* remove */);
+ mInkWindow.destroy();
+ mInkWindow = null;
+ }
+
+ /**
* Sets the duration after which an ongoing stylus handwriting session that hasn't received new
* {@link MotionEvent}s will time out and {@link #finishStylusHandwriting()} will be called.
*
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index bfe6ae6447d0..978bfc7af60d 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -410,4 +410,11 @@ public interface InputMethod {
// intentionally empty
}
+ /**
+ * Remove stylus handwriting window.
+ * @hide
+ */
+ default void removeStylusHandwritingWindow() {
+ // intentionally empty
+ }
}
diff --git a/core/java/com/android/internal/inputmethod/IInputMethod.aidl b/core/java/com/android/internal/inputmethod/IInputMethod.aidl
index 5db2e84845f5..9182d1dc56bf 100644
--- a/core/java/com/android/internal/inputmethod/IInputMethod.aidl
+++ b/core/java/com/android/internal/inputmethod/IInputMethod.aidl
@@ -40,7 +40,6 @@ oneway interface IInputMethod {
IBinder token;
IInputMethodPrivilegedOperations privilegedOperations;
int configChanges;
- boolean stylusHandWritingSupported;
int navigationBarFlags;
}
@@ -86,4 +85,6 @@ oneway interface IInputMethod {
void initInkWindow();
void finishStylusHandwriting();
+
+ void removeStylusHandwritingWindow();
}
diff --git a/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java b/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
index eb73234549c9..3e397468aa87 100644
--- a/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
+++ b/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
@@ -109,13 +109,11 @@ final class IInputMethodInvoker {
@AnyThread
void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privilegedOperations,
- int configChanges, boolean stylusHandWritingSupported,
- @InputMethodNavButtonFlags int navigationBarFlags) {
+ int configChanges, @InputMethodNavButtonFlags int navigationBarFlags) {
final IInputMethod.InitParams params = new IInputMethod.InitParams();
params.token = token;
params.privilegedOperations = privilegedOperations;
params.configChanges = configChanges;
- params.stylusHandWritingSupported = stylusHandWritingSupported;
params.navigationBarFlags = navigationBarFlags;
try {
mTarget.initializeInternal(params);
@@ -279,4 +277,13 @@ final class IInputMethodInvoker {
logRemoteException(e);
}
}
+
+ @AnyThread
+ void removeStylusHandwritingWindow() {
+ try {
+ mTarget.removeStylusHandwritingWindow();
+ } catch (RemoteException e) {
+ logRemoteException(e);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
index b63592c2fedb..23ea39a3b022 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
@@ -286,8 +286,7 @@ final class InputMethodBindingController {
if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
final InputMethodInfo info = mMethodMap.get(mSelectedMethodId);
mSupportsStylusHw = info.supportsStylusHandwriting();
- mService.initializeImeLocked(mCurMethod, mCurToken, info.getConfigChanges(),
- mSupportsStylusHw);
+ mService.initializeImeLocked(mCurMethod, mCurToken, info.getConfigChanges());
mService.scheduleNotifyImeUidToAudioService(mCurMethodUid);
mService.reRequestCurrentClientSessionLocked();
mService.performOnCreateInlineSuggestionsRequestLocked();
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 23f437392d2b..7bd835c73749 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -246,6 +246,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
private static final int MSG_RESET_HANDWRITING = 1090;
private static final int MSG_START_HANDWRITING = 1100;
private static final int MSG_FINISH_HANDWRITING = 1110;
+ private static final int MSG_REMOVE_HANDWRITING_WINDOW = 1120;
private static final int MSG_SET_INTERACTIVE = 3030;
@@ -2719,13 +2720,13 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@GuardedBy("ImfLock.class")
void initializeImeLocked(@NonNull IInputMethodInvoker inputMethod, @NonNull IBinder token,
- @android.content.pm.ActivityInfo.Config int configChanges, boolean supportStylusHw) {
+ @android.content.pm.ActivityInfo.Config int configChanges) {
if (DEBUG) {
Slog.v(TAG, "Sending attach of token: " + token + " for display: "
+ mCurTokenDisplayId);
}
inputMethod.initializeInternal(token, new InputMethodPrivilegedOperationsImpl(this, token),
- configChanges, supportStylusHw, getInputMethodNavButtonFlagsLocked());
+ configChanges, getInputMethodNavButtonFlagsLocked());
}
@AnyThread
@@ -2734,6 +2735,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
@AnyThread
+ void scheduleRemoveStylusHandwritingWindow() {
+ mHandler.obtainMessage(MSG_REMOVE_HANDWRITING_WINDOW).sendToTarget();
+ }
+
+ @AnyThread
void scheduleNotifyImeUidToAudioService(int uid) {
mHandler.removeMessages(MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE);
mHandler.obtainMessage(MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE, uid, 0 /* unused */)
@@ -4363,40 +4369,50 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
private void add(int deviceId) {
synchronized (ImfLock.class) {
- if (mStylusIds == null) {
- mStylusIds = new IntArray();
- } else if (mStylusIds.indexOf(deviceId) != -1) {
- return;
- }
- Slog.d(TAG, "New Stylus device " + deviceId + " added.");
- mStylusIds.add(deviceId);
- // a new Stylus is detected. If IME supports handwriting and we don't have
- // handwriting initialized, lets do it now.
- if (!mHwController.getCurrentRequestId().isPresent()
- && mMethodMap.get(getSelectedMethodIdLocked())
- .supportsStylusHandwriting()) {
- scheduleResetStylusHandwriting();
- }
+ addStylusDeviceIdLocked(deviceId);
}
}
private void remove(int deviceId) {
synchronized (ImfLock.class) {
- if (mStylusIds == null || mStylusIds.size() == 0) {
- return;
- }
- if (mStylusIds.indexOf(deviceId) != -1) {
- mStylusIds.remove(deviceId);
- Slog.d(TAG, "Stylus device " + deviceId + " removed.");
- }
- if (mStylusIds.size() == 0) {
- mHwController.reset();
- }
+ removeStylusDeviceIdLocked(deviceId);
}
}
}, mHandler);
}
+ private void addStylusDeviceIdLocked(int deviceId) {
+ if (mStylusIds == null) {
+ mStylusIds = new IntArray();
+ } else if (mStylusIds.indexOf(deviceId) != -1) {
+ return;
+ }
+ Slog.d(TAG, "New Stylus deviceId" + deviceId + " added.");
+ mStylusIds.add(deviceId);
+ // a new Stylus is detected. If IME supports handwriting, and we don't have
+ // handwriting initialized, lets do it now.
+ if (!mHwController.getCurrentRequestId().isPresent()
+ && mBindingController.supportsStylusHandwriting()) {
+ scheduleResetStylusHandwriting();
+ }
+ }
+
+ private void removeStylusDeviceIdLocked(int deviceId) {
+ if (mStylusIds == null || mStylusIds.size() == 0) {
+ return;
+ }
+ int index;
+ if ((index = mStylusIds.indexOf(deviceId)) != -1) {
+ mStylusIds.remove(index);
+ Slog.d(TAG, "Stylus deviceId: " + deviceId + " removed.");
+ }
+ if (mStylusIds.size() == 0) {
+ // no more supported stylus(es) in system.
+ mHwController.reset();
+ scheduleRemoveStylusHandwritingWindow();
+ }
+ }
+
private static boolean isStylusDevice(InputDevice inputDevice) {
return inputDevice.supportsSource(InputDevice.SOURCE_STYLUS)
|| inputDevice.supportsSource(InputDevice.SOURCE_BLUETOOTH_STYLUS);
@@ -4422,17 +4438,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
final long ident = Binder.clearCallingIdentity();
try {
- if (!mBindingController.supportsStylusHandwriting()) {
- Slog.w(TAG, "Stylus HW unsupported by IME. Ignoring addVirtualStylusId()");
- return;
- }
-
if (DEBUG) Slog.v(TAG, "Adding virtual stylus id for session");
- if (mStylusIds == null) {
- mStylusIds = new IntArray();
- }
- mStylusIds.add(VIRTUAL_STYLUS_ID_FOR_TEST);
- scheduleResetStylusHandwriting();
+ addStylusDeviceIdLocked(VIRTUAL_STYLUS_ID_FOR_TEST);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -4441,10 +4448,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@GuardedBy("ImfLock.class")
private void removeVirtualStylusIdForTestSessionLocked() {
- int index;
- if ((index = mStylusIds.indexOf(VIRTUAL_STYLUS_ID_FOR_TEST)) != -1) {
- mStylusIds.remove(index);
- }
+ removeStylusDeviceIdLocked(VIRTUAL_STYLUS_ID_FOR_TEST);
}
private static IntArray getStylusInputDeviceIds(InputManager im) {
@@ -4922,6 +4926,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
}
return true;
+ case MSG_REMOVE_HANDWRITING_WINDOW:
+ synchronized (ImfLock.class) {
+ IInputMethodInvoker curMethod = getCurMethodLocked();
+ if (curMethod != null) {
+ curMethod.removeStylusHandwritingWindow();
+ }
+ }
+ return true;
}
return false;
}