Service 启动流程

590 阅读7分钟

Service 分为两种工作状态,普通状态和绑定状态

普通状态通过 Context.startService() 函数启动,绑定状态通过 Context.bindService() 函数启动

由于启动方式的不同,Service 两种状态下的生命周期并不相同

通过这篇文章,我们来梳理一下这两种不同的启动流程以及其中我们应该注意的细节

startService 整体流程

startService 整体流程主要由 AMS 管理,AMS 会先判断目标 Service 是否正在运行中

如果目标 Service 正在运行中,AMS 需要 AIDL 调用目标 Service 运行所在进程,回调目标 Service 的 onStartCommand() 函数

如果目标 Service 还未启动,就需要判断目标 Service 运行所在进程是哪个进程

如果目标 Service 要运行在 APP 进程中,AMS 需要 AIDL 调用 APP 进程,回调目标 Service 的 onCreate() 函数和 onStartCommand() 函数

如果目标 Service 要运行在独立的进程中,AMS 需要访问 Zygote 进程请求启动一个新进程用于运行目标 Service;当目标进程启动后,就会进行初始化,回调目标 Service 的 onCreate() 函数和 onStartCommand() 函数

总体流程如下图:

bindService 整体流程

bindService 整体流程主要由 AMS 管理,当目标 Service 启动后,AMS 会先判断目标 Service 启动后与 APP 进程是否绑定过

如果目标 Service 启动后与 APP 进程进行过绑定,AMS 需要 AIDL 调用 APP 进程,回调目标 ServiceConnection 的 onServiceConnected() 函数

如果如果当前只有该 APP 进程与目标 Service 进行绑定,AMS 需要 AIDL 调用目标 Service 运行所在进程,回调目标 Service 的 onReBind() 函数

如果目标 Service 启动后首次与 APP 进程进行绑定,AMS 需要 AIDL 调用目标 Service 运行所在进程,回调目标 Service 的 onBind() 函数;同时 AIDL 调用 APP 进程,回调目标 ServiceConnection 的 onServiceConnected() 函数

总体流程如下图:

源码

startService 流程

ContextImpl.startService()

// frameworks/base/core/java/android/app/ContextImpl.java
public ComponentName startService(Intent service)
{
    warnIfCallingFromSystemProcess();
    return startServiceCommon(service, mUser);
}

ContextImpl.startServiceCommon()

// frameworks/base/core/java/android/app/ContextImpl.java
private ComponentName startServiceCommon(Intent service, UserHandle user)
{
    ......

    // AIDL 调用 AMS 的 startService 函数
    ComponentName cn = ActivityManagerNative.getDefault().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                    getContentResolver()), getOpPackageName(), user.getIdentifier());
    
    ......
    
    return cn;
}

AMS.startService()

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public ComponentName startService(IApplicationThread caller, Intent service,
		String resolvedType, String callingPackage, int userId)
{
    ......

    // 调用 ActiveServices 的 startServiceLocked 函数
    ComponentName res = mServices.startServiceLocked(caller, service,
            resolvedType, callingPid, callingUid, callingPackage, userId);

    ......

    return res;
}

ActiveServices.startServiceLocked()

// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
ComponentName startServiceLocked(IApplicationThread caller, Intent service, 
                                 String resolvedType, int callingPid, 
                                 int callingUid, String callingPackage, int userId
){
    ......

    // 获取目标 Service 的信息 (ServiceRecord)
    ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg);

    ......

    ServiceRecord r = res.record;

    ......

    // 将目标 Service 的信息缓存在 r.pendingStarts
    r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
            service, neededGrants));

    ......

    // 调用 ActiveServices 的 startServiceInnerLocked 函数
    return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}

ActiveServices.startServiceInnerLocked()

// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, 
                                      ServiceRecord r, boolean callerFg, 
                                      boolean addToStarting
){
    ......

    // 调用 ActiveServices 的 bringUpServiceLocked 函数
    String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false);

    ......

    return r.name;
}

ActiveServices.bringUpServiceLocked()

// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, 
                                          boolean execInFg, boolean whileRestarting
){
    // 如果目标 Service 已启动且正在运行中
    if (r.app != null && r.app.thread != null)
    {
        // 回调目标 Service 的 onStartCommand 函数
        sendServiceArgsLocked(r, execInFg, false);
        return null;
    }

    ......

    // 查看目标 Service 是否设置了 FLAG_ISOLATED_PROCESS 标志 (表示 Service 运行在独立的进程中)
    final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
    final String procName = r.processName;
    ProcessRecord app;

    // 如果目标 Service 要运行在 APP 进程中 (isolated = false)
    if (!isolated)
    {
        // 调用 AMS 的 getProcessRecordLocked 函数,
        // 获取 APP 进程的信息 (ProcessRecord)
        app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);

        // 如果 APP 进程已启动且正在运行中
        if (app != null && app.thread != null)
        {
            ......

            // 创建目标 Service 实例
            realStartServiceLocked(r, app, execInFg);
            return null;
        }
    }
    else // 如果目标 Service 要运行在独立的进程中
    {
        // 防止重复启动新进程
        app = r.isolatedProc;
    }

    // 如果需要启动新进程来运行 Service
    if (app == null)
    {
        // 调用 AMS 的 startProcessLocked 函数,
        // 访问 Zygote 进程请求启动一个新进程用于运行目标 Service
        if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                "service", r.name, false, isolated, false)) == null)
        {
            // 如果新进程启动失败
            String msg = "Unable to launch app "
                    + r.appInfo.packageName + "/"
                    + r.appInfo.uid + " for service "
                    + r.intent.getIntent() + ": process is bad";
            // 执行清除操作,如解绑 Service、停止 Service
            bringDownServiceLocked(r);
            return msg;
        }
        if (isolated)
        {
            // 记录新启动的进程信息,防止重复启动
            r.isolatedProc = app;
        }
    }

    // 所有正在被启动的 Service 都缓存在 mPendingServices 中,
    // 如果目标 Service 的信息不在 mPendingServices 缓存中
    if (!mPendingServices.contains(r))
    {
        // 将目标 Service 的信息放入 mPendingServices 缓存
        mPendingServices.add(r);
    }

    return null;
}

ActiveServices.sendServiceArgsLocked()

// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg, 
		boolean oomAdjusted
){
    final int N = r.pendingStarts.size();
    // 只有当 startService 时,会将目标 Service 的信息缓存在 r.pendingStarts,N > 0;
    // 当 bindService 时,N = 0,
    // 所以 bindService 不会回调目标 Service 的 onStartCommand 函数
    if (N == 0)
    {
        return;
    }

    // 遍历 r.pendingStarts
    while (r.pendingStarts.size() > 0)
    {
        si = r.pendingStarts.remove(0);

        ......

        // AIDL 调用目标 Service 运行所在进程 ApplicationThread 的 scheduleServiceArgs 函数
        r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);

        ......
    }
}

ApplicationThread.scheduleServiceArgs() 函数会发送消息 (H.SERVICE_ARGS) 给 ActivityThread 中的内部类 H (Handler),执行 ActivityThread.handleServiceArgs() 函数

ActivityThread.handleServiceArgs() 函数会回调目标 Service 的 onStartCommand() 函数

ActiveServices.realStartServiceLocked()

// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private final void realStartServiceLocked(ServiceRecord r, 
		ProcessRecord app, boolean execInFg
){
    ......

    // AIDL 调用目标 Service 运行所在进程 ApplicationThread 的 scheduleCreateService 函数
    app.thread.scheduleCreateService(r, r.serviceInfo, 
            mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), 
            app.repProcState);

    ......

    // 回调目标 Service 的 onStartCommand 函数
    sendServiceArgsLocked(r, execInFg, true);

    ......
}

ApplicationThread.scheduleCreateService() 函数会发送消息 (H.CREATE_SERVICE) 给 ActivityThread 中的内部类 H (Handler),执行 ActivityThread.handleCreateService() 函数

