本次源码分析是熟悉Service启动过程,让我们对Service的工作原理有进一步的了解。Service分为启动过程和绑定过程,启动状态执行后台计算,绑定状态是其他组件与Service交互。这两种状态可以同时存在。
startService 过程
现在我们开始分析startService启动过程,下图是启动过程的时序图,如图:
当我们调用startService方法时候,紧接着都会调用startServiceCommon,我们来看看这个方法做了哪些事情。
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
...
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
...
}
上述代码看出,直接调用了AMS的startService,在此方法中引入了mServices这个引用实则是ActiveServices类,它是辅助AMS进行Service管理,主要包括启动、绑定和停止等。接着开始调用ActiveServices的startServiceLocked方法。
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId)
throws TransactionTooLargeException {
...
synchronized (this) {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
}
...
}
进入startServiceLocked后我们发现,解析了service且把Service信息封装到了ServiceRecord中,然后在调用startServiceInnerLocked方法。
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage,
final int userId, boolean allowBackgroundActivityStarts)
throws TransactionTooLargeException {
...
//1
ServiceLookupResult res =
retrieveServiceLocked(service, null, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false, false);
ServiceRecord r = res.record;
...
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
在上述代码标记1)解析参数service里面的数据,获取到对应的Service信息并且封装到ServiceRecord,每个Service都有一个ServiceRecord对象,都像Activity都有一个ActivityRecord。ServiceRecord继承Binder可以进程之间通讯。在调用startServiceInnerLocked后接着有调用了bringUpServiceLocked方法。
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
//1
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
//2
final String procName = r.processName;
HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
ProcessRecord app;
if (!isolated) {
//3
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
//4
if (app != null && app.thread != null) {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
}
}
//5
if (app == null && !permissionsReviewRequired) {
if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingRecord, false, isolated, false)) == null) {
bringDownServiceLocked(r);
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
return null;
}
在上述代码标记
1)多次调用startService会多次调用onStartCommand 后面不在执行。
2)描述service需要在那个进程运行,AndroidManifest.xml设置的android:process属性来开启进程。
3)查询service对应的ProcessRecord类型的app。
4)发现有对应的进程都开始执行创建Service。
5)当没有发现有service运行的进程,都需要重新创建进程。
我们分析的是Service创建流程,接下来都应该执行方法realStartServiceLocked。
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
//1
r.setProcess(app);
boolean created = false;
//2
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
app.getReportedProcState());
created = true;
//3
sendServiceArgsLocked(r, execInFg, true);
}
1)ServiceRecord绑定进程。
2)这里开始执行创建Service过程。
3)执行onStartCommand过程,接下来会分析。
我们现在分析创建Service过程,从代码可以看出,我们马上都要跨进程到ApplicationThread调用scheduleCreateService这个方法。此方法里面通过H继承Handler发送了CREATE_SERVICE消息到ActivityThread执行创建Service。
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);
}
最后代码执行到了ActivityThread的handleCreateService方法里面。
private void handleCreateService(CreateServiceData data) {
//创建对象
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
ClassLoader cl = packageInfo.getClassLoader();
//创建service对象
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
} catch (Exception e) {}
try {
//创建上下文
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
//关联service对象
context.setOuterContext(service);
//获取Application对象
Application app = packageInfo.makeApplication(false, mInstrumentation);
//关联上下文和Application对象
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
//data.token都是ServiceRecord,它是binder对象,token与service建立映射关系存储在mServices的map中
mServices.put(data.token, service);
} catch (Exception e) {}
}
通过上述代码,我们可以看出创建了Service对象,创建上下文,然后service调用attach关联Application和上下文,最后调用创建onCreate。mServices是一个ArrayMap,用来存储service对象,ServiceRecord为key值。
接下来我们分析上面提到的sendServiceArgsLocked方法,调用了scheduleServiceArgs方法。
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted) throws TransactionTooLargeException {
r.app.thread.scheduleServiceArgs(r, slice);
}
我们在ApplicationThread找了scheduleServiceArgs方法,里面通过H发送SERVICE_ARGS消息到ActivityThread,调用了handleServiceArgs方法。
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
if (!data.taskRemoved) {
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
} catch (Exception e) {
}
}
}
获取ServiceRecord对应的Service,并且调用了onStartCommand方法。
到此我们把Service的启动流程都分析完了
bindService 过程
我们分析bindService过程。我们先来看一张序列图,如图所示:
当我们在调用bindService后,接着调用了bindServiceCommon方法,
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
String instanceName, Handler handler, Executor executor, UserHandle user) {
IServiceConnection sd;
if (mPackageInfo != null) {
// 1
if (executor != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
} else {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
}
try {
//此token都是AMS创建ActivityRecord创建
IBinder token = getActivityToken();
if (token == null && (flags & BIND_AUTO_CREATE) == 0 && mPackageInfo != null
&& mPackageInfo.getApplicationInfo().targetSdkVersion
< Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
service.prepareToLeaveProcess(this);
int res = ActivityManager.getService().bindIsolatedService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
Context context, Handler handler, Executor executor, int flags) {
synchronized (mServices) {
ServiceDispatcher sd = null;
//根据启动者的context获取arrayMap
ArrayMap map = mServices.get(context);
if (map != null) {
sd = map.get(c);
}
if (sd == null) {
//创建ServiceDispatcher对象,此类是ServiceConnection和InnerConnection桥梁,
if (executor != null) {
sd = new ServiceDispatcher(c, context, executor, flags);
} else {
sd = new ServiceDispatcher(c, context, handler, flags);
}
if (map == null) {
map = new ArrayMap<>();
mServices.put(context, map);
}
//ServiceConnection与ServiceDispatcher建立映射关系
map.put(c, sd);
} else {
sd.validate(context, handler, executor);
}
return sd.getIServiceConnection();
}
}
在标记1)处创建IServiceConnection对象,调用getServiceDispatcherCommon方法作用是将ServiceConnection对象封装成IServiceConnection类型的sd引用,IServiceConnection类实现了Binder机制,这样的封装都是为了支持跨进程。当我们Service绑定成功后会回调ServiceConnection这个类的方法,此类无法跨进程使用,所以必须封装成支持跨进程的IServiceConnection。我们继续调用AMS的bindIsolatedService方法,然后调用了mServices(提到过的ActiveServices)的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 {
//创建ServiceRecord对象,这个类继承Binder
ServiceLookupResult res =
retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
Binder.getCallingPid(), Binder.getCallingUid(), userId, true,
callerFg, isBindExternal, allowInstant);
ServiceRecord s = res.record;
try {
//1
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
//2
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent,
callerApp.uid, callerApp.processName, callingPackage);
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
//3
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
if (s.app != null && b.intent.received) {
try {
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
}
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
//4
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
//5
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
1)应用进程通过Intent来绑定Service,AppBindRecord是Service和应用程序进程桥梁。
2)ConnectionRecord 用于描述应用进程和Service建立一次通信。
3)这都是我们创建Service的过程,创建流程已经写过。
4)首先设置onUnbind返回值true,当我们startService--bindService--unBindService--bindService都会调用onRebind。
5)我们第一次调用bindService都走的是第五步。
我们接着看requestServiceBindingLocked方法,又走到ApplicationThread的scheduleBindService方法。
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.getReportedProcState());
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (TransactionTooLargeException e) {
} catch (RemoteException e) {
}
}
return true;
}
通过H发送BIND_SERVICE到主线程管理类ActivityThread,然后执行handleBindService这个方法。
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
//1
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
//2
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
}
}
}
1)在bindServiceLocked方法提到的走的第5步,调用绑定onBind方法,并且再次调用AMS的publishService方法中去。
2)在bindServiceLocked方法提到的走的第4步,解绑后的重新绑定调用onRebind方法。
接下来我们再去看看publishService方法,调用了ActiveServices的publishServiceLocked方法。
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
try {
if (r != null) {
Intent.FilterComparison filter
= new Intent.FilterComparison(intent);
IntentBindRecord b = r.bindings.get(filter);
if (b != null && !b.received) {
b.binder = service;
b.requested = true;
b.received = true;
ArrayMap> connections = r.getConnections();
for (int conni = connections.size() - 1; conni >= 0; conni--) {
ArrayList clist = connections.valueAt(conni);
for (int i=0; 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) {
}
}
}
}
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
走到这里都明白了,这里是准备bind回调,connected方法跨进程调用了这个类IServiceConnection的connected,然后调用了ServiceDispatcher的connected方法
//ServiceDispatcher.java
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityExecutor != null) {
mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
} else if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
private final class RunConnection implements Runnable {
public void run() {
if (mCommand == 0) {
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
}
public void doConnected(ComponentName name, IBinder service, boolean dead) {
if (service != null) {
mConnection.onServiceConnected(name, service);
} else {
mConnection.onNullBinding(name);
}
}
上述代码看出最终调用了ServiceConnection的onServiceConnected方法。
上面都是所有分析bindService的过程。