Android中APP、AMS、WMS的Binder IPC

本文深入探讨了Android中启动Activity时APP、Activity Manager Service (AMS) 和 Window Manager Service (WMS) 之间的Binder IPC过程。从startActivity流程图开始,详细解析了APP如何获取AMS和WMS的Binder引用,以及APP如何通过WMS将窗口添加到系统,并确保IPC通信的正确执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

APP、AMS、WMS的IPC是一个极其值得深入研究的过程。下面通过非常常见的startActivity来解析APP、AMS、WMS进程之间的通信过程。

1.startActivity Binder IPC流程图

Screen_Shot_2016_03_28_at_5_49_21
ServiceManager,AMS,WMS,SurfaceFlinger都是android系统服务,在前面《从底层看android5.0启动过程》一文中已经解析过,不清楚的可先浏览该文章。在android系统启动完毕后,这些系统服务也随之开启了。

2.APP与AMS间的Binder IPC

2.1.APP启动Activity

当APP内部Activity.startActivity(),当启动一个Activity,APP需要和AMS通信,所以APP需要向ServiceManager查询AMS的Binder引用。下面分析关键源码体会该过程,Activity.startActivity()主线程经过辗转最终调用Instrumentation.execStartActivity(),其关键源码如下

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
            //获取AMS引用并调用AMS.startActiviy()
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }

2.2.APP获取AMS的Binder引用

APP主线程执行ActivityManagerNative.getDefault()获取的就是一个AMS的Binder引用,其关键源码如下

public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
   
   
//...
 private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            //向Se
