接着上一篇StartService,这章分析一下bindService的一个流程。
在Android developer网站上有三种使用创建Bound Service的方法:
一种就是继承Binder Class的,这种方法用在当你的Service只会用在自己的进程当中,而不会出现换进程的调用。也就是所谓的LocalService.
一种是使用Messager,这是通过使用Handler相关的东西,去实现跨进程的调用。
最后一种就是AIDL,最常用的一种跨进程的Service binder调用。
1. ContextImpl.bindService()
通常我们想去调用一个Service的时候,会传递一个Intent和一个ServiceConnection还有一个flags参数。ServiceConnection是需要我们继承的。
flags:Operation options for the binding
1. 通过mPackageInfo.getServiceDispatcher(conn, getOuterContext(),mMainThread.getHandler(), flags);
2. 通过ActivityManagerNative去远程调用AMS。
public boolean bindService(Intent service, ServiceConnection conn,int flags) {
warnIfCallingFromSystemProcess();
return bindService(service, conn, flags, UserHandle.getUserId(Process.myUid()));
}
/** @hide */
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags, int userHandle) {
IServiceConnection sd;
try {
IBinder token = getActivityToken();
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags); ... ...
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, userHandle);
... ...
return res != 0;
} catch (RemoteException e) {
return false;
}
}
1.1 LoaderApk.getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags)
在ServiceDispatcher会保存着传进来的ServiceConnection,同时有一个InnerConnection对象,而InnerConnection是继承自IServiceConnection.Stub,所以InnerConnection是一个Binder的服务端。sd.getIServiceConnection()返回的就是InnerConnection对象mIServiceConnection。
里面有两个Map数组,一个context对应一组(ServiceConnection和ServiceDispatcher的map),一个ServiceConnection对应一个ServiceDispatcher。
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
HashMap 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 HashMap();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference(sd);
}
public void connected(ComponentName name, IBinder service) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service);
}
}
}
private final HashMap mActiveConnections
= new HashMap();
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;
}
1. 直接调用mServices.bindServiceLocked
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType,
IServiceConnection connection, int flags, int userId) {
enforceNotIsolatedCaller("bindService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service, resolvedType,
connection, flags, userId);
}
}
2.1 ActiveService.bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, int userId)
1. 通过传进来的token值到ActivityStack中查询该token值是不是已经有了,就是调用者Activity的 ActivityRecord
2. 通过retrieveServiceLocked找到需要bind的service放到新的ServiceRecord中
3. 新建AppBindRecord, ConnectionRecord, 获取Clinet端传过来的ServiceDispatcher.InnerConnection的IBinder,把IBinder与ConnectionRecord建立关系并保持在对应的connections中。
4. bringUpServiceLocked, 启动Service // goto 2.1.4
int bindServiceLocked(IApplicationThread caller, IBinder token,
Intent service, String resolvedType,
IServiceConnection connection, int flags, int userId) {
ActivityRecord activity = null;
if (token != null) {
activity = mAm.mMainStack.isInStackLocked(token);
if (activity == null) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
} ... ...
int clientLabel = 0;
PendingIntent clientIntent = null;
... ...
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType,
Binder.getCallingPid(), Binder.getCallingUid(), userId, true);
ServiceRecord s = res.record;
try {
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
ArrayList clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList();
s.connections.put(binder, clist);
}
clist.add(c);
b.connections.add(c);
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet();
}
activity.connections.add(c);
}
b.client.connections.add(c);
if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
b.client.hasAboveClient = true;
}
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList();
mServiceConnections.put(binder, clist);
}
clist.add(c);
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), false) != null) {
return 0;
}
}
if (s.app != null) {
// This could have made the service more important.
mAm.updateOomAdjLocked(s.app);
}
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);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortName
+ " 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, true);
}
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, false);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
1. 如果这个Service所在的进程已经起来了,就直接调用realStartServiceLocked(r, app); 如果这个Service还没有起来就先去mAm.startProcessLocked启动对应的process,然后把需要start的service添加到mPendingServices中,等到进程起来之后会调用attachApplicationLocked去启动相应的service,当然还是调用realStartServiceLocked(sr, proc);
private final String bringUpServiceLocked(ServiceRecord r,
int intentFlags, boolean whileRestarting) {
// 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;
ProcessRecord app;
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);
if (DEBUG_MU)
Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName);
realStartServiceLocked(r, app);
return null;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
} else {
// If this service runs in an isolated process, then each time
// we call startProcessLocked() we will get a new isolated
// process, starting another process if we are currently waiting
// for a previous process to come up. To deal with this, we store
// in the service any current isolated process it is running in or
// waiting to have come up.
app = r.isolatedProc;
}
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
return null;
}
2.1.4.1 ActiveService.realStartServiceLocked(ServiceRecord r, ProcessRecord app)
app.services.add(r); //把record加到service所在的进程的ProcessRecord的services的数组中
bumpServiceExecutingLocked(r, "create"); // 把service加到 r.app.executingServices中,说明这个servcie正在执行。
1) app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo)); 通过app.thread.scheduleCreateService去调用ActivityThread的scheduleCreateService。在ActivityThread的中通过handle去发送和处理“CREATE_SERVICE”的消息。调用handleCreateService
2) requestServiceBindingLock() //这个函数在BindService的时候才会起作用
3) sendServiceArgsLocked(r, true); //没有传递的参数,在这边没用
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app) throws RemoteException {
... ...
app.services.add(r);
bumpServiceExecutingLocked(r, "create");
mAm.updateLruProcessLocked(app, true);
boolean created = false;
try {
... ...
EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
r.userId, System.identityHashCode(r), r.shortName,
mAm.mStringBuilder.toString(), r.app.pid);
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
r.postNotification();
created = true;
} finally {
if (!created) {
app.services.remove(r);
scheduleServiceRestartLocked(r, false);
}
}
requestServiceBindingsLocked(r);
// If the service is in the started state, and there are no
// pending arguments, then fake up one so its onStartCommand() will
// be called.
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
null, null));
}
sendServiceArgsLocked(r, true);
}
1) 调用 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind); 去调用ActivityThread的方法
private final void requestServiceBindingsLocked(ServiceRecord r) {
Iterator bindings = r.bindings.values().iterator();
while (bindings.hasNext()) {
IntentBindRecord i = bindings.next();
if (!requestServiceBindingLocked(r, i, false)) {
break;
}
}
}
private final boolean requestServiceBindingLocked(ServiceRecord r,
IntentBindRecord i, boolean rebind) {
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, "bind");
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (RemoteException e) {
if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
return false;
}
}
return true;
}
1) 找到对应的Service,并且调用Service.onBind(自己写的Service都是要实现onBind来返回一个IBinder用来与之交互的), 把返回的IBinder值传回ActiveService, 调用 ActivityManagerNative.getDefault().publishService( data.token, data.intent, binder);
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());
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, 0, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
}
} catch (Exception e) {
... ...
}
}
里面的细节先不关注,这里主要看c.conn.connected(r.name, service); 这个就调到我们之前传进来的ServiceDispatcher.InnerConnection的connected(), 最终就用调用mConnection.onServiceConnected(name, service); 也就是ServiceConnection.onServiceConnected。
ServiceConnection.onServiceConnected传进来的Binder就是Service.onBind()返回的值。
所以这就建立了ServiceConnection与Service之间的关系。
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
if (DEBUG_SERVICE) Slog.v(TAG, "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;
if (r.connections.size() > 0) {
Iterator> it
= r.connections.values().iterator();
while (it.hasNext()) {
ArrayList clist = it.next();
for (int i=0; i
3. ContextImpl.unbindSercie
1) 通过ActivityManagerNative.getDefault().unbindService(sd); 调用ActiveServices.unbindServiceLocked
public void unbindService(ServiceConnection conn) {
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
getOuterContext(), conn);
try {
ActivityManagerNative.getDefault().unbindService(sd);
} catch (RemoteException e) {
}
} else {
throw new RuntimeException("Not supported in system context");
}
}
1) 根据传进来的ServiceDispatcher.InnerConnection的IBinder值获取对应的ConnectionRecord的list,然后依次调用removeConnectionLocked(r, null, null);
boolean unbindServiceLocked(IServiceConnection connection) {
IBinder binder = connection.asBinder();
if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
ArrayList clist = mServiceConnections.get(binder);
if (clist == null) {
Slog.w(TAG, "Unbind failed: could not find connection for "
+ connection.asBinder());
return false;
}
final long origId = Binder.clearCallingIdentity();
try {
while (clist.size() > 0) {
ConnectionRecord r = clist.get(0);
removeConnectionLocked(r, null, null);
if (r.binding.service.app != null) {
// This could have made the service less important.
mAm.updateOomAdjLocked(r.binding.service.app);
}
}
} finally {
Binder.restoreCallingIdentity(origId);
}
return true;
}
1) s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent()); 回调ActivityThread的handleUnbindService,在这个函数中会去s.onUnbind 去做service unBind的动作。
2) bringDownServiceLocked(s, false);
void removeConnectionLocked(
ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
IBinder binder = c.conn.asBinder();
AppBindRecord b = c.binding;
ServiceRecord s = b.service;
ArrayList clist = s.connections.get(binder);
if (clist != null) {
clist.remove(c);
if (clist.size() == 0) {
s.connections.remove(binder);
}
}
b.connections.remove(c);
if (c.activity != null && c.activity != skipAct) {
if (c.activity.connections != null) {
c.activity.connections.remove(c);
}
}
if (b.client != skipApp) {
b.client.connections.remove(c);
if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
b.client.updateHasAboveClientLocked();
}
}
clist = mServiceConnections.get(binder);
if (clist != null) {
clist.remove(c);
if (clist.size() == 0) {
mServiceConnections.remove(binder);
}
}
if (b.connections.size() == 0) {
b.intent.apps.remove(b.client);
}
if (!c.serviceDead) {
if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
+ ": shouldUnbind=" + b.intent.hasBound);
if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
&& b.intent.hasBound) {
try {
bumpServiceExecutingLocked(s, "unbind");
mAm.updateOomAdjLocked(s.app);
b.intent.hasBound = false;
// Assume the client doesn't want to know about a rebind;
// we will deal with that later if it asks for one.
b.intent.doRebind = false;
s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
} catch (Exception e) {
Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
serviceDoneExecutingLocked(s, true);
}
}
if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
bringDownServiceLocked(s, false);
}
}
}
1) 如果force == false也就是并没有要求强制退出,r.connections.size() > 0 说明 这个Service还有其他Client Bind存在就直接return; 要不然r.connections.size() == 0, 说明多有的Client端都已经调用了unbind了,此时就会去把这个Service给destroy掉,通过调用r.app.thread.scheduleStopService(r);
此时s.onDestroy();就会被调用,也就是一个Service的生命周期结束。
2) mStoppingServices.add(r); //加到mStoppingServices数组中。
private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
//Slog.i(TAG, "Bring down service:");
//r.dump(" ");
// Does it still need to run?
if (!force && r.startRequested) {
return;
}
if (r.connections.size() > 0) {
if (!force) {
// XXX should probably keep a count of the number of auto-create
// connections directly in the service.
Iterator> it = r.connections.values().iterator();
while (it.hasNext()) {
ArrayList cr = it.next();
for (int i=0; i> it = r.connections.values().iterator();
while (it.hasNext()) {
ArrayList c = it.next();
for (int i=0; i
3.1.1.2.1 ActivityThread.handleStopService
当handleStopService执行完后,还是会调用ActiveServices.serviceDoneExecutingLocked告诉AMS客户端已经执行完成了。
此时inStopping为true,因为这个ServiceRecord已经加到mStoppingServices中
void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
boolean inStopping = mStoppingServices.contains(r);
if (r != null) {
... ...
final long origId = Binder.clearCallingIdentity();
serviceDoneExecutingLocked(r, inStopping);
Binder.restoreCallingIdentity(origId);
} else {
Slog.w(TAG, "Done executing unknown service from pid "
+ Binder.getCallingPid());
}
}
private void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
+ ": nesting=" + r.executeNesting
+ ", inStopping=" + inStopping + ", app=" + r.app);
else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
r.executeNesting--;
if (r.executeNesting <= 0 && r.app != null) {
if (DEBUG_SERVICE) Slog.v(TAG,
"Nesting at 0 of " + r.shortName);
r.app.executingServices.remove(r);
if (r.app.executingServices.size() == 0) {
if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
"No more executingServices of " + r.shortName);
mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
}
if (inStopping) {
if (DEBUG_SERVICE) Slog.v(TAG,
"doneExecuting remove stopping " + r);
mStoppingServices.remove(r);
r.bindings.clear();
}
mAm.updateOomAdjLocked(r.app);
}
}