- 浏览: 44480 次
- 性别:
- 来自: 成都
文章分类
最新评论
o IBinder接口
IBinder接口是对跨进程的对象的抽象。普通对象在当前进程可以访问,如果希望对象能被其它进程访问,那就必须实现IBinder接口。IBinder接口可以指向本地对象,也可以指向远程对象,调用者不需要关心指向的对象是本地的还是远程。 transact是IBinder接口中一个比较重要的函数,它的函数原型如下: android中的IPC的基本模型是基于客户/服务器(C/S)架构的。 如果IBinder指向的是一个客户端代理,那transact只是把请求发送给服务器。服务端的IBinder的transact则提供了实际的服务。 o 客户端
BpBinder是远程对象在当前进程的代理,它实现了IBinder接口。它的transact函数实现如下: 参数说明: transact只是简单的调用了IPCThreadState::self()的transact,在IPCThreadState::transact中: 这里transact把请求经内核模块发送了给服务端,服务端处理完请求之后,沿原路返回结果给调用者。这里也可以看出请求是同步操作,它会等待直到结果返回为止。 在BpBinder之上进行简单包装,我们可以得到与服务对象相同的接口,调用者无需要关心调用的对象是远程的还是本地的。拿ServiceManager来说: BpServiceManager实现了
IServiceManager和IBinder两个接口,调用者可以把BpServiceManager的对象看作是一个
IServiceManager对象或者IBinder对象。当调用者把BpServiceManager对象当作IServiceManager对象使
用时,所有的请求只是对BpBinder::transact的封装。这样的封装使得调用者不需要关心IServiceManager对象是本地的还是远
程的了。 客户通过defaultServiceManager函数来创建BpServiceManager对象: 先通过ProcessState::self()->getContextObject(NULL)创建一个Binder对象,然后通过
interface_cast和IMPLEMENT_META_INTERFACE(ServiceManager,
“android.os.IServiceManager”)把Binder对象包装成
IServiceManager对象。原理上等同于创建了一个BpServiceManager对象。 ProcessState::self()->getContextObject调用ProcessState::getStrongProxyForHandle创建代理对象: 如果handle为空,默认为context_manager对象,context_manager实际上就是ServiceManager。 PING_TRANSACTION请求用来检查对象是否还存在,这里简单的把
pingBinder的返回值返回给调用者。其它的请求交给onTransact处理。onTransact是BBinder里声明的一个
protected类型的虚函数,这个要求它的子类去实现。比如CameraService里的实现如下: 由此可见,服务端的onTransact是一个请求分发函数,它根据请求码(code)做相应的处理。 o 消息循环
服务端(任何进程都可以作为服务端)有一个线程监听来自客户端的请求,并循环处理这些请求。 如果在主线程中处理请求,可以直接调用下面的函数: 如果想在非主线程中处理请求,可以按下列方式: startThreadPool的实现原理: 这里创建了PoolThread的对象,实现上就是创建了一个线程。所有的线程类都要实现threadLoop虚函数。PoolThread的threadLoop的实现如下: 上述代码,简而言之就是创建了一个线程,然后在线程里调用 IPCThreadState::self()->joinThreadPool函数。 下面再看joinThreadPool的实现: 这个函数在循环中重复执行下列动作: 在IPCThreadState::executeCommand(int32_t cmd)函数中: 按下列方式调用实际的对象: 如果tr.target.ptr不为空,就把tr.cookie转换成一个Binder对象,并调用它的transact函数。如果没有目标对象,
就调用
the_context_object对象的transact函数。奇怪的是,根本没有谁对the_context_object进行初始
化,the_context_object是空指针。原因是context_mgr的请求发给了ServiceManager,所以根本不会走到else
语句里来。 o 内核模块
android使用了一个内核模块binder来中转各个进程之间的消息。模块源代码放在binder.c里,它是一个字符驱动程序,主要通过
binder_ioctl与用户空间的进程交换数据。其中BINDER_WRITE_READ用来读写数据,数据包中有一个cmd域用于区分不同的请求: 从binder_thread_write中调用binder_transaction中转请求和返回结果,binder_transaction的实现如下: 对请求的处理:virtual status_t transact(
uint32_t code,
const
Parcel&
data,
Parcel*
reply,
uint32_t flags =
0
)
=
0
;
客户端
请求通过内核模块中转
服务端
status_t BpBinder::
transact
(
uint32_t code,
const
Parcel&
data,
Parcel*
reply,
uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if
(
mAlive)
{
status_t status =
IPCThreadState::
self
(
)
->
transact(
mHandle,
code,
data,
reply,
flags)
;
if
(
status ==
DEAD_OBJECT)
mAlive =
0
;
return
status;
}
return
DEAD_OBJECT;
}
status_t IPCThreadState::
transact
(
int32_t handle,
uint32_t code,
const
Parcel&
data,
Parcel*
reply,
uint32_t flags)
{
status_t err =
data.errorCheck
(
)
;
flags |=
TF_ACCEPT_FDS;
IF_LOG_TRANSACTIONS(
)
{
TextOutput::
Bundle
_b(
alog)
;
alog <<
"BC_TRANSACTION thr "
<<
(
void
*
)
pthread_self(
)
<<
" / hand "
<<
handle <<
" / code "
<<
TypeCode(
code)
<<
": "
<<
indent <<
data <<
dedent <<
endl;
}
if
(
err ==
NO_ERROR)
{
LOG_ONEWAY(
">>>> SEND from pid %d uid %d %s"
,
getpid(
)
,
getuid(
)
,
(
flags &
TF_ONE_WAY)
==
0
?
"READ REPLY"
:
"ONE WAY"
)
;
err =
writeTransactionData(
BC_TRANSACTION,
flags,
handle,
code,
data,
NULL)
;
}
if
(
err !=
NO_ERROR)
{
if
(
reply)
reply->
setError(
err)
;
return
(
mLastError =
err)
;
}
if
(
(
flags &
TF_ONE_WAY)
==
0
)
{
if
(
reply)
{
err =
waitForResponse(
reply)
;
}
else
{
Parcel fakeReply;
err =
waitForResponse(
&
fakeReply)
;
}
IF_LOG_TRANSACTIONS(
)
{
TextOutput::
Bundle
_b(
alog)
;
alog <<
"BR_REPLY thr "
<<
(
void
*
)
pthread_self(
)
<<
" / hand "
<<
handle <<
": "
;
if
(
reply)
alog <<
indent <<
*
reply <<
dedent <<
endl;
else
alog <<
"(none requested)"
<<
endl;
}
}
else
{
err =
waitForResponse(
NULL,
NULL)
;
}
return
err;
}
status_t IPCThreadState::
waitForResponse
(
Parcel *
reply,
status_t *
acquireResult)
{
int32_t cmd;
int32_t err;
while
(
1
)
{
if
(
(
err=
talkWithDriver(
)
)
<
NO_ERROR)
break
;
err =
mIn.errorCheck
(
)
;
if
(
err <
NO_ERROR)
break
;
if
(
mIn.dataAvail
(
)
==
0
)
continue
;
cmd =
mIn.readInt32
(
)
;
IF_LOG_COMMANDS(
)
{
alog <<
"Processing waitForResponse Command: "
<<
getReturnString(
cmd)
<<
endl;
}
switch
(
cmd)
{
case
BR_TRANSACTION_COMPLETE:
if
(
!
reply &&
!
acquireResult)
goto
finish;
break
;
case
BR_DEAD_REPLY:
err =
DEAD_OBJECT;
goto
finish;
case
BR_FAILED_REPLY:
err =
FAILED_TRANSACTION;
goto
finish;
case
BR_ACQUIRE_RESULT:
{
LOG_ASSERT(
acquireResult !=
NULL,
"Unexpected brACQUIRE_RESULT"
)
;
const
int32_t result =
mIn.readInt32
(
)
;
if
(
!
acquireResult)
continue
;
*
acquireResult =
result ?
NO_ERROR :
INVALID_OPERATION;
}
goto
finish;
case
BR_REPLY:
{
binder_transaction_data tr;
err =
mIn.read
(
&
tr,
sizeof
(
tr)
)
;
LOG_ASSERT(
err ==
NO_ERROR,
"Not enough command data for brREPLY"
)
;
if
(
err !=
NO_ERROR)
goto
finish;
if
(
reply)
{
if
(
(
tr.flags
&
TF_STATUS_CODE)
==
0
)
{
reply->
ipcSetDataReference(
reinterpret_cast(
tr.data
.ptr
.buffer
)
,
tr.data_size
,
reinterpret_cast(
tr.data
.ptr
.offsets
)
,
tr.offsets_size
/
sizeof
(
size_t)
,
freeBuffer,
this)
;
}
else
{
err =
*
static_cast(
tr.data
.ptr
.buffer
)
;
freeBuffer(
NULL,
reinterpret_cast(
tr.data
.ptr
.buffer
)
,
tr.data_size
,
reinterpret_cast(
tr.data
.ptr
.offsets
)
,
tr.offsets_size
/
sizeof
(
size_t)
,
this)
;
}
}
else
{
freeBuffer(
NULL,
reinterpret_cast(
tr.data
.ptr
.buffer
)
,
tr.data_size
,
reinterpret_cast(
tr.data
.ptr
.offsets
)
,
tr.offsets_size
/
sizeof
(
size_t)
,
this)
;
continue
;
}
}
goto
finish;
default
:
err =
executeCommand(
cmd)
;
if
(
err !=
NO_ERROR)
goto
finish;
break
;
}
}
finish:
if
(
err !=
NO_ERROR)
{
if
(
acquireResult)
*
acquireResult =
err;
if
(
reply)
reply->
setError(
err)
;
mLastError =
err;
}
return
err;
}
(frameworks/base/libs/utils/IServiceManager.cpp)class BpServiceManager :
public BpInterface
{
public:
BpServiceManager(
const
sp&
impl)
:
BpInterface(
impl)
{
}
...
virtual
status_t addService(
const
String16&
name,
const
sp&
service)
{
Parcel data,
reply;
data.writeInterfaceToken
(
IServiceManager::
getInterfaceDescriptor
(
)
)
;
data.writeString16
(
name)
;
data.writeStrongBinder
(
service)
;
status_t err =
remote(
)
->
transact(
ADD_SERVICE_TRANSACTION,
data,
&
reply)
;
return
err ==
NO_ERROR ?
reply.readInt32
(
)
:
err;
}
...
}
;
(frameworks/base/libs/utils/IServiceManager.cpp)sp<
IServiceManager>
defaultServiceManager(
)
{
if
(
gDefaultServiceManager !=
NULL)
return
gDefaultServiceManager;
{
AutoMutex _l(
gDefaultServiceManagerLock)
;
if
(
gDefaultServiceManager ==
NULL)
{
gDefaultServiceManager =
interface_cast<
IServiceManager>
(
ProcessState::
self
(
)
->
getContextObject(
NULL)
)
;
}
}
return
gDefaultServiceManager;
}
sp<
IBinder>
ProcessState::
getStrongProxyForHandle
(
int32_t handle)
{
sp<
IBinder>
result;
AutoMutex _l(
mLock)
;
handle_entry*
e =
lookupHandleLocked(
handle)
;
if
(
e !=
NULL)
{
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder*
b =
e->
binder;
if
(
b ==
NULL ||
!
e->
refs->
attemptIncWeak(
this)
)
{
b =
new BpBinder(
handle)
;
e->
binder =
b;
if
(
b)
e->
refs =
b->
getWeakRefs(
)
;
result =
b;
}
else
{
// This little bit of nastyness is to allow us to add a primary
// reference to the remote proxy when this team doesn't have one
// but another team is sending the handle to us.
result.force_set
(
b)
;
e->
refs->
decWeak(
this)
;
}
}
return
result;
}
o 服务端
服务端也要实现IBinder接口,BBinder类对IBinder接口提供了部分默认实现,其中transact的实现如下:status_t BBinder::
transact
(
uint32_t code,
const
Parcel&
data,
Parcel*
reply,
uint32_t flags)
{
data.setDataPosition
(
0
)
;
status_t err =
NO_ERROR;
switch
(
code)
{
case
PING_TRANSACTION:
reply->
writeInt32(
pingBinder(
)
)
;
break
;
default
:
err =
onTransact(
code,
data,
reply,
flags)
;
break
;
}
if
(
reply !=
NULL)
{
reply->
setDataPosition(
0
)
;
}
return
err;
}
status_t CameraService::
onTransact
(
uint32_t code,
const
Parcel&
data,
Parcel*
reply,
uint32_t flags)
{
// permission checks...
switch
(
code)
{
case
BnCameraService::
CONNECT
:
IPCThreadState*
ipc =
IPCThreadState::
self
(
)
;
const
int
pid =
ipc->
getCallingPid(
)
;
const
int
self_pid =
getpid(
)
;
if
(
pid !=
self_pid)
{
// we're called from a different process, do the real check
if
(
!
checkCallingPermission(
String16(
"android.permission.CAMERA"
)
)
)
{
const
int
uid =
ipc->
getCallingUid(
)
;
LOGE(
"Permission Denial: "
"can't use the camera pid=%d, uid=%d"
,
pid,
uid)
;
return
PERMISSION_DENIED;
}
}
break
;
}
status_t err =
BnCameraService::
onTransact
(
code,
data,
reply,
flags)
;
LOGD(
"+++ onTransact err %d code %d"
,
err,
code)
;
if
(
err ==
UNKNOWN_TRANSACTION ||
err ==
PERMISSION_DENIED)
{
// the 'service' command interrogates this binder for its name, and then supplies it
// even for the debugging commands. that means we need to check for it here, using
// ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to
// BnSurfaceComposer before falling through to this code).
LOGD(
"+++ onTransact code %d"
,
code)
;
CHECK_INTERFACE(
ICameraService,
data,
reply)
;
switch
(
code)
{
case
1000
:
{
if
(
gWeakHeap !=
0
)
{
sp h =
gWeakHeap.promote
(
)
;
IMemoryHeap *
p =
gWeakHeap.unsafe_get
(
)
;
LOGD(
"CHECKING WEAK REFERENCE %p (%p)"
,
h.get
(
)
,
p)
;
if
(
h !=
0
)
h->
printRefs(
)
;
bool attempt_to_delete =
data.readInt32
(
)
==
1
;
if
(
attempt_to_delete)
{
// NOT SAFE!
LOGD(
"DELETING WEAK REFERENCE %p (%p)"
,
h.get
(
)
,
p)
;
if
(
p)
delete p;
}
return
NO_ERROR;
}
}
break
;
default
:
break
;
}
}
return
err;
}
IPCThreadState::
self
(
)
->
joinThreadPool(
mIsMain)
;
sp
proc =
ProcessState::
self
(
)
;
if
(
proc->
supportsProcesses(
)
)
{
LOGV(
"App process: starting thread pool.\n
"
)
;
proc->
startThreadPool(
)
;
}
void
ProcessState::
startThreadPool
(
)
{
AutoMutex _l(
mLock)
;
if
(
!
mThreadPoolStarted)
{
mThreadPoolStarted =
true
;
spawnPooledThread(
true
)
;
}
}
void
ProcessState::
spawnPooledThread
(
bool isMain)
{
if
(
mThreadPoolStarted)
{
int32_t s =
android_atomic_add(
1
,
&
mThreadPoolSeq)
;
char
buf[
32
]
;
sprintf(
buf,
"Binder Thread #%d"
,
s)
;
LOGV(
"Spawning new pooled thread, name=%s\n
"
,
buf)
;
sp
t =
new PoolThread(
isMain)
;
t->
run(
buf)
;
}
}
virtual bool threadLoop(
)
{
IPCThreadState::
self
(
)
->
joinThreadPool(
mIsMain)
;
return
false
;
}
do
{
...
result
=
talkWithDriver(
)
;
if
(
result >=
NO_ERROR)
{
size_t IN =
mIn.dataAvail
(
)
;
if
(
IN <
sizeof
(
int32_t)
)
continue
;
cmd =
mIn.readInt32
(
)
;
IF_LOG_COMMANDS(
)
{
alog <<
"Processing top-level Command: "
<<
getReturnString(
cmd)
<<
endl;
}
result =
executeCommand(
cmd)
;
}
...
while
(
...)
;
if
(
tr.target
.ptr
)
{
sp<
BBinder>
b(
(
BBinder*
)
tr.cookie
)
;
const
status_t error =
b->
transact(
tr.code
,
buffer,
&
reply,
0
)
;
if
(
error <
NO_ERROR)
reply.setError
(
error)
;
}
else
{
const
status_t error =
the_context_object->
transact(
tr.code
,
buffer,
&
reply,
0
)
;
if
(
error <
NO_ERROR)
reply.setError
(
error)
;
}
发表评论
-
如何手动编译一个APK
2011-07-07 14:55 1925he good thing about building ma ... -
android上一些方法的区别和用法的注意事项
2011-07-07 10:03 2094Intent中的addflags()和se ... -
编译Android源码的全过程
2011-05-17 23:56 1023在网上看到一篇编译android源码的文章,照着做挺行的, ... -
ubuntu 10.04和10.10上下载编译环境配置android2.2-froyo
2011-05-17 23:11 2001ubuntu 10.04和10.10上下载编译环境配置andr ... -
android进程间通信:使用AIDL
2011-05-17 15:07 1332欢迎阅读本文,你能关注本文,你知道你需要进程间通信、需要AID ... -
android 设置线程的优先级
2011-05-17 15:03 3944有两处API可以设置线程的优先级: (1)an ... -
StatusBar (状态栏)的架构(Android 2.3)
2011-05-17 15:02 1138以前我的文章分析过 StatusBar上图标显示的流程, ... -
对Task和Activity在ANDROID中的解释
2011-03-25 10:39 1403android:allowTaskReparenting ... -
如何调用SQLITE工具查看数据库
2011-02-10 14:33 2591Find and connect to a database ... -
android 多线程
2010-12-11 17:47 995在Android下面也有多线程 ... -
android中activity的四种加载模式
2010-12-11 16:46 1184一、何为加载模式 在android的多activ ...
相关推荐
### Android IPC机制详解 #### 一、概述 Android IPC(Inter-Process Communication)是指在Android系统中不同进程间进行通信的机制。为了确保应用程序的安全性和稳定性,Android将每个应用运行在一个独立的进程中...
### Android IPC 及其...Android的IPC机制主要依赖于Binder,这是一种高效且易于使用的进程间通信方式。通过了解Binder的工作原理、实现步骤以及注意事项,开发者可以更好地利用这一机制构建出高效稳定的Android应用。
"Android IPC机制Messenger实例详解" Android IPC机制Messenger实例详解是Android操作系统中的一种进程间通信机制,通过Messenger对象可以在不同进程间传递Message对象,从而实现进程间的数据传递。Messenger使用...
Android的IPC机制是其架构设计中的一个重要组成部分,它不仅提高了应用的安全性和灵活性,还增强了系统的整体性能。通过深入理解IPC机制,开发者可以更加灵活地构建复杂的应用程序,实现高效稳定的通信。
在Android系统中,Binder机制是实现进程间通信(IPC)的核心工具,尤其在跨应用程序组件交互时至关重要。本文将深入探讨Android Binder机制及其在组件化思想中的应用。 1. Android组件化思想 Android应用的组件化...
Android Binder机制是Android系统的核心组件之一,它负责进程间通信(IPC,Inter-Process Communication),使得不同应用程序或者同一系统中的不同组件能够有效地交互。在Android系统中,由于每个应用程序运行在自己...
相比于传统的IPC机制,Binder在数据传输过程中仅涉及一次拷贝操作,这大大提高了通信效率。具体来说,数据直接从发送方的缓存区拷贝到接收方的缓存区,中间没有经过额外的缓冲区。 #### 五、Binder的安全性 ##### ...
Android AIDL(Android Interface Definition Language)是Android系统提供的一种接口定义语言,用于处理不同进程间的通信(IPC: Interprocess Communication)。在Android应用开发中,当需要在不同的应用程序组件...
### Android O RIL 架构详解 #### Treble 概述 随着移动设备市场的迅速扩张和技术的不断进步,Google 在 Android O 版本中引入了一项重大的软件架构改进——Treble(三重奏)。这一举措旨在降低原始设计制造商 (ODM...
Binder机制是Android独特的进程间通信(IPC)方式,它允许不同进程间的对象交互,确保了系统服务的高效运行。以下是对每个压缩包文件中可能包含的知识点的详细解释: 1. **Binder16.rar**:可能涵盖了Android ...
【Android 进程间通信-Binder 机制详解】 在Android系统中,进程间通信(IPC,Inter-Process Communication)是实现不同应用程序组件协同工作的关键。Binder机制是Android独有的IPC方式,它不同于传统的Unix/Linux...
Android 跨进程 IPC 通信 AIDL 机制原理 Android Interface Definition Language(AIDL)是一种用于生成 Android 不同进程间进行进程通信(IPC)的代码机制。AIDL IPC 机制是面向接口的,像 COM 或 Corba 一样,...
- **Binder IPC驱动**:Binder机制是Android中进程间通信的基础。 - **电源管理(Power Management)**:管理设备的电量,实现节能模式等功能。 #### 三、Android应用程序 Android应用程序是由多个组件组成的,每...
- **Binder**:基础的IPC机制。 - **ServiceManager**:管理所有服务的中心点。 - **Service**:具体的服务实例。 #### 七、Service深入分析 针对Service组件进行了更深层次的研究,探讨其生命周期、工作方式以及...
在Android系统中,进程间的通信(IPC,Inter-Process Communication)是实现组件间协同工作的重要机制。当一个应用需要与另一个应用的组件进行交互时,就需要用到IPC。AIDL(Android Interface Definition Language...
- **简介**:Binder是Android IPC(进程间通信)的核心机制,用于实现跨进程的数据交换和服务调用。 - **工作原理**:通过创建Binder对象并将其注册到ServiceManager中,其他进程可以通过查找该服务名来获取Binder...
Service不仅可以在同一进程中运行,还能跨越进程边界进行调用,这是通过Android提供的轻量级IPC机制实现的。当一个方法在本地进程调用,而实际执行却发生在另一个远程进程时,系统会自动将方法调用和相关参数序列化...