Android - Service 启动过程

相关系列

  • 一篇文章看明白 Android 系统启动时都干了什么
  • 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制
  • 一篇文章看明白 Android 从点击应用图标到界面显示的过程
  • 一篇文章看明白 Activity 与 Window 与 View 之间的关系
  • 一篇文章看明白 Android 图形系统 Surface 与 SurfaceFlinger 之间的关系
  • 一篇文章看明白 Android Service 启动过程
  • 一篇文章看明白 Android PackageManagerService 工作流程
  • 一篇文章看明白 Android v1 & v2 签名机制

概述

Service 启动过程与 Activity 启动过程比较相似,不了解 Activity 启动过程的可以先看一下:Activity 启动过程。

Service 的启动分两种情况:startService,bindService。

startService

通常情况我们在调用 startService 启动 Service 是运行在 App 进程中的。下面主要讨论下运行在单独进程中的情况。

在 AndroidManifest 文件中把 Service 配置 android:process 上属性,Service 就可以启动在单独进程中了。

首先要明白一个问题,在 Activity 中使用的 startService 方法是定义在 Context 的抽象类中,它的真正实现者是 ContextImpl,所以我们首先进入 ContextImpl 类。

  • ContextImpl.startService()
@Overridepublic ComponentName startService(Intent service) {    warnIfCallingFromSystemProcess();    return startServiceCommon(service, mUser); }private ComponentName startServiceCommon(Intent service, UserHandle user) {    try {        validateServiceIntent(service);        service.prepareToLeaveProcess();        ComponentName cn = ActivityManagerNative.getDefault().startService(mMainThread.getApplicationThread(),service,service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());        //......        return cn;    } catch (RemoteException e) {        return null;    }}

从 ContextImpl 类的 startService 开始,然后进入本类的 startServiceCommon 方法,并最终调用 ActivityManagerNative.getDefault() 对象的 startService 方法。其实这里的 ActivityManagerNative.getDefault() 就是 ActivityManagerProxy 对象。这里涉及到 Binder 相关知识,不了解的请看:Binder 机制。

  • ActivityManagerProxy.startService()
public ComponentName startService(IApplicationThread caller, Intent service,            String resolvedType, int userId) throws RemoteException {    Parcel data = Parcel.obtain();    Parcel reply = Parcel.obtain();    data.writeInterfaceToken(IActivityManager.descriptor);    data.writeStrongBinder(caller != null ? caller.asBinder() : null);    service.writeToParcel(data, 0);    data.writeString(resolvedType);    data.writeInt(userId);    mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);    reply.readException();    ComponentName res = ComponentName.readFromParcel(reply);    data.recycle();    reply.recycle();    return res;}

通过 Binder 调用 ActivityManagerNative 类中 onTransact 方法,其识别码为 START_SERVICE_TRANSACTION,并最终调用 ActivityManagerNative 的实现类 ActivityManagerService 的 startService 方法。

  • ActivityManagerService.startService()
@Overridepublic ComponentName startService(IApplicationThread caller, Intent service,            String resolvedType, int userId) {    enforceNotIsolatedCaller("startService");    //......    synchronized(this) {        final int callingPid = Binder.getCallingPid();        final int callingUid = Binder.getCallingUid();        final long origId = Binder.clearCallingIdentity();        ComponentName res = mServices.startServiceLocked(caller, service,                resolvedType, callingPid, callingUid, userId);        Binder.restoreCallingIdentity(origId);        return res;    }}

在这里调用 mServices 对象的 startServiceLocked 方法,这里的 mServices 对象是 ActiveServices 类。

  • ActiveServices.startServiceLocked()
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, int userId) {    //......    ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPid, callingUid, userId, true, callerFg);    ServiceRecord r = res.record;    //......    //这里紧接着会调用 startServiceInnerLocked 方法    return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);}ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,            ServiceRecord r, boolean callerFg, boolean addToStarting) {        //......        synchronized (r.stats.getBatteryStats()) {            r.stats.startRunningLocked();        }        //这里紧接着会调用 bringUpServiceLocked 方法        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false);        //......}

首先通过 retrieveServiceLocked 方法来解析 service 这个 Intent,就是解析前面我们在 AndroidManifest.xml 定义的 Service 标签的 intent-filter 相关内容,然后将解析结果放在 res.record 中,再调用 startServiceInnerLocked 方法。startServiceInnerLocked 方法中会调用 bringUpServiceLocked 方法。

  • ActiveServices.bringUpServiceLocked()
private final String bringUpServiceLocked(ServiceRecord r,            int intentFlags, boolean execInFg, boolean whileRestarting) {    //(1)这里如果当前的 ProcessRecord 不为 null,那就不需要重新创建进程,//而是调用 realStartServiceLocked 方法来启动 Service    if (app != null && app.thread != null) {                try {                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);                    realStartServiceLocked(r, app, execInFg);                    return null;                } 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.            }    //(2)如果是需要创建新进程,那么将调用 ActivityManagerService.startProcessLocked 方法来启动新进程    if (app == null) {            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,                    "service", r.name, false, isolated, false)) == null) {                //......                bringDownServiceLocked(r);                return msg;            }            if (isolated) {                r.isolatedProc = app;            }        }    //最后将 ServiceRecord 保存到成员变量 mPendingServices 中    if (!mPendingServices.contains(r)) {            mPendingServices.add(r);    }}

这个方法比较重要,这里有两种选择,当 Service 所在的进程存在时,将调用realStartServiceLocked 方法来启动 Service,否则的话调用 startProcessLocked 方法来启动新进程。

  • ActivityManagerService.startProcessLocked()
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {    boolean isActivityProcess = (entryPoint == null);    if (entryPoint == null)         entryPoint = "android.app.ActivityThread";    checkTime(startTime, "startProcess: asking zygote to start proc");    //通过 processName,uid 等启动新进程    Process.ProcessStartResult startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, app.info.dataDir, entryPointArgs);}

这里通过 Process 的 start 方法启动 ActivityThread 的新进程,我们进入该类的 main 方法。

  • ActivityThread.main()
public static void main(String[] args) {    //......    Process.setArgV0("");    Looper.prepareMainLooper();    //创建 ActivityThread 对象,并调用其 attach 方法    ActivityThread thread = new ActivityThread();    thread.attach(false);    if (sMainThreadHandler == null) {        sMainThreadHandler = thread.getHandler();    }    if (false) {        Looper.myLooper().setMessageLogging(new                LogPrinter(Log.DEBUG, "ActivityThread"));    }        Looper.loop();    throw new RuntimeException("Main thread loop unexpectedly exited");}private void attach(boolean system) {    final IActivityManager mgr = ActivityManagerNative.getDefault();    try {        //这里调用了 ActivityManagerProxy.attachApplication 方法。        mgr.attachApplication(mAppThread);    } catch (RemoteException ex) {        // Ignore    }}

在 Android 应用程序中,每一个进程对应一个 ActivityThread 实例,然后这里创建了 ActivityThread 对象并调用了其 attach 方法,在 attach 方法中又调用了 ActivityManagerProxy.attachApplication 方法。

  • ActivityManagerProxy.attachApplication()
public void attachApplication(IApplicationThread app) throws RemoteException {    Parcel data = Parcel.obtain();    Parcel reply = Parcel.obtain();    data.writeInterfaceToken(IActivityManager.descriptor);    data.writeStrongBinder(app.asBinder());    mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);    reply.readException();    data.recycle();    reply.recycle();}

通过 Binder 机制会调用 ActivityManagerNative 中的 onTransact 方法,其识别码为 ATTACH_APPLICATION_TRANSACTION,并最终调用 ActivityManagerService 中的 attachApplication 方法。

  • ActivityManagerService.attachApplication()
@Overridepublic final void attachApplication(IApplicationThread thread) {    synchronized (this) {        int callingPid = Binder.getCallingPid();        final long origId = Binder.clearCallingIdentity();        //调用 attachApplicationLocked        attachApplicationLocked(thread, callingPid);        Binder.restoreCallingIdentity(origId);        //......    }}private final boolean attachApplicationLocked(IApplicationThread thread,            int pid) {    // See if the top visible activity is waiting to run in this process...    if (normalMode) {        try {            if (mStackSupervisor.attachApplicationLocked(app)) {                didSomething = true;            }        } catch (Exception e) {            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);            badApp = true;        }    }    // Find any services that should be running in this process...    if (!badApp) {        try {        //这里会调用 ActiveServices 对象的 attachApplicationLocked 方法            didSomething |= mServices.attachApplicationLocked(app, processName);        } catch (Exception e) {            Slog.wtf(TAG, "Exception thrown starting services in " + app, e);            badApp = true;        }    }}

这里如果是启动 Service 将调用 ActiveServices 对象的 attachApplicationLocked 方法,而如果是启动 Activity 将调用 ActivityStackSupervisor 对象的 attachApplicationLocked 方法。

  • ActiveServices.attachApplicationLocked() -> realStartServiceLocked()
private final void realStartServiceLocked(ServiceRecord r,            ProcessRecord app, boolean execInFg) throws RemoteException {    if (app.thread == null) {            throw new RemoteException();        }    //......    app.thread.scheduleCreateService(r, r.serviceInfo,mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),                    app.repProcState);}

此处的 app.thread 是一个 IApplicationThread 对象,而 IApplicationThread 的代理类是 ApplicationThreadProxy,我们进入 app.thread 对象的 scheduleCreateService 方法。

  • ApplicationThreadProxy.scheduleCreateService()
public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) throws RemoteException {    Parcel data = Parcel.obtain();    data.writeInterfaceToken(IApplicationThread.descriptor);    data.writeStrongBinder(token);    info.writeToParcel(data, 0);    compatInfo.writeToParcel(data, 0);    data.writeInt(processState);    mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,            IBinder.FLAG_ONEWAY);    data.recycle();}

通过 Binder 对象调用 ApplicationThreadNative 的 onTransact 方法,在其方法中调用子类的 scheduleCreateService 方法,即最终调用 ApplicationThreadNative 的子类 ApplicationThread 的 scheduleCreateService 方法。

  • ApplicationThread.scheduleCreateService()
public final void scheduleCreateService(IBinder token,  ServiceInfo info, CompatibilityInfo compatInfo, int processState) {    updateProcessState(processState, false);    CreateServiceData s = new CreateServiceData();    s.token = token;    s.info = info;    s.compatInfo = compatInfo;    sendMessage(H.CREATE_SERVICE, s);}

通过 Handler 发送 Message 来处理该操作,并进入到 H 的 handleMessage 方法中,其识别码为 CREATE_SERVICE。

  • H.handleMessage()
private class H extends Handler {    public void handleMessage(Message msg) {        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");        //这里调用 handleCreateService 方法        handleCreateService((CreateServiceData)msg.obj);        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);    }}
  • ApplicationThread.handleCreateService()
private void handleCreateService(CreateServiceData data) {    Service service = null;    try {        //(1)通过类加载器来加载 Service 对象        java.lang.ClassLoader cl = packageInfo.getClassLoader();        service = (Service) cl.loadClass(data.info.name).newInstance();    } catch (Exception e) {        //......    }    //(2)这里创建 ContextImpl 对象    ContextImpl context = ContextImpl.createAppContext(this, packageInfo);    context.setOuterContext(service);    Application app = packageInfo.makeApplication(false, mInstrumentation);    service.attach(context, this, data.info.name, data.token, app,                    ActivityManagerNative.getDefault());    //(3)这里调用 Service 的 onCreate 方法    service.onCreate();    mServices.put(data.token, service);}
  1. 处通过类加载器 ClassLoader 来加载 Service 对象,此处的 data.info.name 就是我们要启动的 Service,加载完成后需要将其强转换为 Service 对象,也就是说我们的 Service 必须要继承于 Service 基类。
  2. 处这里先创建一个 ContextImpl 对象,每个 Activity 和 Service 都有一个 Context 对象。
  3. 处这里调用 Service 的 onCreate 方法。

bindService

  • 如何 bind 一个 Service?
private void test(){    Intent intent = new Intent(this, XXXService.class);    // bindService 的具体实现在 ContextImpl    // BIND_AUTO_CREATE 参数具体使用的代码 ActivityServices    bindService(intent, conn, BIND_AUTO_CREATE);}private ServiceConnection conn = new ServiceConnection() {      @Override      public void onServiceConnected(ComponentName name, IBinder service) {         // 绑定成功       ...    }      @Override      public void onServiceDisconnected(ComponentName name) {       // 绑定结束        ...      }}
  • ContextImpl.bindServce()
@Overridepublic boolean bindService(Intent service, ServiceConnection conn,        int flags) {    // mMainThread.getHandler(),传入的 handle 是主线程的 Handle    return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),            Process.myUserHandle());}private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) {    IServiceConnection sd;    //...    if (mPackageInfo != null) {        // 1,将传入的 ServiceConnection 转化为 IServiceConnection 返回        // mPackgeInfo 是 LoadedApk        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);    }    validateServiceIntent(service);    try {        IBinder token = getActivityToken();        ...        // 2,Binder 调用 AMS 的 bindService 方法,下面具体分析        int res = ActivityManagerNative.getDefault().bindService(            mMainThread.getApplicationThread(), getActivityToken(), service,            service.resolveTypeIfNeeded(getContentResolver()),            sd, flags, getOpPackageName(), user.getIdentifier());        return res != 0;    }     //...}
  • LoadedApk

LoadedApk 对象是 Apk 文件在内存中的表示。 Apk 文件的相关信息,诸如 Apk 文件的代码和资源,甚至代码里面的 Activity,Service 等组件的信息我们都可以通过此对象获取。

public final IServiceConnection getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags) {    synchronized (mServices) {        LoadedApk.ServiceDispatcher sd = null;        // private final ArrayMap> mServices        // 根据当前的 Context 获取 ArrayMap        ArrayMap map = mServices.get(context);        if (map != null) {            // 如果存在,尝试根据当前的 ServiceConnection 获取 ServiceDispatcher            sd = map.get(c);        }        if (sd == null) {            // 如果与 ServiceConnection 对应的 ServiceDispatcher 不存在,创建一个保存了当前 // ServiceConnection 的 ServiceDispatcher 对象,            // 并将之前传入的主线的 Handle 保存,同时创建一个 InnerConnection 对象保存            sd = new ServiceDispatcher(c, context, handler, flags);            if (map == null) {                map = new ArrayMap();                mServices.put(context, map);            }            // 将该 ServiceConnection 与 ServiceDispatcher 关系保存            map.put(c, sd);        } else {            // 如果最开始就获取到 ServiceDispatcher,比如多次 bindService,            // 就会调用 ServiceDispatcher 的 validate 判断此次 bindService 是否合法            // validate 的判断逻辑比较简单:// 1.判断当前的 context 是否和之前 bindService 的一样 // 2.判断当前 handler 是否是主线程的 handle            // 以上两个条件都满足的情况下正常执行,反之抛出相应的异常            sd.validate(context, handler);        }        return sd.getIServiceConnection();    }}
  • ActivityManagerService.bindService()
public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String callingPackage, int userId) throws TransactionTooLargeException {    //...    synchronized(this) {        // 调用 ActiveServices 的 bindServiceLocked 方法        return mServices.bindServiceLocked(caller, token, service,                resolvedType, connection, flags, callingPackage, userId);    }}
  • ActiveServices.bindServiceLocked() -> bringUpServiceLocked() -> realStartServiceLocked()
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException {    //...    try {        //...        // 第一步,调用 ApplicationThread 的 scheduleCreateService 方法,// 之后会实例化 Service 并调用 Service 的 onCreate 方法,这里的过程跟上面 startService 中一样。        // 不会调用 onStartCommand        app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),                app.repProcState);    }     //...    // 第二步,调用 requestServiceBindingLocked    requestServiceBindingLocked(r, execInFg);    updateServiceClientActivitiesLocked(app, null, true);    // 第三步    // 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.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), null, null));    }    // StartItem 的 taskRemoved 如果是 false 的话,// 调用下面方法会调用 Service 的 onStartCommand    sendServiceArgsLocked(r, execInFg, true);    //...}private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException {    //...    if ((!i.requested || rebind) && i.apps.size() > 0) {        try {            //...            // 调用 ApplicationThread 的 scheduleBindService 方法            r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,                    r.app.repProcState);        }         //...    }    //...    return true;}
  • ApplicationThread.scheduleBindService()
private void handleBindService(BindServiceData data) {   // 根据 token 获取 Service token 具体分析    Service s = mServices.get(data.token);    if (s != null) {        try {            // rebind 具体分析            if (!data.rebind) {                // 调用 Service 的 onBind,返回给客户端调用的 Binder                IBinder binder = s.onBind(data.intent);                // 调用 AMS 的 publishService,进而通知客户端连接成功                ActivityManagerNative.getDefault()                    .publishService(data.token, data.intent, binder);            } else {                s.onRebind(data.intent);                ActivityManagerNative.getDefault()                    .serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON,                     0, 0);            }            ensureJitEnabled();        }        ...    }}

调用 ApplicationThread 的 scheduleBindService,scheduleBindService 通过 mH 发送一个 H.BIND_SERVICE 消息,mH 收到该消息调用 handleBindService(BindServiceData data)。

总结

  • startService

使用这种 start 方式启动的 Service 的生命周期如下:
onCreate() -> onStartCommand()(onStart()方法已过时) -> onDestory()

说明:如果服务已经开启,不会重复的执行 onCreate(), 而是会调用 onStart() 和onStartCommand()。
服务停止的时候调用 onDestory()。服务只会被停止一次。

特点:一旦服务开启跟调用者(开启者)就没有任何关系了。
开启者退出了,开启者挂了,服务还在后台长期的运行。
开启者不能调用服务里面的方法。

  • bindService

使用这种 start 方式启动的 Service 的生命周期如下:
onCreate() -> onBind() -> onUnbind() -> onDestory()

注意:绑定服务不会调用 onStart() 或者 onStartCommand() 方法

特点:bind 的方式开启服务,绑定服务,调用者挂了,服务也会跟着挂掉。
绑定者可以调用服务里面的方法。

参考资料

  • startService 启动过程分析
  • 《深入理解 Android 内核设计思想》

其他系列

  • Android 屏幕适配全攻略
  • Windows 环境下载 Android 源码
  • Android 性能优化-UI优化
  • Android 性能优化-内存优化
  • Java 虚拟机内存分配机制
  • Java 虚拟机垃圾回收机制
  • 一篇文章看明白 TCP/IP,TCP,UDP,IP,Socket 之间的关系
  • 一篇文章看明白 HTTP,HTTPS,SSL/TSL 之间的关系

Gradle 系列

  • Gradle - 简介
  • Gradle - Groovy Language
  • Gradle - DSL
  • Gradle - Android Plugin DSL
  • Gradle - 插件开发
  • Gradle - 插件发布

更多文章:

这是我博客长期更新的项目,欢迎大家 Star。
https://github.com/jeanboydev/Android-ReadTheFuckingSourceCode

我的公众号

欢迎你「扫一扫」下面的二维码,关注我的公众号,可以接受最新的文章推送,有丰厚的抽奖活动和福利等着你哦!

如果你有什么疑问或者问题,可以 点击这里 提交 issue,也可以发邮件给我 [email protected]。

同时欢迎你 来一起交流学习,群里有很多大牛和学习资料,相信一定能帮助到你!

更多相关文章

  1. Android(安卓)View中的onMeasure()方法详解
  2. Android中的UI线程详解
  3. Android的HTTP基础与之使用HttpClient和HttpURLConnection
  4. Android(安卓)- 引用计数(sp、wp、Refbase)
  5. ubuntu 编译 Android(安卓)出现的若干错误及解决方法
  6. [转]Android(安卓)设计思想
  7. 从一篇Blog看两个并发编程错误
  8. android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精
  9. Android多线程(三)HandlerThread源码原理解析

随机推荐

  1. Android百度地图一种简单实现多标注及响
  2. Android定制之常见问题解决
  3. ListView去除分割线的问题
  4. Android(安卓)studio 实现简单的视频播放
  5. 使用android中的AIDL让Service与Activity
  6. android 解决viewpager+多个fragment+rec
  7. Android项目中的jcenter()和maven()
  8. android:exported的用法
  9. android xml pull 解析 豆瓣书籍
  10. ArcGIS for Android 100.3.0(1):开发环境配