Service启动源码解析(Android12)

1,552 阅读11分钟

Android的知识体系搭建

一 概述

Service 的启动,应该是四大组件里最简单的,所以我们就从 Service 的启动开始,看来 ActivityManagerService 和四大组件的启动流程。

注:本文源码基于 Android12(android-12.0.0_r1)

二 Context

还是从 Context 出发,当我们调用 startService 的时候,会经过 Context -> ContextWrapper -> ComtextImpl 这个流程,最后调用到 AcitivityManagerService 里。

2.1 startService

[frameworks/base/core/java/android/app/ContextImpl.java]

@Override
public ComponentName startService(Intent service) {
    warnIfCallingFromSystemProcess();
    return startServiceCommon(service, false, mUser);
}

2.2 startServiceCommon



private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);

		// 通过 AMS 的Binder 对象,调用 startService
        ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service,
                service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
                getOpPackageName(), getAttributionTag(), user.getIdentifier());
        ...
}

三 ActivityManagerService

从这一步开始,调用就从应用进程转到了系统进程了。首先是 AMS 中,有一个 mServices 变量,它是一个 ActiveServices 对象。

3.1 startService


[frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java]

@Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage,
        String callingFeatureId, int userId)
        throws TransactionTooLargeException {
	   ...


        try {
	        // mServices 是一个 ActiveServices 对象。
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, callingFeatureId, userId);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return res;
    }
}

调用 ActiveServices 的 startServiceLocked。

四 ActiveServices

ActiveServices 中 startServiceLocked 的流程很长,所以我将其中不重要的代码省略了,只留下了主干代码。

4.1 startServiceLocked

[frameworks/base/services/core/java/com/android/server/am/ActiveServices.java]

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
    int callingPid, int callingUid, boolean fgRequired,
    String callingPackage, @Nullable String callingFeatureId, final int userId,
    boolean allowBackgroundActivityStarts, @Nullable IBinder backgroundActivityStartsToken)
    throws TransactionTooLargeException {

// 是否是前台服务
final boolean callerFg;
if (caller != null) {
    final ProcessRecord callerApp = mAm.getRecordForAppLOSP(caller);
    if (callerApp == null) {
       ...	// 异常处理
    }
    callerFg = callerApp.mState.getSetSchedGroup() != ProcessList.SCHED_GROUP_BACKGROUND;
} else {
    callerFg = true;
}

// 检索服务信息 [见4.2]
ServiceLookupResult res =
    retrieveServiceLocked(service, null, resolvedType, callingPackage,
            callingPid, callingUid, userId, true, callerFg, false, false);

// 一定要检索到对应的服务才能执行后面的流程
if (res == null) {
    return null;
}

if (res.record == null) {
    return new ComponentName("!", res.permission != null
            ? res.permission : "private to package");
}

// res.record 其实就是 ServiceRecord,就是我们要启动的服务
ServiceRecord r = res.record;
setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, r, userId,
        allowBackgroundActivityStarts);

if (!mAm.mUserController.exists(r.userId)) {
    Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId);
    return null;
}

// 是否后台启动服务
final boolean bgLaunch = !mAm.isUidActiveLOSP(r.appInfo.uid);

//
boolean forcedStandby = false;
if (bgLaunch && appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
    forcedStandby = true;
}
... // 省略代码

// 静默禁止标志,如果权限判断不通过,切有此标志,那么会终止启动服务切不通知用户
boolean forceSilentAbort = false;

// 权限判断,是否可以直接前台启动服务
if (fgRequired) {
       ... // 省略代码
}

//不是直接前台启动服务的权限判断,例如应用是否可以后台启动服务
if (forcedStandby || (!r.startRequested && !fgRequired)) {
   ... // 省略代码
}

... // 省略代码,后面都是权限判断的相关逻辑

// 启动服务的代码
return startServiceInnerLocked(r, service, callingUid, callingPid, fgRequired, callerFg,
        allowBackgroundActivityStarts, backgroundActivityStartsToken);
}


