在Activity中使用bindService绑定Service时,会调用ContextWrapper的bindService方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/content/ContextWrapper.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
这个方法的mBase就是一个ContextImpl类型的对象。所以这里调用了ContextImpl类的bindService方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ContextImpl.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
// 关键代码
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
// ...
// 关键代码
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
// ...
}
// ...
}
在bindServiceCommon方法中,先调用LoadedApk类型的变量mPackageInfo.getServiceDispatcher方法,获取一个IServiceConnection类型的对象sd,下面看看LoadedApk类中的这个方法的具体实现:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/LoadedApk.java
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) {
if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
sd = map.get(c);
}
if (sd == null) {
// 关键代码
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
// 关键代码
return sd.getIServiceConnection();
}
}
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
// 关键代码
mIServiceConnection = new InnerConnection(this);
// ...
}
private static class InnerConnection extends IServiceConnection.Stub {
// ...
}
从LoadedApk类的getServiceDispatcher方法内部的逻辑主要是创建其内部类ServiceDispatcher对象,在ServiceDispatcher对象的创建过程中,又创建了ServiceDispatcher的静态内部类InnerConnection的实例。InnerConnection其实是继承IServiceConnection.Stub,所以它是一个Binder。在getServiceDispatcher方法的最后一行,通过sd.getIServiceConnection();返回的就是InnerConnection这类的实例。继续看ContextImpl类的bindServiceCommon方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ContextImpl.java
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
// 关键代码
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
// ...
// 关键代码
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
// ...
}
// ...
}
这个方法内部,通过ActivityManager.getService()获取到system_servier进程中的ActivityManagerService(后面简称AMS)在app进程中的代理对象,然后调用代理对象的bindService方法,并将前面获取的InnerConnection这个Binder对象作为参数传入,
这个过程就是进程间通信,下面看看AMS中的bindService方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public int bindService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, 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");
}
// ...
synchronized(this) {
//关键代码
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}
这个方法内调用了mServices对象的bindServiceLocked方法,mServices是ActiveSerivces类型的,下面看看ActiveServices类的bindServiceLocked方法的具体实现:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
//...
try {
// ...
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
//关键代码
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
// ...
if (s.app != null && b.intent.received) {
try {
//关键代码
c.conn.connected(s.name, b.intent.binder, false);
}
// ...
}
// ...
}
// ...
return 1;
}
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
// ...
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
// 如果要启动的Service所在 进程已经创建,并且进程的ActivityThread也不为null,则直接启动Service
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
}
// ...
}
}
// ...
//要启动的Service所在的进程还未创建
if (app == null && !permissionsReviewRequired) {
// 关键代码
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, 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";
bringDownServiceLocked(r);
return msg;
}
// ...
}
//...
return null;
}
bindServiceLocked这个方法内部,会调用bringUpServiceLocked方法,bringUpServiceLocked内部会根据要绑定的Service所在的进程是否创建,如果进程创建了并且ActivityThread也不为null,则直接走绑定Service流程,否则,要先创建Service所在的进程,然后在走绑定Service的流程。为了分析过程尽量全面,我们就按照Service是在一个新的进程中这种情况分析,下面看mAm.startProcessLocked()这个方法,这里的mAm就是AMS,在AMS中,通过调用几次startProcessLocked()的重载方法后,调用到startProcess方法,接着调用了Process类的start方法,接着调用了ZygoteProcess类的start方法,Process类的start方法调用是system_server进程和ZygoteProcess进程进行进程间通信,他们是通过socket方式进行进程间通信的。ZygoteProcess内部,通过调用start方法,接着调用startViaZygote方法,最终调用zygoteSendArgsAndGetResult方法,完成Servcie所在的进程的创建工作,这样Servcie所在的进程就创建了,执行ActivityThread的main方法,在main方法中,主要完成了主线程的Looper的创建,并创建ActivityThread对象,并调用其attach方法,如果sMainHandler对象为null,则给这个对象赋值,并调用Looper.loop()方法进行消息的抽取。ActivityThread的attach方法中,在次获取system_server进程在app进程的代理对象,然后调用这个代理对象attachApplication方法,这个方法中,将ApplicationThread对象作为参数传入,这样system_servier进程就可以获取到app进程的ApplicationThread这个binder对象在system_server进程中的代理对象。方便后续system_server进程(客户端)向app进程(服务端)发起进程间通信。AMS的attachApplication方法内部又调用了attachApplicationLocked方法,
这个方法内部通过调用ApplicationThread这个对象的bindApplication方法,这个时候是进程间通信(system_server作为客户端,app进程作为服务端),ApplicationThread的bindApplication方法内部,调用了sendMessage(H.Execute_Bind)方法,接着又执行了handleBindApplication方法,handleBindApplication方法内部主要做了三件事:
1.创建Instrumentation对象
2.调用LoadedApk的makeApplication方法,创建Application对象
3.调用Instrumentation的callApplicationOnCreate方法,完成Application的OnCreate方法的执行。
到这里,AMS的attachApplicationLocked方法中的ApplicationThread的bindApplication方法执行过程分析完毕,这个过程的具体分析,可以看Android 9.0 点击桌面应用图标,启动Activity的过程分析
接着继续看AMS的attachApplicationLocked方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@GuardedBy("this")
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// ...
try {
// ...
if (app.isolatedEntryPoint != null) {
thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
} else if (app.instr != null) {
thread.bindApplication(processName, appInfo, providers,
app.instr.mClass,
profilerInfo, app.instr.mArguments,
app.instr.mWatcher,
app.instr.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, isAutofillCompatEnabled);
} else {
// 关键代码
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, isAutofillCompatEnabled);
}
// ...
}
// ...
// Find any services that should be running in this process...
if (!badApp) {
try {
//关键代码
didSomething |= mServices.attachApplicationLocked(app, processName);
checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
// ...
return true;
}
上面已经分析了thread.bindApplication方法,下面继续看mServices.attachApplicationLocked方法,mServices是ActivieServices类型的,所以代码执行到ActivieServices类的attachApplicationLocked方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
boolean didSomething = false;
if (mPendingServices.size() > 0) {
ServiceRecord sr = null;
try {
for (int i=0; i<mPendingServices.size(); i++) {
sr = mPendingServices.get(i);
// ...
// 关键代码
realStartServiceLocked(sr, proc, sr.createdFromFg);
didSomething = true;
// ...
}
}
// ...
}
// ...
return didSomething;
}
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
// ...
boolean created = false;
try {
// ...
// 关键代码
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
// ...
}
// ...
// 关键代码
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
// ...
}
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
//在前面的分析中,Service所在的进程已经创建,并且ActivityThread也创建了,所以这里的判断不成立
if (r.app == null || r.app.thread == null) {
return false;
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
// ...
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
// ...
}
// ...
}
return true;
}
attachApplicationLocked方法内部会r.app.thread.scheduleCreateService方法,r表示ServcieRecord对象,可以理解为是Servcie, r.app其实就是ProcessRecord类型的对象,可以理解为Process,r.app.thread是一个IApplicationThread类型的对象。
所以r.app.thread.scheduleBindService最终会执行到ApplicationThread的scheduleCreateService方法,这里其实是进程间通信。下面看看这个方法的具体实现
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ActivityThread.java
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
// ...
// 关键代码
sendMessage(H.CREATE_SERVICE, s);
}
public void handleMessage(Message msg) {
case CREATE_SERVICE:
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) {
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
// 关键代码
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
}
// ...
try {
// 关键代码
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
mServices.put(data.token, service);
// ...
}
// ...
}
handleCreateService方法内部做了如下事情:
1.通过类加载的方式创建Service实例对象
2.调用LoadedApk类的makeApplication方法,返回一个Application对象
3.调用servcie的attach方法,这个方法内部主要是调用了attachBaseContext方法,将servcie与ContextImpl对象关联
4.调用Servcie的onCreate方法
至此,Servcie被创建,并且OnCreate方法也得到执行。
下面继续看ActiveServices类的realStartServiceLocked方法
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
// ...
boolean created = false;
try {
// ...
// 关键代码
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
// ...
}
// ...
// 关键代码
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
// ...
}
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;
}
}
}
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
//在前面的分析中,Service所在的进程已经创建,并且ActivityThread也创建了,所以这里的判断不成立
if (r.app == null || r.app.thread == null) {
return false;
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
// ...
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
// ...
}
// ...
}
return true;
}
这方法内部继续调用到requestServiceBindingLocked的重载方法,这个重载方法内部,
调用r.app.thread,这个对象的scheduleBindService方法,r.app.thread是一个IApplicationThread类型的对象。所以r.app.thread.scheduleBindService最终会执行到ApplicationThread的scheduleBindService方法,这里其实是进程间通信。下面看看这个方法的具体实现
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ActivityThread.java
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState) {
updateProcessState(processState, false);
// ...
// 关键代码
sendMessage(H.BIND_SERVICE, s);
}
public void handleMessage(Message msg) {
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) {
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
// 关键代码
IBinder binder = s.onBind(data.intent);
// 关键代码
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
// ...
}
// ...
}
// ...
}
}
scheduleBindService方法最终调用到了handleBindService方法,最终调用了s.onBind()方法,这里的s就是Service,所以,至此Service的onBind方法执行。
接着调用了AMS的publishService方法
http://androidxref.com/9.0.0_r3/xref/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);
}
}
这个方法中mServices是ActiveServices类型的,下面看看ActiveServices类的publishServiceLocked方法
http://androidxref.com/9.0.0_r3/xref/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 (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;
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);
if (!filter.equals(c.binding.intent.intent)) {
continue;
}
try {
// 关键代码
c.conn.connected(r.name, service, false);
}
// ...
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
这个方法内部c.conn.connected(r.name, service, false);其中c.conn是LoadedApk类的静态内部类ServiceDispatcher的静态内部类InnerConnection类型对象,而InnerConnection 是继承 IServiceConnection.Stub,所以,c.conn其实就是app进程的InnerConnection这个binder对象在system_server进程中的代理,此时,system_server进程作为客户端,通过这个代理对象向app进程(作为服务端)发起进程间通信,这样,InnerConnection的onConnected方法就得到执行,下面看看InnerConnection的connected的具体实现
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/LoadedApk.java
public final class LoadedApk {
static final class ServiceDispatcher {
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, boolean dead)
throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
// 关键代码
sd.connected(name, service, dead);
}
}
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
// 关键代码
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
}
}
InnerConnection的connected这个方法内部会调用ServiceDispatcher类的connected方法,
ServiceDispatcher类的connected方法又会调用
mActivityThread.post(new RunConnection(name, service, 0, dead));
这里mActivityThread其实就是个handler,下面看看这个RunConnection类,它是LoadedApk的静态内部类ServiceDispatcher的一个内部类
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/LoadedApk.java
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) {
return;
}
old = mActiveConnections.get(name);
if (old != null && old.binder == service) {
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);
}
if (service != null) {
// 关键代码
mConnection.onServiceConnected(name, service);
} else {
// The binding machinery worked, but the remote returned null from onBind().
mConnection.onNullBinding(name);
}
}
run方法中,有调用了doConnected方法,doConnected方法中,mConnection.onServiceConnected方法,这里的mConnection就是我们bindServcie方法中传入的ServiceConnection类型的变量,所以至此,onServiceConnected方法得到回调。
以上便是bindService的整个过程分析