最近在重温Android系统的相关知识点,我们都知道Android有四大组件,Activity、Service、Broadcast Receive、Content Provider,像对比其他知识点来说,重温四大组件最好的方式就是跟着源码再走一遍,说起看源码,我们可能会比较头疼,这是因为一旦扎进去,就会陷在代码的海洋里,不知所措,其实分析源码,最忌讳的是一上来就深挖。这样很难出来,不仅费时间,而且也提取不到有用的信息,最好的方式就是先按照主线流程走一遍,先把主线打通,有时间的话,再对支线进行旁敲侧击。
好,现在按照我们刚刚讲的方式来分析,今天我们主要分析service的启动流程,首先我们知道启动service有两种方式:startService()和bindService(),也就是service的启动和绑定,接下来我们先分析service的启动。
startService
首先我们从context.startService()这个方法为起点进行分析,我们看下他的源码:
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
startService()是一个抽象方法,具体实现在ContextImpl.java里,进入ContextImpl.java看下:
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
又会直接走到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());
if (cn != null) {
if (cn.getPackageName().equals("!")) {
throw new SecurityException(
"Not allowed to start service " + service
+ " without permission " + cn.getClassName());
} else if (cn.getPackageName().equals("!!")) {
throw new SecurityException(
"Unable to start service " + service
+ ": " + cn.getClassName());
} else if (cn.getPackageName().equals("?")) {
throw new IllegalStateException(
"Not allowed to start service " + service + ": " + cn.getClassName());
}
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
从startServiceCommon这个方法中,很容易定位到重点代码:
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
getOpPackageName(), getAttributionTag(), user.getIdentifier());
通过ActivityManager.getService()就会走到AMS中,在AMS里来启动service。
接下来进入AMS,一探究竟:
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage,
String callingFeatureId, int userId)
throws TransactionTooLargeException {
...
try {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, callingFeatureId, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
在这个方法里,会通过ActiveServices调用startServiceLocked,再看startServiceLocked:
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage,
@Nullable String callingFeatureId, final int userId,
boolean allowBackgroundActivityStarts) throws TransactionTooLargeException {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
+ " type=" + resolvedType + " args=" + service.getExtras());
final boolean callerFg;
if (caller != null) {
// 这里记录app的进程信息
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
...
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
...
return cmp;
}
最终调用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;
}
继续调用了bringUpServiceLocked,
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
...
// Service is now being launched, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
r.packageName, false, r.userId);
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ r.packageName + ": " + e);
}
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
ProcessRecord app;
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
//如果service进程存在
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
//启动service
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
}
}
} else {
app = r.isolatedProc;
if (WebViewZygote.isMultiprocessEnabled()
&& r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
hostingRecord = HostingRecord.byWebviewZygote(r.instanceName);
}
if ((r.serviceInfo.flags & ServiceInfo.FLAG_USE_APP_ZYGOTE) != 0) {
hostingRecord = HostingRecord.byAppZygote(r.instanceName, r.definingPackageName,
r.definingUid);
}
}
// 如果不存在此进程
if (app == null && !permissionsReviewRequired) {
// 启动运行的线程
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": process is bad";
Slog.w(TAG, msg);
bringDownServiceLocked(r);
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
...
return null;
}
这个方法做了两件事:
1.如果Service进程已经存在,则直接调用realStartServiceLocked。
2.如果Service进程不存在,则执行startProcessLocked方法创建进程,经过层层调用,最终也会走到
realStartServiceLocked中。
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
...
try {
...
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
app.getReportedProcState());
r.postNotification();
created = true;
}
}
这个方法内部调用了app.thread.scheduleCreateService,而app.thread是一个IApplicationThread类型的,他的实现是ActivityThread的一个内部类ApplicationThread,而这个类正好实现了IApplicationThread.Stub,在ApplicationThread类中,找到对应的调用方法:
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,这个Handler
是ActivityThread
的内部类H
public void handleMessage(Message msg) {
switch (msg.what) {
...
case CREATE_SERVICE:
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
("serviceCreate: " + String.valueOf(msg.obj)));
}
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
}
最终调用了handleCreateService
方法:
private void handleCreateService(CreateServiceData data) {
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
//创建service的context
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
//创建Application
Application app = packageInfo.makeApplication(false, mInstrumentation);
//获取类加载器
java.lang.ClassLoader cl = packageInfo.getClassLoader();
//加载service实例
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
// Service resources must be initialized with the same loaders as the application
// context.
context.getResources().addLoaders(
app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
context.setOuterContext(service);
//初始化service
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
//调用service的onCreate方法
service.onCreate();
mServices.put(data.token, service);
try {
//通过serviceDoneExecuting告知AMS,service已经启动完成
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
来看下这个方法做了哪些事情:
1.首先,创建上下文
2.创建Application,获取类加载器
3.加载service实例,初始化service, 回调通知开发者service创建完成。
4.最后通知AMS,service启动完成。
到这里service已经启动完成。
总结:
整个startService
过程,从进程的角度看Service
的启动流程
proccessA
进程采用Binder
形式向system_server
进程发起startService
请求system_server
进程收到请求后,向zygote
进程发送创建进程的请求zygote
进程fork
出新的进程,创建出新进程的ActivityThread
的main
方法- 新进程通过
Binder
向system_server
进程发起attachApplication
请求 system_server
进程收到请求后,经过一系列的在准备后,通过Binder
向新进程发送scheduleCreateService
请求- 新进程收到请求后,通过
Handler
发送CREATE_SERVICE
消息 - 主线程收到message,创建
Service
,并回调onCreate
bindService
接下来我们分析service的绑定:
无独有偶,也是先从context.bindService这个方法为起点进行分析,看源码:
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
return mBase.bindService(service, conn, flags);
}
同样也是返回bindService,在context的实现类ContextImpl.java中,
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
getUser());
}
调用了bindServiceCommon,来看下:
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, String instanceName, Handler handler, Executor executor, UserHandle user) {
...
try {
...
int res = ActivityManager.getService().bindIsolatedService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
...
}
}
通过ActivityManager.getService()来进入AMS,通过AMS调用bindIsolatedService方法,进入AMS里的这个方法看下:
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调用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 ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
...
//Activity信息
ActivityServiceConnectionsHolder<ConnectionRecord> activity = null;
if (token != null) {
activity = mAm.mAtmInternal.getServiceConnectionsHolder(token);
if (activity == null) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
}
...
try {
...
//如果设置了BIND_AUTO_CREATE标志,则启动bringUpServiceLocked方法,
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
...
if (s.app != null && b.intent.received) {
// Service is already running, so we can immediately
// publish the connection.
try {
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortInstanceName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
// If this is the first app connected back to this binding,
// and the service had previously asked to be told when
// rebound, then do so.
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
maybeLogBindCrossProfileService(userId, callingPackage, callerApp.info.uid);
getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
这个方法会先获取进程与Activity等信息,然后获取Service与应用程序的关系,【注意的是:如果存在了设置BIND_AUTO_CREATE的连接,就不销毁服务直接返回,启动bringUpServiceLocked方法,后面参考Service启动】后面调用requestServiceBindingLocked方法。
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
...
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.getReportedProcState());
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
}
return true;
}
这里的app.thread和service启动那一块是一样的,是一个IApplicationThread类型的,,它的实现是ActivityThread的内部类ApplicationThread, 其中ApplicationThread继承了IApplicationThread.Stub
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;
if (DEBUG_SERVICE)
Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
+ Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
sendMessage(H.BIND_SERVICE, s);
}
看到这个方法里,通过sendMessage把消息交给Handler,通过handleMessage来处理消息
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;
...
}
}
最后还是调用了handleBindService,
final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
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 {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to bind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}
mService是一个存着token与Server关系的Map,先从中获取要绑定的Service,再判断Service是否初次绑定, 是的话回调onBind方法并调用AMS的publishService方法;否则回调onRebind并调用AMS的serviceDoneExecuting方法。
我们先看下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) {
final long origId = Binder.clearCallingIdentity();
try {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r
+ " " + intent + ": " + service);
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<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
for (int conni = connections.size() - 1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
if (!filter.equals(c.binding.intent.intent)) {
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Not publishing to: " + c);
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Published intent: " + intent);
continue;
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
try {
c.conn.connected(r.name, service, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + r.shortInstanceName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
最终走到了serviceDoneExecutingLocked,那我们看下c.conn.connected,
final IServiceConnection conn; // The client connection.
IServiceConnection是一个AIDL接口, 具体实现为ServiceDispatcher.InnerConnection,其中ServiceDispatcher是LoadedApk的内部类。
static final class ServiceDispatcher {
...
private static class InnerConnection extends IServiceConnection.Stub {
@UnsupportedAppUsage
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);
}
}
}
调用了ServiceDispatcher类的connected方法
private final Handler mActivityThread;
private final Executor mActivityExecutor;
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);
}
}
在这个方法里,向ActivityThread post了一个Runnable
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;
}
通过线程池来doConnected
public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
synchronized (this) {
if (mForgotten) {
// We unbound before receiving the connection; ignore
// any connection received.
return;
}
old = mActiveConnections.get(name);
if (old != null && old.binder == service) {
// Huh, already have this one. Oh well!
return;
}
if (service != null) {
// A new service is being connected... set it all up.
info = new ConnectionInfo();
info.binder = service;
info.deathMonitor = new DeathMonitor(name, service);
try {
service.linkToDeath(info.deathMonitor, 0);
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 {
// The named service is being disconnected... clean up.
mActiveConnections.remove(name);
}
if (old != null) {
old.binder.unlinkToDeath(old.deathMonitor, 0);
}
}
// 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 viable service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
} else {
// The binding machinery worked, but the remote returned null from onBind().
mConnection.onNullBinding(name);
}
}
当绑定成功时,会回调mConnection.onServiceConnected(name, service)方法。
总结:
Context
通知AMS
AMS
通知ActivityThread
- 若设置
BIND_AUTO_CREATE
,则直接启动服务,否则继续绑定 ActivityThread
绑定Service
- 若是首次绑定,调用
AMS
的publishService
方法,连接Service
,并回调onBind
,否则直接调用AMS
的serviceDoneExecutingLocked
方法并回调onReBind
至此,关于Service的启动和绑定流程就分析完了,总的来说,过程不是很复杂,细心跟着源码就可以看懂了,如果文章中有写得不对的地方,欢迎在留言区留言大家一起讨论,共同学习进步。如果觉得我的文章给予你帮助,也请给我一个喜欢和关注。