欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android IPC之Messenger源码分析

程序员文章站 2022-05-07 22:06:44
android ipc之messenger分析,在android ipc之messenger一文中,对通过messenger实现ipc的流程做了一个简单的介绍,在文中曾说到me...

android ipc之messenger分析,在android ipc之messenger一文中,对通过messenger实现ipc的流程做了一个简单的介绍,在文中曾说到messenger的底层也是通过aidl实现的,这里通过messenger的源码来看看aidl是如何实现messenger的。

messenger实现ipc流程分析

messenger源码分析

package android.os;

public final class messenger implements parcelable {

    /**
     * imessenger就是通过声明一个.aidl文件生成的对应的接口
     */
    private final imessenger mtarget;

    /**
     * 第一步:在服务端创建messenger
     * 
     *   通过该方法创建一个messenger对象,该对象会持有一个handler的引用,
     *   所有要通过messenger的send()发送的跨进程message,最终都是通过该handler发送,
     *   所以handler是messenger实现跨进程通信的核心类之一
     */
    public messenger(handler target) {
        mtarget = target.getimessenger();
    }

    /**
     * 第二步:将binder对象返回到客户端
     * 
     *     通过调用该方法返回一个binder对象,这个一般在service的onbind()方法中返回ibinder对象时调用。
     */
    public ibinder getbinder() {
        return mtarget.asbinder();
    }


    /**
     * 第三步:客户端服务绑定成功后,通过binder对象创建messenger
     *  
     *      通过binder对象创建一个messenger对象,
     *      这个构造方法一般在客户端调用,当绑定服务成功后,
     *      通过返回的binder对象创建的messenger会和服务端的messenger对象对应
     *      最终在客户端发送消息在服务端可以接收到。
     * 
     */
    public messenger(ibinder target) {
        mtarget = imessenger.stub.asinterface(target);
    }


    /**
     * 第四步:在客户端调用send方法,向服务端发送消息
     *      
     *      通过调用该方法,最终通过handler的send()方法,发送message消息
     */
    public void send(message message) throws remoteexception {
        mtarget.send(message);
    }




    public boolean equals(object otherobj) {
        if (otherobj == null) {
            return false;
        }
        try {
            return mtarget.asbinder().equals(((messenger)otherobj)
                    .mtarget.asbinder());
        } catch (classcastexception e) {
        }
        return false;
    }

    public int hashcode() {
        return mtarget.asbinder().hashcode();
    }


    public int describecontents() {
        return 0;
    }

    public void writetoparcel(parcel out, int flags) {
        out.writestrongbinder(mtarget.asbinder());
    }

    public static final parcelable.creator creator
            = new parcelable.creator() {
        public messenger createfromparcel(parcel in) {
            ibinder target = in.readstrongbinder();
            return target != null ? new messenger(target) : null;
        }

        public messenger[] newarray(int size) {
            return new messenger[size];
        }
    };


    public static void writemessengerornulltoparcel(messenger messenger,
            parcel out) {
        out.writestrongbinder(messenger != null ? messenger.mtarget.asbinder()
                : null);
    }


    public static messenger readmessengerornullfromparcel(parcel in) {
        ibinder b = in.readstrongbinder();
        return b != null ? new messenger(b) : null;
    }

}

在上面的源码中,messenger定义了一个imessenger类型的成员变量mtarget,但是在java源码中看不到imessenger类的相关信息,这是因为imessenger是一个声明的aidl接口,我们可以通过android源码找到这个aidl接口文件,代码如下:

/**
 *文件路径:
 *
 *  ../android-6.0.1_r72/frameworks/base/core/java/android/os/imessenger.aidl
 */

package android.os;

import android.os.message;

/** @hide */
oneway interface imessenger {
    void send(in message msg);
}

在上面的源码中,我们可以看到imessenger对象mtarget对象的初始化是通过调用 handler.getimessenger()完成的。

    public messenger(handler target) {
        mtarget = target.getimessenger();
    }

这里我们看下handler中的getimessenger方法。

final imessenger getimessenger() {
    synchronized (mqueue) {
        if (mmessenger != null) {
            return mmessenger;
        }
        mmessenger = new messengerimpl();
        return mmessenger;
    }
}

/**
 *  最终,messenger的send()方法,是在这里实现的,
 *  这里我们可以确实,messenger实现ipc是通过handler实现的
 */
private final class messengerimpl extends imessenger.stub {
    public void send(message msg) {
        // 这是一个本地方法,用于获取进程的uid,保证在进程间通信
        msg.sendinguid = binder.getcallinguid();

        // 调用handler的sendmessage方法实现ipc
        handler.this.sendmessage(msg);
    }

这里,我们可以得出一个结论messenger实现ipc的流程,底层是通过aidl文件实现的,同时handler也是messenger实现ipc的关键类。

关于handler,想必大多数人对于handler的认识是停留在线程间通信的,至于handler如何实现ipc这里只提一句,handler在native层中通过管道实现ipc通信。