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 的运行和生命周期有着很大的帮助
但源码还是非常庞大的,没办法面面俱到,希望读者能够参照本篇文章尝试自己去阅读源码,加深理解