Service的启动与绑定
分析的源码基于android-8.0.0_r4
《安卓进阶解密》读书笔记
Service的启动过程
分为两部分介绍Service的启动过程
- ContextImpl到AMS的调用过程
- ActivityThread启动Service
ContextImpl -> AMS
时序图如下
要启动Service,我们会先调用startService方法,它在ContextWrapper中实现
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
mBase指的是ContextImpl.
ContextImpl::startService
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
ContextImpl::startServiceCommon
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
getOpPackageName(), getAttributionTag(), user.getIdentifier());
...
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
ActivityManager.getService()获取到的是AMS的本地代理,通过AMS的本地代理,最终会调用到AMS的startService方法
进程切换:应用程序进程 -> AMS所在进程(SystemServer进程).
ActivityThread启动Service
时序图如下
AMS::startService
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int
userId) throws TransactionTooLargeException {
...
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
mServices的类型是ActiveServices方法
ActiveServices::startServiceLocked
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String
resolvedType,int callingPid, int callingUid, boolean fgRequired, String
callingPackage, final int userId) throws TransactionTooLargeException {
...
//1.
ServiceLookupResult res = retrieveServiceLocked(service, resolvedType,
callingPackage,callingPid, callingUid, userId, true, callerFg, false);
if (res == null) {
return null;
}
if (res.record == null) {
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
//2.
ServiceRecord r = res.record;
...
//3.
ComponentName cmp = startServiceInnerLocked(smap, service,
r, callerFg, addToStarting);
return cmp;
}
-
注释1:调用
retrieveServiceLocked方法,查找是否有与参数service对应的ServiceRecord信息,有则封装为ServiceLookupResult返回;没有则调用PackageManagerService去获取参数service对应的Service信息,并封装到ServiceRecord中,再将ServiceRecord封装为ServiceLookupResult返回 -
注释2:获取参数
Intent service对应的ServiceRecord -
注释3:调用
startServiceInnerLocked,并将ServiceRecord r作为参数传递
ActiveServices::startServiceInnerLocked
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,
ServiceRecord r,boolean callerFg, boolean addToStarting)
throws TransactionTooLargeException {
...
String error = bringUpServiceLocked(r,service.getFlags(),callerFg,false,false);
if (error != null) {
return new ComponentName("!!", error);
}
...
return r.name;
}
ActiveServices::bringUpServiceLocked
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean
execInFg,boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
...
//1.获取Service想要在哪个进程中运行
final String procName = r.processName;
String hostingType = "service";
ProcessRecord app;
if (!isolated) {
//2.传入Service的uid和procName,通过AMS查询是否存在一个与Service对应的
//ProcessRecord对象
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
...
//3.如果运行Service的应用程序进程存在
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode,
mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
} ...
}
} else {
...
}
//4.如果用来运行Service的应用程序进程不存在
if (app == null && !permissionsReviewRequired) {
//5.调用AMS的startProcessLocked方法,创建对应的应用程序进程
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, r.name, false, isolated, false)) == null) {
...
return msg;
}
...
}
...
}
我们可以在AndroidManifest.xml中设置android:process,来新开启一个新进程运行Service,这种情况下程序不会进入注释3的If语句,而是会进入注释4的If语句;如果我们不指定android:process,默认情况下,Service会运行在应用程序的当前进程上面。这里我们讨论没有指定android:process的情况,即进入注释3,而不进入注释4。在注释3的If语句中,会调用realStartServiceLocked方法
ActiveServices::realStartServiceLocked
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
...
//为ServiceRecord的app变量赋值ProcessRecord类型的app变量,后面Service绑定时,会用到
//这个判定条件
r.app = app;
...
try {
...
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app);
throw e;
} finally {
...
}
...
}
app.thread是IApplicationThread类型,真正实现是ApplicationThread,app.thread获取到的是ApplicationThread的代理.
进程切换:AMS所在进程(SystemServer进程) -> 应用进程的Binder线程.
ApplicationThread::scheduleCreateService
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
//将启动Service的参数封装成CreateServiceData
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
sendMessage(H.CREATE_SERVICE, s);
}
sendMessage方法
private void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
向主线程的消息管理类H mH发送消息.
线程切换:应用程序Binder线程 -> 应用程序主线程.
H::handleMessage,H是ActivityThread的内部类
private class H extends Handler {
...
public void handleMessage(Message msg) {
...
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
("serviceCreate: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
...
}
调用ActivityThread::handleCreateService
private void handleCreateService(CreateServiceData data) {
...
//1.获取要启动Service的应用程序的LoadedApk
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
//2.获取类加载器
java.lang.ClassLoader cl = packageInfo.getClassLoader();
//3.创建Service实例
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
...
}
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
//4.创建Service的上下文环境ContextImpl对象
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
//5.尝试创建Application,makeApplication内部会调用Application的onCreate
Application app = packageInfo.makeApplication(false, mInstrumentation);
//6.初始化Service
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
//7.调用Service的onCreate,这样Service就启动了
service.onCreate();
//8.将启动的Service加入到ActivityThread的成员变量mServices中,这里的data.token
//实际上是ServiceRecord(ServiceRecord继承至Binder),service的类型是Service,
//mServices是ArrayMap类型
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
...
}
}
到这里,Service就启动起来了
Service的绑定过程
几个相关的类型
-
ServiceRecord:用于描述一个Service(ServiceRecord继承至Binder,后面有将ServiceRecord转型的场景)
-
ProcessRecord:一个进程的信息
-
ConnectionRecord:用于描述应用程序进程和Service建立的一次通信
-
IntentBindRecord:用于描述绑定Service的Intent
-
AppBindRecord:应用程序进程通过Intent绑定Service时,会通过AppBindRecord来维护Service与应用程序进程之间的关联。其内部存储了谁绑定的Service(ProcessRecord)、被绑定的Service(ServiceRecord)、绑定Service的Intent(IntentBindRecord)和所有绑定通信记录的信息(ArraySet
)
分为两部分
- ContextImpl到AMS的调用过程
- Service的绑定过程
- 前半部分
- 后半部分
ContextImpl -> AMS
时序图如下
ContextWrapper::bindService
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
ContextImpl::bindService
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}
mMainThread:ActivityThread mMainThread
mMainThread.getHandler():H mH
ContextImpl::bindServiceCommon
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
Handler handler, UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
//通过LoadedApk,将ServiceConnection封装为IServiceConnection,它实现了Binder机制
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler,
flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
...
//通过Binder机制,调用AMS的bindService,并且传入了参数IServiceConnection sd
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
进程切换:应用程序进程 -> AMS所在进程(SystemServer进程).
Service绑定过程
前半部分
时序图如下
AMS::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);
}
}
ActiveServices::bindServiceLocked
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException{
...
try {
...
//1.s类型是ServiceRecord;callerApp类型是ProcessRecord
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
//内部会将IServiceConnectionRecord connection赋值给ConnectionRecord的变量conn
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
...
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
//2.如果绑定服务时的flag为BIND_AUTO_CREATE,则会调用bringUpServiceLocked启动
//Service,关于Service的启动前面已经阐述
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
...
//3.这里s.app的类型是ProcessRecord,s.app!=null,表示Service已经运行,
// b.intent.received表示当前应用程序进程已经接收到绑定Service时返回的Binder,即
// Service的onBind方法返回的Binder
if (s.app != null && b.intent.received) {
// Service is already running, so we can immediately
// publish the connection.
try {
//4.
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
...
}
//5.
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
//6.
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {//7.
//8.
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
- 注释3:在
Service启动时,ActiveServices::realStartServiceLocked方法中,会为ServiceRecord的app变量赋值。注释3的分支不是我们要分析的情况 - 注释4:
c.conn.connected,这里会通过Binder机制,切回应用程序进程,如果调用到这一个方法,其实是快要绑定完成了,后面会讲到(这里考虑应用进程对Service第一次绑定,且是第一个应用进程对该Service进行绑定的情况,所以不会走到注释3的分支,而是走注释7的分支) - 注释5:如果当前应用程序进程是第一个与Service进行绑定的,并且Service已经调用过onUnBind方法,则走到注释6
- 注释7:如果应用进程的Client端没有发送过绑定Service的请求,则走到注释8。注释7的分支是我们要分析的情况。
- 注释6和注释8的区别:在于调用方法
requestServiceBindingLocked的最后一个参数,该参数为rebind,注释6中该值为true,注释8中该值为false
ActiveServices::requestServiceBindingLocked
# rebind:false
private final boolean requestServiceBindingLocked(ServiceRecord r,
IntentBindRecord i, boolean execInFg, boolean rebind)
throws TransactionTooLargeException {
...
//1.
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
//2.
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (TransactionTooLargeException e) {
...
} catch (RemoteException e) {
...
}
}
return true;
}
- 注释1:左边的判定条件
!i.requested || rebind,i.requested表示是否发送过绑定Service的请求,这里分析的情况中,!i.requested的值为true,左边的判定条件成立;右边的i.apps.size() > 0也为true,具体分析查看 书本P115~116. - 注释2:
r.app.thread类型为IApplicationThread,具体实现为ApplicationThread
进程切换:AMS所在进程(SystemServer进程)->应用程序Binder线程.
ActivityThread.ApplicationThread::scheduleBindService
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState) {
updateProcessState(processState, false);
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;
...
sendMessage(H.BIND_SERVICE, s);
}
ActivityThread::sendMessage
private void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
线程切换:应用程序Binder线程->应用程序主线程.
ActivityThread.H::handleMessage
public void handleMessage(Message msg) {
...
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
private void handleBindService(BindServiceData data) {
//1.获取要绑定的Service
Service s = mServices.get(data.token);
...
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
//2.
if (!data.rebind) {
//3.
IBinder binder = s.onBind(data.intent);
//4.
ActivityManager.getService().publishService(
data.token, data.intent, binder);
//5.
} else {
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} ...
} catch (Exception e) {
...
}
}
}
- 注释2:前面说过,我们要分析的情况是
rebind的值为false,所以这里我们要分析的是注释2的If语句 - 注释3:调用
Service的onBind方法获取IBinder,也就是调用我们代码中的Service的onBind方法,到这里Service就处于绑定状态了 - 注释5:结合前面的
bindServiceLocked方法,可以得出,如果当前应用程序进程第一个与Service进行绑定,并且Service已经调用过onUnBind方法,则会调用Service的onRebind方法 - 注释4:调用AMS的
publishService方法
进程切换:应用程序进程->AMS所在进程(SystemServer进程).
后半部分
时序图如下
AMS::publishService
public void publishService(IBinder token, Intent intent, IBinder service) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
synchronized(this) {
if (!(token instanceof ServiceRecord)) {
throw new IllegalArgumentException("Invalid service token");
}
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
ActiveServices::publishServiceLocked
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
...
for (int conni=r.connections.size()-1; conni>=0; conni--) {
ArrayList clist = r.connections.valueAt(conni);
for (int i=0; i
主要关注c.conn.connected语句,c.conn的类型是IserviceConnection,真正的实现是LoadedApk.ServiceDispatcher.InnerConnection,这里c.conn获取到的是一个代理,调用它的方法,会使进程切回应用程序进程
进程切换:AMS所在进程(SystemServer进程)->应用程序Binder线程.
LoadedApk.ServiceDispatcher.InnerConnection
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference(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);
}
}
}
connected方法中,调用了LoadedApk.ServiceDispatcher的connected方法
LoadedApk.ServiceDispatcher::connected
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
mActivityThread是Handler类型,实际上指向的是H,调用H的post方法,将线程切换到主线程
线程切换:应用程序Binder线程->应用程序主线程.
LoadedApk.RunConnection::run
private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
mName = name;
mService = service;
mCommand = command;
mDead = dead;
}
public void run() {
if (mCommand == 0) {
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
final ComponentName mName;
final IBinder mService;
final int mCommand;
final boolean mDead;
}
这里的mCommand == 0,执行ServiceDispatcher的doConnected方法
ServiceDispatcher::doConnected
public void doConnected(ComponentName name, IBinder service, boolean dead) {
...
// If there was an old service, it is now disconnected.
if (old != null) {
mConnection.onServiceDisconnected(name);
}
if (dead) {
mConnection.onBindingDied(name);
}
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
这里的service就是ActivityThread::handleBindService中,调用Service的onBind方法返回的IBinder。这里调用了ServiceConnection mConnection的onServiceConnected方法,那么客户端实现的接口类ServiceConnection中的onServiceConnected方法就会被执行了。至此,Service的绑定过程就分析完成。
参考
《安卓进阶解密》