// frameworks/base/core/java/android/app/ActivityThread.java
private void handleCreateService(CreateServiceData data)
{
    ......

    Service service = null;

    // 通过反射创建 Service 实例
    java.lang.ClassLoader cl = packageInfo.getClassLoader();
    service = (Service) cl.loadClass(data.info.name).newInstance();

    ......

    // 为此 Service 创建上下文
    ContextImpl context = ContextImpl.createAppContext(this, packageInfo);

    Application app = packageInfo.makeApplication(false, mInstrumentation);
    // 初始化参数
    service.attach(context, this, data.info.name, data.token, app,
            ActivityManagerNative.getDefault());
    // 回调 Service 的 onCreate 函数
    service.onCreate();
    // 将 Service 保存在 mServices 缓存中
    mServices.put(data.token, service);

    ......
}

AMS.startProcessLocked()

如果需要启动新进程来运行目标 Service 时,就会调用 ActivityManagerService.startProcessLocked() 函数访问 Zygote 进程请求启动一个新进程用于运行目标 Service

当目标 Service 运行所在进程启动后,就会进行初始化,调用到 ActivityThread 的 main() 函数

// frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args)
{
    ......

    thread.attach(false, startSeq);

    ......
}

private void attach(boolean system, long startSeq)
{
    ......

    // AIDL 调用 AMS 的 attachApplication 函数
    final IActivityManager mgr = ActivityManagerNative.getService();
    mgr.attachApplication(mAppThread);

    ......
}

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final void attachApplication(IApplicationThread thread)
{
    ......

    attachApplicationLocked(thread, callingPid);

    ......
}

private final boolean attachApplicationLocked(IApplicationThread thread, int pid)
{
    ......

    boolean badApp = false;

    ......

    if (!badApp)
    {
        // 调用 ActiveServices 的 attachApplicationLocked 函数
        didSomething |= mServices.attachApplicationLocked(app, processName);
    }

    ......

    return true;
}

// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
boolean attachApplicationLocked(ProcessRecord proc, String processName)
{
    boolean didSomething = false;
    // 所有正在被启动的 Service 都缓存在 mPendingServices 中,
    // 如果 mPendingServices.size() > 0,说明还有 Service 需要被启动
    if (mPendingServices.size() > 0)
    {
        ServiceRecord sr = null;
        // 遍历 mPendingServices
        for (int i=0; i<mPendingServices.size(); i++)
        {
            sr = mPendingServices.get(i);
            // 如果 Service 不是运行在本进程中,就 continue 跳过本次循环
            if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                    || !processName.equals(sr.processName)))
            {
                continue;
            }

            mPendingServices.remove(i);
            i--;
            proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
                    mAm.mProcessStats);
            // 创建 Service 实例
            realStartServiceLocked(sr, proc, sr.createdFromFg);
            didSomething = true;
        }
    }

    ......

    return didSomething;
}

bindService 流程

ContextImpl.bindService()

// frameworks/base/core/java/android/app/ContextImpl.java
public boolean bindService(Intent service, ServiceConnection conn, int flags)
{
    warnIfCallingFromSystemProcess();
    return bindServiceCommon(service, conn, flags, Process.myUserHandle());
}

ContextImpl.bindServiceCommon()

// frameworks/base/core/java/android/app/ContextImpl.java
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
		UserHandle user
){
    IServiceConnection sd;

    ......

    // APK 包信息不为空,if 命中
    if (mPackageInfo != null)
    {
        // 调用 LoadedApk 的 getServiceDispatcher 函数,
        // 从 mServices 缓存中获取 ServiceConnection 的 Binder 通信接口
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
                mMainThread.getHandler(), flags);
    }

    ......

    // AIDL 调用 AMS 的 bindService 函数
    int res = ActivityManagerNative.getDefault().bindService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfNeeded(getContentResolver()),
            sd, flags, getOpPackageName(), user.getIdentifier());

    ......

    return res != 0;
}

所有可用 (已注册的) 的 Service 信息都保存在 mServices 缓存中

mServices 是一个 ArrayMap,以 Context 为 key,以 ServiceDispatcher 为 value

