android系统核心机制 基础(07)AsyncChannel机制浅析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/vviccc/article/details/91127715

系列文章解读&说明:

Android系统核心机制基础 的 分析主要分为以下部分:

(01)智能指针wp & sp

(02)Thread类解析

(03)Thread同步机制

(04)handler message机制 java

(05)handler使用案例(Java)

(06)handler message机制 Native

(07)AsyncChannel机制浅析

(08)JNI 基础

(09)Android 添加新模块

本模块分享的内容:AsyncChannel机制

扫描二维码关注公众号,回复: 6757355 查看本文章

本章关键点总结 & 说明:

这里主要关注AsyncChannel机制 部分,主要对该机制进行了简单的浅析,该机制基于Binder和handler两种机制。有单通道和双通道两种模式,同时还可以跨进程间通信。

1 AsyncChannel机制说明{异步跨进程handler的扩展使用方法,属于扩展handler相关机制}
AsyncChannel机制是在两个进程的Handler间搭建了通道,用于消息传输。{传统的handler只限于在同一进程内}
AsyncChannel的两个特点:

  1. 可以作为Handler之间的通道,
  2. 这两个Handler可以处于同一个进程,也可以在不同进程之间的Handler消息传递使用Binder通信机制来实现。

AsyncChannel的两种工作模式:

  1. 单项通道模式,在该模式下,客户端只能向服务端发起请求,服务端给出回应。
  2. 双向通道模式,在该模式下,客户端和服务端同时连接上AsyncChannel,客户端可以向服务端发送请求,服务端也可以向客户端发送请求。

AsyncChannel主要用在ConnectivityService框架中,涉及了wifi,mobile data,bluetooth,Tethering等模块。这里目前仅做简单的介绍。

2 AsyncChannel中相同进程 handler连接 &&同步/异步消息发送机制简要分析
2.1 相同进程的handler连接

这里从fullyConnectSync开始分析,实现代码如下:

/**
     * Fully connect two local Handlers synchronously.
     *
     * @param srcContext is the context of the source
     * @param srcHandler is the hander to receive CONNECTED & DISCONNECTED messages
     * @param dstHandler is the hander to send messages to.
     *
     * @return STATUS_SUCCESSFUL on success any other value is an error.
     */
    public int fullyConnectSync(Context srcContext, Handler srcHandler, Handler dstHandler) {
        int status = connectSync(srcContext, srcHandler, dstHandler); //连接初始化操作
        if (status == STATUS_SUCCESSFUL) { //如果连接成功就发送 CMD_CHANNEL_FULL_CONNECTION
            Message response = sendMessageSynchronously(CMD_CHANNEL_FULL_CONNECTION); 
            status = response.arg1;
        }
        return status;
    }

这里继续分析,主要针对connectSync和sendMessageSynchronously两个部分进行分析,通过调用关系{connectSync->connectSync->connected},代码迭代调用分析如下:

public int connectSync(Context srcContext, Handler srcHandler, Messenger dstMessenger) {//2
        if (DBG) log("halfConnectSync srcHandler to the dstMessenger  E");

        // We are connected
        connected(srcContext, srcHandler, dstMessenger);

        if (DBG) log("halfConnectSync srcHandler to the dstMessenger X");
        return STATUS_SUCCESSFUL;
    }

    public int connectSync(Context srcContext, Handler srcHandler, Handler dstHandler) {//1
        return connectSync(srcContext, srcHandler, new Messenger(dstHandler));
    }
	
	public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {//3
        if (DBG) log("connected srcHandler to the dstMessenger  E");

        // Initialize source fields
        mSrcContext = srcContext;
        mSrcHandler = srcHandler;
        mSrcMessenger = new Messenger(mSrcHandler);

        // Initialize destination fields
        mDstMessenger = dstMessenger;

        if (DBG) log("connected srcHandler to the dstMessenger X");
    }

对于同一进程的handler 通信,如果连接相关的对象初始化完成了,双方的连接就没问题。这个消息被发送到 AsyncChannel中的 SyncMessenger,SyncMessenger维护着一个消息栈和消息发送线程。后面会单独分析消息处理这一块。

2.2 同步消息发送机制
同步调用消息采用sendMessageSynchronously的方式,如下:

public Message sendMessageSynchronously(Message msg) {
        Message resultMsg = SyncMessenger.sendMessageSynchronously(mDstMessenger, msg);
        return resultMsg;
    }
	
	...//很多重载sendMessageSynchronously系列方法
    public Message sendMessageSynchronously(int what, Object obj) {
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        Message resultMsg = sendMessageSynchronously(msg);
        return resultMsg;
    }

sendMessageSynchronously包含了很多重载方法,针对各种不同参数,最后都会调用到sendMessageSynchronously(Message msg),而这里会调用同步消息发送机制核心方法为sendMessageSynchronously,实现如下:

