01-18-05 Binder代理与Stub设计

Binder代理模式

Binder是Android跨进程通信(IPC)的核心机制,使用代理模式实现。

设计模式

Client(客户端)
   ↓ 调用
Proxy(代理)
   ↓ Binder IPC
Stub(桩)
   ↓ 调用
Service(服务端)

Binder核心类

IBinder接口

// IBinder.java
public interface IBinder {
    /**
     * 跨进程调用
     */
    boolean transact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException;

    /**
     * 查询本地接口
     */
    IInterface queryLocalInterface(String descriptor);

    /**
     * 判断Binder是否存活
     */
    boolean isBinderAlive();

    /**
     * 注册死亡通知
     */
    void linkToDeath(DeathRecipient recipient, int flags);

    /**
     * 取消死亡通知
     */
    boolean unlinkToDeath(DeathRecipient recipient, int flags);
}

IInterface接口

// IInterface.java
public interface IInterface {
    /**
     * 获取底层Binder对象
     */
    IBinder asBinder();
}

Binder类

// Binder.java
public class Binder implements IBinder {

    /**
     * 本地Binder调用
     */
    @Override
    public final boolean transact(int code, Parcel data, Parcel reply, int flags) {
        // 调用onTransact处理
        boolean res = onTransact(code, data, reply, flags);
        return res;
    }

    /**
     * 子类重写此方法处理请求
     */
    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        // 默认实现
        return false;
    }

    /**
     * 查询本地接口
     */
    @Override
    public IInterface queryLocalInterface(String descriptor) {
        if (mDescriptor != null && mDescriptor.equals(descriptor)) {
            return mOwner;
        }
        return null;
    }
}

AIDL生成的代码分析

AIDL定义

// IBookManager.aidl
package com.example.bookstore;

import com.example.bookstore.Book;

interface IBookManager {
    List<Book> getBookList();
    void addBook(in Book book);
    Book getBookById(int bookId);
}

生成的接口

// IBookManager.java
public interface IBookManager extends android.os.IInterface {

    // 获取书籍列表
    public java.util.List<com.example.bookstore.Book> getBookList()
        throws android.os.RemoteException;

    // 添加书籍
    public void addBook(com.example.bookstore.Book book)
        throws android.os.RemoteException;

    // 根据ID查询
    public com.example.bookstore.Book getBookById(int bookId)
        throws android.os.RemoteException;

    // Stub类定义
    public static abstract class Stub extends android.os.Binder
            implements com.example.bookstore.IBookManager {
        // ...
    }
}

Stub类实现

