一:BindService流程图
BindService补充一:ServiceDispatcher
bindServiceCommon(): 将客户端的ServiceConnection对象转化为ServiceDispatcher.InnerConnection对象。因为ServiceConnection对象不是一个Binder对象,不能跨进程传输。而其onServiceConnected()方法需要借助AMS回调,所以先要把它转换成对应的Binder对象。
这个对象就是IServiceConnection(IInterface)接口的实现类ServiceDispatcher.LoadApk
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
// LoadApk mPackageInfo
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), 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();
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
return false;
}
}
LoadApk.getServiceDispatcher():首先判段map里面是否存储<ServiceConnection, LoadedApk.ServiceDispatcher>的键值对,如果存储过,就取出当前ServiceConnection对应的LoadedApk.ServiceDispatcher,没有就创建一个ServiceDispatcher对象,并存储。然后根据这个ServiceDispatcher对象取出LoadedApk.ServiceDispatcher.InnerConnection对象。
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
LoadApk.ServiceDispatcher.InnerConnection:
这个类是ServiceDispatcher的内部类。而且实现了IServiceConnection.Stub类,所以它是一个Binder对象。可以跨进程传输。在它的内部调用了LoadedApk.ServiceDispatcher的connected()方法。
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) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service);
}
}
}
ServiceDispatcher. connected():
通过一个 handler传递到主线程;mActivityThread的类型是Handler 。
public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0));
} else {
doConnected(name, service);
}
}
补充二 realStartServiceLocked(): realStartServiceLocked()里面有两个比较重要的方法。分别为
(1)scheduleCreateService():走创建Service的方法调用链。
(2)requestServiceBindingsLocked():走Bind Service的方法调用链。
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
...
boolean created = false;
try {
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {
mAm.appDiedLocked(app);
throw e;
} finally {
...
}
requestServiceBindingsLocked(r, execInFg);
// 不关心,略。。
}
网友评论