private static Message sendMessageSynchronously(Messenger dstMessenger, Message msg) {
            SyncMessenger sm = SyncMessenger.obtain();    //获取一个SyncMessenger对象  
            try {
                if (dstMessenger != null && msg != null) {
                    msg.replyTo = sm.mMessenger;    //将SyncMessenger的Messenger放入消息包中 
                    synchronized (sm.mHandler.mLockObject) {
                        dstMessenger.send(msg);    //将CMD_CHANNEL_FULL_CONNECTION发送给远端的服务  
                        sm.mHandler.mLockObject.wait();    //同步等待回复
                    }
                } else {
                    sm.mHandler.mResultMsg = null;
                }
            } catch (InterruptedException e) {
                sm.mHandler.mResultMsg = null;
            } catch (RemoteException e) {
                sm.mHandler.mResultMsg = null;
            }
            Message resultMsg = sm.mHandler.mResultMsg;    //得到返回的消息,消息是从SyncHandler的handleMessage函数中返回来的  
            sm.recycle();
            return resultMsg;    //将结果返回给客户端
        }

2.3 异步消息发送机制
异步消息发送的函数组如下所示:

public void sendMessage(int what) {
        Message msg = Message.obtain();
        msg.what = what;
        sendMessage(msg);
    }

    public void sendMessage(int what, int arg1) {
        Message msg = Message.obtain();
        msg.what = what;
        msg.arg1 = arg1;
        sendMessage(msg);
    }

    public void sendMessage(int what, int arg1, int arg2) {
        Message msg = Message.obtain();
        msg.what = what;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        sendMessage(msg);
    }

    public void sendMessage(int what, int arg1, int arg2, Object obj) {
        Message msg = Message.obtain();
        msg.what = what;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        msg.obj = obj;
        sendMessage(msg);
    }

    public void sendMessage(int what, Object obj) {
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        sendMessage(msg);
    }

    sendMessage最终都会调用到这里,如下:

public void sendMessage(Message msg) {
        msg.replyTo = mSrcMessenger;
        try {
            mDstMessenger.send(msg);
        } catch (RemoteException e) {
            replyDisconnected(STATUS_SEND_UNSUCCESSFUL);
        }
    }

这里 异步消息与同步消息发送不同之处:同步需要wait等待,而异步不需要wait等待而已。

3 AsyncChannel中不同进程handler连接  异步消息发送机制简要分析

跨进程下AsyncChannel只提供了异步操作,没有同步操作过程。 这里主要通过Service的bindService方式获取不同进程的对端Handler,本质就是通过了Binder机制进行进程间通信。为避免进程间通信耗时过长,阻塞关键进程,这里新建了一个线程用于获取对端的Handler。相关代码如下:

public void connect(Context srcContext, Handler srcHandler, String dstPackageName,
            String dstClassName) {
        if (DBG) log("connect srcHandler to dst Package & class E");

        final class ConnectAsync implements Runnable {
            Context mSrcCtx;
            Handler mSrcHdlr;
            String mDstPackageName;
            String mDstClassName;

            ConnectAsync(Context srcContext, Handler srcHandler, String dstPackageName,
                    String dstClassName) {
                mSrcCtx = srcContext;
                mSrcHdlr = srcHandler;
                mDstPackageName = dstPackageName;
                mDstClassName = dstClassName;
            }

            @Override
            public void run() {
                int result = connectSrcHandlerToPackageSync(mSrcCtx, mSrcHdlr, mDstPackageName,
                        mDstClassName);
                replyHalfConnected(result);
            }
        }

        ConnectAsync ca = new ConnectAsync(srcContext, srcHandler, dstPackageName, dstClassName);
        new Thread(ca).start();

        if (DBG) log("connect srcHandler to dst Package & class X");
    }

继续分析关键代码:

public int connectSrcHandlerToPackageSync(
Context srcContext, Handler srcHandler, String dstPackageName, String dstClassName) {
        mConnection = new AsyncChannelConnection();
        mSrcContext = srcContext;
        mSrcHandler = srcHandler;
        mSrcMessenger = new Messenger(srcHandler);
        mDstMessenger = null;

        /* Send intent to create the connection */
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.setClassName(dstPackageName, dstClassName);
        boolean result = srcContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        
        return result ? STATUS_SUCCESSFUL : STATUS_BINDING_UNSUCCESSFUL;
    }

通知调用者Handler对端Handler连接状态。通知消息为CMD_CHANNEL_HALF_CONNECTED成功为STATUS_SUCCESSFUL。

    private void replyHalfConnected(int status) {
        Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_HALF_CONNECTED);
        msg.arg1 = status;
        msg.obj = this;
        msg.replyTo = mDstMessenger;
        if (mConnection == null) {
            mDeathMonitor = new DeathMonitor();
            try {
                mDstMessenger.getBinder().linkToDeath(mDeathMonitor, 0);
            } catch (RemoteException e) {
                mDeathMonitor = null;
                // Override status to indicate failure
                msg.arg1 = STATUS_BINDING_UNSUCCESSFUL;
            }
        }

        mSrcHandler.sendMessage(msg);
    }

调用者Handler接收到CMD_CHANNEL_HALF_CONNECTED消息后,判断是STATUS_SUCCESSFUL后,可直接向对端Handler发起sendMessage操作,如之前分析。

猜你喜欢

转载自blog.csdn.net/vviccc/article/details/91127715