前面两章学习分析了 ServiceManager 的启动流程与获取它代理对象的流程, 本章节开始对 Service 组件启动后注册到 ServiceManager 的流程进行分析.
前言
Service 组件是在 Server 进程中运行的. Server 进程在启动时, 会首先将它里面的 Service 组件注册到 SM 中, 接着再启动一个 Binder 线程池来等待和处理 Client 进程的通信请求.
本章内容以 ActivityManagerService 为例, 一步步分析它是怎么从启动到注册到 SM 中的. 在AMS 服务的的时候不会太详细, 后面会有单独的章节来分析它. 重点在于是如何注册到 SM 中的.
首先是先来到系统服务 SystemServer
中. 看它的 main
方法
一. AMS 的启动
1. SystemServer.main
源码路径 /frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
在内部看到又调用了 run
2. SystemServer.run
源码路径 /frameworks/base/services/java/com/android/server/SystemServer.java
private void run() {
...
mSystemServiceManager = new SystemServiceManager(mSystemContext);
...
try {
//启动引导类服务
02 startBootstrapServices();
//启动核心类服务
startCoreServices();
//启动其他服务
startOtherServices();
} catch (Throwable ex) {
...
}
...
}
这里会先创建 SystemServiceManager
对象, 这个后面会分析到, 直接进入到 2 处 startBootstrapServices()
. AMS 属于引导类服务, 很多服务也都依赖 AMS.
3. SystemServer.startBootstrapServices() 在启动引导类服务中创建 AMS.
源码路径 /frameworks/base/services/java/com/android/server/SystemServer.java
private void startBootstrapServices() {
...
01 mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();
...
02 mActivityManagerService.setSystemProcess();
...
}
在代码 01 处, 看到调用了 mSystemServiceManager.startService
传入的参数是 Class, 那么猜想应该是用来反射的. 进去看一下 startService
这个函数.
4. SystemServiceManager.startService 传入 ActivityManagerService.Lifecycle.class
源码路径: /frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
public <T extends SystemService> T startService(Class<T> serviceClass) {
final String name = serviceClass.getName();
...
final T service;
try {
01 Constructor<T> constructor = serviceClass.getConstructor(Context.class);
02 service = constructor.newInstance(mContext);
} catch (InstantiationException ex) {
...
}
...
03 mServices.add(service);
try {
04 service.onStart();
} catch (RuntimeException ex) {
...
}
return service;
}
代码 01 处 与 02 处创建了 ActivityManagerService.Lifecycle
对象, 并赋值给变量 service
.
代码 03 处将这个创建的 ActivityManagerService.Lifecycle
对象添加到变量 mServices
中. 在最上面看到 mServices
是一个集合. 保存的内容就是 SystemService
类型的.
代码 04 处, 调用 ActivityManagerService.Lifecycle
的 onStart
函数.
找到 ActivityManagerService.Lifecycle
看一下它的构造函数和 onStart
函数.
5. ActivityManagerService.Lifecycle() & ActivityManagerService.Lifecycle.onStart()
源码路径:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
...
public static final class Lifecycle extends SystemService {
private final ActivityManagerService mService;
public Lifecycle(Context context) {
super(context);
mService = new ActivityManagerService(context);
}
@Override
public void onStart() {
mService.start();
}
public ActivityManagerService getService() {
return mService;
}
}
...
Lifecycle
是 AMS 中的一个静态内部类. 在构造函数内可以看到, 是在这里创建了 ActivityManagerService
并保存到 mService
中.
然后在上面第4步中调用的 service.onStart();
实际上调用的就是 ActivityManagerService.start()
函数.
接着将 AMS 添加到 SM 中. 回到第 3 步中. getService()
获得了 AMS 对象, 接着在 02 行代码处将 AMS 添加至 SM 中.
private void startBootstrapServices() {
...
01 mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();
...
02 mActivityManagerService.setSystemProcess();
...
}
二. 将 ActivityManagerService 添加至 ServiceManager
6. mActivityManagerService.setSystemProcess()
源码路径:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void setSystemProcess() {
...
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
...
}
终于看到了 addService
函数的调用. 进入 ServiceManager.addService
看是如何添加的.
其中 Context.ACTIVITY_SERVICE
的定义为 public static final String ACTIVITY_SERVICE = "activity";
`
7. ServiceManager.addService
源码路径: /frameworks/base/core/java/android/os/ServiceManager.java
public static void addService(String name, IBinder service, boolean allowIsolated) {
try {
getIServiceManager().addService(name, service, allowIsolated);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
先调用 ServiceManager
类的静态成员函数 getIServiceManager
来获得一个 ServiceManager
的 Java 代理对象 ServiceManagerProxy
. 接着再调用这个 Java 代理对象的成员函数 addService
将 AMS 注册到 SM 中. 指定了这个 Service 的注册名称为 activity
.
这里通过两步来分析先来看 getIServiceManager
8. getIServiceManager 获得 SM 的代理对象
源码路径: /frameworks/base/core/java/android/os/ServiceManager.java
private static IServiceManager sServiceManager;
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
...
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
首先判断 ServiceManager.java
类的静态成员变量 sServiceManager
是否为 NULL, 不为 NULL 说明之前已经获创建过代理对象. 所以直接返回给调用者.
否则就先通过 BinderInternal
类的静态成员函数 getContextObject
创建一个句柄值等等于 0 的 Java 服务代理对象, 接着再通过 ServiceManagerNative.asInterface
函数将这个 Java 服务代理对象封装成一个 ServiceManagerProxy
对象.保存在 sServiceManager
中并返回给调用者.
下面分别分析BinderInternal.getContextObject()
与 ServiceManagerNative.asInterface
9. BinderInternal.getContextObject()
BinderInternal
类的静态成员函数 getContextObject
是一个 JNI 方法, 定义如下
源码路径: /frameworks/base/core/java/com/android/internal/os/BinderInternal.java
public static final native IBinder getContextObject();
它是由 C++ 层中的函数 android_os_BinderInternal_getContextObject()
来实现的.
源码路径: /frameworks/base/core/java/jni/android_util_Binder.cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
看到这里, 终于看到熟悉的了 ProcessState::self()->getContextObject
. 如果看过上一章, 对这个肯定不会陌生.
这行代码就是创建一个 BpBinder 对象. 接着调用 javaObjectForIBinder
对这个 Binder 代理对象创建一个 Java 服务代理对象, 即一个 BinderProxy 对象. 返回给调用者.
10. javaObjectForIBinder 创建 Java 服务代理对象
源码路径: /frameworks/base/core/java/com/android/internal/os/BinderInternal.java
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
if (val == NULL) return NULL;
//检查是 Binder 代理对象还是 本地丢西
if (val->checkSubclass(&gBinderOffsets)) {
...
}
01 jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) {
02 jobject res = jniGetReferent(env, object);
if (res != NULL) {
...
return res;
}
...
03 val->detachObject(&gBinderProxyOffsets);
...
}
04 object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
05 env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
06 val->incStrong((void*)javaObjectForIBinder);
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
07 val->attachObject(&gBinderProxyOffsets, refObject, jnienv_to_javavm(env), proxy_cleanup);
...
}
return object;
}
代码 01 处调用 Binder 代理对象(BpBinder) val
的成员函数 findObject
来检查当前进程之前是否已经创建过一个 Java 服务代理对象了(BinderProxy), 如果是接着在代码 02 处接着检查它的有效性, 如果未失效则直接返回给调用者. 如果失效就在代码 03 处调用 Binder 代理对象(BpBinder) val
的成员函数 detachObject
来解除它与一个无效 Java 服务代理对象(BinderProxy) 的对应关系.
如果代码 01 处检查之前没有创建过一个 Java 服务代理对象(BinderProxy), 在代码 04 处就会为它创建一个 Java 服务代理对象(BinderProxy) object
. 如果创建成功, 接着来在代码 05 处将 Binder 代理对象(BpBinder) val
的地址值设置到上一步创建的 Java 服务代理对象(BinderProxy) object
的成员变量 mObject
中. 即 BinderProxy.mObject
记录了 BpBinder 对象. 因此在代码 06 处增加 Binder 代理对象(BpBinder) val
的强引用计数, 因为它被 Java 服务代理对象(BinderProxy) object
引用了
代码 07 处通过全局变量 gBinderProxyOffsets
将这个全局引用对象与 Binder 代理对象(BpBinder) val
关联起来. 相当于将创建的 Java 服务代理对象(BinderProxy) object
与 Binder 代理对象(BpBinder)的 val
关联起来. 这样以后再以 Binder 代理对象(BpBinder) val
为参数来调用函数 javaObjectForIBinder
时, 就可以直接获得保存在它内部的成员变量 mObjects
中的 Java 服务代理对象(BinderProxy) 了.
Binder 代理对象内部有一个成员变量
mObjects
, 类型是ObjectManager
, 用来管理与 Binder 代理对象关联的外部对象. 例如javaObjectForIBinder
函数在为一个 Binder 代理对象创建一个 Java 服务代理对象时, 就会将创建出来的 Java 服务代理对象保存在该 Binder 代理对象的成员变量mObjects
中, 以便以后需要获取与该 Binder 代理对象对应的 Java 服务代理对象时, 就可以通过它的成员变量mObjects
来直接获得. 由于一个 Binder 代理对象所关联的外部对象可能不止一个, 因此需要通过额外的一个参数来关联一个 Binder 代理对象和一个 Java 服务代理对象, 这个参数就是全局变量gBinderProxyOffsets
的地址值.
注: Java 服务代理对象即: BinderProxy.
注: Binder 代理对象级: BpBinder.
最后返回这个 Java 服务代理对象. 接着回到第 8 步. 继续向下分析.
BinderInternal.getContextObject()
已经分析完了, 它返回了一个句柄值等于 0 的Java 服务代理对象. 接下来就可以调用 ServiceManagerNative
类的静态成员函数 asInterface
将它封装成一个 ServiceManager 的 Java 代理对象了
private static IServiceManager sServiceManager;
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
...
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
11. ServiceManagerNative.asInterface 创建 ServiceManagerProxy 对象
源码路径: /frameworks/base/core/java/android/os/ServiceManagerNative.java
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
参数 obj
指向的是一个 Java 服务代理对象.即一个 BinderProxy 对象. 它的成员函数 queryLocalInterface
的返回值为 NULL, 因此最后会创建一个 ServiceManagerProxy
代理对象. 即 SM 的 Java 代理对象. 返回给调用者.
class ServiceManagerProxy implements IServiceManager {
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
}
ServiceManagerProxy
构造方法中将传入的Java 服务代理对象赋值给 ServiceManagerProxy
中的类成员变量 mRemote
.
注: mRemote 指向的是句柄值是 0 的 Java 服务代理对象, 即 BinderProxy, BinderProxy 在第 10 步被创建出来后又与 Binder 代理对象 BpBinder 进行了关联.
现在第8步分析完成了, 最终返回了一个 Java 代理对象 ServiceManagerProxy
, 继续向上返回, 返回到第 7 步. 代码如下.
public static void addService(String name, IBinder service, boolean allowIsolated) {
try {
getIServiceManager().addService(name, service, allowIsolated);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
看到又调用了 ServiceManagerProxy
中的函数 addService
, 其中参数 name
对应的值为 activity
. service
为 AMS 对象.
12. ServiceManagerProxy.addService
源码路径: frameworks/base/core/java/android/os/ServiceManagerNative.java$ServiceManagerProxy.java
public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
01 data.writeInterfaceToken(IServiceManager.descriptor);
02 data.writeString(name);
03 data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
04 mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
创建了两个 Parcel
对象 data
与 reply
, data
是用来封装进程间通信数据的, reply
是用来封装进程间通信结果数据的.
代码 01 处调用 Parcel
对象 data
的成员函数 writeInterfaceToken
写入一个进程间通信头.
代码 02 处是写入即将要注册的 Java 服务的名称. 这里的名称为 activity
.
代码 03 处写入要注册的 Java 服务对象.
代码 04 处调用成员变量 mRemote
的 transact
函数向 SM 发送一个类型为 ADD_SERVICE_TRANSACTION
的进程间通信请求, 即请求 SM 将一个 Java 服务注册进去.
mRemote
在第 11 步中有强调过. 它指向一个句柄值为 0 的 Java 服务代理对象 BinderProxy.
这里呢先来分析 data.writeStrongBinder
看是如何将 AMS 写入到 data
中的.
接着再来看 mRemote.transact
是如何处理这个进程间通信请求的.
Parcel
是用来封装进程间通信数据的, Java 层中的每一个Parcel
对象在 C++层中都有一个对应的Parcel
对象, 后者的地址就保存在前者的成员变量mObject
中. 当将进程间通信的数据封装在一个 Java 层的Parcel
对象时, 这个 Java 层中的Parcel
对象就会通过其成员变量mObject
找到与它对应的运行在 C++ 层中的Parcel
对象.并且将这些进程间通信数据封装到 C++ 层中的Parcel
对象里面去.
13. Parcel.writeStrongBinder
Java 层的 writeStrongBinder
是一个 JNI 方法. 定义如下
源码路径: /frameworks/base/core/java/android/os/Parcel.java
public final void writeStrongBinder(IBinder val) {
nativeWriteStrongBinder(mNativePtr, val);
}
对应的实现函数为 android_os_Parcel_writeStrongBinder
.
14. android_os_Parcel.android_os_Parcel_writeStrongBinder
源码路径: /frameworks/base/core/jni/android_os_Parcel.cpp
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
01 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
02 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
...
}
}
代码 01 处. 调用函数 reinterpret_cast
得到一个与 Java 层 Parcel
对应的, 运行在 C++ 层的 Parcel
对象 parcel
.
代码 02 处先调用函数 ibinderForJavaObject
来获得一个与他对应的 Binder 本地对象, 再将这个 Binder 本地对象写入到上一步得到的 C++层的 Parcel
对象 parcel
中.
这里也分为两步. 先看 ibinderForJavaObject
如何获得一个对应的 Binder 本地对象的.
接着再分析 writeStrongBinder
写入.
15. android_util_Binder.ibinderForJavaObject
源码路径: /frameworks/base/core/jni/android_util_Binder.cpp
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
...
//是否是 Java 服务
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
01 JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env, obj) : NULL;
}
//是否是 Java 服务代理对象
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject);
}
...
return NULL;
}
这两个 if
意思是 参数 obj
要么指向一个 Java 服务, 要么指向一个 Java 服务代理对象. 否则最后会返回 NULL, 表示它不能将参数 obj
转换成一个 Binder 本地对象或者 Binder 代理对象.
此时我们传入的 obj
是 AMS, 即是一个 Java 服务.所以命中第一个 if
. gBinderOffsets.mObject
指向的是一个 Java 服务的成员变量 mObject
中保存的与其对应的一个 JavaBBinderHolder
对象.
代码 01 处就是将参数 obj
即 AMS 服务对象的成员变量 mObject
转换为一个 JavaBBinderHolder
对象 jbh
.
接着调用 JavaBBinderHolder
对象的 jbh
的成员函数 get
来获得一个 Binder 本地对象 BBinder.
如果传入的
obj
是一个 Java 服务代理对象, 那么命中第二个if
, 就找到与它对应的一个 Binder 代理对象. 并将这个 Binder 代理对象返回给调用者. 在上面第 10 步中的 05 行代码处创建好 Java 服务代理后将 Binder 代理服务对象的地址保存在 Java 服务代理对象的成员变量mObject
中. 因此这里可以轻易的根据 Java 服务代理对象 BinderProxy 找到与之对应的 Binder 代理对象 BpBinder.
16. JavaBBinderHolder.get 获得 BBinder
源码路径: /frameworks/base/core/jni/android_util_Binder.cpp$JavaBBinderHolder
class JavaBBinderHolder : public RefBase
{
private:
...
wp<JavaBBinder> mBinder;
public:
sp<JavaBBinder> get(JNIEnv* env, jobject obj)
{
...
sp<JavaBBinder> b = mBinder.promote();
if (b == NULL) {
b = new JavaBBinder(env, obj);
mBinder = b;
...
}
return b;
}
}
成员变量 mBinder
指向的是一个类型为 JavaBBinder
的 Binder 本地对象.
参数 obj
指向的是一个 Java 服务即 AMS 服务.
成员函数 get
用来将成员变量 mBinder
所指向的一个JavaBBinder
对象返回给调用者. 由于成员变量 mBinder
是一个弱指针, 此时可能已经被销毁, 因此在返回给调用者之前, 先要调用 mBinder.promote()
将它升级为一个强指针, 如果升级成功, 直接返回给调用者.
否则就需要先创建一个 JavaBBinder
对象, 将 AMS 服务传入, 同时将结果保存在成员变量 mBinder
中.
17. new JavaBBinder
源码路径: /frameworks/base/core/jni/android_util_Binder.cpp$JavaBBinder
class JavaBBinder : public BBinder
{
private:
...
jobject const mObject;
public:
JavaBBinder(JNIEnv* env, jobject object)
: mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
{
ALOGV("Creating JavaBBinder %p\n", this);
android_atomic_inc(&gNumLocalRefs);
incRefsCreated(env);
}
...
}
JavaBBinder
的 Binder 本地对象内部也有一个成员变量 mObject
, 指向的是一个 Java 服务. 在构造函数中被初始化. 流程走到这里 mObject
指向的就是 AMS 服务.
好了, 第 14 步中的 ibinderForJavaObject
分析完了, 返回了一个了一个 JavaBBinder
对象. 第 14 步代码如下
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
01 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
02 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
...
}
}
接着调用 parcel->writeStrongBinder
函数, 传入参数为 JavaBBinder
对象.
18. parcel->writeStrongBinder
源码路径: /frameworks/native/libs/binder/Parcel.cpp
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
return flatten_binder(ProcessState::self(), val, this);
}
这一步操作是调用全局函数 flatten_binder
将 JavaBBinder
封装成为一个 flat_binder_object
结构体.
19. parcel->flatten_binder
源码路径: /frameworks/native/libs/binder/Parcel.cpp
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj;
...
if (binder != NULL) {
IBinder *local = binder->localBinder();
if (!local) {
...
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);
}
} else {
...
}
return finish_flatten_binder(binder, obj, out);
}
首先定义了一个 flat_binder_object
结构体 obj
. 接着判参数 binder
是否为 NULL, 我们传入的参数是 JavaBBinder
对象不为 NULL, 所以直接命中 if
.
通过前面的调用知道参数 binder
指向的是 JavaBBinder
, 它继承了 BBinder. 而 BBinder 又是用来描述一个 Binder 本地对象的. 因此 localBinder
函数返回不为 NULL. 所以 if(!local)
不会命中, 而是直接执行 else
中的代码. 将flat_binder_object
结构体 obj
设置为一个 BINDER_TYPE_BINDER
类型的 Binder 对象, 并且将它的成员变量 cookie
和 binder
的值分别设置为 Binder 本地对象 local
的地址以及其内部的一个弱引用计数对象的地址值.
最后调用全局函数 finish_flatten_binder
将 obj
写入到 Parcel 对象 out
中.
当结构体 flat_binder_object 描述的是一个 Binder 实体对象时, 就使用成员变量 binder 来指向与该 Binder 实体对象对应的一个 Service 组件内部的一个弱引用计数对象的地址, 并且使用成员变量 cookie 来指向该 Service 组件的地址.
当结构体 flat_binder_object 描述的是一个 Binder 引用对象时, 那么就使用成员变量 handle 来描述该 Binder 引用对象的句柄值.
20. parcel->finish_flatten_binder
源码路径: /frameworks/native/libs/binder/Parcel.cpp
inline static status_t finish_flatten_binder(
const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
{
return out->writeObject(flat, false);
}
至此, 在第 12 步中的 data.writeStrongBinder(service);
到这里就分析完了. 在第 12 步中传入的 AMS 服务, 到最后写入的实际上是一个 flat_binder_object
结构体. 接下来继续分析第 12 步中的下一个操作. 第 12 步代码如下
public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
01 data.writeInterfaceToken(IServiceManager.descriptor);
02 data.writeString(name);
03 data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
04 mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
代码 04 处调用成员变量 mRemote 的 transact 函数向 SM 发送一个类型为 ADD_SERVICE_TRANSACTION
的进程间通信请求, 即请求 SM 将一个 Java 服务注册进去. mRemote
即 BinderProxy. 指向一个句柄值为 0 的 Java 服务代理对象.
21. BinderProxy.transact 开始发送进程间通信请求.
BinderProxy
类的成员函数 transact
是一个 JNI 方法. 定义如下
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
return transactNative(code, data, reply, flags);
}
public native boolean transactNative(int code, Parcel data, Parcel reply, int flags) throws RemoteException;
对应的实现在 android_util_Binder.cpp
中的 android_os_BinderProxy_transact
函数.
22. android_util_Binder.android_os_BinderProxy_transact
源码路径 /frameworks/base/core/jni/android_util_Binder.cpp
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
...
01 Parcel* data = parcelForJavaObject(env, dataObj);
...
02 Parcel* reply = parcelForJavaObject(env, replyObj);
...
03 IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject);
...
04 status_t err = target->transact(code, *data, reply, flags);
...
}
代码 01 处与 02 处分别将 Java 层中的两个 Parcel 对象 dataObj
, replyObj
转为 C++层中的 Parcel 对象data
,reply
. data
中包含了要传递给 SM 的进程间通信数据, reply
用来保存从 SM 返回的数据结果.
参数 obj
指向的是一个 Java 服务代理对象, 即 BinderProxy.
代码 03 处就是获得这个代理对象的 Binder 代理对象. 即 BpBinder. 保存到变量 target
中.
代码 04 处调用 target
的成员函数 transact
想 SM 发送一个类型为 code
的进程间通信请求. code
值为 ADD_SERVICE_TRANSACTION
. 当 SM 收到这个进程间通信请求后, 就会将保存在 Parcel对象 data
中的一个 Binder 本地对象的信息取出来后注册到它的内部去. 那现在进入到 BpBinder 的 transact
函数内.
data 中保存的 Binder 本地对象信息即在第 13 - 20 步中写入的 flat_binder_object 结构体, 在 19 步中将这个结构体的成员变量 cookie 设置为 Binder 本地对象. 这个本地对象是在 17 步中创建的 JavaBBinder.
23. BpBinder.transact
源码路径: /frameworks/native/libs/binder/BpBinder.cpp
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
if (mAlive) {
status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
从前面的调用过程可以知道, 第一个参数 code
值为 ADD_SERVICE_TRANSACTION
, 第二个参数 data
包含了要传递给 Binder 驱动程序进程间通信数据. 第三个参数 reply
是一个输出参数, 用来保存进程间通信的结果. 第四个参数 flags
用来描述这是一个同步的进程间通信请求还是异步的. 默认值为 0, 表示同步.
成员变量 mAlive
用来描述 Binder 代理对象所引用的 Binder 本地对象是否还活着, 如果还活着,即值为 1. 在 if
内才会调用当前线程的 IPCThreadState
对象的成员函数 transact
想 Binder 驱动发送一个 BC_TRANSACTION
命令协议.
Binder 代理对象中的成员变量 mHandle
用来描述该 Binder 代理对象的句柄值. 由于目前正在处理的 Binder 代理对象指向的是 SM 的代理对象. 因此 mHandle
的值就等于 0.
现在进入 IPCThreadState
的 transact
函数.
24.IPCThreadState.transact 向 Binder 驱动程序发送 BC_TRANSACTION 命令协议
源码路径: /frameworks/native/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
01 status_t err = data.errorCheck();
02 flags |= TF_ACCEPT_FDS;
...
if (err == NO_ERROR) {
...
03 err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
...
04 if ((flags & TF_ONE_WAY) == 0) {
...
if (reply) {
05 err = waitForResponse(reply);
} else {
...
}
...
} else {
...
}
return err;
}
代码 01 处是检查 Parcel 对象 data
中的进程间通信数据是否正确.
代码 02 处将参数 flag
的 TF_ACCEPT_FDS
位设置为 1, 表示允许 Server 进程在返回结果中携带文件描述.
如果 data
中的数据没有问题, 执行代码 03 处. 调用成员函数 writeTransactionData
将它的内容写到一个 binder_transaction_data
结构体中.
代码 04 处判断是同步请求还是异步请求, 本次为同步请求, 接着判断用来保存通信结果的 reply
是否为 NULL, 不为 NULL 就调用成员函数 waitForResponse
向 Binder 驱动程序发送一个 BC_TRANSACTION
命令协议.
接下来主要是分析两个函数, writeTransactionData
与 waitForResponse
的实现
25. IPCThreadState.writeTransactionData
源码路径: /frameworks/native/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
01 binder_transaction_data tr;
...
tr.target.handle = handle;
tr.code = code;
tr.flags = binderFlags;
...
02 const status_t err = data.errorCheck();
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
tr.data.ptr.offsets = data.ipcObjects();
} else if (statusBuffer) {
...
} else {
...
}
03 mOut.writeInt32(cmd);
04 mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}
在代码 01 处, 先定义了一个 binder_transaction_data
结构体 tr
, 接着下面几行代码就对它进行了初始化操作. 经过前面调用已知 handle = 0, code = ADD_SERVICE_TRANSACTION, binderFlags = TF_ACCEPT_FDS
.
代码 02 处再次确认 data
中进程间通信数据的正确性. 如果没有问题则命中if
.
将 data
内部的数据缓冲区和偏移数组设置为 binder_transaction_data
结构体 tr
的数据缓冲区与偏移数组.
代码 03 与 04 处将 BC_TRANSACTION
命令协议以及 binder_transaction_data
写入到 IPCThreadState
成员变量 mOut
所描述的一个命令协议缓冲区中. 表示它有一个 BC_TRANSACTION
命令协议需要发送给 Binder 驱动程序处理.
将 BC_TRANSACTION
命令协议写入到 IPCThreadState
类内部的命令协议缓冲区后, 回到 第 24 步. 接下来就需要调用成员函数 waitForResponse
向 Binder 驱动程序发送这个命令协议了.
26. IPCThreadState.waitForResponse
源码路径: /frameworks/native/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;
...
}
return err;
}
通过一个 while
循环不断的调用成员函数 talkWithDriver
来与 Binder 驱动程序进行交互. 以便可以将在第 25 步中准备好的 BC_TRANSACTION
命令协议发送给 Binder 驱动程序处理. 并等待 Binder 驱动程序将进程通信结果返回回来.
OK. 其实一路分析到这里, 才算是开始. 现在进入 talkWithDriver
27. IPCThreadState.talkWithDriver
源码路径: /frameworks/native/libs/binder/IPCThreadState.cpp
//参数 doReceive 用来描述调用者是否希望函数 talkWithDriver
//只接受 Binder 驱动程序发送给该进程的返回协议. 该参数默认为 `true`.
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
...
//talkWithDriver 函数使用 IO 控制命令 BINDER_WRITE_READ 来与 Binder 驱动程序进行交互
//因此这里需要先定义一个结构体来指定输入缓冲区和输出缓冲区.
//其中输出缓冲区是保存的是进程发给 Binder 驱动程序的命令协议,
//而输入缓冲区保存的是 Binder 驱动程序发送给进程的返回协议,
//它们分别与 `IPCThreadState` 类内部的命令协议缓冲区 `mOut` 和返回协议缓冲区 `mIn` 相对应.
binder_write_read bwr;
01 const bool needRead = mIn.dataPosition() >= mIn.dataSize();
02 const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
//将变量 write_size 的值设置为 binder_write_read 结构体 bwr 的
//输出缓冲区的长度 write_size
bwr.write_size = outAvail;
//将 IPCThreadState 类内部的命令协议缓冲区 mOut
//设置为 binder_write_read 结构体 bwr 的输出缓冲区.
bwr.write_buffer = (uintptr_t)mOut.data();
03 if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
...
04 do {
...
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
...
05 } while (err == -EINTR);
...
if (err >= NO_ERROR) {
06 if (bwr.write_consumed > 0) {
if (bwr.write_consumed < mOut.dataSize())
mOut.remove(0, bwr.write_consumed);
else
mOut.setDataSize(0);
07 }
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
08 mIn.setDataPosition(0);
}
...
return NO_ERROR;
}
return err;
}
从前面的调用可知, mOut
中存在一个 BC_TRANSACTION
命令协议.
在
IPCThreadState
内部, 除了使用缓冲区mOut
来保存即将要发送给 Binder 驱动程序的命令协议外, 还用缓冲区mIn
来保存那些从 Binder 驱动程序接收到的返回协议
一个进程使用 IO 控制命令 BINDER_WRITE_READ
进入到 Binder 驱动程序, 传递的 binder_write_read
结构体的输出缓冲区和输入缓冲区的长度分别等于 0 和大于 0 时, Binder 驱动程序就不会处理进程发送的命令协议, 而只会对该进程发送返回命令协议, 这样进程就达到了接收返回协议的结果.
只接收返回协议还会受到返回协议缓冲区 mIn
的影响. 如果上次 Binder 发送给进程的返回协议已经处理完成, 即返回协议缓冲区 mIn
中的返回协议已经处理完成, 那么即使参数 doReceive
为 true
, IPCThreadState
的成员函数 talkWithDriver
也会向 Binder 驱动程序发送命令协议.
因此如果返回协议缓冲区 mIn
的返回协议已经处理完成, 即代码 01 处得到的 needRead
变量值为 true
. 或者调用者不是只希望接收 Binder 驱动程序发送给进程的返回协议, 及参数 doReceive
为 false
, 那么代码 02 处就将变量 outAvail
的值设置为 IPCThreadState
类内部的命令协议缓冲区的长度. 否则就设置为 0.
从前面的调用过程可以知道, 参数 doReceive
的值为 true
, 假设此时 IPCThreadState
类内部的返回协议缓冲区 mIn
没有包含未处理的返回协议, 那么 needRead
值为 true
. 命中代码 03 处 if
判断. 在判断内将 binder_write_read
结构体 bwr
的输入缓冲区 read_buffer
设置为类内部的返回协议缓冲区 mIn
.
代码 04 处到 05 处的 while
循环使用 IO 控制命令 BINDER_WRITE_READ
来与 Binder 驱动程序进行交互. 由于这时候传递给 Binder 驱动程序的 binder_write_read
结构体 bwr
输出缓冲区的长度 write_size
和 输入缓冲区 read_size
的长度均大于 0. 因此 Binder 驱动程序在处理 IO 控制命令 BINDER_WRITE_READ
时, 就会首先调用函数 binder_thread_write
来处理进程发送给它的 BC_TRANSACTION
命令协议. 接着又会调用函数 binder_thread_read
来读取 Binder 驱动程序给进程发送的返回协议.
当从驱动层返回后, 代码 06-07 处将 Binder 驱动程序已经处理的命令协议从 IPCThreadState
类内部的命令协议缓冲区 mOut
中移除, 接着在代码 08 处将从 Binder 驱动程序中读取出来的返回协议保存在类内部的返回协议缓冲区 mIn
中. 这样这个函数执行完再返回到第 26 步的时候. 就可以通过解析返回协议缓冲区 mIn
的内容来执行相对应的操作了.
现在就要进入到 Binder 驱动层了, 来分析是如何处理这个命令协议的.
28. binder_ioctl_write_read
源码路径: kernel 3.18下的 /drivers/staging/android/binder.c
static int binder_ioctl_write_read(struct file *filp,
unsigned int cmd, unsigned long arg,
struct binder_thread *thread)
{
...
...
ret = binder_thread_write(proc, thread,
bwr.write_buffer,
bwr.write_size,
&bwr.write_consumed);
...
}
直接进入到 binder_thread_write
函数
29. binder_thread_write
源码路径: kernel 3.18下的 /drivers/staging/android/binder.c
static int binder_thread_write(struct binder_proc *proc,
struct binder_thread *thread,
binder_uintptr_t binder_buffer, size_t size,
binder_size_t *consumed)
{
while (ptr < end && thread->return_error == BR_OK) {
switch (cmd) {
...
case BC_TRANSACTION:
case BC_REPLY: {
...
binder_transaction(proc, thread, &tr, cmd == BC_REPLY, 0);
break;
}
...
}
*consumed = ptr - buffer;
}
return 0;
}
从代码中可以看出又调用了 binder_transaction
函数. 进入到这个函数. 传入的参数中
cmd == BC_REPLY
值为 false, 因为这个时候 cmd
的值为 BC_TRANSACTION
.
30. binder_transaction
源码路径: kernel 3.18下的 /drivers/staging/android/binder.c
这个函数有点长, 将会分为四段来分析.
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply,
binder_size_t extra_buffers_size)
{
struct binder_proc *target_proc;
struct binder_node *target_node = NULL;
...
if (reply) {
...
} else {
if (tr->target.handle) {
...
01 } else {
target_node = context->binder_context_mgr_node;
...
}
...
02 target_proc = target_node->proc;
...
}
03 if (target_thread) {
e->to_thread = target_thread->pid;
target_list = &target_thread->todo;
target_wait = &target_thread->wait;
} else {
target_list = &target_proc->todo;
target_wait = &target_proc->wait;
}
在上一步知道 reply
为 fale
, 所以直接进 else
. 由于目标 Binder 的引用对象的句柄值为 0, 所以直接执行代码 01 处的 else
逻辑. 将目标 Binder 实体对象 target_node
指向一个引用了 SM 的 Binder 实体对象 binder_context_mgr_node
. 如果进的是 if
就需要先获得与句柄值对应的 Binder 引用对象. 再通过这个引用对象的成员变量 node
来找到目标 Binder 实体对象 target_node
.
binder_context_mgr_node
的赋值是在 上一章 Android Service Manager 的启动流程中的第6 步忘记的,可以返回去看一下.
找到了目标 Binder 实体对象以后, 代码 02 处就可以根据它的成员变量 proc
来找到目标进程 target_proc
.
如果在目标进程 target_proc
中找到了一个最优的目标线程 target_thread
来接收 BR_TRANSACTION
返回协议那么就命中代码 03 处 if
, 将变量 target_list
与 target_wait
分别指向最优线程的 todo
与 wait
队列.. 否则就指向目标进程的 todo
与 wait
队列. 有了这两个队列后, 函数接下来就可以将一个 BR_TRANSACTION
返回协议相关的待处理工作项加入到 todo
队列中. 以及通过等待队列将目标进程或线程唤醒来处理这个工作项.
binder_transaction
函数第二部分代码
01 t = kzalloc(sizeof(*t), GFP_KERNEL);
...
02 tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
...
03 if (!reply && !(tr->flags & TF_ONE_WAY))
t->from = thread;
else
t->from = NULL;
...
...
04 t->buffer = binder_alloc_buf(target_proc, tr->data_size, tr->offsets_size, extra_buffers_size, !reply && (t->flags & TF_ONE_WAY));
...
if (target_node)
binder_inc_node(target_node, 1, 0, NULL);
...
05 if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
tr->data.ptr.buffer, tr->data_size)) {
}
06 if (copy_from_user(offp, (const void __user *)(uintptr_t)
tr->data.ptr.offsets, tr->offsets_size)) {
}
代码 01 处分配一个 binder_transaction
结构体 t
, 后面会将它封装为一个 BINDER_WORKTRANSACTION
类型的工作项加入到目标的 todo
队列中. 以便目标线程可以接收到一个 BR_TRANSACTION
返回协议.
代码 02 处分配了一个 binder_work
结构体 tcomplete
. 后面会将它封装成一个 BINDER_WORK_TRANSACTION_COMPLETE
类型的工作项加入到源线程的 todo
队列中, 以便该线程知道可以马上返回用户空间. 并且知道它之前发送给 Binder 驱动程序的 BC_TRANSACTION
命令协议已经被接收了.
代码 03 处判断如果正在处理的是一个 BC_TRANSACTION
命令协议. 并不且它所描述的是一个同步的进程间通信请求, 那么命中 if
就会将 binder_transaction
结构体 t
的成员变量 from
指向源线程, 以便目标进程 target_proc
或者目标线程 target_thread
处理完该进程间通信请求之后, 能够找到发出改进程通信请求的线程. 最终将通信结果返回给它.
代码 04 处是为 binder_transaction
结构体 t
分配内核缓冲区, 以便可以将进程间通信结果拷贝到它里面, 最后传递给目标进程 target_proc
或者目标线程处理.
当前目标进程为 SM . 源线程/进程为 AMS
代码 05, 06 处是分别将 binder_transaction
结构体 tr
的数据缓冲区以及偏移数组的内容拷贝到在代码 04 处为 binder_transaction
结构体 t
分配的内核缓冲区中.
binder_transaction
函数第三部分代码
for (; offp < off_end; offp++) {
struct binder_object_header *hdr;
...
switch (hdr->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: {
01 struct flat_binder_object *fp;
02 struct binder_ref *ref;
03 fp = to_flat_binder_object(hdr);
04 ret = binder_translate_binder(fp, t, thread);
if (ret < 0) {
return_error = BR_FAILED_REPLY;
goto err_translate_failed;
}
} break;
...
}
这整个 for
循环就是依次处理进程间通信数据中的 Binder 对象. 如果 Binder 驱动程序是第一次碰到这些 Binder 对象, 那么 Binder 驱动程序就会根据它们的类型分别创建一个 Binder 实体对象或者 Binder 引用对象.
否则, 就会将之前为他们创建的 Binder 实体对象或者 Binder 引用对象获取回来, 增加引用计数, 避免过早销毁.
代码 01 处定义一个 flat_binder_object
结构体 fp
.
从第 19 步的调用可以知道, 进程间通信数据中包含一个类型为
BINDER_TYPE_BINDER
的 Binder 对象, 即一个flat_binder_object
结构体. 用来描述即将要注册到 SM 中的 Service 组件 AMS.
代码 02 处定义一个 binder_ref
结构体 ref
. 表示 Binder 的引用对象.
代码 03 处获取获取在 19 步写入的 flat_binder_object
结构体, 保存在 fp
中.
主要分析代码 04 处 binder_translate_binder
函数. 进去看一下
31. binder_translate_binder
源码路径: kernel 3.18下的 /drivers/staging/android/binder.c
static int binder_translate_binder(struct flat_binder_object *fp,
struct binder_transaction *t,
struct binder_thread *thread)
{
...
01 node = binder_get_node(proc, fp->binder);
02 if (!node) {
...
}
...
03 ref = binder_get_ref_for_node(target_proc, node);
...
if (fp->hdr.type == BINDER_TYPE_BINDER)
04 fp->hdr.type = BINDER_TYPE_HANDLE;
else
fp->hdr.type = BINDER_TYPE_WEAK_HANDLE;
fp->binder = 0;
fp->handle = ref->desc;
fp->cookie = 0;
05 binder_inc_ref(ref, fp->hdr.type == BINDER_TYPE_HANDLE, &thread->todo);
...
return 0;
}
代码 01 处获得 Binder 实体对象 node
. 接着在代码 02 处判断是否为 NULL, 此处我们获得的 Binder 实体对象不为 NULL,
binder_get_node
函数是根据flat_binder_object
结构体中弱引用计数对象的地址binder
在目标进程proc
中找到一个对应的 Binder 实体对象. 在第 19 步中被赋值.
在代码 03 处调用 binder_get_ref_for_node
函数, 在目标进程 target_proc
中创建一个 Binder 引用对象来引用该 Service 组件 AMS.
在代码 04 处将 flat_binder_object
结构体 fp
的类型修改为 BINDER_TYPE_HANDLE
, 并设置好它的句柄值. 这是因为当 Binder 驱动程序将进程间通信数据传递给目标进程 target_proc
时, 进程间通信数据中的 Binder 实体对象就变量 Binder 引用对象. 所以需要修改它的类型.
在目标进程 target_proc
创建好一个 Binder 引用对象 ref
后, 接着就要将它传递给该目标进程了. 在传递过程中, 必须要保证 Binder 引用对象 ref
不会被销毁, 因此在代码 05 处调用函数 binder_inc_ref
来增加它的引用计数.
继续回到 binder_transaction
中, 看第三部分代码
32. binder_transaction 发送进程间通信
第四部分代码
01 if (reply) {
...
02 } else if (!(t->flags & TF_ONE_WAY)) {
t->need_reply = 1;
t->from_parent = thread->transaction_stack;
thread->transaction_stack = t;
} else {
...
}
03 t->work.type = BINDER_WORK_TRANSACTION;
04 list_add_tail(&t->work.entry, target_list);
05 tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
06 list_add_tail(&tcomplete->entry, &thread->todo);
07 if (target_wait)
08 wake_up_interruptible(target_wait);
代码 01 处值为 false
在第 29 步中有说明.
代码 02 处判断正常处理的是否是一个同步的进程间通信请求, 即 binder_transaction
接头体 t
的成员变量 flags
的 TF_ONE_WAY
为等于 0. 那么命中 else if
, 设置它的成员变量 need_reply
的值为 1, 表示它需要等待回复. 接着将事务 t
压入到源线程 thread
的事务堆栈 transaction_stack
中.
代码 03 与 04 处将 binder_transaction
结构体 t
封装成一个类型为 BINDER_WORK_TRANSACTION
的工作项添加到目标进程 target_proc
或者目标线程 target_thread
的 todo
队列中, 并且在 08 行代码处将目标进程唤醒, 以便处理该工作项.
在 Android Service Manager 的启动流程 一文中的第 12 步分析 3 处调用了
wait_event_freezable_exclusive
函数进行睡眠等待直到其所属的进程有新的未处理工作项. 所以接下来分析SM的时候, 直接从binder_thread_read
处接着分析 SM 被唤醒后的操作.
如果目标进程
todo
队列target_list
指向的是一个 Binder 实体对象的异步事务队列async_todo
, 那么目标wait
等待队列target_wait
就会等于 NULL, 这时候就不需要唤醒目标进程.
代码 05 与 06 行代码处将 binder_work
结构体 tcomplete
封装成一个类型为 BINDER_WORK_TRANSACTION_COMPLETE
的工作项添加到源线程的 todo
队列中, 以便它从 Binder 驱动程序返回到用户空间之前, 可以处理该工作项.
程序执行到这里, 源线程, 目标进程或者目标线程就会并发的去处理各自 todo
队列中的工作项. 为了方便描述,
假设源线程会首先它的 todo
队列中类型为BINDER_WORK_TRANSACTION_COMPLETE
的工作项.
接着目标进程再处理它队列中的类型为 BINDER_WORK_TRANSACTION
的工作项.
注:
此时源线程为 AMS 进程中请求注册 Service 组件的线程与目标进程 SM 需要处理的工作项类型如下
- 源线程: ActivityManagerService 要处理的工作项类型为:
BINDER_WORK_TRANSACTION_COMPLETE
- 目标进程 SM. 需要处理的工作项类型为
BINDER_WORK_TRANSACTION
.
未完待续......
网友评论