Service 的启动原理
1.Service 的启动有哪几种方式
2.Service 启动过程中主要流程有哪些
3.Service 启动过程中涉及哪些参与者,通信过程是怎样的
startService()
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
ContextImpl 的 startService()
// 调用了 startService 下面的 startServiceCommon() 函数
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
// 拿到了 AMS 的 binder 对象,然后调用 AMS 的 startService() 函数 同时把 applicationThread binder 对象作为参数给 AMS 传入。
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
// 。。。
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
startServiceCommon() 函数,拿到了 AMS 的 binder 对象,然后调用其 startService() 函数,并把 ApplicationThread 作为参数给 AMS 传过去。
- 接下来看一下 AMS 的 startService() 函数。
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
synchronized(this) {
ComponentName res;
try {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
AMS 的 startService 中调用了ActiveServices 的 mServices.startServiceLocked() 方法
- mServices.startServiceLocked()
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,...)throws TransactionTooLargeException {
// 根据传入的 Intent 查找到 ServiceRecord 对象。
ServiceLookupResult res =
retrieveServiceLocked(service, 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");
}
// 每个应用端都会有一个 ServiceRecord 对象
ServiceRecord r = res.record;
// 。。。。
// new 了一个 ServiceRecord.StartItem 添加到 pendingStarts ,这个是为了启动后调用 onStartCommond() 用
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
service, neededGrants, callingUid));
// 最后调用了 startServiceInnerLocked() 函数
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
startServiceLocked 获取到的 ServiceRecord 是每个应用都会有的一个对象,记录了应用内运行的或者将要运行的Service 信息。然后把将要启动的Service创建一个 ServiceRecord.StartItem对象添加到代执行列表pendingStarts中,最后调用 startServiceInnerLocked 继续启动流程
- startServiceInnerLocked()
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
// 调用了 bringUpServiceLocked() 继续流程
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
}
- bringUpServiceLocked()
private String bringUpServiceLocked(ServiceRecord r,....){
// 首先查看 Service 是否启动了 app 代表 Service 所在的进程
if (r.app != null && r.app.thread != null) {
// 如果启动了则 调用sendServiceArgsLocked() 其内部线从通过pendingStarts取到Service,然后通过 binder 调用回调到应用端的 Service 的 onStartCommand() 方法。
sendServiceArgsLocked(r, execInFg, false);
return null;
}
// 下面是 Service 还没有启动的情况
ProcessRecord app;
// 先判断进程是否启动了
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
// 如果进程已经启动
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
// 调用 realStartServiceLocked() 真正的启动 Service 去
realStartServiceLocked(r, app, execInFg);
// 然后结束方法 返回 null
return null;
}
}
// 如果进程未启动 或者 app 还没有就绪
if (app == null && !permissionsReviewRequired) {
// 调用 startProcessLocked() 去先启动进程
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, r.name, false, isolated, false)) == null) {
bringDownServiceLocked(r);
return msg;
}
}
// 然后将 ServiceRecord 添加到 mPendingServices列表中;mPendingServices 是用来等进程启动后再来处理 Service 的启动。
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
}
回顾一下之前讲过的进程启动流程
Android Application 的理解
Zygote 启动应用程序流程
Android启动流程大致如下:
当应用启动之后,应用会通过 attachApplication() 处理一些应用组件。
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// 内部会调用这行代码 继续处理 Service 的信息
mServices.attachApplicationLocked(app, processName);
return true;
}
- ActiveServices 的 mServices.attachApplicationLocked(app, processName);
boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
boolean didSomething = false;
if (mPendingServices.size() > 0) {
ServiceRecord sr = null;
// for 循环里处理每一个 service 信息
for (int i=0; i<mPendingServices.size(); i++) {
// ...
realStartServiceLocked(sr, proc, sr.createdFromFg);
}
}
// ...
return didSomething;
}
attachApplicationLocked() 内部通过 for 循环为每个 Service 调用了 realStartServiceLocked() 函数
- realStartServiceLocked() 真正启动 service 的方法
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
// app.thread为 binder 调用,调用到了 应用端的ApplicationThread 的 scheduleCreateService() 函数
// 然后执行 onCreate() 回调 ServiceRecord 其实是一个 binder 对象传回给了客户端,应用端给保存了下来
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
// 调用 sendServiceArgsLocked() 回调到应用端的 onStartCommond() 函数
sendServiceArgsLocked(r, execInFg, true);
}
realStartServiceLocked() 函数先是通过 IPC 调用了客户端的 ApplicationThread 的 scheduleCreateService() 函数进行创建 Service 同时调用 Service 的 onCreate() 函数,binder 调用时将 ServiceRecord 传回客户端。
- 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 信息,将 CreateServiceData() 传入 ,Handler 接收的时候调用了 handleCreateService((CreateServiceData)msg.obj); 函数,所以接下来直接看此函数内部时如何处理的。
- handleCreateService()
private void handleCreateService(CreateServiceData data) {
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
// 先通过 ClassLoader 创建 Service 类
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
}
try {
// 先创建 context 对象
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
// 创建 application 对象,创建好直接返回 application 对象
Application app = packageInfo.makeApplication(false, mInstrumentation);
// 调用 Service 的 attach() 函数
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
// 调用 service.onCreate(); 函数
service.onCreate();
// 将 data.token 就是之前说的那个 ServiceRecord 存储 map 中
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
- sendServiceArgsLocked() 是怎么触发 onStartCommond() 函数的
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
final int N = r.pendingStarts.size();
try {
r.app.thread.scheduleServiceArgs(r, slice);
}
// ...
}
sendServiceArgsLocked 中通过 IPC 操作调用到了客户端 ApplicationThread 中的 scheduleServiceArgs() 函数
- scheduleServiceArgs()
public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
List<ServiceStartArgs> list = args.getList();
for (int i = 0; i < list.size(); i++) {
ServiceStartArgs ssa = list.get(i);
ServiceArgsData s = new ServiceArgsData();
s.token = token;
//...
sendMessage(H.SERVICE_ARGS, s);
}
}
在 scheduleServiceArgs 中 封装了 ServiceStartArgs 后通过 Hander 发送了 SERVICE_ARGS 消息。接收后的方法如下
case SERVICE_ARGS:
handleServiceArgs((ServiceArgsData)msg.obj);
break;
- handleServiceArgs()
private void handleServiceArgs(ServiceArgsData data) {
// 先获取到 Service
Service s = mServices.get(data.token);
if (s != null) {
try {
int res;
if (!data.taskRemoved) {
// 调用的Service 的 onStartCommand() 所以 onStartCommand 是在主线程掉用的
res = s.onStartCommand(data.args, data.flags, data.startId);
}
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
}
ensureJitEnabled();
}
}
}
总结一下启动流程
网上找了几张图
- 进程角度来看都有哪些参与启动 Service
Service 的绑定原理
bindService()
回忆一下 bindService() 的用法
// 定义 aidl 接口
IMyAidlInterface myAidlInterface;
// 创建 ServiceConnection
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myAidlInterface = myAidlInterface.Stub.asInterface(service);
// 发起接口调用
myAidlInterface.call();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private void bindService() {
// 调用 bindService
Intent intent = new Intent(this, MyService.class);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
}
-
总体流程图
-
bindService() 流程
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
}
- bindServiceCommon()
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd;
if (mPackageInfo != null) {
// 根据一个 ServiceConnection 生成一个 IServiceConnection;
// 因为 ServiceConnection 只是一个普通的接口,无法进行跨进程传输。所以通过 ServiceConnection 生成了一个 binder 对象
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
try {
IBinder token = getActivityToken();
// 通过上面为ServiceConnection生成的 binder 对象,生成了 IServiceConnection 传入给 AMS 的 bindeService
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
return res != 0;
}
bindServiceCommon() 先通过 getServiceDispatcher() 函数把 ServiceConnection 对象生成了一个 IServiceConnection 的 binder 对象,方便跨进程传输,IServiceConnection 引用了 ServiceConnection,所以可以跨进程调用。然后将 IServiceConnection 作为参数,调用了 AMS 的 bindService() 函数。
- getServiceDispatcher()
// 入参传入了 ServiceConnection 返回值是一个 IServiceConnection
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
// 先从 mServices 中获取ArrayMap
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
// 如果存在则尝试获取一下 看看是否创建过
sd = map.get(c);
}
if (sd == null) {
// 如果 ServiceDispatcher == null 则创建一个对象出来
sd = new ServiceDispatcher(c, context, handler, flags);
// 如果 map 也为 null 则创建一个 map 缓存数据添加到 mServices 中
if (map == null) {
map = new ArrayMap<>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
// sd.getIServiceConnection(); 就是生成 ServiceDispatcher 对象中的 binder 对象。
return sd.getIServiceConnection();
}
}
- ServiceDispatcher 对象
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mContext = context;
mActivityThread = activityThread;
// ...
}
- InnerConnection 类,它是一个 IServiceConnection.Stub 可以跨进程传递
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service, boolean dead)
throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead);
}
}
}
InnerConnection 传入了 ServiceDispatcher 对象,并设置了成员变量对他进行弱引用,当AMS 调用 connected 方法,mDispatcher 后去到 ServiceDispatcher ,然后调用 connected 方法。
- sd.connected(name, service, dead);
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
// 最后也会走 doConnected()
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
- doConnected(name, service, dead);
public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
synchronized (this) {
// 缓存中取 ServiceDispatcher.ConnectionInfo
old = mActiveConnections.get(name);
if (old != null && old.binder == service) {
// 如果缓存过 则直接 return 防止 onServiceConnected() 重复调用
return;
}
// service != null 代表绑定上了
if (service != null) {
// 创建 ConnectionInfo 对象
info = new ConnectionInfo();
info.binder = service;
//。。。
try {
// 添加到缓存
mActiveConnections.put(name, info);
} catch (RemoteException e) {
// This service was dead before we got it... just
// don't do anything with it.
mActiveConnections.remove(name);
return;
}
} else {
// 如果 service == null 代表已经断开 直接 清除缓存
mActiveConnections.remove(name);
}
}
if (old != null) {
// 这里面是代表 内部原理是 如果 binder 对象挂了 就会回调 onServiceDisconnected ,所以除了系统回收 要不然一般也收不到 onServiceDisconnected() 的回调
old.binder.unlinkToDeath(old.deathMonitor, 0);
}
// If there was an old service, it is now disconnected.
if (old != null) {
// 如果绑定过 old 但是 old.binder != service
// 那么上面没有 return 到,代表已经断开了 直接 onServiceDisconnected
// 基本上这种情况 onServiceDisconnected 方法也接收不到;
mConnection.onServiceDisconnected(name);
}
// If there is a new viable service, it is now connected.
if (service != null) {
// 绑定调用 onServiceConnected
mConnection.onServiceConnected(name, service);
}
}
IServiceConnection 和 ServiceConnection 并不是一对一的关系;一个 Context 和 一个 ServiceConnection 共同构成一个数据和 ServiceConnection关联,意思就是 同一个 ServiceConnection ,用不同的 Context 绑定的话会对应不同的 IServiceConnection;同样的 同一个 Context 绑定不同的 ServiceConnection 也是不同的 IServiceConnection。
- 接下来看看 ActivityManager.getService().bindService() 到底是怎么绑定的
public int bindService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String callingPackage,
int userId) throws TransactionTooLargeException {
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}
bindServiceLocked()
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection,...){
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
// 这个方法就是创建service的
bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired)
}
// 如果已经准备好了 并且已经报告给了AMS
if (s.app != null && b.intent.received) {
// 直接返回给应用端
c.conn.connected(s.name, b.intent.binder, false);
} else if (!b.intent.requested) {
// 去请求 AMS
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
}
bringUpServiceLocked() 这个函数上面 startService 的时候已经讲过了。区别是 bindeService 不会触发 onStartCommond() 回调。 那么 看看上面方法中的 requestServiceBindingLocked() 函数
- requestServiceBindingLocked()
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
// 先判断 service 是否启动了
if (r.app == null || r.app.thread == null) {
// If service is not currently running, can't yet bind.
return false;
}
// 判断是否绑定了 binder 对象 或者 是否触发了 rebind ;并且 需要 i.apps.size() > 0 代表当前有应用需要绑定
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
}
}
return true;
}
- 调用应用端 r.app.thread.scheduleBindService() 最终会通过 handler 调用到 handleBindService()
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (DEBUG_SERVICE)
Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
// 通过判断传回来的数据判断 onBind 还是 onRebind
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
// 通过 binder 调用 发布到 AMS
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
}
}
}
}
- AMS 的 publishService() 会调用到 mServices.publishServiceLocked((ServiceRecord)token, intent, service);
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
if (r != null) {
Intent.FilterComparison filter
= new Intent.FilterComparison(intent);
// 通过 intent 先找到 IntentBindRecord 对象
IntentBindRecord b = r.bindings.get(filter);
if (b != null && !b.received) {
b.binder = service;// 保存 binder 对象
b.requested = true; // 表示是否请求过 bidner 对象
b.received = true; // 表示是否已经收到 binder 对象了
// for 循环找到所有匹配的 对象 调用 connected 把binder 对象返回给应用端
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);
if (!filter.equals(c.binding.intent.intent)) {
continue;
}
try {
c.conn.connected(r.name, service, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + r.name +
" to connection " + c.conn.asBinder() +
" (in " + c.binding.client.processName + ")", e);
}
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
onRebind() 什么时候调用的
- bindServiceLocked() 中有一行代码
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,...){
// service 已经启动 并且已经接收到了 binder 对象
if (s.app != null && b.intent.received) {
// intent 下只有一个 进程绑定 && doRebind 参数为 true
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
// 最后一个参数为 true 表示要调用 onRebind
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
}
}
doRebind 参数和unbindServiceLocked 有关
boolean unbindServiceLocked(IServiceConnection connection) {
IBinder binder = connection.asBinder();
//通过 binder 取出 ConnectionRecord 列表
ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
try {
while (clist.size() > 0) {
ConnectionRecord r = clist.get(0);
// 依次调用 removeConnectionLocked 函数
removeConnectionLocked(r, null, null);
if (clist.size() > 0 && clist.get(0) == r) {
clist.remove(0);
}
}
}
return true;
}
- removeConnectionLocked()
void removeConnectionLocked(
// 如果Service还在 并且binde的 已经没有了进程来bind了
if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
&& b.intent.hasBound) {
try {
// 则 Service 执行 scheduleUnbindService 回调
s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
}
}
}
- handleUnbindService()
private void handleUnbindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
// 一般返回false 除非重写这个方法
boolean doRebind = s.onUnbind(data.intent);
try {
if (doRebind) {
ActivityManager.getService().unbindFinished(
data.token, data.intent, doRebind);
} else {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
}
}
}
}
当没有应用还在bindService以后,调用 ActivityManager.getService().unbindFinished() 的话内部会把 doRebind 属性设置为 true ,那么下次再调用 bindService 的时候会执行 onRebind() 函数