Android开发Android开发经验谈Android技术知识

Activity底层知识之Binder透彻分析

2018-08-13  本文已影响74人  遛狗的程序员

前言:

apk是怎么安装的?资源是怎么加载的?AIDL究竟是什么?Binder又是啥?等等这样的疑问,今天起就开始一一揭开。
先来一张图感受一下:

image

今天重点先分析Binder。

知识准备

在讲解Binder前,我们先了解一些Linux的基础知识。

进程空间划分

所有进程共用1个内核空间

image

进程隔离 & 跨进程通信( IPC )

image

a. 而Binder的作用则是:连接 两个进程,实现了mmap()系统调用,主要负责 创建数据接收的缓存空间 & 管理数据接收缓存

b. 注:传统的跨进程通信需拷贝数据2次,但Binder机制只需1次,主要是使用到了内存映射。

Binder 跨进程通信机制

image

模型原理步骤说明

image

以上内容和图片借鉴:[Android跨进程通信:图文详解 Binder机制 原理] (https://blog.csdn.net/carson_ho/article/details/73560642) (作者图片画的很细致,思路清晰,如若侵权,请联系作者)

Binder组成

(划重点了,作为APP开发人员上面的内容不是非必须的,下面的知识点是必须掌握的)

image

整个通信过程过程可以看做一个拨打电话进行通信的过程,ServericeManager相当于一个电话局,张三(Client)给李四(Server)打电话,电话局先解析电话号码的地址。有的话就可以拨通,没有的话,就报错。

image

AIDL原理

AIDL是Binder的延伸。
Android系统中很多系统服务都是AIDL,比如剪切板,双进程守护。这里举例一下双进程守护:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: /Users/huangchen/workspace/web/yhparter/yh-partner-app/android/app/src/main/aidl/com/yonghuivip/partner/Service_1.aidl
 */
package com.yonghuivip.partner;
// Declare any non-default types here with import statements

public interface Service_1 extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.yonghuivip.partner.Service_1 {
        private static final java.lang.String DESCRIPTOR = "com.yonghuivip.partner.Service_1";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.yonghuivip.partner.Service_1 interface,
         * generating a proxy if needed.
         */
        public static com.yonghuivip.partner.Service_1 asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.yonghuivip.partner.Service_1))) {
                return ((com.yonghuivip.partner.Service_1) iin);
            }
            return new com.yonghuivip.partner.Service_1.Stub.Proxy(obj);
        }

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

        //收到Binder驱动通知后,Server 进程通过回调Binder对象onTransact()进行数据解包 & 调用目标方法
        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            // code即在transact()中约定的目标方法的标识符
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_getName: {
                    // a. 解包Parcel中的数据
                    // a1. 解析目标方法对象的标识符
                    data.enforceInterface(DESCRIPTOR);
                    // a2. 获得目标方法的参数
                    java.lang.String _result = this.getName();
                    reply.writeNoException();
                    // c. 将计算结果写入到reply
                    reply.writeString(_result);
                    return true;
                }
            }
            // 2. 将结算结果返回 到Binder驱动
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.yonghuivip.partner.Service_1 {
            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;
            }
            // 注:在发送数据后,Client进程的该线程会暂时被挂起
// 所以,若Server进程执行的耗时操作,请不要使用主线程,以防止ANR
            @Override
            public java.lang.String getName() throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                java.lang.String _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    //通过 调用代理对象的transact() 将 上述数据发送到Binder驱动
                    mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readString();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_getName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

    public java.lang.String getName() throws android.os.RemoteException;
}


AIDL重要的几个类:

AIDL中涉及到的类图:

image
MyService.asInterface(service).getName()

asInteface作用是判断当前进程是否和自己再同一个进程。Stub调用自己的asInterface方法发现不在同一个进程之内,就调用Proxy的getName()

 //通过 调用代理对象的transact() 将 上述数据发送到Binder驱动
 mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
 //收到Binder驱动通知后,Server 进程通过回调Binder对象onTransact()进行数据解包 & 调用目标方法
        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            // code即在transact()中约定的目标方法的标识符
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_getName: {
                    // a. 解包Parcel中的数据
                    // a1. 解析目标方法对象的标识符
                    data.enforceInterface(DESCRIPTOR);
                    // a2. 获得目标方法的参数
                    java.lang.String _result = this.getName();
                    reply.writeNoException();
                    // c. 将计算结果写入到reply
                    reply.writeString(_result);
                    return true;
                }
            }
            // 2. 将结算结果返回 到Binder驱动
            return super.onTransact(code, data, reply, flags);
        }

四大组件的启动和后续流程,都是在和AMS打交道,四大组件给AMS发消息,四大组件就是Client Binder , AMS就是Server Binder,反之,角色替换。

参考:

声明:此为原创,转载请联系作者


作者:微信公众号添加公众号-遛狗的程序员 ,或者可以扫描以下二维码关注相关技术文章。

qrcode_for_gh_1ba0785324d6_430.jpg

当然喜爱技术,乐于分享的你也可以可以添加作者微信号:

WXCD.jpeg
上一篇下一篇

猜你喜欢

热点阅读