// IBookManager.Stub
public static abstract class Stub extends android.os.Binder
        implements com.example.bookstore.IBookManager {

    // 接口描述符
    private static final java.lang.String DESCRIPTOR =
        "com.example.bookstore.IBookManager";

    // 方法ID常量
    static final int TRANSACTION_getBookList =
        (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_addBook =
        (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    static final int TRANSACTION_getBookById =
        (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);

    /**
     * 构造函数:注册接口
     */
    public Stub() {
        this.attachInterface(this, DESCRIPTOR);
    }

    /**
     * 将IBinder转换为接口
     */
    public static com.example.bookstore.IBookManager asInterface(
            android.os.IBinder obj) {
        if (obj == null) {
            return null;
        }

        // 查询本地接口
        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
        if (iin != null && iin instanceof com.example.bookstore.IBookManager) {
            // 同进程:直接返回本地对象
            return (com.example.bookstore.IBookManager) iin;
        }

        // 跨进程:返回代理对象
        return new com.example.bookstore.IBookManager.Stub.Proxy(obj);
    }

    @Override
    public android.os.IBinder asBinder() {
        return this;
    }

    /**
     * 处理客户端请求
     */
    @Override
    public boolean onTransact(int code, android.os.Parcel data,
            android.os.Parcel reply, int flags) throws android.os.RemoteException {

        switch (code) {
            case INTERFACE_TRANSACTION: {
                reply.writeString(DESCRIPTOR);
                return true;
            }

            case TRANSACTION_getBookList: {
                // 1. 验证接口
                data.enforceInterface(DESCRIPTOR);

                // 2. 调用实现类的方法
                java.util.List<com.example.bookstore.Book> _result =
                    this.getBookList();

                // 3. 写入返回值
                reply.writeNoException();
                reply.writeTypedList(_result);
                return true;
            }

            case TRANSACTION_addBook: {
                // 1. 验证接口
                data.enforceInterface(DESCRIPTOR);

                // 2. 读取参数
                com.example.bookstore.Book _arg0;
                if ((data.readInt() != 0)) {
                    _arg0 = com.example.bookstore.Book.CREATOR
                        .createFromParcel(data);
                } else {
                    _arg0 = null;
                }

                // 3. 调用实现类的方法
                this.addBook(_arg0);

                // 4. 写入返回值
                reply.writeNoException();
                return true;
            }

            case TRANSACTION_getBookById: {
                // 1. 验证接口
                data.enforceInterface(DESCRIPTOR);

                // 2. 读取参数
                int _arg0 = data.readInt();

                // 3. 调用实现类的方法
                com.example.bookstore.Book _result = this.getBookById(_arg0);

                // 4. 写入返回值
                reply.writeNoException();
                if ((_result != null)) {
                    reply.writeInt(1);
                    _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                } else {
                    reply.writeInt(0);
                }
                return true;
            }
        }

        return super.onTransact(code, data, reply, flags);
    }
}

Proxy类实现

// IBookManager.Stub.Proxy
private static class Proxy implements com.example.bookstore.IBookManager {

    // Binder对象
    private android.os.IBinder mRemote;

    Proxy(android.os.IBinder remote) {
        mRemote = remote;
    }

    @Override
    public android.os.IBinder asBinder() {
        return mRemote;
    }

    public java.lang.String getInterfaceDescriptor() {
        return DESCRIPTOR;
    }

    /**
     * 获取书籍列表
     */
    @Override
    public java.util.List<com.example.bookstore.Book> getBookList()
            throws android.os.RemoteException {

        // 1. 创建数据包
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        java.util.List<com.example.bookstore.Book> _result;

        try {
            // 2. 写入接口描述符
            _data.writeInterfaceToken(DESCRIPTOR);

            // 3. 发起跨进程调用
            mRemote.transact(Stub.TRANSACTION_getBookList, _data, _reply, 0);

            // 4. 读取返回值
            _reply.readException();
            _result = _reply.createTypedArrayList(
                com.example.bookstore.Book.CREATOR);
        } finally {
            // 5. 回收数据包
            _reply.recycle();
            _data.recycle();
        }

        return _result;
    }

    /**
     * 添加书籍
     */
    @Override
    public void addBook(com.example.bookstore.Book book)
            throws android.os.RemoteException {

        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();

        try {
            // 1. 写入接口描述符
            _data.writeInterfaceToken(DESCRIPTOR);

            // 2. 写入参数
            if ((book != null)) {
                _data.writeInt(1);
                book.writeToParcel(_data, 0);
            } else {
                _data.writeInt(0);
            }

            // 3. 发起跨进程调用
            mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);

            // 4. 读取返回值
            _reply.readException();
        } finally {
            _reply.recycle();
            _data.recycle();
        }
    }

    /**
     * 根据ID查询
     */
    @Override
    public com.example.bookstore.Book getBookById(int bookId)
            throws android.os.RemoteException {

        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        com.example.bookstore.Book _result;

        try {
            _data.writeInterfaceToken(DESCRIPTOR);
            _data.writeInt(bookId);

            mRemote.transact(Stub.TRANSACTION_getBookById, _data, _reply, 0);

            _reply.readException();
            if ((0 != _reply.readInt())) {
                _result = com.example.bookstore.Book.CREATOR
                    .createFromParcel(_reply);
            } else {
                _result = null;
            }
        } finally {
            _reply.recycle();
            _data.recycle();
        }

        return _result;
    }
}

Binder通信流程

完整调用流程

Client进程                  Binder驱动              Server进程
   │                          │                       │
   │ 1. 调用Proxy.getBookList()│                       │
   ├─────────────────────────>│                       │
   │                          │                       │
   │ 2. Parcel序列化参数       │                       │
   │    _data.writeInt(...)   │                       │
   │                          │                       │
   │ 3. transact()发起IPC     │                       │
   ├─────────────────────────>│                       │
   │                          │ 4. 传递请求            │
   │                          ├──────────────────────>│
   │                          │                       │
   │                          │ 5. onTransact()处理   │
   │                          │    读取参数            │
   │                          │    调用实现方法        │
   │                          │                       │
   │                          │ 6. 返回结果            │
   │                          │<──────────────────────┤
   │ 7. 读取返回值             │                       │
   │<─────────────────────────┤                       │
   │    _reply.readList()     │                       │
   │                          │                       │
   │ 8. 返回给调用者           │                       │

同进程优化

// Stub.asInterface()
public static IBookManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }

    // 查询本地接口
    IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (iin != null && iin instanceof IBookManager) {
        // 同进程:直接返回,无需IPC
        return (IBookManager) iin;
    }

    // 跨进程:返回代理对象
    return new Stub.Proxy(obj);
}

