java世界的binder:AndroidFramework

一、前言

我们阅读分析了native的binder使用案例,覆盖了大多数情景,总结出一套标准的binder机制使用动作。

进程启动后要使用ProcessState操作binder驱动:open与mmap。之后新建线程池和加线程startThreadPool和joinThreadPool,进入waitResponse-->talkWithDriver的死循环,不断地同binder驱动进行ioctl,读操作。这是一个服务端的binder线程要做的工作,就是不断的读驱动然后处理返回数据。

而发起者进程,在发起binder-ipc时,但前线程也是死循环吗?不是的,不同点在waitForResponse方法里,当发起者transact方法发起ipc,正常情况,之后要么收到BR_REPLY表示一个来回的完成,要么是oneway的BR_TRANSACTION_COMPLETE。当然还有其他情况,这几种情况都会goto finish将循环退出,这样就返回到remote()->transact的调用处,下一步就可以处理reply这个返回的parcel数据包了。

简单的两段话,是否让你对native的binder使用流程有了形象的概念,读代码的目的就是将死的文本变成脑海里,动态的,对象之间情景交互,数据的流动。

native我们总结完了,再来思考java世界。

如果给你这个需求,让你设计实现一个java世界的binder使用机制,你会怎么设计?重点有2。

一个是进程的接收能力。每个进程初始化是也要open,mmap以及创建binder线程不断地读驱动。并且线程接收到客户请求之后,也可以走到类似Bnxxx类里的onTransact回调,这样走到真正的实现,然后sendReply。

另一个呢,就是一个进程的发送能力。在发起ipc的时候,也要同native一样,有一个库文件给我们客户端用,类似BpxxxService,直接调用它的接口即可。

完成了这俩功能,思考一下,我们作为普通的app进程就可以给系统服务ipc发消息,然后可以收到答复了

同样的,例如系统服务AMS,可以给别的系统服务ipc发消息收消息,也可以收app进程的请求然后给他答复。

另外,考虑到代码复用,我们最好直接jni调用native现成的接口,也就是libbinder工具库里的接口。

上面我们这些简单的畅想,正是目前aosp里的实现。也就是说,java的binder框架是native框架的映射。(匿名binder后续讨论,也就是app与app进程的binder通信,我们常用的bindeService)

现在就让我们看看SystemServer进程启动时的open,mmap动作和AMS系统服务的注册动作。

二、SystemServer进程的open、mmap

system_server进程怎么启动的可以参考Android 10.0 系统启动之SystemServer进程-[Android取经之路]

其实你应该知道,所有java进程的启动流程都是如此,不管是app进程还是系统服务进程又或者是我们调试用的cmd命令所在的进程,都是通过app_process也就是zygote进程fork出来的子进程。fork完后都会走到ZygoteInit.java的zygoteInit-->nativeZygoteInit,然后跳到native里,在app_main.cpp的onZygoteInit方法里完成我们的第一个需求,open,mmap和建立线程、线程池、死循环读驱动。

frameworks/base/cmds/app_process/app_main.cpp

 92     virtual void onZygoteInit()
93 {
94 sp<ProcessState> proc = ProcessState::self();
95 ALOGV("App process: starting thread pool.\n");
96 proc->startThreadPool();
97 }

又是你,ProcessState。我们见过他最最起码3次了,sm启动(Android11上的)、sf启动、bootanimation启动,加上这次是第四次。

如果你有心可以再去其他的native程序里找找,例如dumpstate啊,vold啊,mediaServer啊等等,都会看到他们的main里调用ProcessState来完成本进程的binder初始化工作。看多了你就有很直白的印象,哦,原来大家用binder的第一步就是ProcessState::self()startThreadPool

system_server进程是一个java世界的进程,是由zygote孵化出来的进程。不止system_server,所有的java进程都是由zygote孵化出来的。所以明显的,我们答案找到了。

system_server进程(或者APP进程),是怎么完成open binder驱动,mmap等等初始化操作的?

答案:还是通过libbinder库的ProcessState类。流程是在zygote fork子进程之后native 的onZygoteInit方法里。

