看完bindService,记得看Activity bindService后销毁及unbindService 记录
public boolean bindService(Intent service, ServiceConnection conn,
int flags)
方法参数
- (ConnectionService实例conn、Intent囊括callerActivity、目标Service信息)
- conn保存到ServiceDispatcher实例sd中
bindService在ContextImpl类中。主要逻辑交由bindServiceCommon处理
//ContextImpl.java
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
IServiceConnection sd;
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags);
}
try {
IBinder token = getActivityToken();
...
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
...
return res != 0;
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
}
看下getServiceDispatcher,逻辑较为简单,主要是将Context, <ServiceConnection, ServiceDispatcher>键值对做保存。其中主要看下ServiceDispatcher对象的创建。
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
//ArrayMap< Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> >
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
sd = map.get(c);
}
if (sd == null) {
//构建ServiceDispatcher对象
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();
}
}
1 ServiceDispatcher
//ContextImpl中的OuterContext值为目标Service对象
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mContext = context;
mActivityThread = activityThread;
mLocation = new ServiceConnectionLeaked(null);
mLocation.fillInStackTrace();
mFlags = flags;
}
ServiceDispatcher中Context(实际是一个Service对象)和Handler的组合来确定一个serviceDispatcher, 见ServiceDispatcher#invalidate
void validate(Context context, Handler activityThread) {
if (mContext != context) {
throw new RuntimeException(
"ServiceConnection " + mConnection +
" registered with differing Context (was " +
mContext + " now " + context + ")");
}
if (mActivityThread != activityThread) {
throw new RuntimeException(
"ServiceConnection " + mConnection +
" registered with differing handler (was " +
mActivityThread + " now " + activityThread + ")");
}
}
ServiceDispatcher对象保存了bindService传入的ServiceConnection对象, 后续还会用到。
bindService经AMS调用ActiveService#bindServiceLocked
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags,
String callingPackage, int userId) throws TransactionTooLargeException {
...
ActivityRecord activity = null;
if (token != null) {// ActivityToken
activity = ActivityRecord.isInStackLocked(token);
if (activity == null) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
}
int clientLabel = 0;
PendingIntent clientIntent = null;
if (callerApp.info.uid == Process.SYSTEM_UID) {
//调用目标Service的为系统应用
...
}
...
//检索目标Servie
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);
...
ServiceRecord s = res.record;
final long origId = Binder.clearCallingIdentity();
...
//xi add: record the binding relation bewteen a client app and current service
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder(); // IServiceConnect
//------------- 记录连接-------------------
//Service records connection
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
clist.add(c);
//client app records connection
b.connections.add(c);
//client activity records connection
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
activity.connections.add(c);
}
b.client.connections.add(c);
clist = mServiceConnections.get(binder); // binder type is IServiceConnection
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
//----------------- 记录连接 -----------------
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
//视目标Service是否运行中,决定是否启动目标Service
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {
return 0;
}
}
...
if (s.app != null && b.intent.received) {// if b.intent.received == true
// Service is already running, so we can immediately
// publish the connection.
try {
//如果目标Service已经处在运行中,直接通知Caller Activity bindService连接成功
c.conn.connected(s.name, b.intent.binder);
} catch (Exception e) {
...
}
...
}
...
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
2.TODO resolveService
(具体交给PMS)
3. 记录连接
类AppBindRecord (An association between a service and one of its client applications. )
ServiceRecord AppBindRecord ActivityRecord 都要记录 connection. 其中,
- ServieRecord中包含 ArrayMap<IBinder, ArrayList> 服务端记录连接
- AppBindRecord中包含 ArraySet 客户端记录连接
- ActivityRecord中包含 HashSet 客户端具体Activity记录连接
4 如必要,bringUpServiceLocked启动目标Service
4.1 目标Service已经启动且处在运行中
发送args到Service。直接返回,后面流程不需要走。
if (r.app != null && r.app.thread != null) {//serviceRecord.app thread不为null, 说明Service已经启动且处于运行中
sendServiceArgsLocked(r, execInFg, false);
return null;
}
4.2 Service所属进程app、线程thread已经启动,但Service没启动。
调用realStartServiceLocked
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
r.app = app;//暂且记录下app
final boolean newService = app.services.add(r); //新Service否
bumpServiceExecutingLocked(r, execInFg, "create");
mAm.updateLruProcessLocked(app, false, null); //与进程调度相关
mAm.updateOomAdjLocked();
boolean created = false;
try {
...
//请求创建Service
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
created = true;
} catch (DeadObjectException e) {
...
} finally {
if (!created) {
//Service创建不成功
// Retry.
...
}
}
//请求绑定Service,调用Service onBind回调方法
requestServiceBindingsLocked(r, execInFg);
//向Service发送args
sendServiceArgsLocked(r, execInFg, true);
if (r.delayed) {// 处理延时启动相关
getServiceMap(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
}
4.2.1 scheduleCreateService
scheduleCreateService位于ActivityThread内部类ApplicationThread,为IApplicationThread服务端实现, IApplicationThread用于AMS和client APP通信。所以,scheduleCreateService逻辑也很简单,向ActivityThread#H发送CREATE_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);
}
H接到消息后调用handleCreateService
case CREATE_SERVICE:
handleCreateService((CreateServiceData)msg.obj);
break;
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) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
...
}
try {
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service); //ContextImpl中outerContext是目标Service实例
...
//调用service的attach方法
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
//调用service的onCreate方法
service.onCreate();
mServices.put(data.token, service);
try {
//Target Service正常启动,启动后做相关工作
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
// nothing to do.
}
} catch (Exception e) {
...
}
}
可以看到handleCreateService方法中获取到ClassLoader实例,利用反射创建了目标Service实例,依次调用它的attach、onCreate方法。同时调用AMS#serviceDoneExecuting方法,执行Service正常启动后的逻辑,其中会移除消息SERVICE_TIMEOUT_MSG,否则系统会提示ANR。
4.2.2 requestServiceBindingsLocked
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if (r.app == null || r.app.thread == null) {
// serviceRecord中app thread为null,表示目标Service并未启动,所以不需要bind,直接return false
return false;
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
...
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) {
// Keep the executeNesting count accurate.
...
} catch (RemoteException e) {
...
}
}
return true;
}
同样,scheduleBindService属于ActivityThread#ApplicationThread中方法,还是发送消息,
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);
}
H接到消息,调用handleBindService
case BIND_SERVICE:
handleBindService((BindServiceData)msg.obj);
break;
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
//回调onBind方法
IBinder binder = s.onBind(data.intent);
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
//调用onRebind
s.onRebind(data.intent);
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
}
} catch (Exception e) {
...
}
}
}
正常handleBindService方法中会去调用Service的onBind,返回目标Service中定义的自定义Binder对象binder,将binder传到AMS publishService方法中,再经过调用Activie#publishServiceLocked
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
if (r != null) {
if (b != null && !b.received) {
...
for (int conni=r.connections.size()-1; conni>=0; conni--) {
ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
...
try {
//调用IConnectionService回调方法connected
c.conn.connected(r.name, service);
} catch (Exception e) {
...
}
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
这里变量c的类型为ConnectionRecord,c.conn类型为IServiceConnection,根据上下文知道,其服务端实现在LoadedApk#ServiceDispatcher#InnerConnection中
4.2.3 LoadedApk#ServiceDispatcher#InnerConnection
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);
}
}
}
InnerConnection中connected方法调用了ServiceDispatcher中的同名方法
public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0));
} else {
doConnected(name, service);
}
}
mActivityThread类型为Handler,为创建sd对象时传入。接着看下RunConnection
public void run() {
if (mCommand == 0) {
doConnected(mName, mService);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
mCommand传入为0,所以调用doConnected方法
4.2.4 doConnected
public void doConnected(ComponentName name, IBinder service) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
synchronized (this) {
...
if (service != null) {
// A new service is being connected... set it all up.
mDied = false;
info = new ConnectionInfo();
info.binder = service;
info.deathMonitor = new DeathMonitor(name, service);
try {
//目标Service接入死亡通知
service.linkToDeath(info.deathMonitor, 0);
//记录<ComponentName, IBinder>
mActiveConnections.put(name, info);
} catch (RemoteException e) {
...
}
}
...
}
...
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
这里就到ServiceConnection#onServiceConnected方法。可以看到目标Service中的自定义Binder对象一路从publishServiceLocked中传递到onServiceConnected中,通过该IBinder对象 ,Caller Activity就能获取到目标Service对象,进而调用Service中的方法。
4.2.5 总结
a. Caller Activity调用bindService时,目标Service没有启动。需要创建目标Service;
b. 调用Service attach、onCreate onBind方法
c. AMS调用publishService,调用IServiceConnect服务端,即LoadedApk#ServiceDispatcher#InnerConnection,调用ServiceConnection#onServiceConnected回调
d.如果Activity调用bindService时,目标Service已经启动,则不需调用Service attach、onCreate、onbind方法,直接调用ServiceConnection#onServiceConnected回调
5.Service所属进程app没有启动
通过AMS请求启动进程,Service存放到PendingService集合中,待启动
if (app == null) {// service所在进程没有启动,那么启动该进程
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", r.name, false, isolated, false)) == null) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": process is bad";
//启动进程失败,关闭Service
bringDownServiceLocked(r);
return msg;
}
...
}
if (!mPendingServices.contains(r)) {//存放Service,待启动
mPendingServices.add(r);
}
在进程启动过程中,attachApplicationLocked会去检测mPendingServices.size()不为0, 表明有需要启动的服务。接着调用realStartServiceLocked启动目标Service。
boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
boolean didSomething = false;
// Collect any services that are waiting for this process to come up.
if (mPendingServices.size() > 0) {// <----------
ServiceRecord sr = null;
try {
for (int i=0; i<mPendingServices.size(); i++) {
sr = mPendingServices.get(i);
...
mPendingServices.remove(i);
i--;
proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
mAm.mProcessStats);
//启动目标Service
realStartServiceLocked(sr, proc, sr.createdFromFg);
didSomething = true;
}
} catch (RemoteException e) {
...
}
}