Merge "Support ANRs from windows that are not tracked by WM" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
1c11a5dfe6
@@ -144,6 +144,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
/*
|
||||
* Wraps the C++ InputManager and provides its callbacks.
|
||||
@@ -2915,48 +2916,17 @@ public class InputManagerService extends IInputManager.Stub
|
||||
|
||||
// Native callback
|
||||
@SuppressWarnings("unused")
|
||||
private void notifyWindowUnresponsive(IBinder token, String reason) {
|
||||
int gestureMonitorPid = -1;
|
||||
synchronized (mInputMonitors) {
|
||||
final GestureMonitorSpyWindow gestureMonitor = mInputMonitors.get(token);
|
||||
if (gestureMonitor != null) {
|
||||
gestureMonitorPid = gestureMonitor.mWindowHandle.ownerPid;
|
||||
}
|
||||
}
|
||||
if (gestureMonitorPid != -1) {
|
||||
mWindowManagerCallbacks.notifyGestureMonitorUnresponsive(gestureMonitorPid, reason);
|
||||
return;
|
||||
}
|
||||
mWindowManagerCallbacks.notifyWindowUnresponsive(token, reason);
|
||||
private void notifyWindowUnresponsive(IBinder token, int pid, boolean isPidValid,
|
||||
String reason) {
|
||||
mWindowManagerCallbacks.notifyWindowUnresponsive(token,
|
||||
isPidValid ? OptionalInt.of(pid) : OptionalInt.empty(), reason);
|
||||
}
|
||||
|
||||
// Native callback
|
||||
@SuppressWarnings("unused")
|
||||
private void notifyMonitorUnresponsive(int pid, String reason) {
|
||||
mWindowManagerCallbacks.notifyGestureMonitorUnresponsive(pid, reason);
|
||||
}
|
||||
|
||||
// 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);
|
||||
private void notifyWindowResponsive(IBinder token, int pid, boolean isPidValid) {
|
||||
mWindowManagerCallbacks.notifyWindowResponsive(token,
|
||||
isPidValid ? OptionalInt.of(pid) : OptionalInt.empty());
|
||||
}
|
||||
|
||||
// Native callback.
|
||||
@@ -3328,35 +3298,23 @@ public class InputManagerService extends IInputManager.Stub
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
void notifyWindowUnresponsive(@NonNull IBinder token, @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);
|
||||
void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid,
|
||||
@NonNull String reason);
|
||||
|
||||
/**
|
||||
* 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 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
|
||||
|
||||
@@ -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.WindowManagerDebugConfig.TAG_WM;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
@@ -35,6 +36,7 @@ import com.android.server.criticalevents.CriticalEventLog;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -75,7 +77,33 @@ class AnrController {
|
||||
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();
|
||||
final int pid;
|
||||
final boolean aboveSystem;
|
||||
@@ -83,10 +111,8 @@ class AnrController {
|
||||
synchronized (mService.mGlobalLock) {
|
||||
InputTarget target = mService.getInputTargetFromToken(inputToken);
|
||||
if (target == null) {
|
||||
Slog.e(TAG_WM, "Unknown token, dropping notifyConnectionUnresponsive request");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
WindowState windowState = target.getWindowState();
|
||||
pid = target.getPid();
|
||||
// Blame the activity if the input token belongs to the window. If the target is
|
||||
@@ -102,34 +128,63 @@ class AnrController {
|
||||
} else {
|
||||
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;
|
||||
synchronized (mService.mGlobalLock) {
|
||||
InputTarget target = mService.getInputTargetFromToken(inputToken);
|
||||
if (target == null) {
|
||||
Slog.e(TAG_WM, "Unknown token, dropping notifyWindowConnectionResponsive request");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
pid = target.getPid();
|
||||
}
|
||||
mService.mAmInternal.inputDispatchingResumed(pid);
|
||||
return true;
|
||||
}
|
||||
|
||||
void notifyGestureMonitorUnresponsive(int gestureMonitorPid, String reason) {
|
||||
preDumpIfLockTooSlow();
|
||||
synchronized (mService.mGlobalLock) {
|
||||
Slog.i(TAG_WM, "ANR in gesture monitor owned by pid:" + gestureMonitorPid
|
||||
+ ". Reason: " + reason);
|
||||
dumpAnrStateLocked(null /* activity */, null /* windowState */, reason);
|
||||
}
|
||||
mService.mAmInternal.inputDispatchingTimedOut(gestureMonitorPid, /* aboveSystem */ true,
|
||||
reason);
|
||||
}
|
||||
|
||||
void notifyGestureMonitorResponsive(int gestureMonitorPid) {
|
||||
mService.mAmInternal.inputDispatchingResumed(gestureMonitorPid);
|
||||
/**
|
||||
* Notify a window owned by the provided pid was responsive after previously being unresponsive.
|
||||
*/
|
||||
private void notifyWindowResponsive(int pid) {
|
||||
mService.mAmInternal.inputDispatchingResumed(pid);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,12 +283,7 @@ class AnrController {
|
||||
mService.mAtmService.saveANRState(reason);
|
||||
}
|
||||
|
||||
private boolean isWindowAboveSystem(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;
|
||||
}
|
||||
private boolean isWindowAboveSystem(@NonNull WindowState windowState) {
|
||||
int systemAlertLayer = mService.mPolicy.getWindowLayerFromTypeLw(
|
||||
TYPE_APPLICATION_OVERLAY, windowState.mOwnerCanAddInternalSystemWindow);
|
||||
return windowState.mBaseLayer > systemAlertLayer;
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.android.internal.util.function.pooled.PooledLambda;
|
||||
import com.android.server.input.InputManagerService;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
final class InputManagerCallback implements InputManagerService.WindowManagerCallbacks {
|
||||
private static final String TAG = TAG_WITH_CLASS_NAME ? "InputManagerCallback" : TAG_WM;
|
||||
@@ -98,23 +99,14 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyGestureMonitorUnresponsive(int pid, @NonNull String reason) {
|
||||
mService.mAnrController.notifyGestureMonitorUnresponsive(pid, reason);
|
||||
public void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid,
|
||||
@NonNull String reason) {
|
||||
mService.mAnrController.notifyWindowUnresponsive(token, pid, reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyWindowUnresponsive(@NonNull IBinder token, String reason) {
|
||||
mService.mAnrController.notifyWindowUnresponsive(token, reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyGestureMonitorResponsive(int pid) {
|
||||
mService.mAnrController.notifyGestureMonitorResponsive(pid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyWindowResponsive(@NonNull IBinder token) {
|
||||
mService.mAnrController.notifyWindowResponsive(token);
|
||||
public void notifyWindowResponsive(@NonNull IBinder token, @NonNull OptionalInt pid) {
|
||||
mService.mAnrController.notifyWindowResponsive(token, pid);
|
||||
}
|
||||
|
||||
/** Notifies that the input device configuration has changed. */
|
||||
|
||||
@@ -96,8 +96,6 @@ static struct {
|
||||
jmethodID notifyNoFocusedWindowAnr;
|
||||
jmethodID notifyWindowUnresponsive;
|
||||
jmethodID notifyWindowResponsive;
|
||||
jmethodID notifyMonitorUnresponsive;
|
||||
jmethodID notifyMonitorResponsive;
|
||||
jmethodID notifyFocusChanged;
|
||||
jmethodID notifySensorEvent;
|
||||
jmethodID notifySensorAccuracy;
|
||||
@@ -308,10 +306,9 @@ public:
|
||||
void notifyConfigurationChanged(nsecs_t when) override;
|
||||
// ANR-related callbacks -- start
|
||||
void notifyNoFocusedWindowAnr(const std::shared_ptr<InputApplicationHandle>& handle) override;
|
||||
void notifyWindowUnresponsive(const sp<IBinder>& token, const std::string& reason) override;
|
||||
void notifyWindowResponsive(const sp<IBinder>& token) override;
|
||||
void notifyMonitorUnresponsive(int32_t pid, const std::string& reason) override;
|
||||
void notifyMonitorResponsive(int32_t pid) override;
|
||||
void notifyWindowUnresponsive(const sp<IBinder>& token, std::optional<int32_t> pid,
|
||||
const std::string& reason) override;
|
||||
void notifyWindowResponsive(const sp<IBinder>& token, std::optional<int32_t> pid) override;
|
||||
// ANR-related callbacks -- end
|
||||
void notifyInputChannelBroken(const sp<IBinder>& token) 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,
|
||||
std::optional<int32_t> pid,
|
||||
const std::string& reason) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
ALOGD("notifyWindowUnresponsive");
|
||||
@@ -851,11 +849,12 @@ void NativeInputManager::notifyWindowUnresponsive(const sp<IBinder>& token,
|
||||
ScopedLocalRef<jstring> reasonObj(env, env->NewStringUTF(reason.c_str()));
|
||||
|
||||
env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyWindowUnresponsive, tokenObj,
|
||||
reasonObj.get());
|
||||
pid.value_or(0), pid.has_value(), reasonObj.get());
|
||||
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
|
||||
ALOGD("notifyWindowResponsive");
|
||||
#endif
|
||||
@@ -866,39 +865,11 @@ void NativeInputManager::notifyWindowResponsive(const sp<IBinder>& 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");
|
||||
}
|
||||
|
||||
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) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
ALOGD("notifyInputChannelBroken");
|
||||
@@ -2506,16 +2477,10 @@ int register_android_server_InputManager(JNIEnv* env) {
|
||||
"(Landroid/view/InputApplicationHandle;)V");
|
||||
|
||||
GET_METHOD_ID(gServiceClassInfo.notifyWindowUnresponsive, clazz, "notifyWindowUnresponsive",
|
||||
"(Landroid/os/IBinder;Ljava/lang/String;)V");
|
||||
|
||||
GET_METHOD_ID(gServiceClassInfo.notifyMonitorUnresponsive, clazz, "notifyMonitorUnresponsive",
|
||||
"(ILjava/lang/String;)V");
|
||||
"(Landroid/os/IBinder;IZLjava/lang/String;)V");
|
||||
|
||||
GET_METHOD_ID(gServiceClassInfo.notifyWindowResponsive, clazz, "notifyWindowResponsive",
|
||||
"(Landroid/os/IBinder;)V");
|
||||
|
||||
GET_METHOD_ID(gServiceClassInfo.notifyMonitorResponsive, clazz, "notifyMonitorResponsive",
|
||||
"(I)V");
|
||||
"(Landroid/os/IBinder;IZ)V");
|
||||
|
||||
GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
|
||||
"filterInputEvent", "(Landroid/view/InputEvent;I)Z");
|
||||
|
||||
Reference in New Issue
Block a user