可以把 ServiceDispatcher 理解为是一个对于 ServiceConnection 及其 Binder 通信接口的封装类

AMS.bindService()

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public int bindService(IApplicationThread caller, IBinder token, 
		Intent service, String resolvedType, IServiceConnection connection, 
		int flags, String callingPackage, int userId
){
    ......

    // 调用 ActiveServices 的 bindServiceLocked 函数
    return mServices.bindServiceLocked(caller, token, service,
            resolvedType, connection, flags, callingPackage, userId);
}

ActiveServices.bindServiceLocked()

// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
int bindServiceLocked(IApplicationThread caller, IBinder token, 
		Intent service, String resolvedType, IServiceConnection connection, 
		int flags, String callingPackage, int userId
){
    ......

    // 获取目标 Service 的信息 (ServiceRecord)
    ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);

    ......

    ServiceRecord s = res.record;
    
    ......

    // 获取目标 Service 与 APP 进程的绑定记录 (AppBindRecord)
    // 每个 APP 进程与 Service 的绑定都会对应一个 AppBindRecord 实例
    AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);

    ......

    // 如果 flag 设置了 BIND_AUTO_CREATE
    if ((flags&Context.BIND_AUTO_CREATE) != 0)
    {
        s.lastActivity = SystemClock.uptimeMillis();
        // 调用 ActiveServices 的 bringUpServiceLocked 函数,启动目标 Service
        if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null)
        {
            // 如果目标 Service 启动失败,则直接返回
            return 0;
        }
    }

    ......

    // 如果目标 Service 启动后与 APP 进程进行过绑定 (received = true),if 命中
    if (s.app != null && b.intent.received)
    {
        // AIDL 调用 APP 进程 InnerConnection 的 connected 函数
        c.conn.connected(s.name, b.intent.binder);

        // 如果当前只有该 APP 进程与目标 Service 进行绑定 (doRebind = true),
        // if 命中,回调目标 Service 的 onReBind 函数
        if (b.intent.apps.size() == 1 && b.intent.doRebind)
        {
            requestServiceBindingLocked(s, b.intent, callerFg, true);
        }
    }
    // 如果目标 Service 启动后首次与 APP 进程进行绑定 (requested = false),
    // else if 命中,回调目标 Service 的 onBind 函数
    else if (!b.intent.requested)
    {
        requestServiceBindingLocked(s, b.intent, callerFg, false);
    }

    ......

    return 1;
}

ActiveServices.requestServiceBindingLocked()

// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, 
		boolean execInFg, boolean rebind
){
    // 如果目标 Service 仍未启动,则直接返回
    if (r.app == null || r.app.thread == null)
    {
        return false;
    }

    // if 一定命中
    if ((!i.requested || rebind) && i.apps.size() > 0)
    {
        ......

        // AIDL 调用目标 Service 运行所在进程 ApplicationThread 的 scheduleBindService 函数
        r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                r.app.repProcState);
        if (!rebind)
        {
            i.requested = true;
        }

        i.doRebind = false;

        ......
    }
    return true;
}

ApplicationThread.scheduleBindService()

// frameworks/base/core/java/android/app/ActivityThread$ApplicationThread.java
public final void scheduleBindService(IBinder token, Intent intent, 
		boolean rebind, int processState
){
    BindServiceData s = new BindServiceData();
    s.token = token;
    s.intent = intent;
    s.rebind = rebind;

    // 发送消息 (H.BIND_SERVICE) 给 ActivityThread 中的内部类 H (Handler)
    sendMessage(H.BIND_SERVICE, s);
}

H.handleMessage()

// frameworks/base/core/java/android/app/ActivityThread$H.java
public void handleMessage(Message msg)
{
    switch (msg.what)
    {
        ......

        case BIND_SERVICE:
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
            handleBindService((BindServiceData)msg.obj);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            break;

        ......
    }
    
    ......
}

ActivityThread.handleBindService()

