Service启动过程过程详解

Service的几种启动方式:


1、startService

public class myActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  startService(new Intent (IMediaScannerService.class.getName()); //"com.android.providers.media.MediaScannerService"
  }

StartService()方法主要用于启动一个服务执行后台任务,不进行通信。调用者和服务之间没有联系,即使调用者退出了,服务依然在运行。


2.bindService

public class myActivity extends Activity {
       ServiceConnection conn = new ServiceConnection() {
        
        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
        
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            
        }
    };


   @Override  public void onCreate(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);

  bindService(new Intent (IMediaScannerService.class.getName(),conn,Context.BIND_AUTO_CREATE);

  }


使用bindService()方法来绑定服务,调用者和绑定者绑在一起,调用者一旦退出如果没有其他用户使用则服务也就终止了。

3.隐式启动服务Implicitly start service

When a service is referenced,it will be started automatically.

For example,the MediaScannerService will be started with following code:

import android.media.MediaScannerConnection;

MediaScannerConnection.MediaScannerConnectionClient client= new MediaScannerConnection.MediaScannerConnectionClient(){
   public void onMediaScannerConnected(){
      conn.scanFile("/mnt//sdcard/test.jpg");
   }
   public void onScanComplete(){
      conn.disconnect(); //close the connection here
   }
}
MediaScannerConnection conn=new MediaScannerConnection(getContext(),client);
conn.connect();         //here will trigger start MediaScannnerService

4.通过广播启动服务

下面通过广播action ACTION_MEDIA_SCANNER_SCAN_FILE从而启动Service并扫描单个文件。

Uri data = Uri.parse("file:///"+fName);  
        sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, data));  



下图描述了当一个服务所在进程已经启动,但服务尚未启动时,调用startService时的调用顺序。


由图可知,在14步时,发出SERVICE_TIMEOUT消息,在29步时,删除此消息。如果此超时消息未能及时删除,则在消息处理时将显示为anr。目前此消息超时时间设为20s。


ActivityManagerService.java

    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType) {
...
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res = startServiceLocked(caller, service,resolvedType, callingPid, callingUid); //入口
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

    ComponentName startServiceLocked(IApplicationThread caller,
            Intent service, String resolvedType,
            int callingPid, int callingUid) {
        synchronized(this) {
            if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
                    + " type=" + resolvedType + " args=" + service.getExtras());

            if (caller != null) {
                final ProcessRecord callerApp = getRecordForAppLocked(caller);
                if (callerApp == null) {
                    throw new SecurityException(
                            "Unable to find app for caller " + caller
                            + " (pid=" + Binder.getCallingPid()
                            + ") when starting service " + service);
                }
            }

            ServiceLookupResult res =
                retrieveServiceLocked(service, resolvedType,
                        callingPid, callingUid);
            if (res == null) {
                return null;
            }
            if (res.record == null) {
                return new ComponentName("!", res.permission != null
                        ? res.permission : "private to package");
            }
            ServiceRecord r = res.record;
            int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
                    callingUid, r.packageName, service);
            if (unscheduleServiceRestartLocked(r)) {
                if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
            }
            r.startRequested = true;
            r.callStart = false;
            r.lastStartId++;
            if (r.lastStartId < 1) {
                r.lastStartId = 1;
            }
            r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
                    service, targetPermissionUid));
            r.lastActivity = SystemClock.uptimeMillis();
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startRunningLocked();
            }
            if (!bringUpServiceLocked(r, service.getFlags(), false)) {
                return new ComponentName("!", "Service process is bad");
            }
            return r.name;
        }
    }

    private final boolean bringUpServiceLocked(ServiceRecord r,
            int intentFlags, boolean whileRestarting) {
        if (r.app != null && r.app.thread != null) { //如果Service已经在运行
            sendServiceArgsLocked(r, false);
            return true;
        }

        if (!whileRestarting && r.restartDelay > 0) {
            // If waiting for a restart, then do nothing.
            return true;
        }

        // We are now bringing the service up, so no longer in the
        // restarting state.
        mRestartingServices.remove(r);
        
        final String appName = r.processName;
        ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
        if (app != null && app.thread != null) { //如果Service所在进程已经运行
            try {
                realStartServiceLocked(r, app);
                return true;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting service " + r.shortName, e);
            }

            // If a dead object exception was thrown -- fall through to
            // restart the application.
        }

        // Not running -- get it started, and enqueue this service record
        // to be executed when the app comes up.
        if (startProcessLocked(appName, r.appInfo, true, intentFlags,
                "service", r.name, false) == null) { //进程尚未启动,启动进程并指定启动对应service
            bringDownServiceLocked(r, true);
            return false;
        }
        
        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }
        
        return true;
    }