在 ActiveServices 的 startServiceLocked 中,首先会检索对应的 Service,它用 ServiceRecord 封装,然后保存到了 ServiceLookupResult 中。

4.2 retrieveServiceLocked

retrieveServiceLocked 就是查找 Service 信息,这个信息会封装在一个 ServiceRecord 中,后续再来查找就可以复用这个信息。

private ServiceLookupResult retrieveServiceLocked(Intent service,
        String instanceName, String resolvedType, String callingPackage,
        int callingPid, int callingUid, int userId,
        boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
        boolean allowInstant) {
    ServiceRecord r = null;

    // 获取 userId
    userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId,
            /* allowAll= */false, getAllowMode(service, callingPackage),
            /* name= */ "service", callingPackage);

    // 在 ActiveServices 中有一个 SparseArray
    // 这里是通过 userId 查询 SparseArray 中对应的 ServiceMa
    ServiceMap smap = getServiceMapLocked(userId);

    // 获取 Service 全类名
    // 全类名 = 包名 + 类名 + instanceName,这里 instanceName 是 null
    final ComponentName comp;
    if (instanceName == null) {
        comp = service.getComponent();
    } else {
        final ComponentName realComp = service.getComponent();
        comp = new ComponentName(realComp.getPackageName(),
                realComp.getClassName() + ":" + instanceName);
    }

    // 在 ServiceMap 中查询 Service 信息,保存在 ServiceRecord 中
    if (comp != null) {
        r = smap.mServicesByInstanceName.get(comp);
    }
    //通过 filter 来查询 Service
    if (r == null && !isBindExternal && instanceName == null) {
        Intent.FilterComparison filter = new Intent.FilterComparison(service);
        r = smap.mServicesByIntent.get(filter);
    }

    ... // 代码省略

    // 如果没有拿到 ServiceRecord
    if (r == null) {
        try {
            ... // 代码省略

            if (userId > 0) {
                if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
                        sInfo.name, sInfo.flags)
                        && mAm.isValidSingletonCall(callingUid, sInfo.applicationInfo.uid)) {
                    userId = 0;
                    smap = getServiceMapLocked(0);
                    // Bypass INTERACT_ACROSS_USERS permission check
                    final long token = Binder.clearCallingIdentity();
                    try {

                    	// 没有可以复用的 ServiceRecord,则需要去 Apk 中查找,查找功能 PMS 完成
                    	// 这里是通过 AMS 拿到 PMS
                        ResolveInfo rInfoForUserId0 =
                                mAm.getPackageManagerInternal().resolveService(service,
                                        resolvedType, flags, userId, callingUid);
                        if (rInfoForUserId0 == null) {
                            return null;
                        }
                        sInfo = rInfoForUserId0.serviceInfo;
                    } finally {
                        Binder.restoreCallingIdentity(token);
                    }
                }
                sInfo = new ServiceInfo(sInfo);
                sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
            }
            ... // 代码省略
        } catch (RemoteException ex) {
            // pm is in same process, this will never happen.
        }
    }

    ... // 代码省略
    return null;
}

查找 Service 信息首先会根据用户的 userId 查找,看看 ActiveService 里有没有现成的,有就直接获取。 如果没有,就需要通过 PMS 解析,然后再将它封装到 ServiceRecord 中。

4.3 startServiceInnerLocked

在 ActiveServices 中,存在两个 startServiceInnerLocked 函数,它们的参数不同,第一个 startServiceInnerLocked 会在结尾调用第二个,所以我们先看第一个函数。

第一个 startServiceInnerLocked

private ComponentName startServiceInnerLocked(ServiceRecord r, Intent service,
		int callingUid, int callingPid, boolean fgRequired, boolean callerFg,
		boolean allowBackgroundActivityStarts, @Nullable IBinder backgroundActivityStartsToken)
		throws TransactionTooLargeException {

	... // 省略代码

	r.lastActivity = SystemClock.uptimeMillis();
	r.startRequested = true;
	r.delayedStop = false;
	r.fgRequired = fgRequired;
	r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
			service, neededGrants, callingUid));

	... // 省略代码
	ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
	return cmp;
}