三、AMS注册到ServiceManager

一些前置

native进程是如何注册自己到sm的?

我想你一定很清楚了,就是使用libbinder库的接口,先defaultServiceManager拿到一个BpServiceManager对象,然后调用它的addService方法,talkwithdriver。通过binder驱动将自己的服务解析为binder_ref和handle,sm记下来保存在svclist里。

那么现在我们带着问题去看代码,java进程里如何注册自己到sm?

不赘述工具辅助类SystemServiceManager的startService流程,注册的地方。

frameworks/base/services/java/com/android/server/SystemServer.java

 623     private void startBootstrapServices() {
777 // Set up the Application instance for the system process and get started.
779 mActivityManagerService.setSystemProcess();

meworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

 2040     public void setSystemProcess() {
2041 try {
2042 ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
2043 DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
//------------------------------------------------------------------------------
2044 ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
2045 ServiceManager.addService("meminfo", new MemBinder(this)
2047 ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
2048 ServiceManager.addService("dbinfo", new DbBinder(this));
2050 ServiceManager.addService("cpuinfo", new CpuBinder(this),

2042行是ams的注册,下面几个是其他服务的注册什么内存啊cpu啊。由于都和ams有强联系,所以在这里初始化和注册。

2042行跳转。会发现我们跳到了一个ServiceManager.java的类里。frameworks/base/core/java/android/os/ServiceManager.java

还记得native是通过啥addService吗?我们需要在mk里依赖libbinder这个so,然后#include <binder/IServiceManager.h>

现在是java世界了,有什么不同吗?

套路上是完全一致的。ServiceManager.java这个类我们在ams里有import。261 import android.os.ServiceManager;

并且也有在编译时依赖一个库,只不过这个库是jar包,且是zygote帮我们preloadclass阶段预加载好的。默认就能用,不需要在java程序的mk里面显式添加依赖。native的libbinder需要显式添加依赖。

frameworks/base/Android.bp

  28 java_defaults {
29 name: "framework-defaults",
30 installable: true,
32 srcs: [
34 "core/java/**/*.java",
77 "core/java/android/app/ISearchManager.aidl",
78 "core/java/android/app/ISearchManagerCallback.aidl",
//----------------------------------------------------------------------------------
825 java_library {
826 name: "framework",
827 defaults: ["framework-defaults"],
828 javac_shard_size: 150,
829 }

现在走进ServiceManager.java#addService

frameworks/base/core/java/android/os/ServiceManager.java

178     /**
179 * Place a new @a service called @a name into the service
180 * manager.
181 *
182 * @param name the name of the new service
183 * @param service the service object
184 * @param allowIsolated set to true to allow isolated sandboxed processes
185 * @param dumpPriority supported dump priority levels as a bitmask
186 * to access this service
187 */
188 @UnsupportedAppUsage
189 public static void addService(String name, IBinder service, boolean allowIsolated,
190 int dumpPriority) {
191 try {
192 getIServiceManager().addService(name, service, allowIsolated, dumpPriority);

研究一下入参。

  • name是Context.ACTIVITY_SERVICE

frameworks/base/core/java/android/content/Context.java

3535     public static final String ACTIVITY_SERVICE = "activity";
  • service是this,也就是ams对象自己,ams是个Binder对象。
//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
401 public class ActivityManagerService extends IActivityManager.Stub
402 implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
//out/soong/.intermediates/frameworks/base/framework/android_common/gen/aidl/frameworks/base/core/java/android/app/IActivityManager.java
11 public interface IActivityManager extends android.os.IInterface
12 {
871 /** Local-side IPC implementation stub class. */
872 public static abstract class Stub extends android.os.Binder implements android.app.IActivityManager
//frameworks/base/core/java/android/os/Binder.java
75 public class Binder implements IBinder {

后俩参数不管了。看getIServiceManager方法的实现。

frameworks/base/core/java/android/os/ServiceManager.java

105     private static IServiceManager getIServiceManager() {
106 if (sServiceManager != null) {
107 return sServiceManager;
108 }
110 // Find the service manager
111 sServiceManager = ServiceManagerNative
112 .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
113 return sServiceManager;
114 }

asinterface,眼熟吗?native那个花里胡哨的宏还是模板,在那个方法里会new一个BpxxxService对象,例如BpServiceManager(new BpBinder(0))、BpSurfaceComposer(new BpBinder(handle))。这里也是类似。

 28 public abstract class ServiceManagerNative extends Binder implements IServiceManager
29 {
35 static public IServiceManager asInterface(IBinder obj){
46 return new ServiceManagerProxy(obj);
47 }

看,是不是和native里长的很像,只不过Bpxxx变成了xxxProxy而已。我们再看看obj这个参数怎么来的。

Binder.allowBlocking(BinderInternal.getContextObject())

frameworks/base/core/java/com/android/internal/os/BinderInternal.java

156     /**
157 * Return the global "context object" of the system. This is usually
158 * an implementation of IServiceManager, which you can use to find
159 * other services.
160 */
161 @UnsupportedAppUsage
162 public static final native IBinder getContextObject();

一看到jni调用猜也能猜到,又是去偷native的ServiceManager实例了。

frameworks/base/core/jni/android_util_Binder.cpp

1033 static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) {
1035 sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
1036 return javaObjectForIBinder(env, b);

1035行又是老熟人,再回顾一下。

frameworks/native/libs/binder/ProcessState.cpp

116 sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
117 {
118 return getStrongProxyForHandle(0);
119 }
259 sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle){
300 b = BpBinder::create(handle);
303 result = b;
313 return result;

native拿到的还是那个BpBinder(0)对象。这里300行是第一次初始化的,单例。之后请求都是存好的,此处为了好说明所以又把create这一行贴出来。

1036行是新东西

frameworks/base/core/jni/android_util_Binder.cpp

 662 // If the argument is a JavaBBinder, return the Java object that was used to create it.
663 // Otherwise return a BinderProxy for the IBinder. If a previous call was passed the
664 // same IBinder, and the original BinderProxy is still alive, return the same BinderProxy.
665 jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val){

简单说一下,就是返回一个BinderProxy对象。BinderProxy关联了native的sm BpBinder对象,放在BinderProxy.mObject成员变量里。native怎么创造出java对象,是通过反向jni,可以自行阅读。

现在,问题的答案浮出水面,返回返回返回到最初的IServiceManager getIServiceManager()方法。

这个方法的返回值就是return new ServiceManagerProxy(new BinderProxy());

还是和native的十分的像,native是new BpServiceManager(new BpBinder())

接着看下一步addService方法。

frameworks/base/core/java/android/os/ServiceManagerNative.java

113 class ServiceManagerProxy implements IServiceManager {
114 public ServiceManagerProxy(IBinder remote) {
115 mRemote = remote;
147 public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
148 throws RemoteException {
149 Parcel data = Parcel.obtain();
150 Parcel reply = Parcel.obtain();
151 data.writeInterfaceToken(IServiceManager.descriptor);
152 data.writeString(name);
153 data.writeStrongBinder(service);
154 data.writeInt(allowIsolated ? 1 : 0);
155 data.writeInt(dumpPriority);
156 mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
157 reply.recycle();
158 data.recycle();
159 }

look,是不是又很眼熟,简直是native的翻版。而且java的代码好读的多,之前我们native的remote()找了半天,现在不用找了,直接给你放旁边

151-155行,java的Parcel啥也没做直接jni调native Parcel.cpp里的实现。

然后156行也是BinderProxy跳到native的BpBinder里用他的transact方法,我们之前分析过,就是IPCThhreadStated里talkwithdriver那套流程。然后返回值也是放在reply这个parcel对象里。

3.1 Parcel:java是对native的封装

看一下writeStrongBinder,比较重要

frameworks/base/core/java/android/os/Parcel.java

 786     public final void writeStrongBinder(IBinder val) {
787 nativeWriteStrongBinder(mNativePtr, val);
788 }

frameworks/base/core/jni/android_os_Parcel.cpp

298 static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object){
300 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
302 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));

看302行,和native不同之处是这里的传参不是服务实体对象,我们进去看一下ibinderForJavaObject。

3.2 ibinderForJavaObject:BinderProxy到BpBinder的映射

frameworks/base/core/jni/android_util_Binder.cpp

 706 sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) {
710 // Instance of Binder?
711 if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
712 JavaBBinderHolder* jbh = (JavaBBinderHolder*)
713 env->GetLongField(obj, gBinderOffsets.mObject);
714 return jbh->get(env, obj);
715 }
716
717 // Instance of BinderProxy?
718 if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
719 return getBPNativeData(env, obj)->mObject;
720 }
724 }

当传入的obj是java里Binder对象就走711行,是BinderProxy就走718行。由于我们传下来的是AMS,又AMS 继承IActivityManager.Stub,Stub又继承android.os.Binder。所以我们走711行分支。

AMS有成员变量mObject吗?有,在父类Binder.java里

 249 //Raw native pointer to JavaBBinderHolder object. Owned by this Java object. Not null.
252 private final long mObject;

这个对象在何时赋值的?在Binder.java构造函数里,在AMS实例化时,走了父类的构造函数

frameworks/base/core/java/android/os/Binder.java

 559     public Binder(@Nullable String descriptor)  {
560 mObject = getNativeBBinderHolder();
561 NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mObject);
571 mDescriptor = descriptor;
572 }

frameworks/base/core/jni/android_util_Binder.cpp

 937 static jlong android_os_Binder_getNativeBBinderHolder(JNIEnv* env, jobject clazz)
938 {
939 JavaBBinderHolder* jbh = new JavaBBinderHolder();
940 return (jlong) jbh;
941 }
418 // ----------------------------------------------------------------------------
420 class JavaBBinderHolder {
422 public:
423 sp<JavaBBinder> get(JNIEnv* env, jobject obj){
425 AutoMutex _l(mLock);
426 sp<JavaBBinder> b = mBinder.promote();
427 if (b == NULL) {
428 b = new JavaBBinder(env, obj);
429 mBinder = b;
432 }
434 return b;
435 }
443 private:
445 wp<JavaBBinder> mBinder;
446 };

所以560行拿到的mObject代表native的JavaBBinderHolder对象。561行registerNativeAllocation是gc相关,可以参考:

Android | 带你理解 NativeAllocationRegistry 的原理与设计思想

ART视角 | 如何让GC同步回收native内存

回到ibinderForJavaObject方法714行的get调用,跳转到JavaBBinderHolder类get方法。423-434行。我们可以看到,get方法里new了一个JavaBBinder实例。看下这个类

 301 class JavaBBinder : public BBinder
302 {
303 public:
304 JavaBBinder(JNIEnv* env, jobject /* Java Binder */ object)
305 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)) {}
410 private:
411 JavaVM* const mVM;
412 jobject const mObject; // GlobalRef to Java Binder

可以看到,构造函数中将java的ams对象拿到了native也存了一份到mObject。

现在要梳理一下java和native这三个对象的关系了。java对象继承了android.os.Binder.java,native的俩对象是JavaBBinderHolder和JavaBBinder

java对象,持有的mObject,是JavaBBinderHolder

JavaBBinderHolder持有的mBinder是JavaBBinder

JavaBBinder持有的mObject是java对象

3.3 BinderProxy.transact是对BpBinder::transact的封装

frameworks/base/core/java/android/os/BinderProxy.java

473     public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
509 try {
510 return transactNative(code, data, reply, flags);

frameworks/base/core/jni/android_util_Binder.cpp

1279 static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
1280 jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
1281 {
1296 IBinder* target = getBPNativeData(env, obj)->mObject.get();
1318 //printf("Transact from Java code to %p sending: ", target); data->print();
1319 status_t err = target->transact(code, *data, reply, flags);

1296行拿出我们BinderProxy之前存好的native的BpBinder对象,然后通过这个BpBinder走入native的binder ipc流程。

之后流程就是之前文章分析的那样,不再赘述。

addService之后,java的SM也就相当于保存了这个新注册的服务,因为java的SM只是native的封装,通过jni调用而已。

四、ActivityManager#getCurrentUser(java世界binder调用的往和返)

4.1 App-->driver

现在分析这样的场景,app进程想使用AMS服务的功能,例如这个接口getCurrentUser。我们假设app进程已经创建,现在处于app的Activity环境里。(这里隐藏的含义就是APP进程已经历了zygoteInit流程里ProcessState的open、mmap、建立binder线程等初始化)

.../MainActivity.java

1 package com.example.app;
2 import android.app.ActivityManager;
3 public class MainActivity extends Activity {
4 @Override
5 protected void onResume() {
6 super.onResume();
7 int currentUserId = ActivityManager.getCurrentUser();
8 Log.d(TAG,"getCurrentUser : " + currentUserId);

走进第7行。

frameworks/base/core/java/android/app/ActivityManager.java

3825     public static int getCurrentUser() {
3826 UserInfo ui;
3827 try {
3828 ui = getService().getCurrentUser();
3829 return ui != null ? ui.id : 0;

看3828行的getService方法。

frameworks/base/core/java/android/app/ActivityManager.java

4041     public static IActivityManager getService() {
4042 return IActivityManagerSingleton.get();}
//--------------------------------------------------------------------------
4050 private static final Singleton<IActivityManager> IActivityManagerSingleton =
4051 new Singleton<IActivityManager>() {
4052 @Override
4053 protected IActivityManager create() {
4054 final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
4055 final IActivityManager am = IActivityManager.Stub.asInterface(b);
4056 return am;
4057 }
4058 };

frameworks/base/core/java/android/util/Singleton.java

 28 public abstract class Singleton<T> {
35 public final T get() {
36 synchronized (this) {
37 if (mInstance == null) {
38 mInstance = create();
39 }
40 return mInstance;

可以看到getService其实拿到的是一个4055行的IActivityManager类型的对象Stub.Proxy(BinderProxy),单例模式,每个进程只有一个。

4054行的IBinder对象如何获取的就不说了,同之前的ServiceManager.addService流程一样。走下去你会发现还是调用这样一句话。

frameworks/base/core/java/android/os/ServiceManager.java

260     private static IBinder rawGetService(String name) throws RemoteException {
263 final IBinder binder = getIServiceManager().getService(name);

现在我们看下4055行的实现。

out/soong/.intermediates/frameworks/base/framework/android_common/gen/aidl/frameworks/base/core/java/androi

d/app/IActivityManager.java

 872   public static abstract class Stub extends android.os.Binder implements android.app.IActivityManager
873 {
884 public static android.app.IActivityManager asInterface(android.os.IBinder obj)
885 {
893 return new android.app.IActivityManager.Stub.Proxy(obj);
894 }
4504 private static class Proxy implements android.app.IActivityManager
4505 {
4506 private android.os.IBinder mRemote;
4507 Proxy(android.os.IBinder remote)
4508 {
4509 mRemote = remote;
4510 }

可以看到。Proxy是Stub的子类,所以最终返回的对象是return new android.app.IActivityManager.Stub.Proxy(new BinderProxy());现在回到4055行、3828行。3828行的getService().getCurrentUser()就是调用这个Stub.Proxy类的getCurrentUser方法

out/soong/.intermediates/frameworks/base/framework/android_common/gen/aidl/frameworks/base/core/java/androi

d/app/IActivityManager.java

7288       @Override public android.content.pm.UserInfo getCurrentUser() throws android.os.RemoteException
7289 {
7290 android.os.Parcel _data = android.os.Parcel.obtain();
7291 android.os.Parcel _reply = android.os.Parcel.obtain();
7292 android.content.pm.UserInfo _result;
7293 try {
7294 _data.writeInterfaceToken(DESCRIPTOR);
7295 boolean _status = mRemote.transact(Stub.TRANSACTION_getCurrentUser, _data, _reply, 0);
7296 if (!_status && getDefaultImpl() != null) {
7297 return getDefaultImpl().getCurrentUser();
7298 }
7299 _reply.readException();
7300 if ((0!=_reply.readInt())) {
7301 _result = android.content.pm.UserInfo.CREATOR.createFromParcel(_reply);
7302 }
7303 else {
7304 _result = null;
7305 }
7306 }
7307 finally {
7308 _reply.recycle();
7309 _data.recycle();
7310 }
7311 return _result;
7312 }

又是眼熟的这样一套写法,7292行准备parcel对象,7294行写进请求数据,7295行借助BinderProxy开始跨进程调用,返回值在入参_reply,7301行将返回数据解包拿出来,7308行清理垃圾。

4.2 driver-->AMS

我们跳过冗杂的binder驱动处理流程,直接跳转到system_server进程中AMS处理这次binder请求的线程。现在它从talkwithdriver中苏醒,返回上层的waitForResponse,然后executecommand,解析cmd是case BR_TRANSACTION。

最后又走到了1213行,

frameworks/native/libs/binder/IPCThreadState.cpp

1208             if (tr.target.ptr) {
1213 error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
1214 &reply, tr.flags);

还是我们之前分析的,tr.cookie是代表服务端的BBinder对象,继续走

frameworks/native/libs/binder/Binder.cpp

123 status_t BBinder::transact(
124 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
129 switch (code) {
133 default:
134 err = onTransact(code, data, reply, flags);
135 break;

这里发生了不同的变化,我们的134行onTransact走向了何方?答案是BBinder的实现类,android_util_Binder.cpp文件class JavaBBinder。

frameworks/base/core/jni/android_util_Binder.cpp

301 class JavaBBinder : public BBinder
302 {
355 status_t onTransact(
356 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) override
357 {
358 JNIEnv* env = javavm_to_jnienv(mVM);
368 jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
369 code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);

368行反向jni调用java的mObiect类里方法"execTransact"。mObject是AMS对象,上一节有分析。

 996     gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");

现在让我们跳到AMS的java世界,现在处于Binder.java类里

frameworks/base/core/java/android/os/Binder.java

 987     private boolean execTransact(int code, long dataObj, long replyObj,
988 int flags) {
993 try {
994 return execTransactInternal(code, dataObj, replyObj, flags, callingUid);
//---------------------------------------------------------------
1000 private boolean execTransactInternal(int code, long dataObj, long replyObj, int flags,
1001 int callingUid) {
1021 res = onTransact(code, data, reply, flags);

继续,由于派生类实现了这个onTransact方法,所以现在跳转到Binder.java的子类,IActivityManager.Stub类

out/soong/.intermediates/frameworks/base/framework/android_common/gen/aidl/frameworks/base/core/java/androi

d/app/IActivityManager.java

 734     protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply,
735 int flags) throws RemoteException {
1703 @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
1704 {
1705 java.lang.String descriptor = DESCRIPTOR;
1706 switch (code)
1707 {
3436 case TRANSACTION_getCurrentUser:
3437 {
3438 data.enforceInterface(descriptor);
3439 android.content.pm.UserInfo _result = this.getCurrentUser();
3440 reply.writeNoException();
3441 if ((_result!=null)) {
3442 reply.writeInt(1);
3443 _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
3444 }
3445 else {
3446 reply.writeInt(0);
3447 }
3448 return true;
3449 }

还记得很久很久以前,我们的APP进程发起mRemote.trancact时传的cmd,是啥吗?

正是TRANSACTION_getCurrentUser。所以现在服务端AMS就switch到这里。

3439行的this是谁?你可别说是Stub对象。要分的清,当前是没有Stub对象的,有的只是AMS,这个Stub里的方法是AMS继承来的,而不是实例化的Stub。

所以跳转到AMS的getCurrentUser。具体怎么实现的我们就不管了了,总之我们拿到了AMS方法处理好的数据,现在开始返回。

3443将数据写进parcel

frameworks/base/core/java/android/content/pm/UserInfo.java

275     public void writeToParcel(Parcel dest, int parcelableFlags) {
276 dest.writeInt(id);
277 dest.writeString(name);
278 dest.writeString(iconPath);
279 dest.writeInt(flags);
280 dest.writeInt(serialNumber);
281 dest.writeLong(creationTime);
282 dest.writeLong(lastLoggedInTime);
283 dest.writeString(lastLoggedInFingerprint);
284 dest.writeInt(partial ? 1 : 0);
285 dest.writeInt(profileGroupId);
286 dest.writeInt(guestToRemove ? 1 : 0);
287 dest.writeInt(restrictedProfileParentId);
288 dest.writeInt(profileBadge);
289 }

是不是解决了你长久以来的一个疑问,读了这么久框架代码,这个writeToParcel啥时候用的?就是在这里用的,工具函数,不用一行一行写了。

4.3 AMS---sendReply--->driver--->App

现在回到了4.2小节的开头,IPCThreadState.cpp的executeCommand方法里。

1068 status_t IPCThreadState::executeCommand(int32_t cmd){
1074 switch ((uint32_t)cmd) {
1148 case BR_TRANSACTION:{
1208 if (tr.target.ptr) {
1211 if (reinterpret_cast<RefBase::weakref_type*>(
1212 tr.target.ptr)->attemptIncStrong(this)) {
1213 error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
1214 &reply, tr.flags);
1216 }
1228 if ((tr.flags & TF_ONE_WAY) == 0) {
1229 LOG_ONEWAY("Sending reply to %d!", mCallingPid);
1230 if (error < NO_ERROR) reply.setError(error);
1231 sendReply(reply, 0);
1232 } else {
1233 LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);

服务端的服务数据计算完毕,从1213行走下来。由于我们APP进程发起时未指定oneway,所以是走到1231行的sendReply,参数reply就是刚才填充的服务数据,我们的currentUserId。之前分析过这个方法,此处不再展开。

略过驱动的又一次数据流转,回到App进程用户空间,也是回到IPCThreadState的waitForResponse里,拿到数据判断是BR_REPLY退出死循环,然后就返回到梦开始的地方。IActivityManager.java第7295行。

out/soong/.intermediates/frameworks/base/framework/android_common/gen/aidl/frameworks/base/core/java/androi

d/app/IActivityManager.java

7288       @Override public android.content.pm.UserInfo getCurrentUser() throws android.os.RemoteException
7289 {
7293 try {
7294 _data.writeInterfaceToken(DESCRIPTOR);
7295 boolean _status = mRemote.transact(Stub.TRANSACTION_getCurrentUser, _data, _reply, 0);
7300 if ((0!=_reply.readInt())) {
7301 _result = android.content.pm.UserInfo.CREATOR.createFromParcel(_reply);
7302 }
7306 }
7311 return _result;
7312 }

我们的transact调用终于tm的结束了,这篇文章我写了一天了,从上午9点写到晚上9点45,太累了。中午没午休,晚饭也没吃,加油写完回家吃饭躺平。

现在走到7301行将AMS返回的数据解包,7311再次返回上层,一直一直一直返回到app的MainActivity第7行,然后第8行就将数据打印出来liao。

java世界的增,查,正向调用流程,逆向返回流程我们都走了一遍,大功告成。回家吃饭

android10Binder(五)java世界的binder:AndroidFramework的更多相关文章

  1. Java 世界的盘古和女娲 —— Zygote

    本文基于 Android 9.0 , 代码仓库地址 : android_9.0.0_r45 文中源码链接: Zygote.java ZygoteInit.java ZygoteServer.java ...

  2. 从linux看android之二--java世界的盘古女娲

    在linux从内核态进入用户态运行init进程后启动的一个进程就是zygote.zygote是在android系统中创建java世界的盘古,他创建了第一个java虚拟机,同时他又是女娲,他成功地繁殖了 ...

  3. 20145213《Java程序设计》实验五Java网络编程及安全

    20145213<Java程序设计>实验五Java网络编程及安全 实验内容 1.掌握Socket程序的编写. 2.掌握密码技术的使用. 3.设计安全传输系统. 实验预期 1.客户端与服务器 ...

  4. 20145206《Java程序设计》实验五Java网络编程及安全

    20145206<Java程序设计>实验五 Java网络编程及安全 实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统. 实验步骤 我和201451 ...

  5. 20145337实验五Java网络编程及安全

    20145337实验五Java网络编程及安全 实验内容 掌握Socket程序的编写 掌握密码技术的使用 设计安全传输系统 实验步骤 基于Java Socket实现安全传输 基于TCP实现客户端和服务器 ...

  6. JAVA课程实验报告 实验五 Java网络编程及安全

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计  班级:1353  姓名:韩玉琪  学号:20135317 成绩:             指导教师:娄嘉 ...

  7. 20145225《Java程序设计》 实验五 Java网络编程及安全

    20145225<Java程序设计> 实验五 Java网络编程及安全 实验报告 一.实验内容 基于Java Socket实现安全传输. 基于TCP实现客户端和服务器,结对编程一人负责客户端 ...

  8. 20145208 实验五 Java网络编程

    20145208 实验五 Java网络编程 实验内容 1.用书上的TCP代码,实现服务器与客户端. 2.客户端与服务器连接 3.客户端中输入明文,利用DES算法加密,DES的秘钥用RSA公钥密码中服务 ...

  9. 20145215实验五 Java网络编程及安全

    20145215实验五 Java网络编程及安全 实验内容 掌握Socket程序的编写: 掌握密码技术的使用: 设计安全传输系统. 实验步骤 本次实验我的结对编程对象是20145208蔡野,我负责编写客 ...

随机推荐

  1. HashMap源码解析和设计解读

    HashMap源码解析 ​ 想要理解HashMap底层数据的存储形式,底层原理,最好的形式就是读它的源码,但是说实话,源码的注释说明全是英文,英文不是非常好的朋友读起来真的非常吃力,我基本上看了差不多 ...

  2. ClickHouse学习系列之四【副本&分片部署说明】

    背景 以前介绍过ClickHouse相关的系列文章,现在继续说明.本文开始说明ClickHouse的副本与分片,和其他数据库一样,ClickHouse也会出现单节点故障和单节点资源到达上限的情况.所以 ...

  3. JavaScript的介绍概括

    1.js是一种轻型的解释性的脚本语言,称为web脚本语言. 2.js的执行原理:当客户端向服务器端请求某个页面时,浏览器端将整个页面中包含JavaScript的脚本代码作为响应内容,发送到客户端的机器 ...

  4. Python中Random随机数返回值方式

    1.a=["1","2","3"] print(random.choice(a)),  随机返回列表a中的一个元素 print(random ...

  5. Unity获取系统时间

    示例如下: Debug.Log(System.DateTime.Now); // 当前本地时间 (年月日时分秒) -- 10/4/2018 9:38:19 PM Debug.Log(System.Da ...

  6. mysql主节点down机后如何恢复操作

    1 停机维护 (1) 先停止上层应用 (2) 检查backup和slave的中继日志是否已经完成了回放及gtid_executed保持一致 mysql> show slave status\G; ...

  7. js 对json数据进行检索 插件 linq.js

    有时界面需要很多数据.但是多次访问服务器效率很低,所以需要检索json数据,最好是像sql查询语句那种 linq.js 插件 LINQ,语言集成查询(Language Integrated Query ...

  8. 调整/home和/root空间容量

    转载请注明出处:http://www.cnblogs.com/gaojiang/p/6767043.html 1.查看磁盘情况:df -h 2.卸载/homeumount /home umount / ...

  9. MySQL 插入中文后,显示为空白

    https://blog.csdn.net/sun_hj_95/article/details/79488583 在MySQL中插入中文后,显示如下: 解决方案: 在my.ini (在MySQL的安装 ...

  10. mac系统终端sudo免输入密码

    p.p1 { margin: 0; font: 12px ".PingFang SC" } p.p2 { margin: 0; font: 12px "Helvetica ...