<think>我们正在讨论BinderIPC机制及其使用方法。根据提供的引用材料,BinderAndroid系统中用于进程间通信(IPC)的一种高效机制。它采用面向对象的设计思想,通过一个定制的内核模块在进程间传递消息。Binder机制的核心思想是将IPC操作模型化为"线程迁移"。当客户端进程发起一个IPC调用时,Binder驱动会将该调用传递给服务端进程,服务端进程执行相应的操作,然后将结果返回给客户端进程。这个过程对开发者是透明的,开发者只需要像调用本地方法一样调用远程方法。在Binder通信模型中,有四个主要角色:1.**Binder驱动**:位于内核空间,负责消息传递和对象转换。2.**ServiceManager**:作为服务注册中心,用于注册和查找Binder服务。3.**服务端(Server)**:提供服务的进程,包含Binder本地对象。4.**客户端(Client)**:使用服务的进程,持有Binder代理对象。使用方法通常包括以下步骤:1.**服务注册**:服务端进程创建Binder本地对象,并通过Binder驱动将其注册到ServiceManager。2.**服务获取**:客户端进程向ServiceManager请求服务,获取Binder代理对象的引用。3.**远程调用**:客户端通过Binder代理对象调用方法,Binder驱动将请求转发给服务端的Binder本地对象执行,并将结果返回给客户端。在Android开发中,我们通常使用AIDL(AndroidInterfaceDefinitionLanguage)来定义跨进程通信的接口。AIDL编译器会自动生成Stub(服务端)和Proxy(客户端)类,简化了Binder使用。例如,定义一个AIDL接口:```aidl//IMyService.aidlinterfaceIMyService{intadd(inta,intb);}```编译器会生成一个包含Stub和Proxy的Java文件:-**Stub**:作为服务端的基类,我们需要继承它并实现具体逻辑。-**Proxy**:作为客户端的代理,它封装了跨进程调用的细节。服务端实现:```javapublicclassMyServiceextendsService{privatefinalIMyService.Stubbinder=newIMyService.Stub(){@Overridepublicintadd(inta,intb){returna+b;}};@OverridepublicIBinderonBind(Intentintent){returnbinder;}}```客户端绑定服务并调用:```java//绑定服务bindService(newIntent(this,MyService.class),serviceConnection,Context.BIND_AUTO_CREATE);//在ServiceConnection中获取代理对象privateServiceConnectionserviceConnection=newServiceConnection(){@OverridepublicvoidonServiceConnected(ComponentNamename,IBinderservice){IMyServicemyService=IMyService.Stub.asInterface(service);try{intresult=myService.add(1,2);//跨进程调用}catch(RemoteExceptione){e.printStackTrace();}}};```在这个例子中,客户端调用`add`方法时,实际上是通过Binder驱动将请求发送到服务端,服务端执行计算后,再将结果通过Binder驱动返回给客户端。Binder机制的优势包括:-**高效**:相比于传统的LinuxIPC(如管道、消息队列等),Binder只需要一次数据拷贝。-**安全**:支持进程间身份验证和权限控制。-**面向对象**:开发者可以用面向对象的方式进行跨进程调用。§§相关问题§§1.Binder驱动在内核中具体做了哪些工作?2.AIDL是如何生成Stub和Proxy类的?3.Binder通信中的一次数据拷贝是如何实现的?4.如何确保Binder通信的安全性?</think>### Binder IPC机制及使用方法 BinderAndroid系统的核心IPC机制,通过定制化的内核模块实现高效进程间通信。其核心思想是将IPC操作模型化为**线程迁移**:当线程A发起IPC调用时,Binder驱动将请求"迁移"到目标进程的线程B执行,再将结果返回,如同线程跨越了进程边界[^1][^3]。 #### 核心设计思想 1. **面向对象抽象** Binder通信的所有实体(客户端、服务端、驱动)都表现为`Binder对象`。客户端持有**Binder代理对象**,服务端持有**Binder本地对象**。用户无需区分本地/远程对象,操作接口完全一致[^2]。 2. **跨进程对象传递** Binder驱动自动完成对象转换:当Binder对象跨进程传递时,驱动会为目标进程生成对应的代理对象,并建立映射关系[^2]。 #### 通信模型四大角色 | 角色 | 功能 | 用户视角 | |------|------|----------| | **Binder驱动** | 内核模块,负责消息路由和对象转换 | 透明不可见 | | **ServiceManager** | 系统服务注册中心(类似DNS) | 通过`getSystemService`访问 | | **服务端(Server)** | 提供服务的进程,持有Binder本地对象 | 实现具体业务逻辑 | | **客户端(Client)** | 消费服务的进程,持有Binder代理对象 | 调用远程方法 | #### 使用方法(以AIDL为例) ##### 步骤1:定义AIDL接口 ```aidl // IMyService.aidl interface IMyService { int add(int a, int b); String getInfo(); } ``` ##### 步骤2:服务端实现 ```java public class MyService extends Service { private final IMyService.Stub binder = new IMyService.Stub() { @Override public int add(int a, int b) { return a + b; // 实际业务逻辑 } @Override public String getInfo() { return "Service Info"; } }; @Override public IBinder onBind(Intent intent) { return binder; // 返回Binder本地对象 } } ``` ##### 步骤3:客户端绑定与调用 ```java // 绑定服务 bindService(new Intent(this, MyService.class), new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 将IBinder转换为代理对象 IMyService myService = IMyService.Stub.asInterface(service); try { int sum = myService.add(5, 3); // 跨进程调用 String info = myService.getInfo(); } catch (RemoteException e) { e.printStackTrace(); } } }, Context.BIND_AUTO_CREATE); ``` #### 关键实现机制 1. **内存映射** Binder使用`mmap()`在内核开辟共享内存,**仅需一次数据拷贝**:发送方数据拷贝到内核缓冲区,接收方直接读取(传统IPC需2次拷贝)[^1]。 2. **线程池管理** 服务端默认使用`Binder线程池`(大小16)处理并发请求,避免线程频繁创建[^3]。 3. **对象引用计数** 驱动通过引用计数管理Binder对象的生命周期,防止内存泄漏[^2]。 4. **身份标识传递** 调用时自动携带PID/UID,服务端可通过`Binder.getCallingPid()`验证调用者身份[^4]。 #### 性能优化特性 - **零拷贝传输**:支持`ParcelFileDescriptor`传递文件描述符 - **同步/异步调用**:`oneway`关键字声明异步方法 - **死亡通知**:通过`linkToDeath()`监控服务端状态 - **事务队列**:驱动层实现请求排队,避免资源竞争 > 应用场景:Android系统服务(AMS/WMS等)、ContentProvider跨进程数据访问、多进程App组件通信[^3][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值