在第一个 startServiceInnerLocked 中,我们需要注意到,系统将我们需要启动的 Service 添加到了一个 pendingStarts 的集合。这个集合后续就是回调我们 Service 生命周期用的。

第二个 startServiceInnerLocked

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
        boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
    synchronized (mAm.mProcessStats.mLock) {
        final ServiceState stracker = r.getTracker();
        if (stracker != null) {
            stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
        }
    }
    r.callStart = false;

    final int uid = r.appInfo.uid;
    final String packageName = r.name.getPackageName();
    final String serviceName = r.name.getClassName();
    FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_STATE_CHANGED, uid, packageName,
            serviceName, FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__START);
    mAm.mBatteryStatsService.noteServiceStartRunning(uid, packageName, serviceName);


    // 启动 Service
    String error = bringUpServiceLocked(r, service.getFlags(), callerFg,
            false /* whileRestarting */,
            false /* permissionsReviewRequired */,
            false /* packageFrozen */,
            true /* enqueueOomAdj */);
    /* Will be a no-op if nothing pending */

    ... // 代码省略
    return r.name;
}

4.4 bringUpServiceLocked

bringUpServiceLocked 这个函数很长,其实逻辑很简单

  1. 如果服务所在的进程存在,就直接回调服务的函数。
  2. 如果服务所在的进程不存在,就先启动服务进程。

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
        boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen,
        boolean enqueueOomAdj)
        throws TransactionTooLargeException {

	// 如果服务所在是进程 ActivityThread 存在,就调用 sendServiceArgsLocked
	// 最后调用到 ActivityThread 中的 scheduleServiceArgs
	// 然后是 handleServiceArgs -> service.onStartCommand
    if (r.app != null && r.app.getThread() != null) {
        sendServiceArgsLocked(r, execInFg, false);
        return null;
    }

    if (!whileRestarting && mRestartingServices.contains(r)) {
        // 如果服务在重启,就什么也不做
        return null;
    }

    if (mRestartingServices.remove(r)) {
        clearRestartingIfNeededLocked(r);
    }

    // 如果服务有延迟启动的标志也去掉,因为现在已经开始启动服务了
    if (r.delayed) {
        getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
        r.delayed = false;
    }

    // 确保服务所在的user已经启动,否则停止。
    if (!mAm.mUserController.hasStartedUserState(r.userId)) {
        // 终止启动服务
        bringDownServiceLocked(r, enqueueOomAdj);
        return msg;
    }

    ... // 省略代码

    if (!isolated) {

		// 先根据进程名和uid,查询进程是否存在
        app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);

        if (app != null) {
	        // 进程存在,就直接启动服务
            final IApplicationThread thread = app.getThread();
            final int pid = app.getPid();
            final UidRecord uidRecord = app.getUidRecord();
            if (thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode,
                            mAm.mProcessStats);

					// 真正启动服务的函数
                    realStartServiceLocked(r, app, thread, pid, uidRecord, execInFg,
                            enqueueOomAdj);
                     // 注意,如果是启动服务,就从这里返回了
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
                }
            }
        }
    } else {
            ... // 代码省略
    }

    // 进程不存在,就要先启动进程
    if (app == null && !permissionsReviewRequired && !packageFrozen) {
	    // mAm 是 ActivityManagerService
	    // 这里就是启动进程的逻辑
        if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated)) == null) {
            // 进程启动失败,终止启动服务
            bringDownServiceLocked(r, enqueueOomAdj);
            return msg;
        }
        if (isolated) {
            r.isolatedProc = app;
        }
    }

    ... // 省略代码

	// 前面进程存在,启动服务的已经返回了,进程不存在的还在启动进程,
	// 所以我们只能先将要启动的服务添加到 mPendingServices 中,等进程启动完成之后
	// 再来启动我们的服务
	if (!mPendingServices.contains(r)) {
		mPendingServices.add(r);
	}

     ... // 代码省略

    return null;
}