效果

  • 同进程:直接方法调用,无序列化开销
  • 跨进程:Binder IPC,需要序列化

Binder死亡通知

DeathRecipient

class BookManagerClient(context: Context) {

    private var bookManager: IBookManager? = null
    private var isBound = false

    // 死亡通知监听器
    private val deathRecipient = IBinder.DeathRecipient {
        Log.e(TAG, "BookManager服务已死亡")

        // 清理资源
        bookManager = null
        isBound = false

        // 尝试重新连接
        reconnect()
    }

    private val connection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            bookManager = IBookManager.Stub.asInterface(service)
            isBound = true

            // 注册死亡通知
            try {
                service?.linkToDeath(deathRecipient, 0)
            } catch (e: RemoteException) {
                e.printStackTrace()
            }
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            Log.w(TAG, "Service disconnected")
            bookManager = null
            isBound = false
        }
    }

    fun connect() {
        val intent = Intent().apply {
            component = ComponentName(
                "com.example.bookstore",
                "com.example.bookstore.BookManagerService"
            )
        }
        context.bindService(intent, connection, Context.BIND_AUTO_CREATE)
    }

    fun disconnect() {
        // 取消死亡通知
        try {
            bookManager?.asBinder()?.unlinkToDeath(deathRecipient, 0)
        } catch (e: Exception) {
            e.printStackTrace()
        }

        if (isBound) {
            context.unbindService(connection)
            isBound = false
        }
    }

    private fun reconnect() {
        // 延迟重连
        Handler(Looper.getMainLooper()).postDelayed({
            connect()
        }, 1000)
    }

    companion object {
        private const val TAG = "BookManagerClient"
    }
}

Binder线程池

线程模型

Server进程:
├── Binder线程1
├── Binder线程2
├── Binder线程3
└── ...

特点:
- 客户端调用会在Binder线程执行
- 服务端需要考虑线程安全

线程安全

class BookManagerService : Service() {

    // CopyOnWriteArrayList线程安全
    private val bookList = CopyOnWriteArrayList<Book>()

    // 监听器列表(线程安全)
    private val listeners = RemoteCallbackList<IBookListener>()

    private val binder = object : IBookManager.Stub() {

        override fun getBookList(): List<Book> {
            // Binder线程调用,CopyOnWriteArrayList线程安全
            return ArrayList(bookList)
        }

        override fun addBook(book: Book?) {
            book ?: return

            // Binder线程调用,需要线程安全
            synchronized(bookList) {
                if (bookList.any { it.id == book.id }) {
                    return
                }
                bookList.add(book)
            }

            // 通知监听器(在Binder线程)
            notifyBookAdded(book)
        }

        override fun registerListener(listener: IBookListener?) {
            listener ?: return
            // RemoteCallbackList线程安全
            listeners.register(listener)
        }

        override fun unregisterListener(listener: IBookListener?) {
            listener ?: return
            listeners.unregister(listener)
        }
    }

