zoukankan      html  css  js  c++  java
  • Android源码分析启动Service服务超时ANR异常,到底多久会超时ANR看源代码一目了然

    • Android启动Service超时ANR异常源代码分析
    frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
    public final class ActiveServices {
       	...
        //其中Build.HW_TIMEOUT_MULTIPLIER一般为1
        // How long we wait for a service to finish executing.	--普通服务20秒
        static final int SERVICE_TIMEOUT = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
    
        // How long we wait for a service to finish executing.
        static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;
    
        // How long the startForegroundService() grace period is to get around to
        // calling startForeground() before we ANR + stop it.	--前台服务10秒
        static final int SERVICE_START_FOREGROUND_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
        ...
    
        //1.发送ActivityManagerService.SERVICE_TIMEOUT_MSG延迟消息,时间到之前如果该消息被移除了
        //就不会出现ANR,否则时间到了执行该消息,抛出ANR异常。ANR原理是这样滴。。。
        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);
        }
        
        //3.服务启动完成后调用该方法,移除SERVICE_TIMEOUT_MSG消息就不会触发ANR异常。
        private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
                boolean finishing) {
            ...
          	if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
                                "No more executingServices of " + r.shortInstanceName);
              mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
              ...
        }
        
        //4.服务启动超时处理,就是我们常见的ANR报错
        void serviceTimeout(ProcessRecord proc) {
            ...
            if (timeout != null && mAm.mProcessList.mLruProcesses.contains(proc)) {//超时了
                    Slog.w(TAG, "Timeout executing service: " + timeout);
                    StringWriter sw = new StringWriter();
                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
                    pw.println(timeout);
                    timeout.dump(pw, "    ");
                    pw.close();
                    mLastAnrDump = sw.toString();
                    mAm.mHandler.removeCallbacks(mLastAnrDumpClearer);
                    mAm.mHandler.postDelayed(mLastAnrDumpClearer, LAST_ANR_LIFETIME_DURATION_MSECS);
                    anrMessage = "executing service " + timeout.shortInstanceName;
                } else {//还没到时间,继续sendMessageAtTime消息
                    Message msg = mAm.mHandler.obtainMessage(
                            ActivityManagerService.SERVICE_TIMEOUT_MSG);
                    msg.obj = proc;
                    mAm.mHandler.sendMessageAtTime(msg, proc.execServicesFg
                            ? (nextTime+SERVICE_TIMEOUT) : (nextTime + SERVICE_BACKGROUND_TIMEOUT));
                }
            ...
        }
    }
    
    frameworks/base/core/java/android/app/ActivityThread.java
    //2.服务启动完成后调用该方法,进而调用上面的serviceDoneExecutingLocked方法
    private void handleCreateService(CreateServiceData data) {
    	...
    	try {
    		ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
    	} catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
    	}
        ...
    }
    
    frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
    //3.服务启动超时后,来到这里SERVICE_TIMEOUT_MSG分歧代码,最后执行mServices.serviceTimeout方法
    final class MainHandler extends Handler {
    	public MainHandler(Looper looper) {
    		super(looper, null, true);
    	}
    	@Override
    	public void handleMessage(Message msg) {
    		switch (msg.what) {;
                case SERVICE_TIMEOUT_MSG: {
                    mServices.serviceTimeout((ProcessRecord)msg.obj);
                } break;
    		}
        }
    }
    
  • 相关阅读:
    Nginx 部署多个 web 项目(虚拟主机)
    Nginx 配置文件
    Linux 安装 nginx
    Linux 安装 tomcat
    Linux 安装 Mysql 5.7.23
    Linux 安装 jdk8
    Linux 安装 lrzsz,使用 rz、sz 上传下载文件
    springMVC 拦截器
    spring 事务
    基于Aspectj 注解实现 spring AOP
  • 原文地址:https://www.cnblogs.com/yongfengnice/p/14822913.html
Copyright © 2011-2022 走看看