Merge "Support ANRs from windows that are not tracked by WM" into tm-dev am: 1c11a5dfe6

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17036645

Change-Id: Ifaa1af369f56c695467f7efedc33ddd2cf24e73e
This commit is contained in:
TreeHugger Robot
2022-03-01 19:20:51 +00:00
committed by Automerger Merge Worker
4 changed files with 106 additions and 141 deletions

View File

@@ -144,6 +144,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.OptionalInt;
/* /*
* Wraps the C++ InputManager and provides its callbacks. * Wraps the C++ InputManager and provides its callbacks.
@@ -2915,48 +2916,17 @@ public class InputManagerService extends IInputManager.Stub
// Native callback // Native callback
@SuppressWarnings("unused") @SuppressWarnings("unused")
private void notifyWindowUnresponsive(IBinder token, String reason) { private void notifyWindowUnresponsive(IBinder token, int pid, boolean isPidValid,
int gestureMonitorPid = -1; String reason) {
synchronized (mInputMonitors) { mWindowManagerCallbacks.notifyWindowUnresponsive(token,
final GestureMonitorSpyWindow gestureMonitor = mInputMonitors.get(token); isPidValid ? OptionalInt.of(pid) : OptionalInt.empty(), reason);
if (gestureMonitor != null) {
gestureMonitorPid = gestureMonitor.mWindowHandle.ownerPid;
}
}
if (gestureMonitorPid != -1) {
mWindowManagerCallbacks.notifyGestureMonitorUnresponsive(gestureMonitorPid, reason);
return;
}
mWindowManagerCallbacks.notifyWindowUnresponsive(token, reason);
} }
// Native callback // Native callback
@SuppressWarnings("unused") @SuppressWarnings("unused")
private void notifyMonitorUnresponsive(int pid, String reason) { private void notifyWindowResponsive(IBinder token, int pid, boolean isPidValid) {
mWindowManagerCallbacks.notifyGestureMonitorUnresponsive(pid, reason); mWindowManagerCallbacks.notifyWindowResponsive(token,
} isPidValid ? OptionalInt.of(pid) : OptionalInt.empty());
// Native callback
@SuppressWarnings("unused")
private void notifyWindowResponsive(IBinder token) {
int gestureMonitorPid = -1;
synchronized (mInputMonitors) {
final GestureMonitorSpyWindow gestureMonitor = mInputMonitors.get(token);
if (gestureMonitor != null) {
gestureMonitorPid = gestureMonitor.mWindowHandle.ownerPid;
}
}
if (gestureMonitorPid != -1) {
mWindowManagerCallbacks.notifyGestureMonitorResponsive(gestureMonitorPid);
return;
}
mWindowManagerCallbacks.notifyWindowResponsive(token);
}
// Native callback
@SuppressWarnings("unused")
private void notifyMonitorResponsive(int pid) {
mWindowManagerCallbacks.notifyGestureMonitorResponsive(pid);
} }
// Native callback. // Native callback.
@@ -3328,35 +3298,23 @@ public class InputManagerService extends IInputManager.Stub
*/ */
void notifyNoFocusedWindowAnr(InputApplicationHandle applicationHandle); void notifyNoFocusedWindowAnr(InputApplicationHandle applicationHandle);
/**
* Notify the window manager about a gesture monitor that is unresponsive.
*
* @param pid the pid of the gesture monitor process
* @param reason the reason why this connection is unresponsive
*/
void notifyGestureMonitorUnresponsive(int pid, @NonNull String reason);
/** /**
* Notify the window manager about a window that is unresponsive. * Notify the window manager about a window that is unresponsive.
* *
* @param token the token that can be used to look up the window * @param token the token that can be used to look up the window
* @param pid the pid of the window owner, if known
* @param reason the reason why this connection is unresponsive * @param reason the reason why this connection is unresponsive
*/ */
void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull String reason); void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid,
@NonNull String reason);
/**
* Notify the window manager about a gesture monitor that has become responsive.
*
* @param pid the pid of the gesture monitor process
*/
void notifyGestureMonitorResponsive(int pid);
/** /**
* Notify the window manager about a window that has become responsive. * Notify the window manager about a window that has become responsive.
* *
* @param token the token that can be used to look up the window * @param token the token that can be used to look up the window
* @param pid the pid of the window owner, if known
*/ */
void notifyWindowResponsive(@NonNull IBinder token); void notifyWindowResponsive(@NonNull IBinder token, @NonNull OptionalInt pid);
/** /**
* This callback is invoked when an event first arrives to InputDispatcher and before it is * This callback is invoked when an event first arrives to InputDispatcher and before it is

View File

@@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static com.android.server.wm.ActivityRecord.INVALID_PID; import static com.android.server.wm.ActivityRecord.INVALID_PID;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.annotation.NonNull;
import android.os.Build; import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.os.Process; import android.os.Process;
@@ -35,6 +36,7 @@ import com.android.server.criticalevents.CriticalEventLog;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.OptionalInt;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -75,7 +77,33 @@ class AnrController {
activity.inputDispatchingTimedOut(reason, INVALID_PID); activity.inputDispatchingTimedOut(reason, INVALID_PID);
} }
void notifyWindowUnresponsive(IBinder inputToken, String reason) {
/**
* Notify a window was unresponsive.
*
* @param token - the input token of the window
* @param pid - the pid of the window, if known
* @param reason - the reason for the window being unresponsive
*/
void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid,
@NonNull String reason) {
if (notifyWindowUnresponsive(token, reason)) {
return;
}
if (!pid.isPresent()) {
Slog.w(TAG_WM, "Failed to notify that window token=" + token + " was unresponsive.");
return;
}
notifyWindowUnresponsive(pid.getAsInt(), reason);
}
/**
* Notify a window identified by its input token was unresponsive.
*
* @return true if the window was identified by the given input token and the request was
* handled, false otherwise.
*/
private boolean notifyWindowUnresponsive(@NonNull IBinder inputToken, String reason) {
preDumpIfLockTooSlow(); preDumpIfLockTooSlow();
final int pid; final int pid;
final boolean aboveSystem; final boolean aboveSystem;
@@ -83,10 +111,8 @@ class AnrController {
synchronized (mService.mGlobalLock) { synchronized (mService.mGlobalLock) {
InputTarget target = mService.getInputTargetFromToken(inputToken); InputTarget target = mService.getInputTargetFromToken(inputToken);
if (target == null) { if (target == null) {
Slog.e(TAG_WM, "Unknown token, dropping notifyConnectionUnresponsive request"); return false;
return;
} }
WindowState windowState = target.getWindowState(); WindowState windowState = target.getWindowState();
pid = target.getPid(); pid = target.getPid();
// Blame the activity if the input token belongs to the window. If the target is // Blame the activity if the input token belongs to the window. If the target is
@@ -102,34 +128,63 @@ class AnrController {
} else { } else {
mService.mAmInternal.inputDispatchingTimedOut(pid, aboveSystem, reason); mService.mAmInternal.inputDispatchingTimedOut(pid, aboveSystem, reason);
} }
return true;
} }
void notifyWindowResponsive(IBinder inputToken) { /**
* Notify a window owned by the provided pid was unresponsive.
*/
private void notifyWindowUnresponsive(int pid, String reason) {
Slog.i(TAG_WM, "ANR in input window owned by pid=" + pid + ". Reason: " + reason);
dumpAnrStateLocked(null /* activity */, null /* windowState */, reason);
// We cannot determine the z-order of the window, so place the anr dialog as high
// as possible.
mService.mAmInternal.inputDispatchingTimedOut(pid, true /*aboveSystem*/, reason);
}
/**
* Notify a window was responsive after previously being unresponsive.
*
* @param token - the input token of the window
* @param pid - the pid of the window, if known
*/
void notifyWindowResponsive(@NonNull IBinder token, @NonNull OptionalInt pid) {
if (notifyWindowResponsive(token)) {
return;
}
if (!pid.isPresent()) {
Slog.w(TAG_WM, "Failed to notify that window token=" + token + " was responsive.");
return;
}
notifyWindowResponsive(pid.getAsInt());
}
/**
* Notify a window identified by its input token was responsive after previously being
* unresponsive.
*
* @return true if the window was identified by the given input token and the request was
* handled, false otherwise.
*/
private boolean notifyWindowResponsive(@NonNull IBinder inputToken) {
final int pid; final int pid;
synchronized (mService.mGlobalLock) { synchronized (mService.mGlobalLock) {
InputTarget target = mService.getInputTargetFromToken(inputToken); InputTarget target = mService.getInputTargetFromToken(inputToken);
if (target == null) { if (target == null) {
Slog.e(TAG_WM, "Unknown token, dropping notifyWindowConnectionResponsive request"); return false;
return;
} }
pid = target.getPid(); pid = target.getPid();
} }
mService.mAmInternal.inputDispatchingResumed(pid); mService.mAmInternal.inputDispatchingResumed(pid);
return true;
} }
void notifyGestureMonitorUnresponsive(int gestureMonitorPid, String reason) { /**
preDumpIfLockTooSlow(); * Notify a window owned by the provided pid was responsive after previously being unresponsive.
synchronized (mService.mGlobalLock) { */
Slog.i(TAG_WM, "ANR in gesture monitor owned by pid:" + gestureMonitorPid private void notifyWindowResponsive(int pid) {
+ ". Reason: " + reason); mService.mAmInternal.inputDispatchingResumed(pid);
dumpAnrStateLocked(null /* activity */, null /* windowState */, reason);
}
mService.mAmInternal.inputDispatchingTimedOut(gestureMonitorPid, /* aboveSystem */ true,
reason);
}
void notifyGestureMonitorResponsive(int gestureMonitorPid) {
mService.mAmInternal.inputDispatchingResumed(gestureMonitorPid);
} }
/** /**
@@ -228,12 +283,7 @@ class AnrController {
mService.mAtmService.saveANRState(reason); mService.mAtmService.saveANRState(reason);
} }
private boolean isWindowAboveSystem(WindowState windowState) { private boolean isWindowAboveSystem(@NonNull WindowState windowState) {
if (windowState == null) {
// If the window state is not available we cannot easily determine its z order. Try to
// place the anr dialog as high as possible.
return true;
}
int systemAlertLayer = mService.mPolicy.getWindowLayerFromTypeLw( int systemAlertLayer = mService.mPolicy.getWindowLayerFromTypeLw(
TYPE_APPLICATION_OVERLAY, windowState.mOwnerCanAddInternalSystemWindow); TYPE_APPLICATION_OVERLAY, windowState.mOwnerCanAddInternalSystemWindow);
return windowState.mBaseLayer > systemAlertLayer; return windowState.mBaseLayer > systemAlertLayer;

View File

@@ -39,6 +39,7 @@ import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.input.InputManagerService; import com.android.server.input.InputManagerService;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.OptionalInt;
final class InputManagerCallback implements InputManagerService.WindowManagerCallbacks { final class InputManagerCallback implements InputManagerService.WindowManagerCallbacks {
private static final String TAG = TAG_WITH_CLASS_NAME ? "InputManagerCallback" : TAG_WM; private static final String TAG = TAG_WITH_CLASS_NAME ? "InputManagerCallback" : TAG_WM;
@@ -98,23 +99,14 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
} }
@Override @Override
public void notifyGestureMonitorUnresponsive(int pid, @NonNull String reason) { public void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid,
mService.mAnrController.notifyGestureMonitorUnresponsive(pid, reason); @NonNull String reason) {
mService.mAnrController.notifyWindowUnresponsive(token, pid, reason);
} }
@Override @Override
public void notifyWindowUnresponsive(@NonNull IBinder token, String reason) { public void notifyWindowResponsive(@NonNull IBinder token, @NonNull OptionalInt pid) {
mService.mAnrController.notifyWindowUnresponsive(token, reason); mService.mAnrController.notifyWindowResponsive(token, pid);
}
@Override
public void notifyGestureMonitorResponsive(int pid) {
mService.mAnrController.notifyGestureMonitorResponsive(pid);
}
@Override
public void notifyWindowResponsive(@NonNull IBinder token) {
mService.mAnrController.notifyWindowResponsive(token);
} }
/** Notifies that the input device configuration has changed. */ /** Notifies that the input device configuration has changed. */

