您的位置:首页 > 移动开发 > Android开发

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 read

here 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 general

abstracts 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) of

the 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 requests

and 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.c

The 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 implementation

and 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: