Remove the current input focused window when ANR

When a freeform app launched and focused, but its window is not ready,
the input focus stays on the window of the previously focused freeform
app. The focus should be removed from the previously foccused app, so
ANR can be triggered correctly.

Bug: 216852742
Test: atest AnrTests#slowOnCreateWithKeyEventTriggersAnr
Change-Id: Id00c147ffab9b11fb2abdf0f3020bc017a31bea7
This commit is contained in:
HQ Liu
2022-02-14 16:52:31 -08:00
parent 45a0712218
commit 964305e1b2
4 changed files with 40 additions and 0 deletions

View File

@@ -248,6 +248,7 @@ public final class SurfaceControl implements Parcelable {
private static native void nativeSetFixedTransformHint(long transactionObj, long nativeObject,
int transformHint);
private static native void nativeRemoveCurrentInputFocus(long nativeObject, int displayId);
private static native void nativeSetFocusedWindow(long transactionObj, IBinder toToken,
String windowName, IBinder focusedToken, String focusedWindowName, int displayId);
private static native void nativeSetFrameTimelineVsync(long transactionObj,
@@ -3652,6 +3653,17 @@ public final class SurfaceControl implements Parcelable {
return this;
}
/**
* Removes the input focus from the current window which is having the input focus. Should
* only be called when the current focused app is not responding and the current focused
* window is not beloged to the current focused app.
* @hide
*/
public Transaction removeCurrentInputFocus(int displayId) {
nativeRemoveCurrentInputFocus(mNativeObject, displayId);
return this;
}
/**
* Adds or removes the flag SKIP_SCREENSHOT of the surface. Setting the flag is equivalent
* to creating the Surface with the {@link #SKIP_SCREENSHOT} flag.

View File

@@ -1833,6 +1833,15 @@ static jlong nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) {
return reinterpret_cast<jlong>(surfaceControl->getHandle().get());
}
static void nativeRemoveCurrentInputFocus(JNIEnv* env, jclass clazz, jlong transactionObj,
jint displayId) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
FocusRequest request;
request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
request.displayId = displayId;
transaction->setFocusedWindow(request);
}
static void nativeSetFocusedWindow(JNIEnv* env, jclass clazz, jlong transactionObj,
jobject toTokenObj, jstring windowNameJstr,
jobject focusedTokenObj, jstring focusedWindowNameJstr,
@@ -2167,6 +2176,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetFixedTransformHint},
{"nativeSetFocusedWindow", "(JLandroid/os/IBinder;Ljava/lang/String;Landroid/os/IBinder;Ljava/lang/String;I)V",
(void*)nativeSetFocusedWindow},
{"nativeRemoveCurrentInputFocus", "(JI)V",
(void*)nativeRemoveCurrentInputFocus},
{"nativeSetFrameTimelineVsync", "(JJ)V",
(void*)nativeSetFrameTimelineVsync },
{"nativeAddJankDataListener", "(JJ)V",

View File

@@ -3793,6 +3793,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/NonAppWindowAnimationAdapter.java"
},
"2001473656": {
"message": "App %s is focused, but the window is not ready. Start a transaction to remove focus from the window of non-focused apps.",
"level": "VERBOSE",
"group": "WM_DEBUG_FOCUS_LIGHT",
"at": "com\/android\/server\/wm\/InputMonitor.java"
},
"2018454757": {
"message": "WS.removeImmediately: %s Already removed...",
"level": "VERBOSE",

View File

@@ -414,6 +414,17 @@ final class InputMonitor {
final IBinder focusToken = focus != null ? focus.mInputChannelToken : null;
if (focusToken == null) {
mInputFocus = null;
// When an app is focused, but its window is not showing yet, remove the input focus
// from the current window.
if (mDisplayContent.mFocusedApp != null) {
ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "App %s is focused,"
+ " but the window is not ready. Start a transaction to remove focus from"
+ " the window of non-focused apps.",
mDisplayContent.mFocusedApp.getName());
EventLog.writeEvent(LOGTAG_INPUT_FOCUS, "Requesting to set focus to null window",
"reason=UpdateInputWindows");
mInputTransaction.removeCurrentInputFocus(mDisplayId);
}
return;
}