上一篇Binder mRemote的前世今生PowerManger.isScreenOn()的调用流程已经调用到了BinderProxy.transact();
/frameworks/base/core/java/android/os/Binder.java
1------> Binder.java——>BinderProxy 2 public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { 3 Binder.checkParcel(this, code, data, "Unreasonably large binder buffer"); 4 return transactNative(code, data, reply, flags); 5 } 6 7 public native boolean transactNative(int code, Parcel data, Parcel reply, 8 int flags) throws RemoteException;
BinderProxy 的transact方法会调用JNI方法transactNative方法;
android_util_Binder.cpp
1------> android_util_Binder.cpp 2static const JNINativeMethod gBinderProxyMethods[] = { 3 /* name, signature, funcPtr */ 4 {"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder}, 5 {"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive}, 6 {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor}, 7 {"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact}, 8 {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath}, 9 {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath}, 10 {"destroy", "()V", (void*)android_os_BinderProxy_destroy}, 11}; 12 13static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, 14 jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException 15{ 16 if (dataObj == NULL) { 17 jniThrowNullPointerException(env, NULL); 18 return JNI_FALSE; 19 } 20 21 Parcel* data = parcelForJavaObject(env, dataObj);//将Java层的Parcel对象数据转换为native Parcel 22 if (data == NULL) { 23 return JNI_FALSE; 24 } 25 Parcel* reply = parcelForJavaObject(env, replyObj); 26 if (reply == NULL && replyObj != NULL) { 27 return JNI_FALSE; 28 } 29 30 IBinder* target = (IBinder*) 31 env->GetLongField(obj, gBinderProxyOffsets.mObject);//核心核心, 32 //还记得这里的gBinderProxyOffsets.mObject吗?你去前一篇文章搜索,会发现 33 //env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());val是从Native中获取的BpBinder对象 34 //setLongField就是将native 的BpBinder对象保存于Java层BinderProxy的mObject对象; 35 //getLongField就是从BinderProxy的mObject对象对象中取出native BpBinder对象;所以target就是一个BpBinder对象; 36 //很多实用JNI的系统类都会有这个做法,这样就不需要每次都去底层获取 37 if (target == NULL) { 38 jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!"); 39 return JNI_FALSE; 40 } 41 42 //printf("Transact from Java code to %p sending: ", target); data->print(); 43 status_t err = target->transact(code, *data, reply, flags);//核心核心,调用target的transact方法, 44 //即调用BpBinder的transact方法; 45 //if (reply) printf("Transact from Java code to %p received: ", target); reply->print(); 46#if ENABLE_BINDER_SAMPLE 47 if (time_binder_calls) { 48 conditionally_log_binder_call(start_millis, target, code); 49 } 50#endif 51 signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/); 52 return JNI_FALSE; 53}
这里IBinder* target就是Java层BinderProxy类的mObject变量,也就是上一篇文章在javaObjectForIBinder方法调用SetLongField保存的BpBinder对象;接下来就是调用BpBinder的transact方法:
/frameworks/native/libs/binder/BpBinder.cpp
1------> BpBinder.cpp 2status_t BpBinder::transact( 3 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 4{ 5 // Once a binder has died, it will never come back to life. 6 if (mAlive) { 7 status_t status = IPCThreadState::self()->transact( 8 mHandle, code, data, reply, flags);//核心核心核心, 9 //这里的mHandle就是对应远程服务**引用的handle** 10 if (status == DEAD_OBJECT) mAlive = 0; 11 return status; 12 } 13 return DEAD_OBJECT; 14}
这里很简单,就是调用 IPCThreadState::self()->transact,这里的mHandle是在初始化BpBinder对象时赋值的,也就是前面我们在调用getService获取服务流程中使用readStrongBinder调用getStrongProxyForHandle(flat->handle)传入的flat->handle;这个mHandle用于标识这个服务的引用。
/frameworks/native/libs/binder/IPCThreadState.cpp
1------> IPCThreadState.cpp 2status_t IPCThreadState::transact(int32_t handle, 3 uint32_t code, const Parcel& data, 4 Parcel* reply, uint32_t flags) 5{ 6 status_t err = data.errorCheck();//数据校验 7 flags |= TF_ACCEPT_FDS; 8 IF_LOG_TRANSACTIONS() { 9 TextOutput::Bundle _b(alog); 10 alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand " 11 << handle << " / code " << TypeCode(code) << ": " 12 << indent << data << dedent << endl; 13 } 14 if (err == NO_ERROR) { 15 LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(), 16 (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY"); 17 err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); 18 //将数据转为binder_transaction_data 19 } 20 if (err != NO_ERROR) { 21 if (reply) reply->setError(err); 22 return (mLastError = err); 23 } 24 if ((flags & TF_ONE_WAY) == 0) { 25 #if 0 26 if (code == 4) { // relayout 27 ALOGI(">>>>>> CALLING transaction 4"); 28 } else { 29 ALOGI(">>>>>> CALLING transaction %d", code); 30 } 31 #endif 32 if (reply) { 33 err = waitForResponse(reply);//核心核心核心 34 } else { 35 Parcel fakeReply; 36 err = waitForResponse(&fakeReply); 37 } 38 #if 0 39 if (code == 4) { // relayout 40 ALOGI("<<<<<< RETURNING transaction 4"); 41 } else { 42 ALOGI("<<<<<< RETURNING transaction %d", code); 43 } 44 #endif 45 IF_LOG_TRANSACTIONS() { 46 TextOutput::Bundle _b(alog); 47 alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand " 48 << handle << ": "; 49 if (reply) alog << indent << *reply << dedent << endl; 50 else alog << "(none requested)" << endl; 51 } 52 } else { 53 err = waitForResponse(NULL, NULL); 54 } 55 return err;
从第一篇Binder到现在,差不多一口气写了这么多,都差点忘记我写的是否正确,这是一个不好的习惯,这里我通过Log的方式来验证一下上面讲解的是否正确?
对于我添加的Log,也直接贴代码吧:
APP:
1 String TAG = "Bindertest MainActivity"; 2 Log.e(TAG,"App begin nativeCall"); 3 boolean bool = powerManager.isScreenOn(); 4 Log.e(TAG,"App end nativeCall");
Binder.java——>BinderProxy class
1 public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { 2 Binder.checkParcel(this, code, data, "Unreasonably large binder buffer"); 3 Log.e("BinderProxy.java transact","Keiven-Chen");//自己添加的打印Log 4 return transactNative(code, data, reply, flags); 5 }
BpBinder.cpp
1status_t BpBinder::transact( 2 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 3{ 4 // Once a binder has died, it will never come back to life. 5 if (mAlive) { 6 ALOGE("Keiven-Chen-BpBinder.cpp transact");//自己添加的打印Log 7 status_t status = IPCThreadState::self()->transact( 8 mHandle, code, data, reply, flags); 9 if (status == DEAD_OBJECT) mAlive = 0; 10 return status; 11 } 12 13 return DEAD_OBJECT; 14}
IPCThreadState.cpp
1status_t IPCThreadState::transact(int32_t handle, 2 uint32_t code, const Parcel& data, 3 Parcel* reply, uint32_t flags) 4{ 5 status_t err = data.errorCheck(); 6 7 flags |= TF_ACCEPT_FDS; 8 if (getpid()==g_nTargetPid)//判断条件 9 ALOGE("Keiven-Chen_IPCThread IPCThreadState::transact()");//自己添加的打印Log,这里使用getpid()==g_nTargetPid过滤条件, 10 //因为IPCThreadState::transact在系统中会被很多进程频繁调用,如果不加过滤将会很多Log输出,不便于跟踪分析; 11 IF_LOG_TRANSACTIONS() { 12 TextOutput::Bundle _b(alog); 13 alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand " 14 << handle << " / code " << TypeCode(code) << ": " 15 << indent << data << dedent << endl; 16 } 17...... 18} 19 20status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, 21 int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer) 22{ 23 binder_transaction_data tr; 24 ...... 25 if(getpid()==g_nTargetPid)//判断条件 26 ALOGE("Keiven-Chen IPCThreadState::writeTransactionData() tr.data_size = %d, offsets_size = %d, 27 target.handle = %d, data.ipcObjects() = %d, ipcObjectsCount() = %d", 28 tr.data_size, tr.offsets_size, tr.target.handle, data.ipcObjects(), data.ipcObjectsCount()); 29 //自己添加的打印Log,过滤进程号为getpid()==g_nTargetPid的Log(因为writeTransactionData方法被系统频繁调用); 30 mOut.writeInt32(cmd); 31 mOut.write(&tr, sizeof(tr)); 32 33 return NO_ERROR; 34}
这里我添加的Log就是根据前一篇的mRemote的追踪来添加的,Log说明前面的分析应该没问题;
需要清楚一件事,Binder通信调用到 IPCThreadState::transact方法时还没有跨进程,而是还在Client进程内;上述代码中getpid()方法用于获取到当前Client进程ID(PID),那g_nTargetPid从哪里来呢??? g_nTargetPid是我在Client中调用IPCThreadState的方法,然后在IPCThreadState中记录的Client进程号(PID);调用IPCThreadState的什么方法能记录下这个PID呢,肯定不是每个Client都默认调用的,而只在我的Client中才调用?这肯定就需要我们自己在IPCThreadState.cpp中添加特定方法来记录这个g_nTargetPid,这个方法也很简单,就是给g_nTargetPid赋值(g_nTargetPid = getpid()),这样我的client再次进入 IPCThreadState::transact时就能通过比较g_nTargetPid和getpid()的值来判断是否是我的client进程;这个就是在前一篇中中调用的processInfo.nativeSelfCall()来实现,nativeSelfCall是一个JNI,在该方法的实现中调用IPCThreadState::selfCall(),在selfCall()方法中记录实现g_nTargetPid = getpid()就能记录我们的Client进程ID了;
APP 部分
1 findViewById(R.id.mybtn).setOnClickListener(new View.OnClickListener() { 2 @Override 3 public void onClick(View v) { 4 ProcessInfo processInfo = new ProcessInfo(); 5 processInfo.nativeSelfCall();//JNI调用IPCThreadState.cpp的selfCall 6 PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 7 Log.e(TAG,"App begin nativeCall"); 8 boolean bool = powerManager.isScreenOn(); 9 Log.e(TAG,"App end nativeCall"); 10 Log.e(TAG,"" + bool); 11 } 12 }); 13 14ProcessInfo.java 的全包名必须是com.example.bindservice.ProcessInfo.java 15public class ProcessInfo { 16 static { 17 System.loadLibrary("jnidemo"); 18 } 19 public native void nativeSelfCall(); 20 21}
JNI 部分
1jni 可以在系统中很多地方创建,这里我放在 /frameworks/native/libs目录下: 2------> /frameworks/native/libs/jnidemo/ProcessInfo.cpp 3 4static void JNI_nativeSelfCall(JNIEnv* env, jobject thiz)//实现JNI方法 5{ 6 ALOGE("Keiven-Chen JNI_nativeSelfCall 111");//Log 7 IPCThreadState::self()->selfCall();//核心调用,调用IPCThreadState.cpp中自己实现的方法 8 ALOGE("Keiven-Chen JNI_nativeSelfCall 222"); 9} 10 11static JNINativeMethod gMethods[] = { 12 {"nativeSelfCall", "()V", (void*)JNI_nativeSelfCall}, //绑定JNI方法 13}; 14JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void* reserved) { 15 JNIEnv* env = NULL; 16 jint result = -1; 17 18 if ((jvm)->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) 19 { 20 return -1; 21 } 22 23 jclass clazz = (env)->FindClass("com/example/bindservice/ProcessInfo");//绑定Java类, 24 //必须在这个全类名中声明nativeSelfCall,这里指定了使用该JNI的Java类,所以我的ProcessInfo必须要要有上述包名; 25 if (clazz) 26 { 27 if((env)->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) < 0)//注册JNI 28 ALOGE("Keiven-Chen RegisterNatives natives NOT ok"); 29 else 30 ALOGE("Keiven-Chen RegisterNatives natives ok"); 31 } 32 else 33 ALOGE("Keiven-Chen could not find class"); 34 35 result = JNI_VERSION_1_4; 36 return result; 37}
编译JNI脚本
1LOCAL_PATH := $(call my-dir) 2include $(CLEAR_VARS) 3LOCAL_LDLIBS := -lm -llog 4LOCAL_MODULE := libjnidemo //生成jnidemo.so库 5 6LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libbinder 7 8LOCAL_SRC_FILES := ProcessInfo.cpp 9include $(BUILD_SHARED_LIBRARY)
这里看到JNI其实很简单,就是调用 IPCThreadState::self()->selfCall();,需要去IPCThreadState.cpp中实现selfCall方法;JNI知识可以参见之前的文章JNI/NDK;
IPCThreadState.cpp
1------> IPCThreadState.cpp 2void IPCThreadState::selfCall() 3{ 4 ALOGE("Keiven-Chen_IPCThread IPCThreadState::selfCall() 111 pid = %d, size of bwr is %d", 5 getpid(), sizeof(binder_write_read)); 6 ioctl(mProcess->mDriverFD, 123456, NULL);//这里向Binder驱动传递命令数据,用于跟踪内核驱动,后续再说 7 g_nTargetPid = getpid();/这里为g_nTargetPid 赋值,用于保存当前进程ID,后续通过该进程ID来过滤LOG 8 ALOGE("Keiven-Chen_IPCThread IPCThreadState::selfCall() 222"); 9}
根据在应用Activity中的逻辑,程序的执行流程是先执行JNI调用IPCThreadState.cpp的selfCall,先执行该方法,此时得到我的应用进程号(PID)g_nTargetPid = getpid()=4385,在根据这个PID在IPCThreadState.cpp中过滤掉其他跨进程调用transact方法Log;下面是完整的Log截图,先调用selfCall,再调用isScreenOn。
到这里,对于APP层是如何调用到IPCThreadState.cpp的transact应该很清晰了,接下来从IPCThreadState的transact继续往下跟踪;
IPCThreadState::transact方法中核心就是调用waitForResponse方法:
1------> IPCThreadState.cpp 2status_t IPCThreadState::transact(int32_t handle, 3 uint32_t code, const Parcel& data, 4 Parcel* reply, uint32_t flags) 5{ 6 status_t err = data.errorCheck(); 7 8 flags |= TF_ACCEPT_FDS; 9 if (getpid()==g_nTargetPid) 10 ALOGE("Keiven-Chen_IPCThread IPCThreadState::transact()"); 11 12 ...... 13 14 if (reply) { 15 err = waitForResponse(reply);//核心调用 16 } else { 17 Parcel fakeReply; 18 err = waitForResponse(&fakeReply); 19 } 20 ...... 21status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) 22{ 23 int32_t cmd; 24 int32_t err; 25 //if((g_nTargetPid>0) && (getpid()==g_nTargetPid)) //添加Log用于过滤 26 //ALOGE("11111 IPCThreadState::waitForResponse() mOut.data %d", *(int*)(mOut.data())); 27 while (1) { 28 if ((err=talkWithDriver()) < NO_ERROR) break; //核心调用,和驱动沟通 29 err = mIn.errorCheck(); 30 if (err < NO_ERROR) break; 31 if (mIn.dataAvail() == 0) continue; 32 33 cmd = mIn.readInt32();//从mIn中获取Binder 驱动返回命令 34 35 switch (cmd) { //根据驱动不同的返回值执行不同操作 36 case BR_TRANSACTION_COMPLETE: 37 if (!reply && !acquireResult) goto finish; 38 break; 39 40 case BR_DEAD_REPLY: 41 err = DEAD_OBJECT; 42 goto finish; 43 44 case BR_FAILED_REPLY: 45 err = FAILED_TRANSACTION; 46 goto finish; 47 48 case BR_ACQUIRE_RESULT: 49 { 50 ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT"); 51 const int32_t result = mIn.readInt32(); 52 if (!acquireResult) continue; 53 *acquireResult = result ? NO_ERROR : INVALID_OPERATION; 54 } 55 goto finish; 56 57 case BR_REPLY: 58 { 59 binder_transaction_data tr; 60 err = mIn.read(&tr, sizeof(tr)); 61 ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY"); 62 if (err != NO_ERROR) goto finish; 63 64 if (reply) { 65 if ((tr.flags & TF_STATUS_CODE) == 0) { 66 reply->ipcSetDataReference( 67 reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), 68 tr.data_size, 69 reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), 70 tr.offsets_size/sizeof(binder_size_t), 71 freeBuffer, this); 72 } else { 73 err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer); 74 freeBuffer(NULL, 75 reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), 76 tr.data_size, 77 reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), 78 tr.offsets_size/sizeof(binder_size_t), this); 79 } 80 } else { 81 freeBuffer(NULL, 82 reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), 83 tr.data_size, 84 reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), 85 tr.offsets_size/sizeof(binder_size_t), this); 86 continue; 87 } 88 } 89 goto finish; 90 91 default: 92 err = executeCommand(cmd); //核心调用,用于处理驱动返回cmd 93 if (err != NO_ERROR) goto finish; 94 break; 95 } 96 } 97 98finish: 99 if (err != NO_ERROR) { 100 if (acquireResult) *acquireResult = err; 101 if (reply) reply->setError(err); 102 mLastError = err; 103 } 104 105 return err; 106} 107......
waitForResponse的核心就是调用talkWithDriver,talkWithDriver真正和驱动程序打交道;waitForResponse还需要处理驱动返回值,根据Binder 驱动回传的cmd执行其他操作;
1------> IPCThreadState.cpp 2 3status_t IPCThreadState::talkWithDriver(bool doReceive) 4{ 5 if (mProcess->mDriverFD <= 0) { 6 return -EBADF; 7 } 8 binder_write_read bwr; 9 // Is the read buffer empty? 10 const bool needRead = mIn.dataPosition() >= mIn.dataSize(); 11 // We don't want to write anything if we are still reading 12 // from data left in the input buffer and the caller 13 // has requested to read the next data. 14 const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0; 15 bwr.write_size = outAvail; 16 bwr.write_buffer = (uintptr_t)mOut.data();//mOut数据在前面的writeTransactionData中初始化,bwr是用于和Binder驱动通信的结构体; 17 // This is what we'll read. 18 if (doReceive && needRead) { 19 bwr.read_size = mIn.dataCapacity(); 20 bwr.read_buffer = (uintptr_t)mIn.data(); 21 } else { 22 bwr.read_size = 0; 23 bwr.read_buffer = 0; 24 } 25 // Return immediately if there is nothing to do. 26 if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;//没有读写数据 27 28 bwr.write_consumed = 0; 29 bwr.read_consumed = 0; 30 status_t err; 31 do { 32 IF_LOG_COMMANDS() { 33 alog << "About to read/write, write size = " << mOut.dataSize() << endl; 34 } 35#if defined(HAVE_ANDROID_OS) 36 //if(getpid()==g_nTargetPid) 37 // ALOGE("Keiven-Chen IPCThreadState::talkWithDriver() now into ioctl"); 38 if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) //通过ioctl不停的读写操作,跟Binder Driver进行通信 39 err = NO_ERROR; 40 else 41 err = -errno; 42 //if(getpid()==g_nTargetPid) 43 // ALOGE("Keiven-Chenkai IPCThreadState::talkWithDriver() now out of ioctl"); 44#else 45 err = INVALID_OPERATION; 46#endif 47 if (mProcess->mDriverFD <= 0) { 48 err = -EBADF; 49 } 50 } while (err == -EINTR); 51 if (err >= NO_ERROR) { 52 if (bwr.write_consumed > 0) { 53 if (bwr.write_consumed < mOut.dataSize()) 54 mOut.remove(0, bwr.write_consumed); 55 else 56 mOut.setDataSize(0); 57 } 58 if (bwr.read_consumed > 0) { 59 mIn.setDataSize(bwr.read_consumed); 60 mIn.setDataPosition(0); 61 } 62 63 return NO_ERROR; 64 } 65 66 return err; 67}
binder_write_read结构体用来与Binder设备交换数据的结构, 通过ioctl与mDriverFD通信,是真正与Binder驱动进行数据读写交互的过程。
talkWithDriver的核心就是调用ioctl与mDriverFD通信,具体这个ioctl是如何实现的呢?ioctl其实是一个SysCall,这里记录一下ioctl的这个SysCall的调用流程;
1IPCThreadState.cpp 2ioctl(#include <sys/ioctl.h>) 3=====> 4ioctl.h(bionic/libc/include/sys/ioctl.h) 5__BEGIN_DECLS 6extern int ioctl(int, int, ...); 7__END_DECLS 8======> 9bionic/ioctl.cpp(/bionic/libc/bionic/ioctl.c) 10#include <stdarg.h> 11extern int __ioctl(int, int, void *); 12int ioctl(int fd, int request, ...) 13{ 14 va_list ap; 15 void * arg; 16 17 va_start(ap, request); 18 arg = va_arg(ap, void *); 19 va_end(ap); 20 return __ioctl(fd, request, arg); 21} 22======> 23/bionic/libc/arch-arm/syscalls/__ioctl.S 24#include <private/bionic_asm.h> 25ENTRY(__ioctl) 26 mov ip, r7 27 ldr r7, =__NR_ioctl //__NR_ioctl 是ioctl的系统调用号 28 swi #0 //软中断命令 29 mov r7, ip 30 cmn r0, #(MAX_ERRNO + 1) 31 bxls lr 32 neg r0, r0 33 b __set_errno_internal 34END(__ioctl)
__NR_ioctl 是在/kernel/include/uapi/asm-generic/unistd.h中定义的宏
1------> unistd.h 2/* fs/ioctl.c */ //说明sys_ioctl在这个文件中实现 3#define __NR_ioctl 29 4__SC_COMP(__NR_ioctl, sys_ioctl, compat_sys_ioctl) 5 6 7------> kernel/arch/arm/kernel/calls.S 8 CALL(sys_ni_syscall) /* was sys_lock */ 9 CALL(sys_ioctl) //调用sys_ioctl 10 11 12------> /kernel/include/linux/syscalls.h 13 14#define SYSCALL_DEFINE0(sname) \ 15 SYSCALL_METADATA(_##sname, 0); \ 16 asmlinkage long sys_##sname(void) 17 18#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__) 19#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__) 20#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__) 21#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__) 22#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__) 23#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__) 24 25#define SYSCALL_DEFINEx(x, sname, ...) \ 26 SYSCALL_METADATA(sname, x, __VA_ARGS__) \ 27 __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) 28 29#define __PROTECT(...) asmlinkage_protect(__VA_ARGS__) 30#define __SYSCALL_DEFINEx(x, name, ...) \ 31 asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ //我们的 sys_ioctl是从这里展开的 32 static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ 33 asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ 34 { \ 35 long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ 36 __MAP(x,__SC_TEST,__VA_ARGS__); \ 37 __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ 38 return ret; \ 39 } \ 40 SYSCALL_ALIAS(sys##name, SyS##name); \ 41 static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) 42 43asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, 44 unsigned long arg);
asmlinkage是gcc标签,代表函数读取的参数来自于栈中,而非寄存器。
由上述代码,知道我们的ioctl是通过SYSCALL_DEFINE3来定义的,到kernel/fs/ioctl.c中;
1------> ioctl.c 2 3SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) 4{ 5 int error; 6 struct fd f = fdget(fd);//我们在IPCThreadState.cpp中传递的mDriverFD,代表/dev/binder设备 7 8 if (!f.file) 9 return -EBADF; 10 error = security_file_ioctl(f.file, cmd, arg); 11 if (!error) 12 error = do_vfs_ioctl(f.file, fd, cmd, arg); 13 fdput(f); 14 return error; 15}
这里我们知道我们的ioctl将会怎么调用,这里ioctl的完整调用流程如下:
ioctl()→do_vfs_ioctl()→vfs_ioctl()→f_op->unlocked_ioctl()->binder_ioctl()
1------> /kernel/drivers/staging/android/binder.c 2static const struct file_operations binder_fops = { 3 .owner = THIS_MODULE, 4 .poll = binder_poll, 5 .unlocked_ioctl = binder_ioctl, 6 .compat_ioctl = binder_ioctl, 7 .mmap = binder_mmap, 8 .open = binder_open, 9 .flush = binder_flush, 10 .release = binder_release, 11}; 12 13static struct miscdevice binder_miscdev = { 14 .minor = MISC_DYNAMIC_MINOR, 15 .name = "binder",//注册binder设备为杂项设备/dev/binder 16 .fops = &binder_fops 17};
这里理清了IPCThreadState.cpp中的ioctl是如何调用到驱动binder.c的binder_ioctl;
Binder驱动层有无数大神讲过,比如老罗,袁神;为了文章的完整性,粗略提一下Binder内核驱动处理流程;上面讲到talkWithDriver方法中会传递BINDER_WRITE_READ cmd给内核,内核中会根据这个cmd来操作驱动;核心就是根据是否有数据和Binder驱动交互来调用binder_thread_write或者binder_thread_read方法;binder_thread_write方法中会调用binder_transaction方法处理cmd 为BC_TRANSACTION 和BC_REPLY;binder_transaction会根据根据处理结果返回BR_xxx,Server端waitForResponse会根据BR_xxx进行不同的处理;
1------>/kernel/drivers/staging/android/binder.c binder_ioctl 2 3 switch (cmd) { 4 case BINDER_WRITE_READ: { 5 struct binder_write_read bwr; 6 if (size != sizeof(struct binder_write_read)) { 7 ret = -EINVAL; 8 goto err; 9 } 10 if (copy_from_user(&bwr, ubuf, sizeof(bwr))) { 11 ret = -EFAULT; 12 goto err; 13 } 14 binder_debug(BINDER_DEBUG_READ_WRITE, 15 "%d:%d write %lld at %016llx, read %lld at %016llx\n", 16 proc->pid, thread->pid, 17 (u64)bwr.write_size, (u64)bwr.write_buffer, 18 (u64)bwr.read_size, (u64)bwr.read_buffer); 19 20 if (bwr.write_size > 0) { 21 ret = binder_thread_write(proc, thread, bwr.write_buffer, bwr.write_size, &bwr.write_consumed); 22 trace_binder_write_done(ret); 23 if (ret < 0) { 24 bwr.read_consumed = 0; 25 if (copy_to_user(ubuf, &bwr, sizeof(bwr))) 26 ret = -EFAULT; 27 goto err; 28 } 29 } 30 if (bwr.read_size > 0) { 31 ret = binder_thread_read(proc, thread, bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK); 32 trace_binder_read_done(ret); 33 if (!list_empty(&proc->todo)) 34 wake_up_interruptible(&proc->wait); 35 if (ret < 0) { 36 if (copy_to_user(ubuf, &bwr, sizeof(bwr))) 37 ret = -EFAULT; 38 goto err; 39 } 40 }
Client端将handle,cmd,data,code等数据封装到binder_transaction_data,再封装到binder_write_read结构体,调用ioctl和驱动交互,驱动调用binder_thread_write和binder_thread_read处理相关事务;IPCThreadState.cpp:BC_TRANSACTION ——> binder.c:binder_ioctl ——> IPCThreadState.cpp:BR_TRANSACTION
下图借鉴袁神:
1------> IPCThreadState.cpp waitForResponse ---> executeCommand 2switch (cmd) { 3 ...... 4 case BR_TRANSACTION: 5 ...... 6 if (tr.target.ptr) { 7 sp<BBinder> b((BBinder*)tr.cookie);//这里的BBinder 对象b,cookie域存放的是是Binder对象 8 ////核心核心 9 ALOGE("Keiven-Chen_IPCThread IPCThreadState::BR_TRANSACTIO tr.target.ptr=true , %d \n",tr.target.ptr); 10 error = b->transact(tr.code, buffer, &reply, tr.flags);//调用BBinder对象的transact方法; 11 12 } else { 13 ALOGE("Keiven-Chen_IPCThread IPCThreadState::BR_TRANSACTIO tr.target.ptr=false \n"); 14 error = the_context_object->transact(tr.code, buffer, &reply, tr.flags); 15 } 16}
BR_TRANSACTION是由Server端处理,所以这里已经切换到了Server进程;后续的流程都是在Server进程中处理;
Server进程调用BBinder的transact方法,BBinder的transact会调用onTransact方法,实现BBinder的地方是在JavaBBinder ,所以最终会调用JavaBBinder 的onTransact方法,JavaBBinder定义在android_util_Binder.cpp中;
1------> Binder.cpp class BBinder 2status_t BBinder::transact( 3 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 4{ 5 data.setDataPosition(0); 6 ALOGE("Keiven-Chen_IPCThread BBinder::transact \n"); 7 status_t err = NO_ERROR; 8 switch (code) { 9 case PING_TRANSACTION: 10 reply->writeInt32(pingBinder()); 11 break; 12 default: 13 err = onTransact(code, data, reply, flags);//这里onTransact被子类实现,调用子类的onTransact方法 14 break; 15 } 16 if (reply != NULL) { 17 reply->setDataPosition(0); 18 } 19 return err; 20} 21 22 23------> android_util_Binder.cpp 24class JavaBBinder : public BBinder 25 26virtual status_t onTransact( 27 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) 28 { 29 JNIEnv* env = javavm_to_jnienv(mVM); 30 IPCThreadState* thread_state = IPCThreadState::self(); 31 32 jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,//核心核心, 33 //调用Binder.java 的execTransact方法,从这个方法调用到Java 层Stub 的onTransact方法 34 code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags); 35 36 if (thread_state->getStrictModePolicy() != strict_policy_before) { 37 set_dalvik_blockguard_policy(env, strict_policy_before); 38 } 39 // Need to always call through the native implementation of 40 // SYSPROPS_TRANSACTION. 41 if (code == SYSPROPS_TRANSACTION) { 42 BBinder::onTransact(code, data, reply, flags); 43 } 44 }
看到这里其实我是有疑问的,为何一定是走JavaBBinder的onTransact方法,这需要从注册服务说起;
1------> ServiceManagerNative.java class ServiceManagerProxy 2public void addService(String name, IBinder service, boolean allowIsolated) 3 throws RemoteException { 4 Parcel data = Parcel.obtain(); 5 Parcel reply = Parcel.obtain(); 6 data.writeInterfaceToken(IServiceManager.descriptor);//每个服务在这里写入的descriptor都是固定的 7 //这里是Parcel写入,我在Parcel JNI的android_os_Parcel_writeInterfaceToken中调用android_util_Binder.cpp中的testString方法 8 data.writeString(name); 9 data.writeStrongBinder(service);//这里写入的service 10 data.writeInt(allowIsolated ? 1 : 0); 11 mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); 12 reply.recycle(); 13 data.recycle(); 14 } 15------> android_os_Parcel.cpp 16static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr, 17 jstring name) 18{ 19 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 20 if (parcel != NULL) { 21 // In the current implementation, the token is just the serialized interface name that 22 // the caller expects to be invoking 23 const jchar* str = env->GetStringCritical(name, 0); 24 if (str != NULL) { 25 testString(String16(str, env->GetStringLength(name)));//调用android_util_Binder.cpp中自己实现的方法, 26 //将name传递到android_util_Binder用于判断ibinderForJavaObject 内部调用过程 27 parcel->writeInterfaceToken(String16(str, env->GetStringLength(name))); 28 env->ReleaseStringCritical(name, str); 29 } 30 } 31} 32static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object) 33{ 34 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 35 if (parcel != NULL) { 36 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); 37 //ibinderForJavaObject方法在android_util_Binder.java中实现 38 if (err != NO_ERROR) { 39 signalExceptionForError(env, clazz, err); 40 } 41 } 42} 43------> android_util_Binder.cpp 44 45const char *namePower = NULL; 46void testString(const String16& str){//自己添加的方法,注册方法的时候调用writeInterfaceToken时调用,便于过滤Log 47 namePower = String8(str).string(); 48 ALOGE("kaikaikaichenchen %s \n", namePower); 49} 50 51sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) 52{ 53 if (obj == NULL) return NULL; 54 if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) { 55 JavaBBinderHolder* jbh = (JavaBBinderHolder*) 56 env->GetLongField(obj, gBinderOffsets.mObject); 57 if (strcmp(namePower, "android.os.IPowerManager") == 0) 58 { 59 ALOGE("kaikaikaiChen: Binder %p",jbh); 60 ALOGE("kaikaikaiChen: Binder hahahahaha");//Log 标记,便于跟踪,Log 如下面截图 61 ALOGE("kaikaikaiChen: Binder %p ", obj); 62 } 63 return jbh != NULL ? jbh->get(env, obj) : NULL;//调用JavaBBinderHolder的get方法, 64 //即创建JavaBBinder,这里确定注册IPowerManager时走的是这里 65 } 66 if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) { 67 if (strcmp(namePower, "android.os.IPowerManager") == 0) 68 ALOGE("kaikaikaiChen: BinderProxy %p ", obj);//根据Log来判断,这个返回的到底是什么值 69 return (IBinder*) 70 env->GetLongField(obj, gBinderProxyOffsets.mObject); 71 } 72 73 ALOGW("ibinderForJavaObject: %p is not a Binder object", obj); 74 return NULL; 75}

综上:所以这里会调用JavaBBinder的onTransact方法,JavaBBinder的onTransact会调用Binder.java 的execTransact,execTransact方法调用onTransact方法(onTransact方法被子类实现,这里会调用子类的onTransact方法),IPowerManger.Stub 继承自Binder,实现了onTransact方法,所以最终会调用IPowerManger.Stub的onTransact方法,Binder的完整调用流程如下图,下图借鉴与袁神与网络大神:

上面两张图诠释了Binder的主线;
经过上述一大堆铺垫,我们PowerManger.isScreenOn()调用流程将会走到IPowerManager.Stub的onTransact方法,onTransact根据code来执行不同方法,这里isScreenOn的code为TRANSACTION_isInteractive:
1------> IPowerManager.java class Stub 2 case TRANSACTION_isInteractive: { 3 data.enforceInterface(DESCRIPTOR); 4 boolean _result = this.isInteractive(); 5 reply.writeNoException(); 6 reply.writeInt(((_result) ? (1) : (0))); 7 return true; 8 } 9 10public boolean isInteractive() throws android.os.RemoteException;
PowerManagerService继承自IPowerManager.Stub, 即isInteractive方法在PowerManagerService.java中实现,这里会调用PowerManagerService.java的isInteractive;这里阐述了从Client端transact —>Binder驱动—>Server端onTransact的全过程,到此一个完整的Binder Call 就到此结束了;
智能硬件中很多有很多需要Native Service,推荐一篇Chloe_Zhang的Native Service
Native Service 实现步骤如下:
1.实现一个接口文件,IXXXService,继承IInterface
2.定义BnXXX,继承BnInterface<IXXXService>。实现一个XXXService,继承BnXXX,并实现onTransact()函数。
3.定义BpXXX,继承BpInterface<IXXXService>。