4.5 realStartServiceLocked

private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
        IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg,
        boolean enqueueOomAdj) throws RemoteException {
    ... // 代码省略

	// 判断超时
    bumpServiceExecutingLocked(r, execInFg, "create", null /* oomAdjReason */);

     ... // 代码省略
    try {

          ... // 代码省略

         // scheduleCreateService
         // 调用 Service 的 onCreate
        thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                app.mState.getReportedProcState());
        r.postNotification();
        created = true;
    } catch (DeadObjectException e) {
        Slog.w(TAG, "Application dead when creating service " + r);
        mAm.appDiedLocked(app, "Died when creating service");
        throw e;
    } finally {
        if (!created) {
            // Keep the executeNesting count accurate.
            final boolean inDestroying = mDestroyingServices.contains(r);
            serviceDoneExecutingLocked(r, inDestroying, inDestroying, false);

            // Cleanup.
            if (newService) {
                psr.stopService(r);
                r.setProcess(null, null, 0, null);
            }

            // Retry.
            if (!inDestroying) {
	            // 服务启动失败,重试一次
                scheduleServiceRestartLocked(r, false);
            }
        }
    }

    if (r.allowlistManager) {
        psr.mAllowlistManager = true;
    }

	// 请求 Service 绑定 [见9.3]
    requestServiceBindingsLocked(r, execInFg);

      ... // 代码省略

	// 调用 Service 的 onStartCommand
    sendServiceArgsLocked(r, execInFg, true);

    if (r.delayedStop) {
        r.delayedStop = false;
        if (r.startRequested) {
            // 停止服务
            stopServiceLocked(r, enqueueOomAdj);
        }
    }
}

realStartServiceLocked 名字就是看得出来,它的真正启动服务的函数,所以这里会做启动服务的操作,后续还会回调 Service 对应的生命周期。

  • scheduleCreateService -> 调用 Service 的 onCreate
  • sendServiceArgsLocked -> 通过 r.app.getThread().scheduleServiceArgs -> ActivityThread.handleServiceArgs 调用到 Service 的 onStartCommand

然后关于 Service 启动时,出现的 ANR 也是这里进行的。

然后这里还有一个 scheduleServiceRestartLocked,它是用于服务重启的,服务启动失败是会自动重启的,这个函数会将要重启的服务,添加到一个 pendingStarts 集合,然后调用到 startServiceInnerLocked 中进行启动服务的操作。

关于服务重启的流程,这里就不扩展了,服务重启的相关参数也会保存到 ServiceRecord 中,并且如果重启失败,重启的次数也会记录在 ServiceRecord 中,重启失败的次数越多,下次重启所延迟的时间也就越久。

4.6 bumpServiceExecutingLocked

    private boolean bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why,
            @Nullable String oomAdjReason) {

        ... // 省略代码

        if (r.executeNesting == 0) {
            r.executeFg = fg;
            ...

            if (r.app != null) {
                psr = r.app.mServices;
                psr.startExecutingService(r);
                psr.setExecServicesFg(psr.shouldExecServicesFg() || fg);
                if (timeoutNeeded && psr.numberOfExecutingServices() == 1) {
	       // 发送判断超时的消息
                    scheduleServiceTimeoutLocked(r.app);
                }
            }
        } else if (r.app != null && fg) {
            psr = r.app.mServices;
            if (!psr.shouldExecServicesFg()) {
                psr.setExecServicesFg(true);
                if (timeoutNeeded) {
	       // 发送判断超时的消息
                    scheduleServiceTimeoutLocked(r.app);
                }
            }
        }

        ... // 省略代码
        return oomAdjusted;
    }

4.7 scheduleServiceTimeoutLocked


// 前台超时时间是 20 秒
static final int SERVICE_TIMEOUT = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;

// 后台超时时间是前台的 10 倍
static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;

void scheduleServiceTimeoutLocked(ProcessRecord proc) {
	...

	Message msg = mAm.mHandler.obtainMessage(
			ActivityManagerService.SERVICE_TIMEOUT_MSG);
	msg.obj = proc;
	// 发送一个延迟消息,到时候服务服务还没有启动,就会报 ANR
	// mAm 是 ActivityManagerService
	mAm.mHandler.sendMessageDelayed(msg, proc.mServices.shouldExecServicesFg()
			? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
}

在 scheduleServiceTimeoutLocked 函数中发送了一个延迟消息,前台和后台的服务时间是不一样的,如果到了时间这个消息还没有被移除,那么就会在 ActivityManagerService 中处理这条消息。这里的调用很简单,最后会调用到 ActiveServices 的 serviceTimeout 中。

void serviceTimeout(ProcessRecord proc) {
	... // 省略代码

	if (anrMessage != null) {
		// 最后调用 AMS 中的 mAnrHelper.appNotResponding
		mAm.mAnrHelper.appNotResponding(proc, anrMessage);
	}
}

4.8 sendServiceArgsLocked

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

	ArrayList<ServiceStartArgs> args = new ArrayList<>();

	... // 省略代码
	try {
		r.app.getThread().scheduleServiceArgs(r, slice);
	} catch (TransactionTooLargeException e) {

	... // 省略代码
}

最后再来看一下 onStartCommand 生命周期是如何回调的,在 sendServiceArgsLocked 函数中首先会判断 pendingStarts 这个集合是否为空。

之前的 realStartServiceLocked 中已经将我们要启动的 Service 添加进去了,然后在这里通过 r.app.getThread().scheduleServiceArgs 调用到 ActivityThread 中,最后通过 Handler 机制切换线程,调用到 Service 的 onStartCommand 中。

到此,Service 的 startService 启动流程我们就梳理完一半了。

五 进程启动后

前面的 [4.4] 中我们详细说了如果进程存在,我们可以直接启动服务,那么如果进程不存在呢?我们还要先启动进程。

启动进程的流程很长,它需要 Zygote 先 fork 出我们需要的进程,然后执行 Application 的启动,这里我们就不详细说明这个流程了,后续会单独说明。当进程启动完成之后,会回调到 AMS 中的 attachApplicationLocked 这个函数,而在这个函数中,又会回调到 ActiveServices 的 attachApplicationLocked。

5.1 attachApplicationLocked

    boolean attachApplicationLocked(ProcessRecord proc, String processName)
            throws RemoteException {
        boolean didSomething = false;
        // mPendingServices 就是我们之前添加的服务,这里取出来
        if (mPendingServices.size() > 0) {
            ServiceRecord sr = null;
            try {
                for (int i=0; i<mPendingServices.size(); i++) {
                    sr = mPendingServices.get(i);
                    ... // 省略代码

		            // 启动服务后面的流程 [见4.4]
                    realStartServiceLocked(sr, proc, thread, pid, uidRecord, sr.createdFromFg,
                            true);
                    didSomething = true;
                    ...

                }
            } catch (RemoteException e) {
                throw e;
            }
        }
        ... // 省略代码
        return didSomething;
    }

可见,如果 Service 所在的进程没有启动,在进程启动后,依旧会走 realStartServiceLocked 这条服务启动的流程。

六 startService 小结

到这里,startService 服务的启动流程已经走完了,虽然出现了几种不同的场景,不过系统的大致思路我们可以总结一下

  1. 首先是参数判断和权限的判断,各种权限判断服务是否可以启动,是否需要终止等等
  2. 然后就是复用的判断,判断是否有 ServiceRecord 可以复用
  3. 最后就是进程的判断,是否已经启动,然后根据已启动和未启动做相应的流程
  4. 然后再通过一条延迟消息,判断服务启动是否会 ANR

七 bindService

前面说了 startService 的流程,接下来我们说说 bindService。 bindService 也是从 ComtextImpl 开始,分别调用

  • ComtextImpl.bindService
  • ComtextImpl.bindServiceCommon
  • ActivityManagerService.bindIsolatedService

八 ActivityManagerService

8.1 bindIsolatedService

public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service,
		String resolvedType, IServiceConnection connection, int flags, String instanceName,
		String callingPackage, int userId) throws TransactionTooLargeException {
	... // 省略代码

	synchronized(this) {
		return mServices.bindServiceLocked(caller, token, service,
				resolvedType, connection, flags, instanceName, callingPackage, userId);
	}
}