以下发出超时消息,此消息必须在规定时间内被删除,否则出现anr。SERVICE_TIMEOUT=20*1000ms.

    private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
        long now = SystemClock.uptimeMillis();
        if (r.executeNesting == 0 && r.app != null) {
            if (r.app.executingServices.size() == 0) {
                Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
                msg.obj = r.app;
                mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT); //规定最迟处理时间
            }
            r.app.executingServices.add(r);
        }
        r.executeNesting++;
        r.executingStart = now;
    }


下面函数将从AM启动Service

    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app) throws RemoteException {
        if (app.thread == null) { //检查所在进程是否存在
            throw new RemoteException();
        }

        r.app = app;
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis(); //记录启动时间

        app.services.add(r);
        bumpServiceExecutingLocked(r, "create");  //发送超时消息
        updateLruProcessLocked(app, true, true);

        boolean created = false;
        try {
            mStringBuilder.setLength(0);
            r.intent.getIntent().toShortString(mStringBuilder, false, true);
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startLaunchedLocked(); //电池数据统计启动
            }
            ensurePackageDexOpt(r.serviceInfo.packageName); //???
            app.thread.scheduleCreateService(r, r.serviceInfo); //通知Service所在进程创建Service
            r.postNotification();
            created = true;
        } finally {
            if (!created) {
                app.services.remove(r);
                scheduleServiceRestartLocked(r, false);
            }
        }

        requestServiceBindingsLocked(r); //等待Service运行成功才返回?
        
        // If the service is in the started state, and there are no
        // pending arguments, then fake up one so its onStartCommand() will
        // be called.
        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
            r.lastStartId++;
            if (r.lastStartId < 1) {
                r.lastStartId = 1;
            }
            r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
        }
        
        sendServiceArgsLocked(r, true); //引起Service.onStartCommand被调用
    }

下面函数将消息SERVICE_ARGS发送到Service进程的消息队列,在此将传来的Intent传给指定Service:


    private final void sendServiceArgsLocked(ServiceRecord r,
            boolean oomAdjusted) {
        final int N = r.pendingStarts.size();
        if (N == 0) {
            return;
        }

        while (r.pendingStarts.size() > 0) {
            try {
                ServiceRecord.StartItem si = r.pendingStarts.remove(0);
                if (si.intent == null) {
                    // If somehow we got a dummy start at the front, then
                    // just drop it here.
                    continue;
                }
                si.deliveredTime = SystemClock.uptimeMillis();
                r.deliveredStarts.add(si);
                si.deliveryCount++;
                if (si.targetPermissionUid >= 0) {
                    grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
                            r.packageName, si.intent, si.getUriPermissionsLocked());
                }
                bumpServiceExecutingLocked(r, "start"); //启动超时消息
                if (!oomAdjusted) {
                    oomAdjusted = true;
                    updateOomAdjLocked(r.app);
                }
                int flags = 0;
                if (si.deliveryCount > 0) {
                    flags |= Service.START_FLAG_RETRY;
                }
                if (si.doneExecutingCount > 0) {
                    flags |= Service.START_FLAG_REDELIVERY;
                }
                r.app.thread.scheduleServiceArgs(r, si.id, flags, si.intent); //发送Intent到Service所在进程消息队列,引起Service.onStartCommand被调用
            } catch (RemoteException e) {
                // Remote process gone...  we'll let the normal cleanup take
                // care of this.
                break;
            } catch (Exception e) {
                Slog.w(TAG, "Unexpected exception", e);
                break;
            }
        }
    }

