前言:我们经常分析ANR log,但是它是如何生成到本地的,系统又如何知道发生了ANR并且将相关log收集起来的。那就看接下来吧!
1,Android系统处理input事件的是inputFlinger,每次处理input 事件的时候,要执行到native的一个方法:
1.1 判断focusedWindowHandle == nullptr and focusedApplicationHandle != nullptr 时,执行handleTargetsNotReadyLocked()方法
int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
const EventEntry* entry, std::vector& inputTargets,
nsecs_t* nextWakeupTime) {
// If there is no currently focused window and no focused application
// then drop the event.
//当前没有焦点窗口and没有焦点应用,执行handleTargetsNotReadyLocked
if (focusedWindowHandle == nullptr) {
if (focusedApplicationHandle != nullptr) {
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
focusedApplicationHandle, nullptr, nextWakeupTime,
"Waiting because no window has focus but there is a "
"focused application that may eventually add a window "
"when it finishes starting up.");
goto Unresponsive;
}
}
}1.2 handleTargetsNotReadyLocked() : 超过5s没有响应,就调用onANRLocked(),开始anr的逻辑
int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,const
EventEntry* entry,
const sp& applicationHandle,
const sp& windowHandle,
nsecs_t* nextWakeupTime, const char* reason) {
//currentTime >= mInputTargetWaitTimeoutTime 大致意思是超过5s没响应,
//则执行触发anr的逻辑onANRLocked
if (currentTime >= mInputTargetWaitTimeoutTime) {
onANRLocked(currentTime, applicationHandle, windowHandle,
entry->eventTime, mInputTargetWaitStartTime, reason);
}
}1.3 onANRLocked():这个方法内会收集Application is not responding.....,Window,Reason等的信息,然后通过调用InputDispatcher::doNotifyANRLockedInterruptible,去notify ANR
void InputDispatcher::onANRLocked(nsecs_t currentTime, const sp& applicationHandle,
const sp& windowHandle,
nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) {
ALOGI("Application is not responding: %s. "
"It has been %0.1fms since event, %0.1fms since wait started. Reason: %s",
getApplicationWindowLabel(applicationHandle, windowHandle).c_str(),
dispatchLatency, waitDuration, reason);
mLastANRState += INDENT "ANR:\n";
mLastANRState += StringPrintf(INDENT2 "Time: %s\n", timestr);
mLastANRState += StringPrintf(INDENT2 "Window: %s\n",
getApplicationWindowLabel(applicationHandle, windowHandle).c_str());
mLastANRState += StringPrintf(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency);
mLastANRState += StringPrintf(INDENT2 "WaitDuration: %0.1fms\n", waitDuration);
mLastANRState += StringPrintf(INDENT2 "Reason: %s\n", reason);
//这个方法会打印类似DispatchEnabled....这类的log,很重要的方法
dumpDispatchStateLocked(mLastANRState);
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doNotifyANRLockedInterruptible);
}Application is not responding.....这句log,相信看过ANR log的同学应该很熟悉,继续往下看
1.4 上面的代码会通过postCommandLocked(........doNotifyANRLockedInterruptible),执行doNotifyANRLockedInterruptible()方法 通过调用 mPolicy->notifyANR,真正的去notify anr
void InputDispatcher::doNotifyANRLockedInterruptible(
CommandEntry* commandEntry) {
nsecs_t newTimeout = mPolicy->notifyANR(
commandEntry->inputApplicationHandle,
commandEntry->inputChannel ? commandEntry->inputChannel->getToken() : nullptr,
commandEntry->reason)
} 1.5 notifyANR():通过jni调用java端的方法,即调用了java端的notifyANR()方法
参数:mServiceObj: 是指InputManagerService.java 参考1.5.1
nsecs_t NativeInputManager::notifyANR(const sp& inputApplicationHandle,
const sp& token, const std::string& reason) {
JNIEnv* env = jniEnv();
jlong newTimeout = env->CallLongMethod(mServiceObj,
gServiceClassInfo.notifyANR, tokenObj,reasonObj);
}1.5.1
1,mServiceObj,是通过传入的serviceObj参数赋值的,继续查看NativeInputManager
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp& looper) :
mLooper(looper), mInteractive(true) {
mServiceObj = env->NewGlobalRef(serviceObj);
}
2,NativeInputManager,是在nativeInit中初始化的,参数也是从nativeInit中传入的,
该方法是在java端调用的
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
}
3,通过java端的方法可以看出,serviceObj = this = InputManagerService.java
public InputManagerService(Context context) {
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
} 1.5.2 gServiceClassInfo.notifyANR:jmethodID = notifyANR
static struct {
jclass clazz;
jmethodID notifyANR;
} gServiceClassInfo;接下来,我们就要看看java端的notifyANR()方法了,详情请看下一篇