【安卓 R 源码】 bindService 源码分析
使用bindService主要分两种情形:1. Service的调用者client与Service在同一个App中;2. Service的调用者client是App1中的一个Activity,而Service是App2中的Service,client与service分属两个App,这种情形下主要用于实现跨进程的通信。bindService 的生命周期:Service被绑定bindService()
使用bindService主要分两种情形:
1. Service的调用者client与Service在同一个App中;
2. Service的调用者client是App1中的一个Activity,而Service是App2中的Service,client与service分属两个App,这种情形下主要用于实现跨进程的通信。
bindService 的生命周期:
Service被绑定bindService()的时候调用onCreate()和onBind()方法,onStartCommand()方法不被被调用
完整的客户端生命周期:onCreate() → onBind() → unbindService → onUnbind() → onDestroy()
bindService 源码分析
相关类介绍
- Instrumentation
用于实现应用程序测试代码的基类。当在打开仪器的情况下运行时,这个类将在任何应用程序代码之前为您实例化,允许您监视系统与应用程序的所有交互。可以通过AndroidManifest.xml的<Instrumentation>标签描述该类的实现。
- ActivityManager
该类提供与Activity、Service和Process相关的信息以及交互方法, 可以被看作是ActivityManagerService的辅助类。
- ActivityManagerService
Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用程序的管理和调度等工作。
- ActivityThread
管理应用程序进程中主线程的执行,根据Activity管理者的请求调度和执行activities、broadcasts及其相关的操作。
- frameworks/base/core/java/android/content/Context.java
抽象函数,具体的实现是在 子类中
public abstract boolean bindService(@RequiresPermission Intent service,
@NonNull ServiceConnection conn, @BindServiceFlags int flags);
- frameworks/base/core/java/android/content/ContextWrapper.java
public ContextWrapper(Context base) {
mBase = base;
}
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
- frameworks/base/core/java/android/app/ContextImpl.java
可以看到 ContextWrapper类的bindService方法直接调用到 mBase.bindService方法,mBase其实就是ContextImpl实例,所以我们跟进去ContextImpl的bindService方法:
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
warnIfCallingFromSystemProcess();
// executor 为空
return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
getUser());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
String instanceName, Handler handler, Executor executor, UserHandle user) {
// Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
IServiceConnection sd;
// 前面对一些异常处理
if (mPackageInfo != null) {
if (executor != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
} else {
// 1. 将 ServiceConnection对象转换成ServiceDispatcher.InnerConnection对象
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 准备离开这个进程
service.prepareToLeaveProcess(this);
// 2. binder 调用,最终调用到ActivityManagerService的bindIsolatedService方法
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();
}
}
获取 service 过程:
先看第一点:
1. 将 ServiceConnection对象转换成ServiceDispatcher.InnerConnection对象
-------------------------------------------------start-------------------------------------------------
mPackageInfo.getServiceDispatcher方法,将 ServiceConnection对象转换成ServiceDispatcher.InnerConnection对象
- frameworks/base/core/java/android/app/LoadedApk.java
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Executor executor, int flags) {
return getServiceDispatcherCommon(c, context, null, executor, flags);
}
private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,
Context context, Handler handler, Executor executor, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
// 存储了一个应用当前活动的 ServiceConnection和 ServiceDispatcher之间的映射关系
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
sd = map.get(c);
}
if (sd == null) {
if (executor != null) {
sd = new ServiceDispatcher(c, context, executor, flags);
} else {
// 这里创建一个 ServiceDispatcher
sd = new ServiceDispatcher(c, context, handler, flags);
}
if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
if (map == null) {
map = new ArrayMap<>();
mServices.put(context, map);
}
// 保存到 map 中
map.put(c, sd);
} else {
sd.validate(context, handler, executor);
}
// 通过 ServiceDispatcher 获取 IServiceConnection
return sd.getIServiceConnection();
}
}
看下 ServiceDispatcher 的 构造方法:
在ServiceDispatcher的构造方法中,首先创建了InnerConnection对象,并赋值给它的成员变量mIServiceConnection,接着将ServiceConnection 对象conn赋值给成员变量mConnection ,将ActivityThread类中的Handler H mH赋值给mActivityThread 成员变量。
private final ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
= new ArrayMap<ComponentName, ServiceDispatcher.ConnectionInfo>();
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
// 这里创建了 mIServiceConnection
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mContext = context;
mActivityThread = activityThread;
mActivityExecutor = null;
mLocation = new ServiceConnectionLeaked(null);
mLocation.fillInStackTrace();
mFlags = flags;
}
其中 sd.getIServiceConnection(),就是获取了 mIServiceConnection 对象
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
IServiceConnection getIServiceConnection() {
return mIServiceConnection;
}
InnerConnection为ServiceDispatcher中的静态内部类,继承自 IServiceConnection.Stub,很显然,它是一个binder对象。类似于ApplicationThread,InnerConnection中的方法是运行在客户端进程中的Binder线程池中的,它主要参与Service绑定后ServiceConnection 中onServiceConnected方法的回调过程。可以看到在InnerConnection的构造方法中只是对外部传入的ServiceDispatcher对象通过WeakReference做了一次封装,使得InnerConnection对象持有ServiceDispatcher对象的引用
private static class InnerConnection extends IServiceConnection.Stub {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service, boolean dead)
throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead);
}
}
}
-------------------------------------------------end-------------------------------------------------
接下来继续:binder 调用,调用到ActivityManagerService的bindIsolatedService方法,而sd 作为参数继续往下走
- frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
final ActiveServices mServices;
public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String instanceName,
String callingPackage, int userId) throws TransactionTooLargeException {
enforceNotIsolatedCaller("bindService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
if (callingPackage == null) {
throw new IllegalArgumentException("callingPackage cannot be null");
}
// Ensure that instanceName, which is caller provided, does not contain
// unusual characters.
if (instanceName != null) {
for (int i = 0; i < instanceName.length(); ++i) {
char c = instanceName.charAt(i);
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9') || c == '_' || c == '.')) {
throw new IllegalArgumentException("Illegal instanceName");
}
}
}
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, instanceName, callingPackage, userId);
}
}
- frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
调用ActiveServices的bindServiceLocked。
bindServiceLocked比较长我们只看关键部分。它的主要操作步骤如下。
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
//…
//1、首先会根据token找到其对应的ActivityRecord,ActivityRecord表示的是一个activity记录,此处指的是调用bindService的activity
ActivityRecord activity = null;
if (token != null) {
activity = ActivityRecord.isInStackLocked(token);
if (activity == null) {
Slog.w(TAG, “Binding with unknown activity: “ + token);
return 0;
}
}
//…
//2、调用retrieveServiceLocked解析传入的intent等参数获得一个ServiceRecord对象
// retrieveServiceLocked查找对应的service
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
ServiceRecord s = res.record;
//...
//3、把传入的connection封装成一个ConnectionRecord对象,connection就是步骤3获得的InnerConnection,
// 因为后续AMS需要使用它来告诉activity service已经启动起来了,所以要把它保存起来,这里保存在好几个地方
//AppBindRecord中存储了当前ServiceRecord, intent以及发起方的进程信息。
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是ServiceRecord.connections的成员变量
clist.add(c);
//b是指AppBindRecord
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);
//...
//4、最初绑定service时传入的flag是BIND_AUTO_CREATE,所以此处符合条件进而调用bringUpServiceLocked启动要绑定的service
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
//…
if (s.app != null) {
if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
s.app.treatLikeActivity = true;
}
//5、更新service所在进程的优先级
mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities
|| s.app.treatLikeActivity, b.client);
mAm.updateOomAdjLocked(s.app);
}
if (s.app != null && b.intent.received) {
try {
//6、Service已经正在运行,则调用InnerConnection的代理对象
c.conn.connected(s.name, b.intent.binder);
} catch (Exception e) {
...
}
//7、当第一个app连接到该binding, 且之前已被bind过, 则回调onRebind()方法
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
//8、最终回调onBind()方法
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
return 1;
}
bindServiceLocked做的事情比较多,我们再来梳理一下,首先在注释1处查找请求绑定的Activity是否存在,之后在注释2处通过retrieveServiceLocked查找对应的service。在注释3处创建AppBindRecord和ConnectionRecord,AppBindRecord记录着当前ServiceRecord, intent以及发起方的进程信息,ConnectionRecord则是对connection进行封装。创建完成后会把ConnectionRecord存到ServiceRecord和AppBindRecord中。注释4处通过bringUpServiceLocked来启动service,之后在注释5处更新service所在进程的优先级,在注释6处Service已经正在运行,调用InnerConnection的代理对象。注释7处判断是否回调onRebind方法。注释8处requestServiceBindingLocked最终回调onBind()方法。
4. bringUpServiceLocked启动要绑定的service
-------------------------------------------------start------------------------------------------------
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen,
boolean enqueueOomAdj)
throws TransactionTooLargeException {
if (r.app != null && r.app.getThread() != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
-----
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
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) {
final IApplicationThread thread = app.getThread();
final int pid = app.getPid();
final UidRecord uidRecord = app.getUidRecord();
if (thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode,
mAm.mProcessStats);
// 重点代码--
realStartServiceLocked(r, app, thread, pid, uidRecord, execInFg,
enqueueOomAdj);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
}
service的启动最终是在realStartServiceLocked里
private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg,
boolean enqueueOomAdj) throws RemoteException {
if (thread == null) {
throw new RemoteException();
}
if (DEBUG_MU)
Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
+ ", ProcessRecord.uid = " + app.uid);
r.setProcess(app, thread, pid, uidRecord);
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
final ProcessServiceRecord psr = app.mServices;
final boolean newService = psr.startService(r);
bumpServiceExecutingLocked(r, execInFg, "create", null /* oomAdjReason */);
mAm.updateLruProcessLocked(app, false, null);
updateServiceForegroundLocked(psr, /* oomAdj= */ false);
// Force an immediate oomAdjUpdate, so the client app could be in the correct process state
// before doing any service related transactions
mAm.enqueueOomAdjTargetLocked(app);
mAm.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
// 记录是否呗创建
boolean created = false;
try {
if (LOG_SERVICE_START_STOP) {
String nameTerm;
int lastPeriod = r.shortInstanceName.lastIndexOf('.');
nameTerm = lastPeriod >= 0 ? r.shortInstanceName.substring(lastPeriod)
: r.shortInstanceName;
EventLogTags.writeAmCreateService(
r.userId, System.identityHashCode(r), nameTerm, r.app.uid, pid);
}
final int uid = r.appInfo.uid;
final String packageName = r.name.getPackageName();
final String serviceName = r.name.getClassName();
FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_LAUNCH_REPORTED, uid, packageName,
serviceName);
mAm.mBatteryStatsService.noteServiceStartLaunch(uid, packageName, serviceName);
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
// 1.发起SystemServer进程到客户端进程的单向IPC操作,创建Service对象并调用其onCreate方法
thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
app.mState.getReportedProcState());
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app, "Died when creating service");
throw e;
} finally {
if (!created) {
// Keep the executeNesting count accurate.
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying, false);
// Cleanup.
if (newService) {
psr.stopService(r);
r.setProcess(null, null, 0, null);
}
// Retry.
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
if (r.allowlistManager) {
psr.mAllowlistManager = true;
}
// 2.若当前Service的启动方式为bindService,则执行Service的绑定操作
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(psr, null, true);
if (newService && created) {
psr.addBoundClientUidsOfNewService(r);
}
// 3. 若当前Service的启动方式为startService,则新创建一个ServiceRecord.StartItem对象并添加到ServiceRecord对象 r的pendingStarts集合中
// 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, 0));
}
// 4.若当前Service的启动方式为startService,则回调当前Service对象的 onStartCommand方法
sendServiceArgsLocked(r, execInFg, true);
if (r.delayed) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
if (r.delayedStop) {
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
"Applying delayed stop (from start): " + r);
stopServiceLocked(r, enqueueOomAdj);
}
}
}
1 处,发起SystemServer进程到客户端进程的单向IPC操作,创建Service对象并调用其onCreate方法
由于当前Service的启动方式为bindService,所以3处if条件不满足,导致ServiceRecord r的pendingStarts集合为empty,之后4处调用到sendServiceArgsLocked方法,在 sendServiceArgsLocked方法内部获取到pendingStarts.size()为0直接return掉了,至此当前Service对象的 onStartCommand方法并不会被回调。这也就解释了我们通过bindService的方式启动Service,onStartCommand方法并不会被回调的原因。
thread.scheduleCreateService
- frameworks/base/core/java/android/app/ActivityThread.java
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);
}
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case CREATE_SERVICE:
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
("serviceCreate: " + String.valueOf(msg.obj)));
}
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
private void handleCreateService(CreateServiceData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
Application app = packageInfo.makeApplication(false, mInstrumentation);
final java.lang.ClassLoader cl;
if (data.info.splitName != null) {
cl = packageInfo.getSplitClassLoader(data.info.splitName);
} else {
cl = packageInfo.getClassLoader();
}
// 通过反射获取到 service 对象
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
// 获取 context
ContextImpl context = ContextImpl.getImpl(service
.createServiceBaseContext(this, packageInfo));
if (data.info.splitName != null) {
context = (ContextImpl) context.createContextForSplit(data.info.splitName);
}
if (data.info.attributionTags != null && data.info.attributionTags.length > 0) {
final String attributionTag = data.info.attributionTags[0];
context = (ContextImpl) context.createAttributionContext(attributionTag);
}
// Service resources must be initialized with the same loaders as the application
// context.
context.getResources().addLoaders(
app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
context.setOuterContext(service);
// 与 context 绑定
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
// 回调 onCreate 方法
service.onCreate();
mServicesData.put(data.token, data);
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
在binder线程通过Hander(mH)给主线程发送消息,让主线程来处理,
mH
接收到CREATE_SERVICE
的消息,调用handleCreateService()
来处理函数中通过获取ClassLoader反射创建了Service对象(与Activity的创建方式一致),并绑定context,执行
onCreate()
的生命周期方法
继续往下走,走到 Service的绑定操作 requestServiceBindingsLocked
private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
throws TransactionTooLargeException {
for (int i=r.bindings.size()-1; i>=0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
break;
}
}
}
当我们通过bindService的方式启动Service时,会对ServiceRecord r.bindings集合进行put操作,这样子就导致r.bindings.size()不为0,会调用到for循环中的 requestServiceBindingLocked方法,而当我们通过startService的方式启动Service时,r.bindings.size()为0,for循环条件不满足直接退出。这也就解释了我们通过StartService的方式启动Service时,Service的onBind方法不会回调的原因。
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if (r.app == null || r.app.getThread() == null) {
// If service is not currently running, can't yet bind.
return false;
}
if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
+ " rebind=" + rebind);
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
//发送bind开始的消息
bumpServiceExecutingLocked(r, execInFg, "bind",
OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
// 调用 ActivityThread 的私有类,去绑定服务
r.app.getThread().scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.mState.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, false);
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, false);
return false;
}
}
return true;
}
- frameworks/base/core/java/android/app/ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
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;
if (DEBUG_SERVICE)
Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
+ Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
sendMessage(H.BIND_SERVICE, s);
}
case BIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
private void handleBindService(BindServiceData data) {
CreateServiceData createData = mServicesData.get(data.token);
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());
data.intent.prepareToEnterProcess(isProtectedComponent(createData.info),
s.getAttributionSource());
try {
// 如果不是重新绑定的话
if (!data.rebind) {
// 回调 service 的onBind 方法
IBinder binder = s.onBind(data.intent);
// 把 获取的binder(即onBind的返回值)传递给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);
}
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to bind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}
进去AMS的publishService方法:
- frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void publishService(IBinder token, Intent intent, IBinder service) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
synchronized(this) {
if (!(token instanceof ServiceRecord)) {
throw new IllegalArgumentException("Invalid service token");
}
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
- frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "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;
ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
for (int conni = connections.size() - 1; conni >= 0; conni--) {
// 从ServiceRecord.connections中取出ConnectionRecord
ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
if (!filter.equals(c.binding.intent.intent)) {
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Not publishing to: " + c);
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Published intent: " + intent);
continue;
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
try {
// 回调 connected 方法,上面代码有讲过
c.conn.connected(r.name, service, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + r.shortInstanceName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false, false);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
- frameworks/base/core/java/android/app/LoadedApk.java
private static class InnerConnection extends IServiceConnection.Stub {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service, boolean dead)
throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead);
}
}
}
private final Handler mActivityThread;
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityExecutor != null) {
mActivityExecutor.execute(new RunConnection(name, service, 0, dead));
} else if (mActivityThread != null) {
// 走到主线程操作
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
此处的mActivityThread就是主线程的Handler,通过该Handler post消息。
private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
mName = name;
mService = service;
mCommand = command;
mDead = dead;
}
public void run() {
if (mCommand == 0) {
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
final ComponentName mName;
final IBinder mService;
final int mCommand;
final boolean mDead;
}
public void doConnected(ComponentName name, IBinder service, boolean dead) {
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.
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 now disconnected.
if (old != null) {
mConnection.onServiceDisconnected(name);
}
if (dead) {
mConnection.onBindingDied(name);
} else {
// If there is a new viable service, it is now connected.
if (service != null) {
// 回调onServiceConnected,至此我们就在绑定端的onServiceConnected回调函数中拿到service返回的binder了
mConnection.onServiceConnected(name, service);
} else {
// The binding machinery worked, but the remote returned null from onBind().
mConnection.onNullBinding(name);
}
}
}
可以看到在doConnected方法的最后调用到了ServiceConnection的onServiceConnected方法。
-------------------------------------------------end-------------------------------------------------
至此bindService的过程就结束了,总结来整个过程大概分为以下几步:
1、首先调用bindService通知AMS绑定service,AMS会先启动service回调其onCreate函数。
2、AMS启动service完成之后继续调用service的onBind函数,获取service返回的binder。
3、AMS把上一步获得的Binder对象通过绑定时传入的ServiceConnection的onServiceConnected函数传给调用端,这样调用端就可以通过binder来调用service提供的相关方法。
- Client进程: 通过getServiceDispatcher获取Client进程的匿名Binder服务端,即LoadedApk.ServiceDispatcher.InnerConnection,该对象继承于IServiceConnection.Stub; 再通过bindService调用到system_server进程;
- system_server进程: 依次通过scheduleCreateService和scheduleBindService方法, 远程调用到target进程;
- target进程: 依次执行onCreate()和onBind()方法; 将onBind()方法的返回值IBinder(作为target进程的binder服务端)通过publishService传递到system_server进程;
- system_server进程: 利用IServiceConnection代理对象向Client进程发起connected()调用, 并把target进程的onBind返回Binder对象的代理端传递到Client进程;
- Client进程: 回调到onServiceConnection()方法, 该方法的第二个参数便是target进程的binder代理端. 到此便成功地拿到了target进程的代理, 可以畅通无阻地进行交互.
参考:
更多推荐
所有评论(0)