我是靠谱客的博主 不安钢铁侠,最近开发中收集的这篇文章主要介绍android ANR源码分析 --- 之一1, Service Timeout,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

概述:

ANR(ApplicationNot responding),是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间

能未能得到有效响应或者响应时间过长,都会造成ANR。一般地,这时往往会弹出一个提示框,告知用户当前xxx未响应,用户可选择

继续等待或者Force Close。

那么哪些场景会造成ANR呢?

1,Service Timeout:服务在20s内未执行完成;

2,BroadcastQueueTimeout:比如前台广播在10s内执行完成

3,ContentProviderTimeout:内容提供者执行超时

4,inputDispatchingTimeout: 输入事件分发超时5s,包括按键分发事件的超时。

1, Service Timeout

ServiceTimeout触发时机,简单说就是AMS中的mHandler收到SERVICE_TIMEOUT_MSG消息时触发。

在service启动时,最后会调用system_server进程中的ActiveServices的attachApplicationLocked方法,然后调用realStartServiceLocked方法完成服务的启动。

详细过程见http://blog.csdn.net/u012439416/article/details/77394649

整个过程主要分为3个部分:

1,在启动service之前发送SERVICE_TIMEOUT_MSG 消息;

2,如果service顺利启动,则删除SERVICE_TIMEOUT_MSG 消息;

3,如果SERVICE_TIMEOUT_MSG 未删除,时间到后就会发生ANR。

1.1 发送消息

ActiveServices的realStartServiceLocked方法在调用service的OnCreate方法之前就会发送消息,调用流程图如下,


realStartServiceLocked方法调用如下,

bumpServiceExecutingLocked(r, execInFg, "create");//发送消息
•••
app.thread.scheduleCreateService(r, r.serviceInfo,
  mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState);
//调用service的OnCreate方法

在bumpServiceExecutingLocked方法中回调用scheduleServiceTimeoutLocked方法发送SERVICE_TIMEOUT_MSG 消息。

scheduleServiceTimeoutLocked方法如下,

long now = SystemClock.uptimeMillis();
Message msg = mAm.mHandler.obtainMessage(ActivityManagerService.SERVICE_TIMEOUT_MSG);
msg.obj = proc;
mAm.mHandler.sendMessageAtTime(msg, proc.execServicesFg ? (now+SERVICE_TIMEOUT) : (now+ SERVICE_BACKGROUND_TIMEOUT));

首先获取系统的当前时间,然后利用AMS的mHandler变量构造SERVICE_TIMEOUT_MSG消息,最后调用AMS的mHandler变量的sendMessageAtTime方法发送消息。

SERVICE_TIMEOUT和SERVICE_BACKGROUND_TIMEOUT定义如下,

// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20*1000;
// How long we wait for a service to finish executing.
static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;

因此, 对于前台服务,则超时为SERVICE_TIMEOUT,即timeout=20s;

对于后台服务,则超时为SERVICE_BACKGROUND_TIMEOUT,即timeout=200s;

1.2 删除消息

在比较多的地方会删除消息,

比如,在realStartServiceLocked方法中

app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);

调用service的OnCreate方法时进程挂掉之后会调用serviceDoneExecutingLocked方法删除消息。

catch (DeadObjectException e) {
    Slog.w(TAG, "Application dead when creating service " + r);
    mAm.appDiedLocked(app);
    throw e;
} finally {
    if (!created) {
        // Keep the executeNesting count accurate.
        final boolean inDestroying = mDestroyingServices.contains(r);
        serviceDoneExecutingLocked(r, inDestroying, inDestroying);

或者在sendServiceArgsLocked方法中,启动service抛出异常也会调用serviceDoneExecutingLocked方法删除消息。

if (caughtException != null) {
    // Keep nesting count correct
    final boolean inDestroying = mDestroyingServices.contains(r);
    serviceDoneExecutingLocked(r, inDestroying, inDestroying);

app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);

此处会调用ActivityThread的内部类ApplicationThread的scheduleCreateService方法,最后会调用handleCreateService方法。

ActivityThread的handleCreateService方法主要逻辑如下,

1,加载service 对象,

LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
     java.lang.ClassLoader cl = packageInfo.getClassLoader();
     service = (Service) cl.loadClass(data.info.name).newInstance();

2,调用service的onCreate方法,

Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault());
service.onCreate();
mServices.put(data.token, service);

3,成功调用service的onCreate方法之后,跨进程调用AMS的serviceDoneExecuting方法删除消息。

try {
   ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);

AMS的serviceDoneExecuting方法如下,

mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);

直接调用ActiveServices的serviceDoneExecutingLocked方法.

由此可见,删除SERVICE_TIMEOUT_MSG 消息一般通过ActiveServices的serviceDoneExecutingLocked方法。

serviceDoneExecutingLocked方法逻辑如下,

if (r.app.executingServices.size() == 0) {
    if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
                            "No more executingServices of " + r.shortName);
mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);

如果当前服务所在进程中没有正在执行的service,就删除SERVICE_TIMEOUT_MSG消息。

1.3 处理消息

AMS中内部类MainHandler的handleMessage方法对SERVICE_TIMEOUT_MSG消息处理如下,

mServices.serviceTimeout((ProcessRecord)msg.obj);

调用ActiveServices的serviceTimeout方法进行处理,

serviceTimeout方法逻辑如下,

if (anrMessage != null) {
    mAm.appNotResponding(proc, null, null, false, anrMessage);
}

调用AMS的appNotResponding方法统一处理。处理过程后面详细论述。

其中, anrMessage 字符串为 executing service [发送超时serviceRecord信息]

最后

以上就是不安钢铁侠为你收集整理的android ANR源码分析 --- 之一1, Service Timeout的全部内容,希望文章能够帮你解决android ANR源码分析 --- 之一1, Service Timeout所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(58)

评论列表共有 0 条评论

立即
投稿
返回
顶部