r.app.thread.scheduleServiceArgs将发送消息SERVICE_ARGS到ActivityThread.Handler,在此将调用handleServiceArgs来完成

ActivityThread.java

    private final void handleServiceArgs(ServiceArgsData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                if (data.args != null) {
                    data.args.setExtrasClassLoader(s.getClassLoader());
                }
                int res = s.onStartCommand(data.args, data.flags, data.startId); //调用Service.onStartCommand方法

                QueuedWork.waitToFinish(); //等待本进程所有异步操作完成

                try {
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                            data.token, 1, data.startId, res); //通知操作完成,并删除超时消息
                } catch (RemoteException e) {
                    // nothing to do.
                }
                ensureJitEnabled();  //确保JIT优化启动(如果未启动则启动),但为何在此做??
            } catch (Exception e) {
                if (!mInstrumentation.onException(s, e)) {
                    throw new RuntimeException(
                            "Unable to start service " + s
                            + " with " + data.args + ": " + e.toString(), e);
                }
            }
        }
    }

每当AM需要异步执行Service操作时,在操作完后均需调用函数 serviceDoneExecuting以防止Service操作超时。

    public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
        r.executeNesting--;
        if (r.executeNesting <= 0 && r.app != null) {
            r.app.executingServices.remove(r);
            if (r.app.executingServices.size() == 0) { //为何?
                mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app); //删除所有object=r.app的超时消息
            }
            if (inStopping) {
                mStoppingServices.remove(r);
                r.bindings.clear();
            }
            updateOomAdjLocked(r.app); //检查是否需要kill app以避免OOM
        }
    }


 

                
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前言 第一篇 网站基础知识 第1章 网站架构及其演变过程2 1.1 软件的三大类型2 1.2 基础的结构并不简单3 1.3 架构演变的起点5 1.4 海量数据的解决方案5 1.4.1 缓存和页面静态化5 1.4.2 数据库优化6 1.4.3 分离活跃数据8 1.4.4 批量读取和延迟修改8 1.4.5 读写分离9 1.4.6 分布式数据库10 1.4.7 NoSQL和Hadoop10 1.5 高并发的解决方案11 1.5.1 应用和静态资源分离11 1.5.2 页面缓存12 1.5.3 集群与分布式12 1.5.4 反向代理13 1.5.5 CDN14 1.6 底层的优化15 1.7 小结15 第2章 常见协议和标准17 2.1 DNS协议17 2.2 TCP/IP协议与Socket18 2.3 HTTP协议20 2.4 Servlet与Java Web开发22 第3章 DNS的设置23 3.1 DNS解析23 3.2 Windows 7设置DNS服务器24 3.3 Windows设置本机域名和IP的对应关系25 第4章 Java中Socket的用法26 4.1 普通Socket的用法26 4.2 NioSocket的用法28 第5章 自己动手实现HTTP协议33 第6章 详解Servlet37 6.1 Servlet接口37 6.2 GenericServlet40 6.3 HttpServlet41 第7章 Tomcat分析44 7.1 Tomcat的顶层结构及启动过程44 7.1.1 Tomcat的顶层结构44 7.1.2 Bootstrap的启动过程45 7.1.3 Catalina的启动过程47 7.1.4 Server的启动过程48 7.1.5 Service启动过程50 7.2 Tomcat的生命周期管理52 7.2.1 Lifecycle接口52 7.2.2 LifecycleBase53 7.3 Container分析59 7.3.1 ContainerBase的结构59 7.3.2 Container的4个子容器60 7.3.3 4种容器的配置方法60 7.3.4 Container的启动62 7.4 Pipeline-Value管道69 7.4.1 Pipeline-Value处理模式69 7.4.2 Pipeline-Value的实现方法70 7.5 Connector分析73 7.5.1 Connector的结构73 7.5.2 Connector自身类74 7.5.3 ProtocolHandler77 7.5.4 处理TCP/IP协议的Endpoint77 7.5.5 处理HTTP协议的Processor80 7.5.6 适配器Adapter81 第二篇 俯视Spring MVC 第8章 Spring MVC之初体验84 8.1 环境搭建84 8.2 Spring MVC最简单的配置84 8.2.1 在web.xml中配置Servlet85 8.2.2 创建Spring MVC的xml配置文件85 8.2.3  创建Controller和view86 8.3 关联spring源代码87 8.4 小结89 第9章 创建Spring MVC之器90 9.1 整体结构介绍90 9.2 HttpServletBean93 9.3 FrameworkServlet95 9.4 DispatcherServlet100 9.5 小结107 第10章 Spring MVC之用108 10.1 HttpServletBean108 10.2 FrameworkServlet108 10.3 DispatcherServlet114 10.4 doDispatch结构118 10.5 小结123 第三篇 Spring MVC组件分析 第11章 组件概览126 11.1 HandlerMapping126 11.2 HandlerAdapter128 11.3 HandlerExceptionResolver130 11.4 ViewResolver131 11.5 RequestToViewNameTranslator133 11.6 LocaleResolver133 11.7 ThemeResolver135 11.8 MultipartResolver137 11.9 FlashMapManager138 11.10 小结139 第12章 HandlerMapping140 12.1 AbstractHandlerMapping140 12.1.1 创建AbstractHandlerMapping之器141 12.1.2 AbstractHandlerMapping之用142 12.2 AbstractUr
├─第一阶段 │      源码+ppt.rar │      高并发编程第一阶段01讲、课程大纲及主要内容介绍.wmv │      高并发编程第一阶段02讲、简单介绍什么是线程.wmv │      高并发编程第一阶段03讲、创建并启动线程.mp4 │      高并发编程第一阶段04讲、线程生命周期以及start方法源码剖析.mp4 │      高并发编程第一阶段05讲、采用多线程方式模拟银行排队叫号.mp4 │      高并发编程第一阶段06讲、用Runnable接口将线程的逻辑执行单元从控制中抽取出来.mp4 │      高并发编程第一阶段07讲、策略模式在Thread和Runnable中的应用分析.mp4 │      高并发编程第一阶段08讲、构造Thread对象你也许不知道的几件事.mp4 │      高并发编程第一阶段09讲、多线程与JVM内存结构的关系,虚拟机栈实验.mp4 │      高并发编程第一阶段10讲、Thread构造函数StackSize详细讲解.mp4 │      高并发编程第一阶段11讲、Thread构造函数StackSize详细讲解-续.mp4 │      高并发编程第一阶段12讲、Daemon线程的创建以及使用场景分析.mp4 │      高并发编程第一阶段13讲、线程ID,优先级讲解.mp4 │      高并发编程第一阶段14讲、Thread的join方法详细介绍,结合一个典型案例.mp4 │      高并发编程第一阶段15讲、Thread中断Interrupt方法详细讲解.mp4 │      高并发编程第一阶段16讲、采用优雅的方式结束线程生命周期.mp4 │      高并发编程第一阶段17讲、Thread API综合实战,编写ThreadService实现暴力结束线程的综合实战.mp4 │      高并发编程第一阶段18讲、数据同步的引入与Synchronized的简单介绍.mp4 │      高并发编程第一阶段19讲、结合jconsole,jstack以及汇编指令认识synchronized关键字.mp4 │      高并发编程第一阶段20讲、同步代码块以及同步方法之间的区别和关系.mp4 │      高并发编程第一阶段21讲、通过实验分析This锁的存在.mp4 │      高并发编程第一阶段22讲、通过实验分析Class锁的存在.mp4 │      高并发编程第一阶段23讲、多线程死锁分析,案例介绍.mp4 │      高并发编程第一阶段24讲、线程间通信快速入门,使用wait和notify进行线程间的数据通信.mp4 │      高并发编程第一阶段25讲、多Produce多Consume之间的通讯导致出现程序假死的原因分析.mp4 │      高并发编程第一阶段26讲、多线程下的生产者消费者模型,以及详细介绍notifyAll方法.mp4 │      高并发编程第一阶段27讲、wait和sleep的本质区别是什么,深入分析(面试常见问题).mp4 │      高并发编程第一阶段28讲、线程生产者消费者的综合实战结合Java8语法.mp4 │      高并发编程第一阶段29讲、如何实现一个自己的显式锁Lock精讲上.mp4 │      高并发编程第一阶段30讲、如何实现一个自己的显式锁Lock精讲下(让锁具备超时功能).mp4 │      高并发编程第一阶段31讲、如何给你的应用程序注入钩子程序,Linux下演示.mp4 │      高并发编程第一阶段32讲、如何捕获线程运行期间的异常.mp4 │      高并发编程第一阶段33讲、ThreadGroup API介绍之一.mp4 │      高并发编程第一阶段34讲、ThreadGroup API介绍之二.mp4 │      高并发编程第一阶段35讲、线程池原理与自定义线程池.mp4 │      高并发编程第一阶段36讲、自定义个简单的线程池并且测试.mp4 │      高并发编程第一阶段37讲、给线程池增加拒绝策略以及停止方法.mp4 │      高并发编程第一阶段38讲、给线程池增加自动扩充线程数量,以及闲时自动回收的功能.mp4 │      高并发编程第一阶段39讲、课程结束,内容回顾,下季内容预告.mp4 │ ├─第二阶段 │       Java并发编程.png │       ppt+源码.rar │       高并发编程第二阶段01讲、课程大纲及主要内容介绍.wmv │       高并发编程第二阶段02讲、介绍四种Singleton方式的优缺点在多线程情况下.wmv │       高并发编程第二阶段03讲、介绍三种高效优雅的Singleto
[经典文档]Android核心分析 核心分析之一 ----- 分析方法论探讨之设计意图 核心分析之二 ----- 方法论探讨之概念空间篇 核心分析之三 ----- 手机之硬件形态 核心分析之四 ----- 手机之软件形态 核心分析之五 ----- 基本空间划分 核心分析之六 ----- IPC框架分析Binder,Service,Service Manager 核心分析之七 ----- Service 深入分析 核心分析之八 ----- Android 启动过程详解 核心分析之九 ----- Zygote Service 核心分析之十 ----- Android GWES之基本原理篇 核心分析之十一 ----- Android GWES之消息系统 核心分析之十二 ----- Android GWES窗口管理之基本架构原理 核心分析之十三 ----- Android GWES之Android窗口管理 核心分析之十四 ----- Android GWES之输入系统 核心分析之十五 ----- Android 输入系统之输入路径详解 核心分析之十六 ----- Android 电话系统-概述篇 核心分析之十七 ----- Android 电话系统-RILD 核心分析之十八 ----- Android 电话系统之RIL-JAVA 核心分析之十九 ----- 电话系统之GSMCall Tracker 核心分析之二十 ----- Android 应用程序框架之无边界设计意图 核心分析之二十一 ----- Android 应用框架之Android Application 核心分析之二十二 ----- Android 应用框架之Activity 核心分析之二十三 ----- Android GDI之显示缓冲管理 核心分析之二十四 ----- Android GDI之共享缓冲区机制 核心分析之二十五 ----- Android GDI之SurfaceFlinger 核心分析之二十六 ----- Android GDI之SurfaceFlinger动态结构示意图 核心分析之二十七 ----- Android GDI之Surface&Canvas;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值