在这篇文章中,我们来分析一下Service组件的绑定过程。
和这部门相关的源码文件如下所列:
Context.java 位于 frameworks/base/core/java/android/content/Context.java
ContextWrapper.java位于 frameworks/base/core/java/android/content/ContextWrapper.java
ContextImpl.java位于 frameworks/base/core/java/android/app/ContextImpl.java
ServiceConnectionframeworks.java 位于/base/core/java/android/content/ServiceConnection.java
LoadedApk.java 位于frameworks/base/core/java/android/app/LoadedApk.java
ActivityManagerNative.java 位于 frameworks/base/core/java/android/app/ActivityManagerNative.java
ActivityManagerService.java 位于 frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
ActivityServices.java 位于 frameworks/base/services/java/com/android/server/am/ActivityServices.java
ServiceRecord.java 位于frameworks/base/services/java/com/android/server/am/ServiceRecord.java
AppBindRecord.javaframeworks 位于/base/services/java/com/android/server/am/AppBindRecord.java
ConnectionRecord.java 位于frameworks/base/services/java/com/android/server/am/ConnectionRecord.java
我们从ContextImpl的bindService函数开始,完整分析Service的绑定过程。ContextImpl的bindService函数定义如下:
参数Service表示要绑定的Service
conn相当于暴露给用户的接口,当绑定成功时,会回调conn的onServiceConnected函数,以便用户可以获得Binder代理对象
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
warnIfCallingFromSystemProcess();
return bindService(service, conn, flags, UserHandle.getUserId(Process.myUid()));
}
public boolean bindService(Intent service, ServiceConnection conn, int flags, int userHandle) {
//将conn参数封装在一个ServiceDispatcher对象中
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags);
} else {
throw new RuntimeException("Not supported in system context");
}
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.setAllowFds(false);
//通知ActivityManagerService来执行bindService的操作
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, userHandle);
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
return false;
}
}
在bindService函数中,会首先将传进来的conn参数封装在一个ServiceDispatcher对象中。注意:ServiceDispatcher是在LoadedApk中定义的!
紧接着,会利用Binder通信来通知ActivityManagerService执行bindService的操作!ActivityManagerService的bindService函数执行如下:
final ActiveServices mServices;
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);
}
}
在ActivityManagerService中,类型为ActiveServices的成员变量mServices管理着所有已经启动的Service, 因此bindService会调用mServices的bindServiceLocked函数来执行BinderService的操作,ActiveServices的bindServiceLocked函数定义如下:
int bindServiceLocked(IApplicationThread caller, IBinder token,
Intent service, String resolvedType,
IServiceConnection connection, int flags, int userId) {
if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
+ " type=" + resolvedType + " conn=" + connection.asBinder()
+ " flags=0x" + Integer.toHexString(flags));
//得到发起者的进程信息
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when binding service " + service);
}
//指向发起bind的activity
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;
if (callerApp.info.uid == Process.SYSTEM_UID) {
// Hacky kind of thing -- allow system stuff to tell us
// what they are, so we can report this elsewhere for
// others to know why certain services are running.
try {
clientIntent = (PendingIntent)service.getParcelableExtra(
Intent.EXTRA_CLIENT_INTENT);
} catch (RuntimeException e) {
}
if (clientIntent != null) {
clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
if (clientLabel != 0) {
// There are no useful extras in the intent, trash them.
// System code calling with this stuff just needs to know
// this will happen.
service = service.cloneFilter();
}
}
}
//得到要绑定的Service
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType,
Binder.getCallingPid(), Binder.getCallingUid(), userId, true);
if (res == null) {
return 0;
}
if (res.record == null) {
return -1;
}
ServiceRecord s = res.record;
final long origId = Binder.clearCallingIdentity();
try {
//将这个Service对象从要重启的Service列表中删除掉
if (unscheduleServiceRestartLocked(s)) {
if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
+ s);
}
//构造一个ConnectionRecord对象,并将其保存起来
//AppBindRecord表示启动者和被启动的Service之间的连接
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
clist.add(c);
b.connections.add(c);
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
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<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
//将Service启动起来
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 (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
+ ": received=" + b.intent.received
+ " apps=" + b.intent.apps.size()
+ " doRebind=" + b.intent.doRebind);
if (s.app != null && b.intent.received) {
// Service is already running, so we can immediately
// publish the connection.
try {
//和Service绑定成功,回调
//这实际上会调用ServiceDispatcher的connected函数
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;
}
在bindServiceLocked函数的实现中,首先会调用retrieveServiceLocked来得到绑定的Service对象,这个对象有可能是还没有启动起来的。我们来看一看retrieveServiceLocked函数的实现:
private ServiceLookupResult retrieveServiceLocked(Intent service,
String resolvedType, int callingPid, int callingUid, int userId,
boolean createIfNeeded) {
//r指向要绑定的Service
ServiceRecord r = null;
if (DEBUG_SERVICE) Slog.v(TAG, "retrieveServiceLocked: " + service
+ " type=" + resolvedType + " callingUid=" + callingUid);
userId = mAm.handleIncomingUser(callingPid, callingUid, userId,
false, true, "service", null);
//根据Component来查找该Service
if (service.getComponent() != null) {
r = mServiceMap.getServiceByName(service.getComponent(), userId);
}
//根据filter来查找该Service
if (r == null) {
Intent.FilterComparison filter = new Intent.FilterComparison(service);
r = mServiceMap.getServiceByIntent(filter, userId);
}
//没有找到,则说明该Service还没有启动起来
if (r == null) {
try {
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveService(
service, resolvedType,
ActivityManagerService.STOCK_PM_FLAGS, userId);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
Slog.w(TAG, "Unable to start service " + service + " U=" + userId +
": not found");
return null;
}
ComponentName name = new ComponentName(
sInfo.applicationInfo.packageName, sInfo.name);
if (userId > 0) {
if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,
sInfo.name, sInfo.flags)) {
userId = 0;
}
sInfo = new ServiceInfo(sInfo);
sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
}
r = mServiceMap.getServiceByName(name, userId);
//需要创建一个Service组件
if (r == null && createIfNeeded) {
Intent.FilterComparison filter = new Intent.FilterComparison(
service.cloneFilter());
ServiceRestarter res = new ServiceRestarter();
BatteryStatsImpl.Uid.Pkg.Serv ss = null;
BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
ss = stats.getServiceStatsLocked(
sInfo.applicationInfo.uid, sInfo.packageName,
sInfo.name);
}
//创建一个ServiceRecord
r = new ServiceRecord(mAm, ss, name, filter, sInfo, res);
res.setService(r);
mServiceMap.putServiceByName(name, UserHandle.getUserId(r.appInfo.uid), r);
mServiceMap.putServiceByIntent(filter, UserHandle.getUserId(r.appInfo.uid), r);
// Make sure this component isn't in the pending list.
int N = mPendingServices.size();
for (int i=0; i<N; i++) {
ServiceRecord pr = mPendingServices.get(i);
if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
&& pr.name.equals(name)) {
mPendingServices.remove(i);
i--;
N--;
}
}
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
}
if (r != null) {
if (mAm.checkComponentPermission(r.permission,
callingPid, callingUid, r.appInfo.uid, r.exported)
!= PackageManager.PERMISSION_GRANTED) {
if (!r.exported) {
Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+ " from pid=" + callingPid
+ ", uid=" + callingUid
+ " that is not exported from uid " + r.appInfo.uid);
return new ServiceLookupResult(null, "not exported from uid "
+ r.appInfo.uid);
}
Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+ " from pid=" + callingPid
+ ", uid=" + callingUid
+ " requires " + r.permission);
return new ServiceLookupResult(null, r.permission);
}
return new ServiceLookupResult(r, null);
}
return null;
}
回到bindServiceLocked函数中,得到了要绑定的Service对象之后,就会调用bringUpServiceLocked来将该Service组件启动起来。这一部分的逻辑已经在Service的启动文章中分析过了。
最后,bindServiceLocked要做的就是绑定该Service了,也就是要回调用户的接口。
这实际上是调用的ServiceDispatcher的connected函数,ServiceDispatcher的connected函数实现如下:
public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0));
} else {
doConnected(name, service);
}
}
从上面的代码中,我们看出connected的逻辑是向主进程Handler中发送一个消息来完成的。RunConnection类是LoadedApk的一个内部类,定义如下:
private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command) {
mName = name;
mService = service;
mCommand = command;
}
public void run() {
if (mCommand == 0) {
doConnected(mName, mService);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
final ComponentName mName;
final IBinder mService;
final int mCommand;
}
处理该消息的时候,会调用RunConnection的run函数,在run函数中,会调用doConnected函数。doConnected函数的实现如下:
private final HashMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections = new HashMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
public void doConnected(ComponentName name, IBinder service) {
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.
mDied = false;
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 not disconnected.
if (old != null) {
mConnection.onServiceDisconnected(name);
}
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
在doConnected函数中,如果发现之前绑定的参数和现在要绑定的参数不是同一个!则会首先调用Disconnect之前的绑定,并调用新的参数的onServiceConnected,表示绑定成功!
分析到这里,我们就完整的分析了Service的绑定过程!