Android Service启动ANR原理

一、前言

    在Service组件StartService()方式启动流程分析文章中,针对Context#startService()启动Service流程分析了源码,其实关于Service启动还有一个比较重要的点是Service启动的ANR,因为因为线上出现了上百例的"executing service " + service.shortName的异常。

二、Service-ANR原理

2.1 Service启动ANR原理简述

    Service的ANR触发原理,是在启动Service前使用Handler发送一个延时的Message(埋炸弹过程),然后在Service启动完成后remove掉这个Message(拆炸弹过程)。如果在指定的延迟时间内没有remove掉这个Message,那么就会触发ANR(没有在炸弹爆炸前拆掉就会爆炸),弹出AppNotResponding的弹窗。
Android Service启动ANR原理_第1张图片
    其实这个机制跟Windows/MacOS的应用程序无响应,是类似的交互设计。
Android Service启动ANR原理_第2张图片
Android Service启动ANR原理_第3张图片

2.2 Service启动ANR源码执行过程

    ps: 还是基于Android SDK28源码分析
    基于文章:Service组件StartService()方式启动流程分析的总结,我们已经很清楚,通过startService的方式启动Service的源码过程。因此,本文直接从com.android.server.am.ActiveServices#bringUpServiceLocked方法的源码开始分析,如有不清楚前置的启动流程的同学,可以参考我之前的文章,然后打开AS对照看下这部分的代码。

2.2.1 ActiveServices#bringUpServiceLocked

    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
        realStartServiceLocked(r, app, execInFg);
    }

2.2.2 ActiveServices#realStartServiceLocked

private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
    // ...
    // 会转调到scheduleServiceTimeoutLocked(r.app)方法进行埋炸弹操作
	bumpServiceExecutingLocked(r, execInFg, "create");
	try {
	app.thread.scheduleCreateService(r, r.serviceInfo,
        mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
        app.repProcState);
    } catch (DeadObjectException e) {
    	mAm.appDiedLocked(app);
    	throw e;
    } finally {
        // serviceDoneExecutingLocked方法内会拆除炸弹
    	serviceDoneExecutingLocked(r, inDestroying, inDestroying);
    	// ...
    }
}

2.2.4 埋炸弹过程:ActiveServices#bumpServiceExecutingLocked

private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
	// ...
	scheduleServiceTimeoutLocked(r.app);
	// ...
}
  • com.android.server.am.ActiveServices#scheduleServiceTimeoutLocked
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
    if (proc.executingServices.size() == 0 || proc.thread == null) {
        return;
    }
    Message msg = mAm.mHandler.obtainMessage(
            ActivityManagerService.SERVICE_TIMEOUT_MSG);
    msg.obj = proc;
    mAm.mHandler.sendMessageDelayed(msg,
            proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
}

2.2.4 拆炸弹过程:ActiveServices#serviceDoneExecutingLocked

private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
        boolean finishing) {
    // ...
	mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app); 
	// ...       
}

你可能感兴趣的:(Android四大组件相关,Android,Framework,开发经验总结,android)