Android Native Binder
2016-04-15 07:49
453 查看
Android binder(S)
A key part of Android is the Binder mechanism.A bit of history/background
The Android binder mechanism was originally based on the OpenBinder project. As you can readhere Dianne Hackborn open sourced a project called
OpenBinder when she left PalmSource. If you read the OpenBinder documentation that can be found
here you will find
similarities with how binder works in Android. The current binder in Android is incompatible
with the original binder implementation still key information can be found at
Binder
IPC mechanism .
The documentation on this page is an atempt at documenting how binder really works on Android
Warning
This page has not been reviewed and probably does contains many errors.The kernel view
Binder is a linux-kernel module that can send messages between userland processes(using IOCTL’s)A program using binder can send serialized messages. This serialized message can contain basic types but also include
local pointers. Pointers are accompanied with meta-data about it being a pointers.
A program using binder can read serialized messages.
It is possible to request a more permanent “handle” object by acquiring this from binder (ref counting).
The binder kernel module is able to translate local object pointers with handles and can keep track of those handles
There is no real client or server at this stage the process calling is waiting in a
IOCLT for results and the process
being called will wake-up from the IOCTL it was calling and it can also happen that a process will call itself.
(
TODO is this really true? How about threading are message queued?) (TODO the kernel module does contain threading information like
MAX THREAD) how does this work?
Most programs do not directly use this operational mode but one of them talking at this level is the service manager.
frameworks/base/cmds/servicemanager/binder.c and frameworks/base/cmds/servicemanager/service_manager.c show the real
guts of the binder framework (including requesting a reference to a binder object)
The kernel drivers
The kernel module accepts module options allowing it to be more verbose
the module parameter is called debug_mask and in an unsigned int. It’s value can be determined
by looking the binder source code: drivers/staging/android/binder.c
enum { BINDER_DEBUG_USER_ERROR = 1U << 0, BINDER_DEBUG_FAILED_TRANSACTION = 1U << 1, BINDER_DEBUG_DEAD_TRANSACTION = 1U << 2, BINDER_DEBUG_OPEN_CLOSE = 1U << 3, BINDER_DEBUG_DEAD_BINDER = 1U << 4, BINDER_DEBUG_DEATH_NOTIFICATION = 1U << 5, BINDER_DEBUG_READ_WRITE = 1U << 6, BINDER_DEBUG_USER_REFS = 1U << 7, BINDER_DEBUG_THREADS = 1U << 8, BINDER_DEBUG_TRANSACTION = 1U << 9, BINDER_DEBUG_TRANSACTION_COMPLETE = 1U << 10, BINDER_DEBUG_FREE_BUFFER = 1U << 11, BINDER_DEBUG_INTERNAL_REFS = 1U << 12, BINDER_DEBUG_BUFFER_ALLOC = 1U << 13, BINDER_DEBUG_PRIORITY_CAP = 1U << 14, BINDER_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 15, };
contains proc debugging entries :
state
stats
transactions
transaction_log
failed_transaction_log
Sample “low level” scenario
The Service opens the binder kernel module ( file open “/dev/binder” )It registers a thread pool for callbacks (ioctl bcSET_THREAD_ENTRY , *createNewThread, void * data)) (This is no
longer true for binder in android is it?)
The service performs a transaction using a special “known” remote reference “0” (handle) to the IServiceManager to map
itself with a name
The client opens the binder kernel module ( file open “/dev/binder” )
It is requests a handle to the service by calling a method from the the IServiceManager
It is creates a transaction to the Service to call the service (ioctl BINDER_WRITE_READ)
It response to the transaction
The
CPP view
The cpp layer of binder eases development of binder code. It makes use of smart pointers and threading and in generalabstracts many of the details of obtaining handles to object.
Overview of the critical classes
There are a few critical classes the IInterface,IBinder,BBinder,BnInterface and BpInterface. The first letter(s) ofthe class tell something about them. I as in Interface , B as in Base class, Bn as in Base native and Bp as in Base
proxy.
I = Interface defines an object that will be accessible over binderB = Base implementationBn = Base native (local object implementation)Bp = Base proxy
The IInterface class defines an object that can represent itself as a binder object. in a pure native implementation
there will be two implementation of this interface. One Proxy implementation that will represent the client end and one
native implementation that will convert binder calls to method calls on the “server”.
class IInterface extends RefBase
+ asBinder()
+ onAsBinder();
The IBinder class (frameworks/base/include/binder/IBinder.h) defines a class that is intended to be use to implement
binder services it declares the transac method to perform the binder transactions
and the attach/detach object to implement reference counting (of bound objects?) in userland.
class IBinder extends RefBase
+ transac(core , parcel in , parcel out, flags)
+ attachObject (id,object)
+ detachObject (id )
The BBinder class is the standard implementation of IBinder for a IInterface object using binder as communication
mechanism (IBinder and IInterface objects don’t actually need to use binder)
class BBinder implements IBinder
+ getInterfaceDescriptor() // string representing the name of the service interface
The remaining binder related classes in the framework are BnInterface and and BpInterface
The BnInterface is used to implement the native end of an IInterface
class BnInterface extends BBinder
+ queryLocalInterface(descriptor)
the BpInterface is used to implement Proxy classes
class BpInterface extends BpRefBase
+ onAsBinder();
+ remote() IBinder (declared in BpRefBase)
If you want more information on how to implement native binder services you are encouraged to read the code of
Android-HelloWorldService
binder threading
The basic programming model followed when developing a binder service is to spawn threads for incoming requestsand perform outgoing request directly.
Specifically, each process has a pool of “binder threads” which sit there waiting for incoming IPCs from other process.
When an IPC is dispatched to your process, one of these threads comes out of the pool to process it.
Backtrace on idling
__ioctl () at bionic/libc/arch-arm/syscalls/__ioctl.S:15 15 ldmfd sp!, {r4, r7} (gdb) bt #0 __ioctl () at bionic/libc/arch-arm/syscalls/__ioctl.S:15 #1 0xafd26a6c in ioctl (fd=<value optimized out>, request=16) at bionic/libc/bionic/ioctl.c:41 #2 0xa8215fa4 in android::IPCThreadState::talkWithDriver (this=0xa470, doReceive=true) at frameworks/base/libs/binder/IPCThreadState.cpp:791 #3 0xa8216980 in android::IPCThreadState::joinThreadPool (this=0xa470, isMain=true) at frameworks/base/libs/binder/IPCThreadState.cpp:446 #4 0x0000869e in main (argc=<value optimized out>, argv=<value optimized out>) at mycomp/Android-HelloWorldService/helloworld/main_helloworldservice.cpp:27
Backtrace on a incomming request
#0 android::HelloWorldService::hellothere (this=0xa760, str=0xac20 "fun") at mycomp/Android-HelloWorldService/libhelloworldservice/src/helloworldservice.cpp:3 #1 0x80003654 in android::HelloWorldService::onTransact (this=0xa760, code=<value optimized out>, data=<value optimized out>, reply=0xbe9e5ae8, flags=17) at m #2 0xa821359e in android::BBinder::transact (this=0xa764, code=1, data=..., reply=0xbe9e5ae8, flags=17) at frameworks/base/libs/binder/Binder.cpp:107 #3 0xa82167bc in android::IPCThreadState::executeCommand (this=0xa470, cmd=<value optimized out>) at frameworks/base/libs/binder/IPCThreadState.cpp:1012 #4 0xa821699e in android::IPCThreadState::joinThreadPool (this=0xa470, isMain=true) at frameworks/base/libs/binder/IPCThreadState.cpp:457 #5 0x0000869e in main (argc=<value optimized out>, argv=<value optimized out>) at mycomp/Android-HelloWorldService/helloworld/main_helloworldservice.cpp:27
The service manager service.
frameworks/base/cmds/servicemanager/service_manager.cThe Java layer on top
An Overview of the Java binder implementation
Android Service , Activities and Intent
Android Services Activities and Intent follow many of the principles found in the Native binder implementationand they can make use of the available remoting facilities. It in important however to understand that there are big
differences.
First of all Service and Activities do not register themself to the IServiceManager the Only component that is actually
registered to the IServicemManager is the ActivityManager himelf. This Activity manager enhances the lower binder
implementation by providing process lifecycle.
IActivityManager → publishService usefull as counter part of bindService?
ActivityThread.java → really calles the onBind of a service
more stuff I found
-
Quoting the essential stuff ( from the open binder documentation)The Binder communicates between processes using a small custom kernel module. This is used instead of
standard Linux IPC facilities so that we can efficiently model our
IPC operations as “thread migration”.
That is, an IPC between processes looks as if the thread instigating the
IPC has hopped over to the destination process
to execute the code there, and then hopped back with the result.
The Binder IPC mechanism itself, however, is not actually implemented using thread migration. Instead, the Binder’s
user-space code maintains a pool of available threads in each process, which are used to process incoming IPCs and
execute local events in that process. The kernel module emulates a thread migration model by propagating thread
priorities across processes as IPCs are dispatched and ensuring that, if an
IPC recurses back into an originating
process, the IPC is handled by its originating thread.
In addition to IPC itself, the Binder’s kernel module is also responsible for tracking object references across
processes. This involves mapping from remote object references in one process to the real object in its host process,
and making sure that objects are not destroyed as long as other processes hold references on them.
Also read
Android services in the android framework group and
threading in the android-developers group.
Hackborn about connecting to a binder c++ service
- An IBinder object represents a unique handle, which will be
maintained across IPCs. That is, if you have an IBinder that you send
from process A to process B, and at any point process B sends that
object back to process A, then process A will receive the exact same
IBinder object it originally sent. This is another part of
maintaining consistency with a local call, and can be very useful for
implementing things like tokens that are sent around, since there is
no way for a process to spoof them (and you can use
IBinder.linkToDeath() to be informed when the process hosting a token
as gone away).
HOWEVER, IInterface objects are not currently a unique identity —basically IMyInterface.asInterface() will always return a new instanceof the interface (proxy) every time you call it. So when comparingobjects, always be sure to call
IInterface.asBinder() and compare theunderlying IBinder objects.
原文地址: https://github.com/keesj/gomo/wiki/AndroidNativeBinder
相关文章推荐
- Android Debuggerd 简要介绍和源码分析
- Android类动态加载技术
- Android MediaRecorder系统结构
- Android: 使用JitPack发布你的Github开源库
- Android Studio 2.0 download
- Android应用程序的组成部分
- android国际化
- Android开发中,有哪些让你觉得相见恨晚的方法、类或接口
- Android开发笔记之《JNI常用知识汇总》
- 关于android studio中装插件genymotion时遇到的一些问题
- Android 开发中的新技术
- 初步理解MVC与MVP
- android layout_weight 使用总结
- ORB_SLAM2在Android上的移植过程
- Android 版本
- 一个Demo学会用Android兼容包新控件
- Android遍历Cursor所有数据的正确姿势
- LruCache详解之 Android 内存优化
- Android中Service类onStartCommand
- Android AlarmManager.set()方法参数相关