本文分析bindService的流程,首先我们通过阅读源码获取一个主线的调用地图,然后提出若干问题,包括:APP进程中如何获取AMS,AMS如何启动APP-service的进程,AMS中如何获取ApplicationThread并与之通讯,Service的启动及绑定流程;然后再通过源码一一解答。最后再整体总结梳理一下整体流程;
预先知识:
- Binder通信机制
整体分析与总结
主线地图与问题提出
我们从bindService一路跟踪,初步绘制了如下的调用序列图,我们可以以下面的图作为一个主线地图,避免走失,然后根据具体问题进行细节分析。
从上图中,我们提出如下问题:
- bindServiceCommon到IActivityManager的调用中,是如何获取到ActivityManagerService的?
- AMS中如何获取ApplicationThread并与之通讯?
- ApplicatoinThread的用途?ApplicationThread运行的进程是哪个?
- 进程如何启动-即AMS如何创建APP:server进程?
- Service如何启动?
- Service如何绑定?
- ServiceConnection 的回调方法何时使用?
问题解答汇总
我们将相关问题的结论提前到此小节,便于后续从比较抽象的层次上来进行复习及预览;
APP进程如何获取AMS?
-
APP进程中通过
ServiceManager.getService(Context.ACTIVITY_SERVICE)
获取的ActivityManagerService的客户端操作代理对象(Proxy)。该对象位于APP进程中,可以使用此对象(通过Binder进程间通信)来要求(位于system_process中)的ActivityManagerService进行对应的服务操作;
AMS如何获取ApplicationThread?
-
APP进程在binderSerice时,将自己进程中的ApplicationThread取出,通过Binder机制传递给AMS进程,传递过程中会转换成一个Proxy对象;
ActivityManager.getService().bindIsolatedService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
服务如何绑定?服务如何启动?进程如何启动?
- 进程启动:
- 在独立的进程中运行的服务需要先将进程启动,进程的启动是通过APP进程,请求系统进程中的AMS来执行,通过AMS的
startProcessLocked
方法启动进程,最终会通过socket接口请求zygote进程来启动进程。 - 在启动时会指定java的入口点为ActivityThread,即进程启动后会运行ActivityThread的main方法;
- AMS中会记录启动的进程记录(ProcessRecord),对应的ProcessRecord中会记录进程对应的ApplicationThread;
- 在独立的进程中运行的服务需要先将进程启动,进程的启动是通过APP进程,请求系统进程中的AMS来执行,通过AMS的
- 服务启动:
- 服务的启动需要请求AMS来完成
- 启动时需要先通过PID获取要启动到的ProcessRecord,通过ProcessRecord中记录的ApplicationThread来与对应的进程通信。
- AMS通过ApplicationThread来通知对应的进程创建服务,ApplicationThread作为通信的接口,实际上最终会通过ActivityThread的handleCreateService来创建服务的实例;
- 服务创建时,是在APP进程(可能是独立的进程)中进行的,需要通过类加载器加载对应的Service的类,同时构造相应的上下文及资源对象等,然后构造对应的实例;
- 服务创建成功后,会记录到ActivityThread的一个Service列表中,以便后续管理;
- 服务绑定:
- 服务绑定先在APP进程中,通过AMS代理对象发起请求,由AMS来安排bind(ActivityManagerService.bindIsolatedService);
- 然后具体的绑定动作还是通过IApplicationThread安排到APP的Service进程中,最终执行的
ActivityThread#handleBindService
; - 在APP进程中,会将Service取出,然后调用其onBind方法来获取IBinder远程操作对象;
- 之后再通过AMS调用
ActivityManagerService#publishService
来通知绑定成功的通知到对应的需要绑定服务的APP进程; - publishService中会调用ServiceConnection的onServiceConnected方法通知服务连接了;
整体流程总结
待补充
详细分析解答问题
APP进程中如何获取AMS?
说明:
第一次先逐项查看各个小节,最后再看此处的总结;
后续直接查看总结来快速获取结论;
总结:
- APP进程中通过
ServiceManager.getService(Context.ACTIVITY_SERVICE)
获取的ActivityManagerService
的客户端操作代理对象(Proxy)。 - 该对象位于APP进程中,可以使用此对象(通过Binder进程间通信)来要求(位于
system_process
中)的ActivityManagerService
进行对应的服务操作;
具体查看如下代码:
ContextImpl.bindServiceCommon
我们看 ContextImpl.bindServiceCommon
方法的实现,可以看到是调用了 ActivityManager.getService()
获取的;
frameworks/base/core/java/android/app/ContextImpl.java
:
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 (executor != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
} else {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
//
int res = ActivityManager.getService().bindIsolatedService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
}
ActivityManager.getService()
如下代码,getService实际上是从ServiceManager获取一个ActivityService的Binder远程服务接口对象,并且这个会被设置为单例模式;
frameworks/base/core/java/android/app/ActivityManager.java
:
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
// 直接通过 ServiceManager.getService 获取一个IBinder对象
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
public static IActivityManager getService() {
// 直接从IActivityManagerSingleton获取实例
return IActivityManagerSingleton.get();
}
AMS如何获取到 ApplicatoinThread?
首先,AMS实际上位于系统进程(system_process),而ApplicationThread则位于我们的APP进程,那么为什么需要这个跨进程的操作呢?
- Service的创建需要经过系统的管理,比方说鉴权及其他管理需要;
- 而开发者定义的Service的实例的创建逻辑也还是需要开发者来实现,Service对应的类也应该只加载在开发者自己的进程之中,Service使用方实际上还是开发者自己,所以服务的真实实例的创建过程要在应用的进程中;
那么,系统进程(中的AMS)如何获取ApplicationThread呢?
ApplicationThread的来源?
查看 ContextImpl.bindServiceCommon 的代码,可以看到,是在调用AMS的bindService方法时,将自己进程中的ApplicationThread
及ActivityToken
取出传递给了AMS服务;
// frameworks/base/core/java/android/app/ContextImpl.java
final @NonNull ActivityThread mMainThread;
private final @Nullable IBinder mToken;
public IBinder getActivityToken() {
return mToken;
}
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;
try {
service.prepareToLeaveProcess(this);
// 调用时传递了ApplicationThread和IBinder
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();
}
}
实际上,上面的mMainThread.getApplicationThread()
取出的是我们的APP进程中的ApplicationThread的服务端对象,然后经过IActivityManager进行binder传输(transact)前,会将其转换为一个Proxy代理对象,用于在AMS中请求我们进程的ApplicationThread来提供服务;
// android.app.IActivityManager.Stub#TRANSACTION_bindIsolatedService
case TRANSACTION_bindIsolatedService:
{
data.enforceInterface(descriptor);
android.app.IApplicationThread _arg0;
// 这里将IApplicationThread的服务对象转换成一个Proxy代理对象
_arg0 = android.app.IApplicationThread.Stub.asInterface(data.readStrongBinder());
android.os.IBinder _arg1;
_arg1 = data.readStrongBinder();
android.content.Intent _arg2;
if ((0!=data.readInt())) {
_arg2 = android.content.Intent.CREATOR.createFromParcel(data);
}
else {
_arg2 = null;
}
java.lang.String _arg3;
_arg3 = data.readString();
android.app.IServiceConnection _arg4;
// 同理,这里将IServiceConnection的服务对象也转换成一个Proxy代理对象
_arg4 = android.app.IServiceConnection.Stub.asInterface(data.readStrongBinder());
int _arg5;
_arg5 = data.readInt();
java.lang.String _arg6;
_arg6 = data.readString();
java.lang.String _arg7;
_arg7 = data.readString();
int _arg8;
_arg8 = data.readInt();
int _result = this.bindIsolatedService(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
// android.app.IApplicationThread.Stub
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements android.app.IApplicationThread
{
private static final java.lang.String DESCRIPTOR = "android.app.IApplicationThread";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an android.app.IApplicationThread interface,
* generating a proxy if needed.
*/
public static android.app.IApplicationThread asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof android.app.IApplicationThread))) {
return ((android.app.IApplicationThread)iin);
}
// 这里构造成了Proxy
return new android.app.IApplicationThread.Stub.Proxy(obj);
}
}
这里我们暂不考虑ApplicationThread由何处而来,每个进程中都对应一个ActivityThread,ActivityThread中有一个ApplicationThread对象。
ApplicationThread在bind流程中的使用
我们发现,最终是使用 ApplicationThread
的 requestServiceBindingLocked
方法来绑定服务的(r.app.thread.scheduleBindService
),我们先梳理一下ServiceRecord类同ApplicationThread的关系;
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
// com.android.server.am.ActiveServices#requestServiceBindingLocked
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if (r.app == null || r.app.thread == null) {
// If service is not currently running, can't yet bind.
return false;
}
// 调用ApplicationThread的绑定方法来进行绑定
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.getReportedProcState());
return true;
}
// frameworks/base/services/core/java/com/android/server/am/ServiceRecord.java
ProcessRecord app; // where this service is running or null.
// frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
IApplicationThread thread; // the actual proc... may be null only if
// 'persistent' is true (in which case we
// are in the process of launching the app)
其中 ServiceRecord.app
的类型为 ProcessRecord
,ServiceRecord.app.thread
的类型为 IApplicationThread
,我们梳理下对应的几个类的关系,如下图:
现在我们看下 ServiceRecord 是何时构造的,首先,根据方法的调用层次,我们可以看到:
ActiveServices.bindServiceLocked
方法中,参数中没有ServiceRecord,有的是IApplicationThread及一个IBinder。ActiveServices.requestServiceBindingLocked
方法中,则变成了ServiceRecord类型。
提示:上述调用层次可以在IDEA中选中
ActiveServices.requestServiceBindingLocked
方法,然后通过“Navigate|Call Hierarchy”(快捷键为ctrl+opt+H)弹出。
所以,接下来我们看下 ActiveServices.bindServiceLocked
方法如何将ApplicationThread
存入到ServiceRecord
对象中。
ActiveServices.bindServiceLocked
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String instanceName, String callingPackage, final int userId)
throws TransactionTooLargeException {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
// 这里获取了 ProcessRecord
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
// 将IApplicationThread及IBinder放入到ServiceRecord中的过程在retrieveServiceLocked中
ServiceLookupResult res =
retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
callingPid, callingUid, userId, true,
callerFg, isBindExternal, allowInstant);
// 此处获取ServiceRecord,故在上面
ServiceRecord s = res.record;
if (s.app != null && b.intent.received) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
return 1;
}
到这里,我们可以发现ServiceRecord是通过retrieveServiceLocked
方法获取到的ServiceLookupResult
获取到的。
粗略看了下这个retrieveServiceLocked
方法,其中逻辑比较多,我们这里转换下思路,直接查找 ServiceRecord.app
的赋值操作。
ServiceRecord.app
的赋值
我们可以找到ServiceRecord.app(ProcessRecord)的赋值操作的调用方法为:com.android.server.am.ActiveServices#realStartServiceLocked
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
// 在此处赋值
r.setProcess(app);
// ...
}
查看 realStartServiceLocked
的调用序列:
也就是又回到了我们的 bindServiceLocked
方法,其中有一段逻辑是,如果需要创建服务,就执行 bringUpServiceLocked
方法。
// com.android.server.am.ActiveServices#bindServiceLocked
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String instanceName, String callingPackage, final int userId)
throws TransactionTooLargeException {
// ...
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
// ...
}
也就是说,在绑定服务的时候,如果服务没有创建,就先使用bringUpServiceLocked
-realStartServiceLocked
进行创建,创建过程中会将ServiceRecord中的app赋值,然后存储起来;
提示:我们可以通过如下IDEA操作来查找赋值操作
选中成员(这里是 app);
Ctrl+B 或者 Command+鼠标单击,弹出使用列表弹窗;
然后在弹窗中设置仅查看write访问操作的;然后我们可以找到对应的赋值代码行;
通过勾选其中的方法图标,我们可以显示赋值的代码行所在的方法(这里是setProcess);
然后我们继续在方法上执行上述操作,可以获取到更加上一步的赋值调用在哪;
服务如何绑定?服务如何启动?进程如何启动?
- bringUpServiceLocked(ServiceRecord r,...) 第一个参数为ServiceRecord,其中的app属性可存储一个进程记录;
- 如传入的ServiceRecord参数中表明服务已经启动过,
r.app(ProcessRecord)
不为null,且r.app.thread(IApplicationThread)
也不为null,则不创建,直接更新参数; - 结下来,则分为两种情况,1)服务为声明单独的进程,则可直接在当前进程中启动;2)服务声明了单独的进程,则需要先启动进程,然后再启动服务;
- 非单独进程:
- 进程记录获取:通过AMS直接查询,并未创建,因为进程已经存在了,具体代码为
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false)
- 服务启动:使用
realStartServiceLocked(r, app, execInFg);
方法启动
- 进程记录获取:通过AMS直接查询,并未创建,因为进程已经存在了,具体代码为
- 单独进程:
- 进程记录获取: 通过AMS.mAm.startProcessLocked 方法启动一个新的进程;
app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)
- 服务启动:未在此方法中直接调用
realStartServiceLocked
- 进程记录获取: 通过AMS.mAm.startProcessLocked 方法启动一个新的进程;
这里我们可以看到,在单独进程的服务启动流程中,并没有即时调用realStartServiceLocked
来启动服务,那么这里就又个问题,独立进程情况下服务何时启动?
- 单独进程服务启动: 将待启动的服务加入到
mPendingServices(ArrayList<ServiceRecord>)
,在启动进程后再从此列表中读取需要启动的服务,然后启动;
总结:
-
进程记录如何获取?
- 通过AMS的
startProcessLocked
方法创建(非独立进程的也应该是通过此方法创建,只是创建时机不是这里)
- 通过AMS的
-
服务如何启动?
-
通过
realStartServiceLocked
方法启动(独立进程的应该也是此方法启动,会等到进程启动之后再启动) -
realStartServiceLocked
中通过IApplicationThread
执行scheduleCreateService
来启动服务,最终调用android.app.ActivityThread.ApplicationThread#scheduleCreateService
来启动;
-
进程创建
问题:
- 进程何时创建?- 已解决
- ApplicationThread(代理)对象何时设置到ProcessRecord中? - 已解决
- ActivityThread#main的入口点中,如何获取之前的结果? - 已解决
下面为创建进程的调用序列,注意如下序列中只是创建了一个ProcessRecord的对象,对应于Linux上的进程创建我们再起文章进行分析,对于我们的Service来说,拿到ProcessRecord对象即可供我们来创建服务;
- 进程创建的执行位于AMS所在的系统进程之中;
- (AMS进程)首先,构建一个ProcessRecord记录,并将其记录到AMS中;
- (AMS进程)AMS通过socket通信,通知zygote来创建一个新的进程,同时指定入口点为
android.app.ActivityThread
; - (APP进程)新的进程启动后,执行ActivityThread中的方法,通知AMS来执行attachApplication;
- (AMS进程)AMS中,通过PID获取之前存储的ProcessRecord,然后将ApplicationThread(代理对象)赋值给ProcessRecord的成员变量thread;
- 支持完成了关联;
构造ProcessRecord实例
com.android.server.am.ProcessList#startProcessLocked
,简化下来就两句:
- 构造ProcessRecord对象:
app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord)
- 启动进程:
startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride)
// com.android.server.am.ProcessList#newProcessRecordLocked
// frameworks/base/services/core/java/com/android/server/am/ProcessList.java
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs,
Runnable crashHandler) {
long startTime = SystemClock.uptimeMillis();
ProcessRecord app;
if (app == null) {
// 构造ProcessRecord对象
app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord);
app.crashHandler = crashHandler;
app.isolatedEntryPoint = entryPoint;
app.isolatedEntryPointArgs = entryPointArgs;
} else {
// If this is a new package in the process, add the package to the list
app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats);
}
// 启动进程
final boolean success =
startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);
checkSlow(startTime, "startProcess: done starting proc!");
return success ? app : null;
}
启动进程
startProcessLocked
: 启动了一个进程,并指定了入口点为 android.app.ActivityThread,也就是进程启动后将会执行 android.app.ActivityThread的main方法。
// frameworks/base/services/core/java/com/android/server/am/ProcessList.java
// com.android.server.am.ProcessList#startProcessLocked(com.android.server.am.ProcessRecord, com.android.server.am.HostingRecord, int, boolean, boolean, boolean, java.lang.String)
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
boolean mountExtStorageFull, String abiOverride) {
if (app.pendingStart) {
return true;
}
long startTime = SystemClock.uptimeMillis();
try {
try {
final int userId = UserHandle.getUserId(app.uid);
AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
int uid = app.uid;
int[] gids = null;
// ...
app.mountMode = mountExternal;
app.gids = gids;
app.setRequiredAbi(requiredAbi);
app.instructionSet = instructionSet;
final String seInfo = app.info.seInfo
+ (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
// 指定入口点为ActivityThread,启动进程
final String entryPoint = "android.app.ActivityThread";
return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
instructionSet, invokeWith, startTime);
} catch (RuntimeException e) {
return false;
}
}
boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
app.pendingStart = true;
app.killedByAm = false;
app.removed = false;
app.killed = false;
final long startSeq = app.startSeq = ++mProcStartSeqCounter;
app.setStartParams(uid, hostingRecord, seInfo, startTime);
app.setUsingWrapper(invokeWith != null
|| Zygote.getWrapProperty(app.processName) != null);
mPendingStarts.put(startSeq, app);
if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
return true;
} else {
try {
// 启动进程,并传入entrypoint
final Process.ProcessStartResult startResult = startProcess(hostingRecord,
entryPoint, app,
uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
requiredAbi, instructionSet, invokeWith, startTime);
// 做启动后的操作
handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
startSeq, false);
} catch (RuntimeException e) {
}
return app.pid > 0;
}
}
这里我们省略其他更加底层的步骤的分析,我们只需要知道到了这里之后,会启动一个进程,进程启动后会执行 android.app.ActivityThread#main 方法;
记录进程记录到AMS
ProcessList#handleProcessStartedLocked(com.android.server.am.ProcessRecord, int, boolean, long, boolean)
这个地方有个关键的代码将之前创建的进程记录存储到了AMS的进程记录表中。
// com.android.server.am.ProcessList#handleProcessStartedLocked(com.android.server.am.ProcessRecord, int, boolean, long, boolean)
// frameworks/base/services/core/java/com/android/server/am/ProcessList.java
ActivityManagerService mService = null;
boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,
long expectedStartSeq, boolean procAttached) {
// 将ProcessRecord 存储到AMS中
mService.addPidLocked(app);
}
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
void addPidLocked(ProcessRecord app) {
synchronized (mPidsSelfLocked) {
// 将进程记录添加到一个记录表中
mPidsSelfLocked.doAddInternal(app);
}
synchronized (sActiveProcessInfoSelfLocked) {
if (app.processInfo != null) {
sActiveProcessInfoSelfLocked.put(app.pid, app.processInfo);
} else {
sActiveProcessInfoSelfLocked.remove(app.pid);
}
}
mAtmInternal.onProcessMapped(app.pid, app.getWindowProcessController());
}
// 完整代码
// com.android.server.am.ProcessList#handleProcessStartedLocked(com.android.server.am.ProcessRecord, int, boolean, long, boolean)
// frameworks/base/services/core/java/com/android/server/am/ProcessList.java
boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,
long expectedStartSeq, boolean procAttached) {
mPendingStarts.remove(expectedStartSeq);
final String reason = isProcStartValidLocked(app, expectedStartSeq);
if (reason != null) {
Slog.w(TAG_PROCESSES, app + " start not valid, killing pid=" +
pid
+ ", " + reason);
app.pendingStart = false;
killProcessQuiet(pid);
Process.killProcessGroup(app.uid, app.pid);
noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_INVALID_START, reason);
return false;
}
mService.mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);
checkSlow(app.startTime, "startProcess: done updating battery stats");
EventLog.writeEvent(EventLogTags.AM_PROC_START,
UserHandle.getUserId(app.startUid), pid, app.startUid,
app.processName, app.hostingRecord.getType(),
app.hostingRecord.getName() != null ? app.hostingRecord.getName() : "");
try {
AppGlobals.getPackageManager().logAppProcessStartIfNeeded(app.processName, app.uid,
app.seInfo, app.info.sourceDir, pid);
} catch (RemoteException ex) {
// Ignore
}
Watchdog.getInstance().processStarted(app.processName, pid);
checkSlow(app.startTime, "startProcess: building log message");
StringBuilder buf = mStringBuilder;
buf.setLength(0);
buf.append("Start proc ");
buf.append(pid);
buf.append(':');
buf.append(app.processName);
buf.append('/');
UserHandle.formatUid(buf, app.startUid);
if (app.isolatedEntryPoint != null) {
buf.append(" [");
buf.append(app.isolatedEntryPoint);
buf.append("]");
}
buf.append(" for ");
buf.append(app.hostingRecord.getType());
if (app.hostingRecord.getName() != null) {
buf.append(" ");
buf.append(app.hostingRecord.getName());
}
mService.reportUidInfoMessageLocked(TAG, buf.toString(), app.startUid);
app.setPid(pid);
app.setUsingWrapper(usingWrapper);
app.pendingStart = false;
checkSlow(app.startTime, "startProcess: starting to update pids map");
ProcessRecord oldApp;
synchronized (mService.mPidsSelfLocked) {
oldApp = mService.mPidsSelfLocked.get(pid);
}
// If there is already an app occupying that pid that hasn't been cleaned up
if (oldApp != null && !app.isolated) {
// Clean up anything relating to this pid first
Slog.wtf(TAG, "handleProcessStartedLocked process:" + app.processName
+ " startSeq:" + app.startSeq
+ " pid:" + pid
+ " belongs to another existing app:" + oldApp.processName
+ " startSeq:" + oldApp.startSeq);
mService.cleanUpApplicationRecordLocked(oldApp, false, false, -1,
true /*replacingPid*/);
}
// 注意这里
mService.addPidLocked(app);
synchronized (mService.mPidsSelfLocked) {
if (!procAttached) {
Message msg = mService.mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
mService.mHandler.sendMessageDelayed(msg, usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
}
checkSlow(app.startTime, "startProcess: done updating pids map");
return true;
}
写入thread值到ProcessRecord
从上面的流程中,我们发现构造出来的ProcessRecord的thread(ApplicationThread)成员变量还是没有被赋值,那么这个thread何时被赋值呢?
查找
ProcessRecord
中thread
赋值的入口:
通过查找
thread
成员的赋值写入方法,可以确定起始点是,com.android.server.am.ProcessRecord#makeActive
,接下来查看调用这个方法的列表:这里我们显然选择
com.android.server.am.ActivityManagerService#attachApplicationLocked
android.app.ActivityThread#attach
这里我们遇到两个选择:
显然,应该选择第二个:
android.app.ActivityThread#main
这里我们却无法直接通过IDEA的调用层次功能找到任何调用方法,说明可能是通过反射来调用的,所以直接通过全局字符串搜索android.app.ActivityThread,可以找到在
ProcessList.startProcessLocked
中调用的。
通过上面的分析,这里我们从ActivityThread的main函数开始。
ActivityThread#main
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
// Install selective syscall interception
AndroidOs.install();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
// Call per-process mainline module initialization.
initializeMainlineModules();
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
// It will be in the format "seq=114"
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
// 直接构造一个ActivityThread对象
ActivityThread thread = new ActivityThread();
// 执行attach方法
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
ActivityThread#attach
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
// 将当前ApplicationThread的Binder对象保存为一个静态成员
RuntimeInit.setApplicationObject(mAppThread.asBinder());
// 获取AMS
final IActivityManager mgr = ActivityManager.getService();
try {
// 通知AMS来 attachApplication
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} else {
}
}
ActivityManagerService#attachApplication & attachApplicationLocked
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
if (thread == null) {
throw new SecurityException("Invalid application interface");
}
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
上面的方法只是调用了 attachApplicationLocked:
有个关键的步骤是,从 AMS的进程记录表中根据PID取出一个 ProcessRecord: app = mPidsSelfLocked.get(pid)
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// Find the application record that is being attached... either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
long bindApplicationTimeMillis;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
// 从进程记录中获取
app = mPidsSelfLocked.get(pid);
}
}
// Make app active after binding application or client may be running requests (e.g
// starting activities) before it is ready.
// 关联thread到app(ProcessRecord)
app.makeActive(thread, mProcessStats);
return true;
}
经过上面的步骤,即完成了ProcessRecord到进程的ApplicationThread的关联。
启动服务
从AMS中调用ApplicationThread的方法来在Service自己应该所属的进程中创建Service对象的实例。
ActiveServices#bringUpServiceLocked
// com.android.server.am.ActiveServices#bringUpServiceLocked
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
// 已经存在进程记录,并且进程记录中的IApplicationThread已经存在,则不创建服务,仅发送参数
if (r.app != null && r.app.thread != 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, false);
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
// 非独立进程中,直接启动服务
realStartServiceLocked(r, app, execInFg);
// 调用启动方法后直接返回
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.
}
} else {
// 独立进程则先尝试使用之前保存的
app = r.isolatedProc;
}
// 之前没有启动对应的进程,则开始创建,启动了,则无需进行赋值操作,因为ServiceRecord中已经有了
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingRecord, ZYGOTE_POLICY_FLAG_EMPTY, false, isolated, false)) == null) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": process is bad";
Slog.w(TAG, msg);
bringDownServiceLocked(r);
// 进程启动失败,返回错误消息
return msg;
}
if (isolated) {
// 独立进程,缓存进程信息到传入的ServiceRecord参数中,以便后续直接使用
r.isolatedProc = app;
}
}
// 将服务记录加入的mPendingServices中,由于非独立进程创建后已经直接返回,所以这里适用于独立进程的
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
// 创建成功或者之前已经又了缓存,则返回null
return null;
}
独立进程何时启动服务?
-
一般来说,封装较好的代码会保证入口统一,如果非独立进程情况下服务的启动使用的是
realStartServiceLocked
方法来启动服务,那么独立进程情况下,服务的启动也应该使用此方法,所以我们查看realStartServiceLocked
方法的调用层次,如下:图片版本:
详细调用序列:
ActiveServices.attachApplicationLocked
(ProcessRecord, String) (com.android.server.am)- ActivityManagerService.attachApplicationLocked(IApplicationThread, int, int, long) (com.android.server.am)
- ActivityManagerService.attachApplication(IApplicationThread, long) (com.android.server.am)
- ActivityManagerService.attachApplicationLocked(IApplicationThread, int, int, long) (com.android.server.am)
ActiveServices.bringUpServiceLocked
(ServiceRecord, int, boolean, boolean, boolean) (com.android.server.am)- ActiveServices.startServiceInnerLocked(ServiceMap, Intent, ServiceRecord, boolean, boolean) (com.android.server.am)
- ActiveServices.bindServiceLocked(IApplicationThread, IBinder, Intent, String, IServiceConnection, int, String, ...) (com.android.server.am)
- ActiveServices.performServiceRestartLocked(ServiceRecord) (com.android.server.am)
也就是调用了
ActiveServices.attachApplicationLocked
,最终是通过AMS的ActivityManagerService.attachApplication
来触发的;也就是只要找到mAm.startProcessLocked
到ActivityManagerService.attachApplication
的调用序列即可证明此猜想;我们可以找到如下调用序列,即最终实际上是从ActivityThread的main函数进入的,所以做出以下猜想:进程启动后,创建ActivityThread时,如果有需要创建的服务,就启动服务;
我们再看
attachApplicationLocked
的逻辑,可以发现,会检查mPendingServices
中是否有待启动的服务,然后逐一处理,如果有需要启动的服务,则会调用realStartServiceLocked(sr, proc, sr.createdFromFg)
来启动服务。// com.android.server.am.ActiveServices#attachApplicationLocked // frameworks/base/services/core/java/com/android/server/am/ActiveServices.java 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); // 排除非独立Service if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid || !processName.equals(sr.processName))) { continue; } mPendingServices.remove(i); i--; proc.addPackage(sr.appInfo.packageName, sr.appInfo.longVersionCode, mAm.mProcessStats); // 启动服务 realStartServiceLocked(sr, proc, sr.createdFromFg); } } catch (RemoteException e) { Slog.w(TAG, "Exception in new application when starting service " + sr.shortInstanceName, e); throw e; } } }
ActivityThread#handleCreateService
这里我们省略bringUpServiceLocked
方法及下方的几个中间步骤,直接查看android.app.ActivityThread#handleCreateService
方法:
- 通过ClassLoader加载并实例化了对应的Service对象;
- 将Service存储到ActivityThread中的一个ArrayMap中;
// android/app/ActivityThread.java
// android.app.ActivityThread#handleCreateService
final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
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);
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
Application app = packageInfo.makeApplication(false, mInstrumentation);
java.lang.ClassLoader cl = packageInfo.getClassLoader();
// 创建对应的Service实例
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
// 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);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
绑定服务
我们的问题是:
- 绑定服务时,传入的ServiceConnection对象,如何被调用来通知?
- 还做了些什么?
连接对象去哪里了?
查看ContextImpl.bindServiceCommon
方法可以看到,传入了参数 ServiceConnection conn
,然后方法中这个conn放入到了一个 ServiceDispatcher
中.
- IServiceConnection 包含两个接口:
- connected(): 连接到服务
- asBinder(): 服务转Binder
- 这里会将我们自行编写的ServiceConnection对象构造出一个ServiceDispatcher对象,然后将ServiceDispatcher提供一个IServiceconnection接口(
ServiceDispatcher$InnerConnection
类),用于提供服务; - 这个
ServiceDispatcher$InnerConnection
类的connect方法会调用sd的connect方法,最终会调用我们提供的ServiceConnection的回调方法:mConnection.onServiceConnected(name, service)
也就是说,使用sd.connect()
就可以触发我们的连接对象的onServiceConnected
回调方法;
final @NonNull LoadedApk mPackageInfo;
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 实际上就是持有ServiceDispatcher的弱引用对象,然后将ServiceDispatcher的少量方法暴露出去
IServiceConnection sd;
if (mPackageInfo != null) {
if (executor != null) {
// mPackageInfo 是一个 LoadedApk 对象
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
} else {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
}
} else {
}
int res = ActivityManager.getService().bindIsolatedService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
// 调用AMS的服务式这里传入了sd
sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
//...
}
// com.android.server.am.ActiveServices#bindServiceLocked
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent,
callerApp.uid, callerApp.processName, callingPackage);
// 提供 IBinder
IBinder binder = connection.asBinder();
s.addConnection(binder, c);
b.connections.add(c);
ServiceDispatcher类位于 android.app.LoadedApk.ServiceDispatcher
:
// 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;
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 {
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.put(c, sd);
} else {
sd.validate(context, handler, executor);
}
return sd.getIServiceConnection();
}
}
static final class ServiceDispatcher {
private final ServiceDispatcher.InnerConnection mIServiceConnection;
@UnsupportedAppUsage
private final ServiceConnection mConnection;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final Context mContext;
private final Handler mActivityThread;
private final Executor mActivityExecutor;
private final ServiceConnectionLeaked mLocation;
private final int mFlags;
private static class InnerConnection extends IServiceConnection.Stub {
@UnsupportedAppUsage
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);
}
}
}
@UnsupportedAppUsage
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mContext = context;
mActivityThread = activityThread;
mActivityExecutor = null;
mLocation = new ServiceConnectionLeaked(null);
mLocation.fillInStackTrace();
mFlags = flags;
}
ServiceConnection getServiceConnection() {
return mConnection;
}
// SD中提供了connected方法
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);
}
}
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);
}
// If there is a new viable service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
} else {
// The binding machinery worked, but the remote returned null from onBind().
mConnection.onNullBinding(name);
}
}
}
IServiceConnection说明
服务绑定时,IServiceConnection的用途?如何实现在APP的Activity进程中调用ServiceConnection的onServiceConnected方法?
- IServiceConnect的服务端位于APP进程中,在ContextImpl的binderServiceCommon方法中初始化,也就是LoadApk类中的ServiceDispatcher类。
- 传递给AMS的实际上是一个Binder的远程代理对象;
// android.app.IActivityManager.Stub#TRANSACTION_bindService
// android/app/IActivityManager.java
case TRANSACTION_bindService:
{
data.enforceInterface(descriptor);
android.app.IApplicationThread _arg0;
_arg0 = android.app.IApplicationThread.Stub.asInterface(data.readStrongBinder());
android.os.IBinder _arg1;
_arg1 = data.readStrongBinder();
android.content.Intent _arg2;
if ((0!=data.readInt())) {
_arg2 = android.content.Intent.CREATOR.createFromParcel(data);
}
else {
_arg2 = null;
}
java.lang.String _arg3;
_arg3 = data.readString();
android.app.IServiceConnection _arg4;
// 这里可以看到,是在这个地方见IServiceConnection的服务端对象转换成客户端代理对象的
_arg4 = android.app.IServiceConnection.Stub.asInterface(data.readStrongBinder());
int _arg5;
_arg5 = data.readInt();
java.lang.String _arg6;
_arg6 = data.readString();
int _arg7;
_arg7 = data.readInt();
int _result = this.bindService(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
asInterface 中: new android.app.IServiceConnection.Stub.Proxy(obj)
即是将Stub转换为Proxy对象;
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements android.app.IServiceConnection
{
private static final java.lang.String DESCRIPTOR = "android.app.IServiceConnection";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an android.app.IServiceConnection interface,
* generating a proxy if needed.
*/
public static android.app.IServiceConnection asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof android.app.IServiceConnection))) {
return ((android.app.IServiceConnection)iin);
}
return new android.app.IServiceConnection.Stub.Proxy(obj);
}
}
也就是说,ActivityManagerService.bindService方法中的IServiceConnection参数实际上是一个Proxy对象;
// 这里的Connection是一个代理对象
public int bindService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags,
String callingPackage, int userId) throws TransactionTooLargeException {
return bindIsolatedService(caller, token, service, resolvedType, connection, flags,
null, callingPackage, userId);
}
ActivityThread#handleBindService
实际上就做了两件事情
// android.app.ActivityThread#handleBindService
// frameworks/base/core/java/android/app/ActivityThread.java
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) {
// 调用Service的onBind接口获取IBinder对象
IBinder binder = s.onBind(data.intent);
// 通知AMS来publicService
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) {
}
}
}
ActivityManagerService#publishService
// com.android.server.am.ActivityManagerService#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");
}
// com.android.server.am.ActiveServices#publishServiceLocked
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
ActiveServices#publishServiceLocked
下面我们可以看到,在publishServiceLocked方法中,取出了一个连接记录列表,然后循环的调用了其中的IServiceConnection的connected方法,也就是会调用到我们自行定义的ServiceConnnection对象的connected方法。
不过我们有个问题,就是这个ConnectionRecord对象是何时构造的?
// com.android.server.am.ConnectionRecord
// frameworks/base/services/core/java/com/android/server/am/ConnectionRecord.java
final class ConnectionRecord {
final AppBindRecord binding; // The application/service binding.
final ActivityServiceConnectionsHolder<ConnectionRecord> activity; // If non-null, the owning activity.
final IServiceConnection conn; // The client connection.
}
// com.android.server.am.ActiveServices#publishServiceLocked
// 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 {
// 如果服务记录为null,就什么都不做
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;
// 取出连接记录ConnectionRecord
ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
for (int conni = connections.size() - 1; conni >= 0; conni--) {
ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
for (int i = 0; i < clist.size(); i++) {
ConnectionRecord c = clist.get(i);
try {
// 调用IServiceConnection的connected方法
c.conn.connected(r.name, service, false);
} catch (Exception e) {
}
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
}
} finally {
}
}
构造 ConnectionRecord - bindServiceLocked
实际上这个构建ConnectRecord的过程位于bindServiceLocked方法中。
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String instanceName, String callingPackage, final int userId)
throws TransactionTooLargeException {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
ActivityServiceConnectionsHolder<ConnectionRecord> activity = null;
if (token != null) {
activity = mAm.mAtmInternal.getServiceConnectionsHolder(token);
if (activity == null) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
}
ServiceLookupResult res = retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
callingPid, callingUid, userId, true,
callerFg, isBindExternal, allowInstant);
ServiceRecord s = res.record;
try {
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
// 构造连接记录对象
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent,
callerApp.uid, callerApp.processName, callingPackage);
IBinder binder = connection.asBinder();
// 添加到ServiceRecord对象中
s.addConnection(binder, c);
b.connections.add(c);
if (activity != null) {
activity.addConnection(c);
}
b.client.connections.add(c);
c.startAssociationIfNeeded();
} finally {
}
return 1;
}
部分方法的源码
ContextImpl.bindService
-
bindService
: (frameworks/base/core/java/android/app/ContextImpl.java
)@Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null, getUser()); } @Override public boolean bindService( Intent service, int flags, Executor executor, ServiceConnection conn) { warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, null, null, executor, getUser()); }
ContextImpl.bindServiceCommon
-
bindServiceCommon
: (frameworks/base/core/java/android/app/ContextImpl.java
)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 (conn == null) { throw new IllegalArgumentException("connection is null"); } if (handler != null && executor != null) { throw new IllegalArgumentException("Handler and Executor both supplied"); } if (mPackageInfo != null) { if (executor != null) { sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags); } else { sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); } } else { throw new RuntimeException("Not supported in system context"); } validateServiceIntent(service); try { // WindowContext构造函数中的 WindowTokenClient 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.prepareToLeaveProcess(this); 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(); } }
ActivityManagerService.bindIsolatedService
从这里开始,实际上位于AMS的Server端了,即我们的Activity所在的进程发送了一个启动服务的IPC请求给AMS(sysmte_server进程中)。
-
ActivityManagerService.java : (frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java)
public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String instanceName, String callingPackage, int userId) throws TransactionTooLargeException { // .... synchronized(this) { // 调用Binder接口 return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, instanceName, callingPackage, userId); } }
ActiveServices.bindServiceLocked
-
ActiveServices.bindServiceLocked
: (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 instanceName, String callingPackage, final int userId)
throws TransactionTooLargeException {
// 获取调用方的权限
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + callingPid
+ ") when binding service " + service);
}
ActivityServiceConnectionsHolder<ConnectionRecord> activity = null;
if (token != null) {
activity = mAm.mAtmInternal.getServiceConnectionsHolder(token);
if (activity == null) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
}
int clientLabel = 0;
PendingIntent clientIntent = null;
final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;
final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
ServiceLookupResult res =
retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
callingPid, callingUid, userId, true,
callerFg, isBindExternal, allowInstant);
if (res == null) {
return 0;
}
if (res.record == null) {
return -1;
}
ServiceRecord s = res.record;
try {
if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: "
+ s);
}
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (!s.hasAutoCreateConnections()) {
// This is the first binding, let the tracker know.
ServiceState stracker = s.getTracker();
if (stracker != null) {
stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),
s.lastActivity);
}
}
}
if ((flags & Context.BIND_RESTRICT_ASSOCIATIONS) != 0) {
mAm.requireAllowedAssociationsLocked(s.appInfo.packageName);
}
mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
callerApp.getCurProcState(), s.appInfo.uid, s.appInfo.longVersionCode,
s.instanceName, s.processName);
// Once the apps have become associated, if one of them is caller is ephemeral
// the target app should now be able to see the calling app
mAm.grantImplicitAccess(callerApp.userId, service,
callerApp.uid, UserHandle.getAppId(s.appInfo.uid));
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent,
callerApp.uid, callerApp.processName, callingPackage);
IBinder binder = connection.asBinder();
s.addConnection(binder, c);
b.connections.add(c);
if (activity != null) {
activity.addConnection(c);
}
b.client.connections.add(c);
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
ArrayList<ConnectionRecord> 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(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
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, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortInstanceName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
} finally {
}
return 1;
}
ActiveServices.realStartServiceLocked
/**
* Note the name of this method should not be confused with the started services concept.
* The "start" here means bring up the instance in the client, and this method is called
* from bindService() as well.
*/
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
r.setProcess(app);
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
// 创建服务
final boolean newService = app.startService(r);
bumpServiceExecutingLocked(r, execInFg, "create");
mAm.updateLruProcessLocked(app, false, null);
updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
mAm.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
boolean created = false;
try {
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
// 创建服务
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
app.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 {
//
}
// 绑定服务
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
if (newService && created) {
app.addBoundClientUidsOfNewService(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, 0));
}
sendServiceArgsLocked(r, execInFg, true);
}