    override fun onBind(intent: Intent?): IBinder {
        return binder
    }

    private fun notifyBookAdded(book: Book) {
        // RemoteCallbackList遍历模式
        val count = listeners.beginBroadcast()
        for (i in 0 until count) {
            try {
                listeners.getBroadcastItem(i).onBookAdded(book)
            } catch (e: RemoteException) {
                e.printStackTrace()
            }
        }
        listeners.finishBroadcast()
    }
}

Binder性能优化

1. 减少IPC次数

// [未通过] 多次IPC
for (id in bookIds) {
    val book = bookManager.getBookById(id)  // N次IPC
    books.add(book)
}

// [通过] 批量IPC
val books = bookManager.getBooksByIds(bookIds)  // 1次IPC

2. 异步调用

// 异步获取书籍列表
fun loadBooks(callback: (List<Book>) -> Unit) {
    CoroutineScope(Dispatchers.IO).launch {
        try {
            val books = bookManager?.getBookList()
            withContext(Dispatchers.Main) {
                books?.let { callback(it) }
            }
        } catch (e: RemoteException) {
            e.printStackTrace()
        }
    }
}

3. 使用oneway修饰符

// 单向调用,不等待返回
interface IBookListener {
    oneway void onBookAdded(in Book book);
    oneway void onBookRemoved(in Book book);
}

特点

  • 客户端调用后立即返回,不等待服务端执行完成
  • 适用于通知类方法

总结

Binder代理模式核心

  1. Stub:服务端实现,处理客户端请求
  2. Proxy:客户端代理,封装IPC细节
  3. asInterface:根据是否同进程返回Stub或Proxy
  4. onTransact:服务端处理请求
  5. transact:客户端发起请求

Binder通信特点

  • 同进程:直接方法调用
  • 跨进程:Binder IPC + 序列化
  • 线程池:服务端多线程处理
  • 死亡通知:监听服务端崩溃

开发建议

  • 使用RemoteCallbackList管理监听器
  • 注意线程安全(CopyOnWriteArrayList、synchronized)
  • 注册死亡通知监听服务端状态
  • 减少IPC次数,批量操作
  • 使用oneway优化单向调用

Android 16 (API 36) Binder变化

Binder事务缓冲区优化

Android 16 的 Binder 事务改进:
- 增大的默认事务缓冲区大小
- 更智能的缓冲区回收策略
- 减少 TransactionTooLargeException 的发生

死亡通知增强

// Android 16:更可靠的 Binder 死亡检测
// 新增 linkToDeath 的超时机制
fun monitorServiceWithTimeout(binder: IBinder, timeoutMs: Long = 5000) {
    val deathRecipient = IBinder.DeathRecipient {
        Log.w(TAG, "Binder died, initiating reconnect...")
        reconnectService()
    }

    try {
        binder.linkToDeath(deathRecipient, 0)
        // Android 16: 可配合 Coroutines 使用
        // 新增 awaitBinderDeath 扩展
    } catch (e: RemoteException) {
        // 服务已经死亡
        reconnectService()
    }
}

Binder 线程池调优

// Android 16 默认 Binder 线程池更大
// 服务端需要注意:
// 1. 更多并发 Binder 调用可能同时到达
// 2. 使用更精细的锁策略
// 3. 避免在 Binder 线程执行耗时操作
class BookManagerService : Service() {
    // 推荐使用 Dispatcher 控制并发
    private val binderScope = CoroutineScope(
        Dispatchers.IO.limitedParallelism(4)  // 限制并发数
    )
}

关键要点:Binder代理模式是Android IPC的核心,理解Stub和Proxy的实现是掌握Binder的关键

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