// frameworks/base/core/java/android/app/ActivityThread.java
private void handleBindService(BindServiceData data)
{
    // 查找 mServices 缓存中是否有目标 Service
    Service s = mServices.get(data.token);

    // 如果目标 Service 已启动,那么 mServices 中一定缓存了目标 Service,即 s 不为空
    if (s != null)
    {
        ......

        // 如果目标 Service 启动后首次与 APP 进程进行绑定
        if (!data.rebind)
        {
            // 回调目标 Service 的 onBind 函数
            IBinder binder = s.onBind(data.intent);
            // AIDL 调用 AMS 的 publishService 函数
            ActivityManagerNative.getDefault().publishService(
                    data.token, data.intent, binder);
        }
        // 如果目标 Service 启动后与 APP 进程进行过绑定且当前仅有该 APP 进程与之进行绑定
        else
        {
            // 回调目标 Service 的 onRebind 函数
            s.onRebind(data.intent);

            ......
        }

        ......
    }
}

AMS.publishService()

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void publishService(IBinder token, Intent intent, IBinder service)
{
    ......

    // 调用 ActiveServices 的 publishServiceLocked 函数
    mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}

// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service)
{
    ......

    // if 命中
    if (r != null)
    {
        ......

        IntentBindRecord b = r.bindings.get(filter);
        // 如果目标 Service 启动后首次与 APP 进程进行绑定 (received = false)
        if (b != null && !b.received)
        {
            b.binder = service;
            b.requested = true;
            b.received = true;
            // connections 缓存了所有与目标 Service 绑定的 ServiceConnection,
            // 遍历 connections 寻找本次绑定所对应的 ServiceConnection
            for (int conni=r.connections.size()-1; conni>=0; conni--)
            {
            	ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
            	for (int i=0; i<clist.size(); i++)
            	{
                    ConnectionRecord c = clist.get(i);
                    // 比较 intent,如果 intent 不同说明当前 ServiceConnection 不是对应本次绑定的,
                    // 则 continue 跳过本次循环
                    if (!filter.equals(c.binding.intent.intent))
                    {
                    	continue;
                    }

                    ......

                    // AIDL 调用 APP 进程 InnerConnection 的 connected 函数
                    c.conn.connected(r.name, service);

                    ......
            	}
            }
        }

        ......
    }

    ......
}

// frameworks/base/core/java/android/app/LoadedApk$ServiceDispatcher$InnerConnection.java
public void connected(ComponentName name, IBinder service)
{
    // 获取 ServiceDispatcher (弱引用,防止内存泄漏)
    LoadedApk.ServiceDispatcher sd = mDispatcher.get();
    if (sd != null)
    {
        sd.connected(name, service);
    }
}

// frameworks/base/core/java/android/app/LoadedApk$ServiceDispatcher.java
public void connected(ComponentName name, IBinder service)
{
    // mActivityThread = 主线程 Handler,不为空,if 命中
    if (mActivityThread != null)
    {
        // 发送消息给 ActivityThread 中的内部类 H (Handler)
        // 从 Binder 线程切换到主线程执行
        mActivityThread.post(new RunConnection(name, service, 0));
    }
    else
    {
        ......
    }
}

// frameworks/base/core/java/android/app/LoadedApk$ServiceDispatcher$RunConnection.java
public void run()
{
    // 此时 mCommand = 0,if 命中
    if (mCommand == 0)
    {
        doConnected(mName, mService);
    }
    else if (mCommand == 1)
    {
        ......
    }
}

// frameworks/base/core/java/android/app/LoadedApk$ServiceDispatcher.java
public void doConnected(ComponentName name, IBinder service)
{
    ......

    // service 不为空,if 命中
    if (service != null)
    {
        // 回调目标 ServiceConnection 的 onServiceConnected 函数
        mConnection.onServiceConnected(name, service);
    }
}

总结

本篇文章分析了 startService 和 bindService 这两种不同的启动流程,将其中对于我们开发者而言比较有意义的部分代码进行了分析

了解这两种启动流程,对于我们理解 Service 的运行和生命周期有着很大的帮助

但源码还是非常庞大的,没办法面面俱到,希望读者能够参照本篇文章尝试自己去阅读源码,加深理解