九 ActiveServices

9.1 bindServiceLocked

bindServiceLocked 这个函数非常长,所以我省略了大部分代码只保留了主干代码。

int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
		String resolvedType, final IServiceConnection connection, int flags,
		String instanceName, String callingPackage, final int userId)
		throws TransactionTooLargeException {

	final int callingPid = Binder.getCallingPid();
	final int callingUid = Binder.getCallingUid();
	final ProcessRecord callerApp = mAm.getRecordForAppLOSP(caller);


	ActivityServiceConnectionsHolder<ConnectionRecord> activity = null;
	if (token != null) {
		// mAtmInternal 其实就是 ActivityTaskManagerService
		// 这里拿到的 ActivityServiceConnectionsHolder 其实就是
		// activity 和 service 的数据组合
		activity = mAm.mAtmInternal.getServiceConnectionsHolder(token);
		if (activity == null) {
			return 0;
		}
	}

	... //  这里省略大段的权限判断

	// 检索服务信息 [见9.3]
	ServiceLookupResult res =
		retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
				callingPid, callingUid, userId, true,
				callerFg, isBindExternal, allowInstant);
	if (res == null) {
		return 0;
	}
	if (res.record == null) {
		return -1;
	}
	ServiceRecord s = res.record;

	... // 省略代码

	try {
		... // 省略代码

		// 将要绑定的 Service 添加到 AppBindRecord 集合 [见9.2]
		AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
		ConnectionRecord c = new ConnectionRecord(b, activity,
				connection, flags, clientLabel, clientIntent,
				callerApp.uid, callerApp.processName, callingPackage);

		IBinder binder = connection.asBinder();
		s.addConnection(binder, c);
		b.connections.add(c);
		if (activity != null) {
			activity.addConnection(c);
		}
		final ProcessServiceRecord clientPsr = b.client.mServices;
		clientPsr.addConnection(c);
		c.startAssociationIfNeeded();

		... // 省略代码

		// 如果
		if ((flags&Context.BIND_AUTO_CREATE) != 0) {
			s.lastActivity = SystemClock.uptimeMillis();
			needOomAdj = true;

			// 如果 Service 没有启动,但是又有自动创建的标志
			// BIND_AUTO_CREATE
			// 那么久会触发 Service 的启动流程 [见4.3]
			if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
					permissionsReviewRequired, packageFrozen, true) != null) {
				mAm.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
				return 0;
			}
		}

		... // 省略代码

		if (s.app != null && b.intent.received) {
			try {
				// 服务已经启动起来了,我们调用 connected 函数
				c.conn.connected(s.name, b.intent.binder, false);
			} catch (Exception e) {
			}
		... // 省略代码
	return 1;
}

在 bindServiceLocked 函数中,主要做了这样几件事

  • 将 Activity 和 Service 关联,保存在 ActivityServiceConnectionsHolder 中
  • 如果有 BIND_AUTO_CREATE 标志,并且服务部存在就会创建服务
  • 通过 connected 调用 Service 的 onServiceConnected 函数

9.2 retrieveAppBindingLocked

public AppBindRecord retrieveAppBindingLocked(Intent intent,
		ProcessRecord app) {

	// 将 intent 封装成一个 Intent.FilterComparison
	// 并将 filter 保存到 bindings 这个 Map 集合中
	Intent.FilterComparison filter = new Intent.FilterComparison(intent);
	IntentBindRecord i = bindings.get(filter);
	if (i == null) {
		i = new IntentBindRecord(this, filter);
		bindings.put(filter, i);
	}
	AppBindRecord a = i.apps.get(app);
	if (a != null) {
		return a;
	}
	a = new AppBindRecord(this, i, app);
	i.apps.put(app, a);
	return a;
}

