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, private static native void nativeSetFixedTransformHint(long transactionObj, long nativeObject,
int transformHint); int transformHint);
private static native void nativeRemoveCurrentInputFocus(long nativeObject, int displayId);
private static native void nativeSetFocusedWindow(long transactionObj, IBinder toToken, private static native void nativeSetFocusedWindow(long transactionObj, IBinder toToken,
String windowName, IBinder focusedToken, String focusedWindowName, int displayId); String windowName, IBinder focusedToken, String focusedWindowName, int displayId);
private static native void nativeSetFrameTimelineVsync(long transactionObj, private static native void nativeSetFrameTimelineVsync(long transactionObj,
@@ -3652,6 +3653,17 @@ public final class SurfaceControl implements Parcelable {
return this; 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 * 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. * 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()); 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, static void nativeSetFocusedWindow(JNIEnv* env, jclass clazz, jlong transactionObj,
jobject toTokenObj, jstring windowNameJstr, jobject toTokenObj, jstring windowNameJstr,
jobject focusedTokenObj, jstring focusedWindowNameJstr, jobject focusedTokenObj, jstring focusedWindowNameJstr,
@@ -2167,6 +2176,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetFixedTransformHint}, (void*)nativeSetFixedTransformHint},
{"nativeSetFocusedWindow", "(JLandroid/os/IBinder;Ljava/lang/String;Landroid/os/IBinder;Ljava/lang/String;I)V", {"nativeSetFocusedWindow", "(JLandroid/os/IBinder;Ljava/lang/String;Landroid/os/IBinder;Ljava/lang/String;I)V",
(void*)nativeSetFocusedWindow}, (void*)nativeSetFocusedWindow},
{"nativeRemoveCurrentInputFocus", "(JI)V",
(void*)nativeRemoveCurrentInputFocus},
{"nativeSetFrameTimelineVsync", "(JJ)V", {"nativeSetFrameTimelineVsync", "(JJ)V",
(void*)nativeSetFrameTimelineVsync }, (void*)nativeSetFrameTimelineVsync },
{"nativeAddJankDataListener", "(JJ)V", {"nativeAddJankDataListener", "(JJ)V",

View File

@@ -3793,6 +3793,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS", "group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/NonAppWindowAnimationAdapter.java" "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": { "2018454757": {
"message": "WS.removeImmediately: %s Already removed...", "message": "WS.removeImmediately: %s Already removed...",
"level": "VERBOSE", "level": "VERBOSE",

View File

@@ -414,6 +414,17 @@ final class InputMonitor {
final IBinder focusToken = focus != null ? focus.mInputChannelToken : null; final IBinder focusToken = focus != null ? focus.mInputChannelToken : null;
if (focusToken == null) { if (focusToken == null) {
mInputFocus = 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; return;
} }