You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

2.4 KiB

主线程为什么没有 ANR?
  1. 了解 ANR 的触发的原理
  2. 了解应用大致启动流程
  3. 了解线程的消息循环机制
  4. 了解应用和系统服务通信过程

ANR 是什么?

final void appNotResponding(ProcessRecord app, ...){
    Message msg = Message.obtain();
    msg.what = SHOW_NOT_RESPONDING_MSG;
    mUiHandler.sendMessage(msg);
}
// SystemService 进程
Dialog d = new AppNotRespondingDialog(...);
d.show();

ANR 场景有哪些?

  1. Service Timeout
  2. BroadcastQueue Timeout
  3. ContentProvider Timeout
  4. InputDispatching Timeout

以 Service 为例,看一下 ANR 是怎么触发的?

void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInfg){
	bumpServiceExecutingLocked(r, execInFg, "create");
    app.thread.scheduleCreateService(r, r.serviceInfo, ...);
}
void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why){
    scheduleServiceTimeoutLocked(r.app);
}
void scheduleServiceTimeoutLocked(ProcessRecord proc){
    long now = SystemClock.uptimeMillis();
    Message msg = mAm.mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
    mAm.mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
}
void serviceTimeout(ProcessRecord proc){
    mAm.appNotResponding(proc, ...);
}
// 应用端处理 Service 请求
private void handleCreateService(CreateServiceData data) {
    service = (Service)cl.loadClass(data.info.name).newInstance();
    ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
    Application app = packageInfo.makeApplication(false, mInstrumentation);
    service.attach(context, this, data.info.name, data.token, ...);
    service.onCreate();
    ActivityManagerNative.getDefault().serviceDoneExecuting(...);
}
private void serviceDoneExecutingLocked(ServiceRecord r, ...){
    mAm.mHandler.removeMessage(SERVICE_TIMEOUT_MSG, r.app);
}

往主线程发消息:

@Override
void scheduleLaunchActivity(Intent intent, IBinder token, ...){
    sendMessage(H.LAUNCH_ACTIVITY, r);
}
void scheduleCreateService(IBinder token, ...){
    sendMessage(H.CREATE_SERVICE, s);
}
void scheduleReceiver(Intent intent, ActivityInfo info, ...){
    sendMessage(H.RECEIVER, r);
}

总结

  1. ANR 是应用没有在规定的时间内完成 AMS 指定的任务导致的
  2. AMS 请求调用应用端 binder 线程,再丢消息去唤醒主线程来处理
  3. ANR 不是因为主线程 loop 循环,而是因为主线程有耗时任务