-
Notifications
You must be signed in to change notification settings - Fork 43
android ANR
- 由一个问题,引起对ANR相关code的学习。 对ANR形成一个全面的认识。
- 由于xx问题想改平台ANR的时间实验, 但在哪里改呢? 于是吭哧吭哧走起。。。
- appNotResponding
housy@housy-desktop:~/android-4.3.1-r2/frameworks/base$ ack appNotResponding core/java/android/app/IActivityController.aidl 60: int appNotResponding(String processName, int pid, String processStats);
cmds/am/src/com/android/commands/am/Am.java 961: public int appNotResponding(String processName, int pid, String processStats)
services/java/com/android/server/am/ActivityRecord.java 888: service.appNotResponding(anrApp, r, this, false, "keyDispatchingTimedOut");
services/java/com/android/server/am/ActivityManagerService.java 3251: final void appNotResponding(ProcessRecord app, ActivityRecord activity, 3359: int res = mController.appNotResponding(app.processName, app.pid, info.toString()); 7388: appNotResponding(proc, null, null, aboveSystem, "keyDispatchingTimedOut");
services/java/com/android/server/am/ActiveServices.java 1856: mAm.appNotResponding(proc, null, null, false, anrMessage);
services/java/com/android/server/am/BroadcastQueue.java 161: mService.appNotResponding(mApp, null, null, false, mAnnotation);
* http://stackoverflow.com/questions/17613709/application-not-responding-aosp
// Default input dispatching timeout if there is no focused application or paused window // from which to determine an appropriate dispatching timeout. const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
* http://blog.csdn.net/itachi85/article/details/6918761
// How long we wait until we timeout on key dispatching.
static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
* http://blog.csdn.net/ameyume/article/details/7038265
// How long we allow a receiver to run before giving up on it.
static final int BROADCAST_TIMEOUT = 10*1000;
// How long we wait until we timeout on key dispatching.
static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
* ANR分析和实例 http://blog.csdn.net/duzc309/article/details/9363465
# 初步分析-1 (基于android-4.3.1-r2)
1. appNotResponding of ActivityManagerService, 这个函数调用时代表ANR已经发生,这个函数主要作了:输出Log,dump trace,发消息给主线程弹ANR对话框。
1. appNotResponding的可见性是包级的,那谁调用的他? 查找结果如下:
* ActiveServices.java, serviceTimeout [包级可见]
* BroadcastQueue.java, broadcastTimeoutLocked [包级可见]
* ActivityManagerService.java, inputDispatchingTimedOut [public]
* ActivityRecord.java, keyDispatchingTimedOut [public]
# 初步分析-2 (基于初步分析-1中的结论)
### ActiveServices.java, serviceTimeout [包级可见]
-
在执行service生命周期相关函数时调用并发送延迟消息, bumpServiceExecutingLocked ->mAm.mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
-
service相关函数调用结束调用并remove消息, serviceDoneExecutingLocked ->mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
-
若调用timeout了,则ActivityManagerService收到消息并调用ActiveServices的serviceTimeout, 最终调到appNotResponding
-
bumpServiceExecutingLocked,serviceDoneExecutingLocked粗粗看了下, 应该是和生命函数开始结束相关的,留作TODO吧
1. 开始处理广播 scheduleBroadcastsLocked->processNextBroadcast//BROADCAST_INTENT_MSG
2. 设置timeout processNextBroadcast->setBroadcastTimeoutLocked
->mHandler.sendMessageAtTime(msg, timeoutTime);
->broadcastTimeoutLocked(true);
3. 取消timeout processNextBroadcast->cancelBroadcastTimeoutLocked->mHandler.removeMessages(BROADCAST_TIMEOUT_MSG, this);
4. timeout broadcastTimeoutLocked->mHandler.post(new AppNotResponding(app, anrMessage));
//AppNotResponding会掉用mService.appNotResponding(mApp, null, null, false, mAnnotation);
5. processNextBroadcast->broadcastTimeoutLocked(false);// forcibly finish this broadcast,
//if now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers),
//从comment看应该是个special case
- for more info, see http://blog.csdn.net/hehui1860/article/details/30727537 or http://blog.csdn.net/luoshengyang/article/details/6744448
1. InputDispatcher.cpp, handleTargetsNotReadyLocked中mInputTargetWaitTimeoutTime的取值详见代码
nsecs_t timeout;
if (windowHandle != NULL) {
timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
} else if (applicationHandle != NULL) {
timeout = applicationHandle->getDispatchingTimeout(
DEFAULT_INPUT_DISPATCHING_TIMEOUT);
} else {
timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
}
mInputTargetWaitTimeoutTime = currentTime + timeout;
上面涉及的getDispatchingTimeout函数见本文最后 附录1 getDispatchingTimeout。
2. InputDispatcher.cpp, handleTargetsNotReadyLocked->onANRLocked// if currentTime >= mInputTargetWaitTimeoutTime
3. InputDispatcher.cpp, onANRLocked->doNotifyANRLockedInterruptible
4. InputDispatcher.cpp, doNotifyANRLockedInterruptible->nsecs_t newTimeout = mPolicy->notifyANR
//mPolicy->notifyANR就是com_android_server_input_InputManagerService.cpp, notifyANR
5. com_android_server_input_InputManagerService.cpp, notifyANR-> env->CallLongMethod(mServiceObj,
gServiceClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj);
//本步骤完成从native callback to java layer
6. InputManagerService.java, notifyANR->mWindowManagerCallbacks.notifyANR(inputApplicationHandle, inputWindowHandle);
//InputManagerService.java, notifyANR是一个native callback
7. InputMonitor, notifyANR->ActivityManagerNative.getDefault().inputDispatchingTimedOut(
windowState.mSession.mPid, aboveSystem); // TODO: Unify this code with ActivityRecord.keyDispatchingTimedOut().
1. InputMonitor, notifyANR->appWindowToken.appToken.keyDispatchingTimedOut();
2. ActivityRecord的内部类static class Token extends IApplicationToken.Stub,
keyDispatchingTimedOut->activity.keyDispatchingTimedOut();
3. NOTE 1, 难怪有这样一个comment, // TODO: Unify this code with ActivityRecord.keyDispatchingTimedOut().
NOTE 2, 步骤1之前的流程同上一节 ActivityManagerService.java, inputDispatchingTimedOut [public]
- 检测timeout可以在action前发送一个延迟消息,action按时处理完后则remove该消息,否则延迟的消息被收到视为timeout
- appNotResponding of ActivityManagerService 是处理ANR弹框的地方
- ANR有三种, service,broadcast 和 input dispatch
- service ANR发生在相关的生命周期函数中,timeout值在ActiveServices.java
// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20*1000;
* broadcast timeout的值在 ActivityManagerService.java
// How long we allow a receiver to run before giving up on it
static final int BROADCAST_FG_TIMEOUT = 101000;
static final int BROADCAST_BG_TIMEOUT = 601000;
used in http://androidxref.com/4.3_r2.1/xref/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java#1634
1634 mFgBroadcastQueue = new BroadcastQueue(this, "foreground", BROADCAST_FG_TIMEOUT);
1635 mBgBroadcastQueue = new BroadcastQueue(this, "background", BROADCAST_BG_TIMEOUT);
* keyDispatchingTimedOut 的可能的取值范围是[附录1 可以进一步验证]
-
InputDispatcher.cpp 65// Default input dispatching timeout if there is no focused application or paused window 66// from which to determine an appropriate dispatching timeout. 67const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
-
ActivityManagerService.java
256 // How long we wait until we timeout on key dispatching. 257 static final int KEY_DISPATCHING_TIMEOUT = 5*1000;
259 // How long we wait until we timeout on key dispatching during instrumentation. 260 static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT = 60*1000; //这个是小黑 一看就不像 有木有
- WindowManagerService.java // Default input dispatching timeout in nanoseconds. static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
# 扩展
* 如何分析ANR问题
* input manager, activity mangager, window manager,找度娘和谷歌+http://androidxref.com ,android发展到现在相信有很多人在分析
# 附录1 getDispatchingTimeout
getDispatchingTimeout xref: /frameworks/base/services/input/InputApplication.h inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const { 54 return mInfo ? mInfo->dispatchingTimeout : defaultValue; 55 }
xref: /frameworks/base/services/input/InputWindow.h
175 inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const {
176 return mInfo ? mInfo->dispatchingTimeout : defaultValue;
177 }
178
前两者归结为一个关键字1 dispatchingTimeout H A D com_android_server_input_InputApplicationHandle.cpp 75 mInfo->dispatchingTimeout = env->GetLongField(obj, gInputApplicationHandleClassInfo.dispatchingTimeoutNanos); int register_android_server_InputApplicationHandle(JNIEnv* env) { 138 int res = jniRegisterNativeMethods(env, "com/android/server/input/InputApplicationHandle", 139 gInputApplicationHandleMethods, NELEM(gInputApplicationHandleMethods)); 140 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 141 142 jclass clazz; 143 FIND_CLASS(clazz, "com/android/server/input/InputApplicationHandle"); 144 145 GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, clazz, 146 "ptr", "I"); 147 148 GET_FIELD_ID(gInputApplicationHandleClassInfo.name, clazz, 149 "name", "Ljava/lang/String;"); 150 151 GET_FIELD_ID(gInputApplicationHandleClassInfo.dispatchingTimeoutNanos, 152 clazz, 153 "dispatchingTimeoutNanos", "J"); 154 155 return 0; 156}
InputApplicationHandle.java, dispatchingTimeoutNanos
H A D com_android_server_input_InputWindowHandle.cpp 114 mInfo->dispatchingTimeout = env->GetLongField(obj,
int register_android_server_InputWindowHandle(JNIEnv* env) {
224 int res = jniRegisterNativeMethods(env, "com/android/server/input/InputWindowHandle",
225 gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods));
226 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
227
228 jclass clazz;
229 FIND_CLASS(clazz, "com/android/server/input/InputWindowHandle");
230
231 GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, clazz,
232 "ptr", "I");
233
234 GET_FIELD_ID(gInputWindowHandleClassInfo.inputApplicationHandle,
235 clazz,
236 "inputApplicationHandle", "Lcom/android/server/input/InputApplicationHandle;");
237
238 GET_FIELD_ID(gInputWindowHandleClassInfo.inputChannel, clazz,
239 "inputChannel", "Landroid/view/InputChannel;");
240
241 GET_FIELD_ID(gInputWindowHandleClassInfo.name, clazz,
242 "name", "Ljava/lang/String;");
243
244 GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsFlags, clazz,
245 "layoutParamsFlags", "I");
246
247 GET_FIELD_ID(gInputWindowHandleClassInfo.layoutParamsType, clazz,
248 "layoutParamsType", "I");
249
250 GET_FIELD_ID(gInputWindowHandleClassInfo.dispatchingTimeoutNanos, clazz,
251 "dispatchingTimeoutNanos", "J");
InputWindowHandle.java dispatchingTimeoutNanos
前两者归结为一个关键字2 dispatchingTimeoutNanos H A D FakeWindowImpl.java 57 mApplicationHandle.dispatchingTimeoutNanos = WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; 67 mWindowHandle.dispatchingTimeoutNanos = WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; H A D DragState.java 109 mDragApplicationHandle.dispatchingTimeoutNanos = WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS 119 mDragWindowHandle.dispatchingTimeoutNanos = WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
WindowManagerService.java
// Default input dispatching timeout in nanoseconds.
static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
!!! [this is DONE] !!!
H A D InputMonitor.java 170 inputWindowHandle.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
H A D WindowState.java 685 public long getInputDispatchingTimeoutNanos() { method in class:WindowState
public long getInputDispatchingTimeoutNanos() {
return mAppToken != null
? mAppToken.inputDispatchingTimeoutNanos
: WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
}
!!! [this is DONE] !!!
403 handle.dispatchingTimeoutNanos = newApp.inputDispatchingTimeoutNanos;
H A D WindowManagerService.java 3332 long inputDispatchingTimeoutNanos;
3334 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
3337 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
3347 atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
WindowManagerService.java
// Default input dispatching timeout in nanoseconds.
static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
!!! [this is DONE] !!!
getKeyDispatchingTimeout
H A D ActivityRecord.java 301 @Override public long getKeyDispatchingTimeout() throws RemoteException { method in class:ActivityRecord.Token
304 return activity.getKeyDispatchingTimeout();
880 public long getKeyDispatchingTimeout() { method in class:ActivityRecord
/** Returns the key dispatching timeout for this application token. */
public long getKeyDispatchingTimeout() {
synchronized(service) {
ActivityRecord r = getWaitingHistoryRecordLocked();
if (r != null && r.app != null
&& (r.app.instrumentationClass != null || r.app.usingWrapper)) {
return ActivityManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT;
}
return ActivityManagerService.KEY_DISPATCHING_TIMEOUT;
}
}
!!! [this is DONE] !!!
Just build something.