View File

@@ -96,8 +96,6 @@ static struct {
jmethodID notifyNoFocusedWindowAnr; jmethodID notifyNoFocusedWindowAnr;
jmethodID notifyWindowUnresponsive; jmethodID notifyWindowUnresponsive;
jmethodID notifyWindowResponsive; jmethodID notifyWindowResponsive;
jmethodID notifyMonitorUnresponsive;
jmethodID notifyMonitorResponsive;
jmethodID notifyFocusChanged; jmethodID notifyFocusChanged;
jmethodID notifySensorEvent; jmethodID notifySensorEvent;
jmethodID notifySensorAccuracy; jmethodID notifySensorAccuracy;
@@ -308,10 +306,9 @@ public:
void notifyConfigurationChanged(nsecs_t when) override; void notifyConfigurationChanged(nsecs_t when) override;
// ANR-related callbacks -- start // ANR-related callbacks -- start
void notifyNoFocusedWindowAnr(const std::shared_ptr<InputApplicationHandle>& handle) override; void notifyNoFocusedWindowAnr(const std::shared_ptr<InputApplicationHandle>& handle) override;
void notifyWindowUnresponsive(const sp<IBinder>& token, const std::string& reason) override; void notifyWindowUnresponsive(const sp<IBinder>& token, std::optional<int32_t> pid,
void notifyWindowResponsive(const sp<IBinder>& token) override; const std::string& reason) override;
void notifyMonitorUnresponsive(int32_t pid, const std::string& reason) override; void notifyWindowResponsive(const sp<IBinder>& token, std::optional<int32_t> pid) override;
void notifyMonitorResponsive(int32_t pid) override;
// ANR-related callbacks -- end // ANR-related callbacks -- end
void notifyInputChannelBroken(const sp<IBinder>& token) override; void notifyInputChannelBroken(const sp<IBinder>& token) override;
void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) override; void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) override;
@@ -838,6 +835,7 @@ void NativeInputManager::notifyNoFocusedWindowAnr(
} }
void NativeInputManager::notifyWindowUnresponsive(const sp<IBinder>& token, void NativeInputManager::notifyWindowUnresponsive(const sp<IBinder>& token,
std::optional<int32_t> pid,
const std::string& reason) { const std::string& reason) {
#if DEBUG_INPUT_DISPATCHER_POLICY #if DEBUG_INPUT_DISPATCHER_POLICY
ALOGD("notifyWindowUnresponsive"); ALOGD("notifyWindowUnresponsive");
@@ -851,11 +849,12 @@ void NativeInputManager::notifyWindowUnresponsive(const sp<IBinder>& token,
ScopedLocalRef<jstring> reasonObj(env, env->NewStringUTF(reason.c_str())); ScopedLocalRef<jstring> reasonObj(env, env->NewStringUTF(reason.c_str()));
env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyWindowUnresponsive, tokenObj, env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyWindowUnresponsive, tokenObj,
reasonObj.get()); pid.value_or(0), pid.has_value(), reasonObj.get());
checkAndClearExceptionFromCallback(env, "notifyWindowUnresponsive"); checkAndClearExceptionFromCallback(env, "notifyWindowUnresponsive");
} }
void NativeInputManager::notifyWindowResponsive(const sp<IBinder>& token) { void NativeInputManager::notifyWindowResponsive(const sp<IBinder>& token,
std::optional<int32_t> pid) {
#if DEBUG_INPUT_DISPATCHER_POLICY #if DEBUG_INPUT_DISPATCHER_POLICY
ALOGD("notifyWindowResponsive"); ALOGD("notifyWindowResponsive");
#endif #endif
@@ -866,39 +865,11 @@ void NativeInputManager::notifyWindowResponsive(const sp<IBinder>& token) {
jobject tokenObj = javaObjectForIBinder(env, token); jobject tokenObj = javaObjectForIBinder(env, token);
env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyWindowResponsive, tokenObj); env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyWindowResponsive, tokenObj,
pid.value_or(0), pid.has_value());
checkAndClearExceptionFromCallback(env, "notifyWindowResponsive"); checkAndClearExceptionFromCallback(env, "notifyWindowResponsive");
} }
void NativeInputManager::notifyMonitorUnresponsive(int32_t pid, const std::string& reason) {
#if DEBUG_INPUT_DISPATCHER_POLICY
ALOGD("notifyMonitorUnresponsive");
#endif
ATRACE_CALL();
JNIEnv* env = jniEnv();
ScopedLocalFrame localFrame(env);
ScopedLocalRef<jstring> reasonObj(env, env->NewStringUTF(reason.c_str()));
env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyMonitorUnresponsive, pid,
reasonObj.get());
checkAndClearExceptionFromCallback(env, "notifyMonitorUnresponsive");
}
void NativeInputManager::notifyMonitorResponsive(int32_t pid) {
#if DEBUG_INPUT_DISPATCHER_POLICY
ALOGD("notifyMonitorResponsive");
#endif
ATRACE_CALL();
JNIEnv* env = jniEnv();
ScopedLocalFrame localFrame(env);
env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyMonitorResponsive, pid);
checkAndClearExceptionFromCallback(env, "notifyMonitorResponsive");
}
void NativeInputManager::notifyInputChannelBroken(const sp<IBinder>& token) { void NativeInputManager::notifyInputChannelBroken(const sp<IBinder>& token) {
#if DEBUG_INPUT_DISPATCHER_POLICY #if DEBUG_INPUT_DISPATCHER_POLICY
ALOGD("notifyInputChannelBroken"); ALOGD("notifyInputChannelBroken");
@@ -2506,16 +2477,10 @@ int register_android_server_InputManager(JNIEnv* env) {
"(Landroid/view/InputApplicationHandle;)V"); "(Landroid/view/InputApplicationHandle;)V");
GET_METHOD_ID(gServiceClassInfo.notifyWindowUnresponsive, clazz, "notifyWindowUnresponsive", GET_METHOD_ID(gServiceClassInfo.notifyWindowUnresponsive, clazz, "notifyWindowUnresponsive",
"(Landroid/os/IBinder;Ljava/lang/String;)V"); "(Landroid/os/IBinder;IZLjava/lang/String;)V");
GET_METHOD_ID(gServiceClassInfo.notifyMonitorUnresponsive, clazz, "notifyMonitorUnresponsive",
"(ILjava/lang/String;)V");
GET_METHOD_ID(gServiceClassInfo.notifyWindowResponsive, clazz, "notifyWindowResponsive", GET_METHOD_ID(gServiceClassInfo.notifyWindowResponsive, clazz, "notifyWindowResponsive",
"(Landroid/os/IBinder;)V"); "(Landroid/os/IBinder;IZ)V");
GET_METHOD_ID(gServiceClassInfo.notifyMonitorResponsive, clazz, "notifyMonitorResponsive",
"(I)V");
GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz, GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
"filterInputEvent", "(Landroid/view/InputEvent;I)Z"); "filterInputEvent", "(Landroid/view/InputEvent;I)Z");