ActiveService 中有一个 bindings 成员变量,它是一个 Map 集合,保存了 Intent 和 IntentBindRecord 的关系。这个 Intent 就是要绑定的 Service。

9.3 requestServiceBindingsLocked

private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg) throws TransactionTooLargeException {
	for (int i=r.bindings.size()-1; i>=0; i--) {
		IntentBindRecord ibr = r.bindings.valueAt(i);
		// 从 ServiceRecord 中取出 IntentBindRecord
		// 然后再调用 requestServiceBindingLocked
		if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
			break;
		}
	}
}

在 requestServiceBindingsLocked 中,会取出 bindings 里保存的 IntentBindRecord,然后分别调用 requestServiceBindingLocked 进行绑定。

9.4 requestServiceBindingLocked

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
		boolean execInFg, boolean rebind) throws TransactionTooLargeException {

	if ((!i.requested || rebind) && i.apps.size() > 0) {
		try {
			bumpServiceExecutingLocked(r, execInFg, "bind",
					OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);

			// 调用 ActivityThread 的 scheduleBindService
			// 最后会调用到 Service 的 onBind
			r.app.getThread().scheduleBindService(r, i.intent.getIntent(), rebind,
					r.app.mState.getReportedProcState());
			if (!rebind) {
				i.requested = true;
			}
			i.hasBound = true;
			i.doRebind = false;
		} catch (TransactionTooLargeException e) {
			...
		}
	}
	return true;
}

在 requestServiceBindingLocked 中,会调用 r.app.getThread 拿到 ActivityThread,然后调用 scheduleBindService,这个函数会通过消息机制进行如下调用。

  • ActivityThread.scheduleBindService
  • ActivityThread.handleBindService
  • Service.onBind

这部分比较简单,这里就不详细扩展了。

总结

最后再来总结一下 Service 的启动流程,Service 的启动分为两种

  • 第一种是 activity.startService
  • 第二种是 activity.bindService

当然,不论是哪一种,整个过程会有四个进程参与,一个是 App 进程,一个是 AMS 所在是进程(system_server 进程),还有一个就是 Zygote 进程,最后则是 Service 所在进程。

对应 startService,整体的启动流程如下

  1. APP 进程发起 startService 的请求,然后经过一下调用
    1. ContextWrapper.startService
    2. ContextImpl.startService
    3. ContextImpl.startServiceCommon
    4. 接下来进入 AMS 所在的 system_server 进程
  2. 在 AMS 中,有一个专门用于服务相关的类 ActiveServices 进行处理,大致的处理流程如下
    1. 服务的判断(前台还是后台)
    2. 权限的判断
    3. 启动服务(又分为 Service 所在的进程已启动还是未启动)
      1. 进程未启动:先启动进程,将服务添加到 mPendingServices 中。然后在进程启动后的 attachApplicationLocked 中启动服务
      2. 进程已启动,直接启动服务
    4. 发送延迟消息判断 ANR
  3. 在 Service 进程的 ActivityThread 中,通过消息机制,切换线程,并回调到 Service 的生命周期函数

流程图如下

startService启动过程.png

对于 bindService,整体流程如下

  1. APP 进程发起 bindService 的请求,然后经过一下调用
    1. ContextWrapper.bindService
    2. ContextImpl.bindService
    3. ContextImpl.bindServiceCommon
    4. 接下来进入 AMS 所在的 system_server 进程
  2. 在 AMS 中,有一个专门用于服务相关的类 ActiveServices 进行处理,大致的处理流程如下
    1. 服务的判断(前台还是后台),权限的判断和启动服务的逻辑都和 startService 一样
    2. bindService 会将 Service 和 Activity 封装到一个对应的数据结构 ConnectionRecord 中
    3. 要绑定的 Service 会保存到 ActiveServices 的成员变量 bindings 中,方便后续调用生命周期 onBind
  3. 在 Service 进程的 ActivityThread 中,通过消息机制,切换线程,并回调到 Service 的生命周期 onBind 函数

流程图如下

bindService启动过程.png