[TOC]
# 概要
![](https://img.kancloud.cn/8e/2b/8e2bbf0ac592f8f25eeb5d4ec3d13be4_1288x502.png)
## AIDL
### 使用方法
服务端:1.创建接口,2.定义binder,实现接口,3.创建服务,返回binder;
客户端:1.绑定服务,2.实现ServiceConnection绑定监听,3.在绑定成功的回调中,将IBinder转换成AIDL的接口代理对象。
客户端和服务端绑定成功后,就可以通过AIDL的接口代理对象,就像直接调用本地方法一样,调用服务端的方法了。需要注意的是,AIDL间传递的对象要实现Parcelable接口。
### 绑定过程
客户端先调用bindService方法,发起绑定服务的请求,通过ServiceManager,拿到ActivityManagerService,也就是AMS,然后通过AMS向服务端发起bindService的请求。然后服务端接收到绑定请求,以Handler消息机制的方式,发送一个绑定服务的Message,然后在ActivityThread中处理这个绑定请求,调用onBind函数,并返回对应的IBinder对象。这个返回IBinder对象的操作,基本就和绑定过程的通过ServiceManager、AMS类似了。
### AIDL和Binder的关系
AIDL的使用实质就是对Binder机制的封装,主要就是将Binder封装成一个代理对象proxy,从用户的角度看,就像是客户端直接调用了服务端的代码。
## oneway
### 主要有两个特性:
oneway 主要有两个特性:异步调用和串行化处理。异步调用是指应用向 binder 驱动发送数据后不需要挂起线程等待 binder 驱动的回复,而是直接结束。像一些系统服务调用应用进程的时候就会使用 oneway,比如 AMS 调用应用进程启动 Activity,这样就算应用进程中做了耗时的任务,也不会阻塞系统服务的运行。
### binder 协议
非oneway
![](https://img.kancloud.cn/49/1a/491a646523ad76742f0c54cfa6599992_1200x830.png)
如果是 oneway 的话,客户端就不需要挂起线程等待:
![](https://img.kancloud.cn/bd/ee/bdee05a63e30486474fe6ee0151427f4_1200x560.png)
涉及到的 binder 命令也有规律,由外部发送给 binder 驱动的都是 BC\_ 开头,由 binder 驱动发往外部的都是 BR\_开头。
### 怎么理解客户端线程挂起等待呢?有没有实际占用 CPU 的调度?
这里的挂起相当于 Thread 的 sleep,是真正的"休眠",底层调用的是 waiteventinterruptible() Linux 系统函数。
### waiteventinterruptible函数
Handle 中最关键的地方就是 Looper 的阻塞与唤醒,阻塞是调用了 nativePollOnce() 方法,当时对它的底层实现感兴趣,就去了解了一下,也学习到 Linux 用来实现阻塞/唤醒的 select、poll 和 epoll 机制
## Intent 直接传 Bitmap
Bitmap 太大会抛 TransactionTooLargeException 异常,原因是:底层判断只要 Binder Transaction 失败,且 Intent 的数据大于 200k 就会抛这个异常了。(见:android\_util\_Binder.cpp 文件 signalExceptionForError 方法)
### Intent 传值会有大小限制。
应用进程在启动 Binder 机制时会映射一块 1M 大小的内存,所有正在进行的 Binder 事务共享这 1M 的缓冲区 。当使用 Intent 进行 IPC 时申请的缓存超过 1M - 其他事务占用的内存时,就会申请失败抛 TransactionTooLargeException 异常了
### 绕开这个限制呢?
通过 AIDL 使用 Binder 进行 IPC 就不受这个限制,具体代码如下:
```
Bundle bundle = new Bundle();
bundle.putBinder("binder", new IRemoteGetBitmap.Stub() {
@Override public Bitmap getBitMap() throws RemoteException { return mBitmap; } }); intent.putExtras(bundle);
```
### 总结
较大的 bitmap 直接通过 Intent 传递容易抛异常是因为 Intent 启动组件时,系统禁掉了文件描述符 fd 机制 , bitmap 无法利用共享内存,只能拷贝到 Binder 映射的缓冲区,导致缓冲区超限, 触发异常; 而通过 putBinder 的方式,避免了 Intent 禁用描述符的影响,bitmap 写 parcel 时的 allowFds 默认是 true , 可以利用共享内存,所以能高效传输图片。
# 参考资料
[Android 深入浅出AIDL(二)](https://blog.csdn.net/qian520ao/article/details/78074983)
[看你简历上写熟悉 AIDL,说一说 oneway 吧](https://juejin.cn/post/6844904147947356173)
[Android Binder 原理分析](https://juejin.cn/post/6874616109266370568)
[跨进程传递大图,你能想到哪些方案呢?](https://juejin.cn/post/6844904182126739470)
- Android
- 四大组件
- Activity
- Fragment
- Service
- 序列化
- Handler
- Hander介绍
- MessageQueue详细
- 启动流程
- 系统启动流程
- 应用启动流程
- Activity启动流程
- View
- view绘制
- view事件传递
- choreographer
- LayoutInflater
- UI渲染概念
- Binder
- Binder原理
- Binder最大数据
- Binder小结
- Android组件
- ListView原理
- RecyclerView原理
- SharePreferences
- AsyncTask
- Sqlite
- SQLCipher加密
- 迁移与修复
- Sqlite内核
- Sqlite优化v2
- sqlite索引
- sqlite之wal
- sqlite之锁机制
- 网络
- 基础
- TCP
- HTTP
- HTTP1.1
- HTTP2.0
- HTTPS
- HTTP3.0
- HTTP进化图
- HTTP小结
- 实践
- 网络优化
- Json
- ProtoBuffer
- 断点续传
- 性能
- 卡顿
- 卡顿监控
- ANR
- ANR监控
- 内存
- 内存问题与优化
- 图片内存优化
- 线下内存监控
- 线上内存监控
- 启动优化
- 死锁监控
- 崩溃监控
- 包体积优化
- UI渲染优化
- UI常规优化
- I/O监控
- 电量监控
- 第三方框架
- 网络框架
- Volley
- Okhttp
- 网络框架n问
- OkHttp原理N问
- 设计模式
- EventBus
- Rxjava
- 图片
- ImageWoker
- Gilde的优化
- APT
- 依赖注入
- APT
- ARouter
- ButterKnife
- MMKV
- Jetpack
- 协程
- MVI
- Startup
- DataBinder
- 黑科技
- hook
- 运行期Java-hook技术
- 编译期hook
- ASM
- Transform增量编译
- 运行期Native-hook技术
- 热修复
- 插件化
- AAB
- Shadow
- 虚拟机
- 其他
- UI自动化
- JavaParser
- Android Line
- 编译
- 疑难杂症
- Android11滑动异常
- 方案
- 工业化
- 模块化
- 隐私合规
- 动态化
- 项目管理
- 业务启动优化
- 业务架构设计
- 性能优化case
- 性能优化-排查思路
- 性能优化-现有方案
- 登录
- 搜索
- C++
- NDK入门
- 跨平台
- H5
- Flutter
- Flutter 性能优化
- 数据跨平台