Remove ZeroJankProxy.Callback#isInputShownLocked()
This reworks our previous CL [1], which addressed an observable
unintentional behavior change when ZeroJankProxy is enabled, in a way
that ZeroJankProxy.Callback does not need to have
ZeroJankProxy.Callback#isInputShownLocked(),
which will soon need to become concurrent multi-user aware.
The problem is when it becomes concurrent multi-user aware,
ZeroJankProxy needs to know whose IME is in use, which is tricky
because the IME user ID is dynamically resolved with
InputMethodManagerService#resolveImeUserIdLocked().
The core logic should remain unchanged.
[1]: Ie2f262128eb32db5a7922373fdfaebd2945ea36a
2aed68440258fbc3cdb803d4faa1855638579bf1
Bug: 349904272
Test: presubmit
Flag: android.view.inputmethod.use_zero_jank_proxy
Change-Id: Ib719f6018965c3554c8c2d8c2050ad51962d8a25
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 0770c8e..f7faee1 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1812,8 +1812,7 @@
}
@GuardedBy("ImfLock.class")
- @Override
- public boolean isInputShownLocked() {
+ private boolean isInputShownLocked() {
return mVisibilityStateComputer.isInputShown();
}
@@ -3004,52 +3003,75 @@
}
}
+ @GuardedBy("ImfLock.class")
+ private void sendResultReceiverFailureLocked(@Nullable ResultReceiver resultReceiver) {
+ final boolean isInputShown = mVisibilityStateComputer.isInputShown();
+ resultReceiver.send(isInputShown
+ ? InputMethodManager.RESULT_UNCHANGED_SHOWN
+ : InputMethodManager.RESULT_UNCHANGED_HIDDEN, null);
+ }
+
@Override
public boolean showSoftInput(IInputMethodClient client, IBinder windowToken,
@NonNull ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
int lastClickToolType, ResultReceiver resultReceiver,
@SoftInputShowHideReason int reason) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showSoftInput");
- final int uid = Binder.getCallingUid();
- final int callingUserId = UserHandle.getUserId(uid);
ImeTracing.getInstance().triggerManagerServiceDump(
"InputMethodManagerService#showSoftInput", mDumper);
synchronized (ImfLock.class) {
- final int userId = resolveImeUserIdLocked(callingUserId);
- if (!canInteractWithImeLocked(uid, client, "showSoftInput", statsToken,
- userId)) {
- ImeTracker.forLogging().onFailed(
- statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- return false;
+ final boolean result = showSoftInputLocked(client, windowToken, statsToken, flags,
+ lastClickToolType, resultReceiver, reason);
+ // When ZeroJankProxy is enabled, the app has already received "true" as the return
+ // value, and expect "resultReceiver" to be notified later. See b/327751155.
+ if (!result && Flags.useZeroJankProxy()) {
+ sendResultReceiverFailureLocked(resultReceiver);
}
- final var userData = getUserData(userId);
- final long ident = Binder.clearCallingIdentity();
- try {
- if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
- if (Flags.refactorInsetsController()) {
- boolean wasVisible = isInputShownLocked();
- if (userData.mImeBindingState != null
- && userData.mImeBindingState.mFocusedWindowClient != null
- && userData.mImeBindingState.mFocusedWindowClient.mClient != null) {
- userData.mImeBindingState.mFocusedWindowClient.mClient
- .setImeVisibility(true, statsToken);
- if (resultReceiver != null) {
- resultReceiver.send(
- wasVisible ? InputMethodManager.RESULT_UNCHANGED_SHOWN
- : InputMethodManager.RESULT_SHOWN, null);
- }
- return true;
+ return result; // ignored when ZeroJankProxy is enabled.
+ }
+ }
+
+ @GuardedBy("ImfLock.class")
+ private boolean showSoftInputLocked(IInputMethodClient client, IBinder windowToken,
+ @NonNull ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
+ int lastClickToolType, ResultReceiver resultReceiver,
+ @SoftInputShowHideReason int reason) {
+ final int uid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getUserId(uid);
+ final int userId = resolveImeUserIdLocked(callingUserId);
+ if (!canInteractWithImeLocked(uid, client, "showSoftInput", statsToken,
+ userId)) {
+ ImeTracker.forLogging().onFailed(
+ statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ return false;
+ }
+ final var userData = getUserData(userId);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
+ if (Flags.refactorInsetsController()) {
+ boolean wasVisible = isInputShownLocked();
+ if (userData.mImeBindingState != null
+ && userData.mImeBindingState.mFocusedWindowClient != null
+ && userData.mImeBindingState.mFocusedWindowClient.mClient != null) {
+ userData.mImeBindingState.mFocusedWindowClient.mClient
+ .setImeVisibility(true, statsToken);
+ if (resultReceiver != null) {
+ resultReceiver.send(
+ wasVisible ? InputMethodManager.RESULT_UNCHANGED_SHOWN
+ : InputMethodManager.RESULT_SHOWN, null);
}
- return false;
- } else {
- return showCurrentInputLocked(windowToken, statsToken, flags, lastClickToolType,
- resultReceiver, reason, userId);
+ return true;
}
- } finally {
- Binder.restoreCallingIdentity(ident);
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ return false;
+ } else {
+ return showCurrentInputLocked(windowToken, statsToken, flags, lastClickToolType,
+ resultReceiver, reason, userId);
}
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
@@ -3444,50 +3466,64 @@
public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken,
@NonNull ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
- final int uid = Binder.getCallingUid();
- final int callingUserId = UserHandle.getUserId(uid);
ImeTracing.getInstance().triggerManagerServiceDump(
"InputMethodManagerService#hideSoftInput", mDumper);
synchronized (ImfLock.class) {
- final int userId = resolveImeUserIdLocked(callingUserId);
- if (!canInteractWithImeLocked(uid, client, "hideSoftInput", statsToken, userId)) {
- if (isInputShownLocked()) {
- ImeTracker.forLogging().onFailed(
- statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
- } else {
- ImeTracker.forLogging().onCancelled(statsToken,
- ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+ final boolean result = hideSoftInputLocked(client, windowToken, statsToken, flags,
+ resultReceiver, reason);
+ // When ZeroJankProxy is enabled, the app has already received "true" as the return
+ // value, and expect "resultReceiver" to be notified later. See b/327751155.
+ if (!result && Flags.useZeroJankProxy()) {
+ sendResultReceiverFailureLocked(resultReceiver);
+ }
+ return result; // ignored when ZeroJankProxy is enabled.
+ }
+ }
+
+ @GuardedBy("ImfLock.class")
+ private boolean hideSoftInputLocked(IInputMethodClient client, IBinder windowToken,
+ @NonNull ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
+ ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
+ final int uid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getUserId(uid);
+ final int userId = resolveImeUserIdLocked(callingUserId);
+ if (!canInteractWithImeLocked(uid, client, "hideSoftInput", statsToken, userId)) {
+ if (isInputShownLocked()) {
+ ImeTracker.forLogging().onFailed(
+ statsToken, ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+ } else {
+ ImeTracker.forLogging().onCancelled(statsToken,
+ ImeTracker.PHASE_SERVER_CLIENT_FOCUSED);
+ }
+ return false;
+ }
+ final var userData = getUserData(userId);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideSoftInput");
+ if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
+ if (Flags.refactorInsetsController()) {
+ if (userData.mImeBindingState != null
+ && userData.mImeBindingState.mFocusedWindowClient != null
+ && userData.mImeBindingState.mFocusedWindowClient.mClient != null) {
+ boolean wasVisible = isInputShownLocked();
+ // TODO add windowToken to interface
+ userData.mImeBindingState.mFocusedWindowClient.mClient
+ .setImeVisibility(false, statsToken);
+ if (resultReceiver != null) {
+ resultReceiver.send(wasVisible ? InputMethodManager.RESULT_HIDDEN
+ : InputMethodManager.RESULT_UNCHANGED_HIDDEN, null);
+ }
+ return true;
}
return false;
+ } else {
+ return InputMethodManagerService.this.hideCurrentInputLocked(
+ windowToken, statsToken, flags, resultReceiver, reason, userId);
}
- final var userData = getUserData(userId);
- final long ident = Binder.clearCallingIdentity();
- try {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideSoftInput");
- if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
- if (Flags.refactorInsetsController()) {
- if (userData.mImeBindingState != null
- && userData.mImeBindingState.mFocusedWindowClient != null
- && userData.mImeBindingState.mFocusedWindowClient.mClient != null) {
- boolean wasVisible = isInputShownLocked();
- // TODO add windowToken to interface
- userData.mImeBindingState.mFocusedWindowClient.mClient
- .setImeVisibility(false, statsToken);
- if (resultReceiver != null) {
- resultReceiver.send(wasVisible ? InputMethodManager.RESULT_HIDDEN
- : InputMethodManager.RESULT_UNCHANGED_HIDDEN, null);
- }
- return true;
- }
- return false;
- } else {
- return InputMethodManagerService.this.hideCurrentInputLocked(windowToken,
- statsToken, flags, resultReceiver, reason, userId);
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
diff --git a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
index 770e12d..fdb2e6f 100644
--- a/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
+++ b/services/core/java/com/android/server/inputmethod/ZeroJankProxy.java
@@ -86,8 +86,6 @@
interface Callback extends IInputMethodManagerImpl.Callback {
@GuardedBy("ImfLock.class")
ClientState getClientStateLocked(IInputMethodClient client);
- @GuardedBy("ImfLock.class")
- boolean isInputShownLocked();
}
private final Callback mInner;
@@ -178,19 +176,8 @@
@Nullable ImeTracker.Token statsToken, @InputMethodManager.ShowFlags int flags,
@MotionEvent.ToolType int lastClickToolType, ResultReceiver resultReceiver,
@SoftInputShowHideReason int reason) {
- offload(
- () -> {
- if (!mInner.showSoftInput(
- client,
- windowToken,
- statsToken,
- flags,
- lastClickToolType,
- resultReceiver,
- reason)) {
- sendResultReceiverFailure(resultReceiver);
- }
- });
+ offload(() -> mInner.showSoftInput(
+ client, windowToken, statsToken, flags, lastClickToolType, resultReceiver, reason));
return true;
}
@@ -198,30 +185,11 @@
public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken,
@Nullable ImeTracker.Token statsToken, @InputMethodManager.HideFlags int flags,
ResultReceiver resultReceiver, @SoftInputShowHideReason int reason) {
- offload(
- () -> {
- if (!mInner.hideSoftInput(
- client, windowToken, statsToken, flags, resultReceiver, reason)) {
- sendResultReceiverFailure(resultReceiver);
- }
- });
+ offload(() -> mInner.hideSoftInput(
+ client, windowToken, statsToken, flags, resultReceiver, reason));
return true;
}
- private void sendResultReceiverFailure(@Nullable ResultReceiver resultReceiver) {
- if (resultReceiver == null) {
- return;
- }
- final boolean isInputShown;
- synchronized (ImfLock.class) {
- isInputShown = mInner.isInputShownLocked();
- }
- resultReceiver.send(isInputShown
- ? InputMethodManager.RESULT_UNCHANGED_SHOWN
- : InputMethodManager.RESULT_UNCHANGED_HIDDEN,
- null);
- }
-
@Override
@IInputMethodManagerImpl.PermissionVerified(Manifest.permission.TEST_INPUT_METHOD)
public void hideSoftInputFromServerForTest() {