话不多说,上代码(本文基于Android 29 源码分析):
bindService(Intent(this, MyService::class.java), MyConnection(), Context.BIND_AUTO_CREATE)
其中MyConection代码为:
inner class MyConnection : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
}
}
日常操作,就不用解释了,下面从 bindService 开始,跟踪源码,理解整个过程。activity继承至contextWrapper,contextWrapper其实是contextImpl的代理类,所以bindService直接跟进到contextImpl中,最终到bindServiceCommon:
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
String instanceName, Handler handler, Executor executor, UserHandle user) {
// 后面会分析,这地方记住这个句柄 sd 是 IServiceConnection 对象
IServiceConnection sd;
...
if (mPackageInfo != null) {
if (executor != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
} else {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
&& mPackageInfo.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
//准备离开本进程,提前打个招呼,做些准备操作
service.prepareToLeaveProcess(this);
// 关键点 1:跳转到AMS处理,开始了跨进程之旅
int res = ActivityManager.getService().bindIsolatedService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, instanceName, 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();
}
}
关键点1处注意几个参数:
getApplicationThread: 都知道进程启动、activity启动都会有一个ApplicationThread,同理这地方也是,在启动service的时候依然是走到 ActivityThread,走生命周期。
getActivityToken:每一个Activity都有一个token,该token会在ActivityRecord中保存,由WMS有关,这地方就是找到指定的Activity
sd:IServiceConnection对象,后面会用到
接着走到AMS,看一下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);
}
}
参数对应上,又调用 了bindServiceLocked方法,go on:
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);
...
//本质上就是创建一个ServiceRecord对象,该对象实现了binder接口
ServiceLookupResult res =
retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
Binder.getCallingPid(), Binder.getCallingUid(), userId, true,
callerFg, isBindExternal, allowInstant);
if (res == null) {
return 0;
}
if (res.record == null) {
return -1;
}
ServiceRecord s = res.record;
...
try {
...
//关键点1
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent,
callerApp.uid, callerApp.processName, callingPackage);
IBinder binder = connection.asBinder();
s.addConnection(binder, c);
b.connections.add(c);
if (activity != null) {
activity.addConnection(c);
}
b.client.connections.add(c);
c.startAssociationIfNeeded();
if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
b.client.hasAboveClient = true;
}
if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
s.whitelistManager = true;
}
if ((flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) {
s.setHasBindingWhitelistingBgActivityStarts(true);
}
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
// 关键点2
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
...
return 1;
}
该方法较长,分析关键 的流程,在关键点1处,创建了ConnectionRecord对象,从名称可看出就是我们bind service方法调用传的 Connection对象,不过这地方是包装的IServiceConnection ,这个就是上面说的sd对象,先知道是包装了Connection的对象,后面会分析,接着一些flag相关。关键点2 这个是真正重要的地方,先看flag判断,(flags&Context.BIND_AUTO_CREATE) != 0,如果参数是Context.BIND_AUTO_CREATE,就会走到bringUpServiceLocked,Context.BIND_AUTO_CREATE就是bindeservice方法最后一个参数,
bindService(Intent(this, MyService::class.java), MyConnection(), Context.BIND_AUTO_CREATE)
这个参数的意义就是,自动startService,在执行绑定操作,继续跟进bringUpServiceLocked,
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
...
realStartServiceLocked(r, app, execInFg);
....
}
该方法关键的就是执行realStartServiceLocked(r, app, execInFg);其他没什么好分析的 ,继续跟进:
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
r.setProcess(app);
...
boolean created = false;
try {
//关键点1 : 开始回调调用者进程,熟悉的调用方式
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
app.getReportedProcState());
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app);
throw e;
} finally {
...
}
...
//关键点 2
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
...
}
看到关键点1 有没有熟悉的感觉,没错就是跟activity启动流程类似的调用,该方法的执行会到ActivityThread执行service的启动,同理,注意相关参数
r:ServiceRecord,service的记录,后续会通过该对象作为key保存启动的Service
跨进程到了调用者进程,找到ActivityThread,跟进如下:
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);
}
包装一个CreateServiceData,发送一个message ,进入主线程调用,最终到:
private void handleCreateService(CreateServiceData data) {
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
//反射方式创建一个service对象
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to instantiate service " + data.info.name
+ ": " + e.toString(), e);
}
}
try {
// 创建了一个context 对象,本质上一个service对应一个context
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
// 关键点1 执行service的oncreate 生命周期
service.onCreate();
mServices.put(data.token, service);
try {
// 关键点2 继续跨进程到AMS 继续执行后续操作
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看出我们的service的生命周期开始执行了,关键点2,又开始了跨进程之旅,到这我门的bind操作还没真正执行,目前只是start service了,好继续serviceDoneExecuting的跟踪,其实serviceDoneExecuting的执行很简单,就是没有做任何有用的操作,这地方有兴趣的自己可以跟踪过去,注意对照SERVICE_DONE_EXECUTING_ANON参数看。
我们回到上面的realStartServiceLocked方法,继续看下面的关键点2的执行,发现执行完启动过程,会紧跟着执行requestServiceBindingsLocked方法,这个又是做什么的,源码如下:
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if (r.app == null || r.app.thread == null) {
// If service is not currently running, can't yet bind.
return false;
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
// 关键点1 ,熟悉的调用方式
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) {
// Keep the executeNesting count accurate.
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e);
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
throw e;
} catch (RemoteException e) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r);
// Keep the executeNesting count accurate.
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
return false;
}
}
return true;
}
看到在关键点1处,又跨进程执行了ActivityThread的scheduleBindService方法,从名字也可猜出执行到了我们的bind操作,nice,继续看ActivityThread的执行过程,最终经过 handler 回调到 handleBindService:
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
...
if (!data.rebind) {
//关键点1 终于到了我们的onbind
IBinder binder = s.onBind(data.intent);
//关键点2 再一次跨进程到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);
}
...
}
}
关键点1 终于到了我们的onbind方法,还记得我们service中onbind会返回bind对象,然后关键点2处又开始将我们返回的binder对象传递到AMS ,那么继续跟进去看看 :
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
...
ConnectionRecord c = clist.get(i);
// conn :IServiceConnectio service: 对应上面的返回的binder
c.conn.connected(r.name, service, false);
...
}
该方法做了精简主要的地方就是调用了connected方法,conn还记得开始分析的IServiceConnection吗,没错,就是我们执行bindServiceCommon方法中的sd对象(忘了的翻到上面的bindServiceCommon方法看看就知道了),我们看看这个对象怎么生成的,
很简单跟踪源码可以看到就是new ServiceDispatcher(c, context, executor, flags)的操作,对应的构造函数
ServiceDispatcher(ServiceConnection conn,
Context context, Executor activityExecutor, int flags) {
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mContext = context;
mActivityThread = null;
mActivityExecutor = activityExecutor;
mLocation = new ServiceConnectionLeaked(null);
mLocation.fillInStackTrace();
mFlags = flags;
}
回到上面的c.conn.connected(r.name, service, false); 就是ServiceDispatcher的connected(r.name, service, false),这个方法如下:
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityExecutor != null) {
mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
} else if (mActivityThread != null) {
//执行到这,毕竟 ActivityThread 是存在的,service:对应上面的返回的binder
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
这地方post了一个runnable对象,就是执行到了相关的run方法,在run方法中会调用到我们的onServiceConnected(name, service);
public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
synchronized (this) {
...
// 关键点1 终于执行了onServiceConnected
if (service != null) {
mConnection.onServiceConnected(name, service);
} else {
// The binding machinery worked, but the remote returned null from onBind().
mConnection.onNullBinding(name);
}
}
}
就是我们自己写的MyConnection中的onServiceConnected,这地方的service参数就是service的onbind方法返回的binder对象,到此跟踪了整个service的bind过程,bindService方式的源码分析也就结束了。
网友评论