Andorid Binder进程间通信---Java接口源代码--System和应用程序进程间通信

本文参考《Android系统源代码情景分析》,作者罗升阳

一、架构代码:

~/Android/frameworks/base/core/java/android/os

----IInterface.java (Interface)

----IServiceManager.java (IServiceManager)

----IBinder.java (IBinder)

----Binder.java (BinderProxy,Binder)

----ServiceManagerNative.java (ServiceManagerProxy,ServiceManagerNative)

----ServiceManager.java (ServiceManager)

~/Android/frameworks/base/core/jni

----android_util_Binder.cpp

测试代码:(参考实现硬件访问服务和开发Android应用程序来使用硬件访问服务两篇文章)

~/Android/frameworks/base/services/java/com/android/server

----SystemServer.java

~/Android/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os

----IFregService.java

~/Android/frameworks/base/services/java/com/android/server

----FregService.java

~/Android/packages/experimental/Freg

----src----shy/luo/freg----Freg.java

二、源码分析

上面介绍的Freg这个Activity获得了FregService的远程接口后,就可以使用它的服务了。我们以使用IFregService.getVal函数为例详细说明。在Freg::onClick函数中调用了IFregService.getVal函数:

~/Android/packages/experimental/Freg

----src----shy/luo/freg----Freg.java

public class Freg extends Activity implements OnClickListener {
	......

	@Override
        public void onCreate(Bundle savedInstanceState) {
	    super.onCreate(savedInstanceState);
	    setContentView(R.layout.main);

	    fregService = IFregService.Stub.asInterface(
		ServiceManager.getService("freg"));

	 ......

	   Log.i(LOG_TAG, "Freg Activity Created");
       }
	@Override
	public void onClick(View v) {
		if(v.equals(readButton)) {
			int val = fregService.getVal();
			......
		}
		else if(v.equals(writeButton)) {
			......
		}
		else if(v.equals(clearButton)) {
			......
		}
	}

	......
}

1、应用程序进程,获得实现了IFregService接口的IFregService.Stub.Proxy对象

参考http://blog.csdn.net/jltxgcy/article/details/29861583,Android应用程序进程和Service Manager进程通信。

2、应用程序进程,封装进程间通信数据

通知前面的分析,我们知道,这里的fregService接口实际上是一个IFregService.Stub.Proxy对象,因此,我们进入到IFregService.Stub.Proxy类的getVal函数中:

public interface IFregService extends android.os.IInterface
{
	/** Local-side IPC implementation stub class. */
	public static abstract class Stub extends android.os.Binder implements android.os.IFregService
	{

		......

		private static class Proxy implements android.os.IFregService
		{
			private android.os.IBinder mRemote;//BinderProxy对象(其中mObject成员变量记录了这个Android应用程序进程代理对象BpBinder对象的地址)

			......

			public int getVal() throws android.os.RemoteException
			{
				android.os.Parcel _data = android.os.Parcel.obtain();
				android.os.Parcel _reply = android.os.Parcel.obtain();
				int _result;
				try {
					_data.writeInterfaceToken(DESCRIPTOR);//android.os.IFregService
					mRemote.transact(Stub.TRANSACTION_getVal, _data, _reply, 0);
					_reply.readException();
					_result = _reply.readInt();
				}
				finally {
					_reply.recycle();
					_data.recycle();
				}
				return _result;
			}
		}

		......
		static final int TRANSACTION_getVal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
	}

	......
}

此时没有对象要传递,只有字符串。

参考Andorid Binder进程间通信---FregClient和FregServer进程间通信http://blog.csdn.net/jltxgcy/article/details/28428853一文中的第2点。

3、应用程序进程,发送BC_TRANSACTION,睡眠等待

先参考http://blog.csdn.net/jltxgcy/article/details/29861583一文中System进程和Service Manager进程间通信中的第3点。

再参考Andorid Binder进程间通信---FregClient和FregServer进程间通信http://blog.csdn.net/jltxgcy/article/details/28428853一文中的第3点。

根据应用程序进程代理对象的句柄值,首先找到应用程序进程代理对象,通过应用程序代理对象再找到System进程的实体对象,通过System进程的实体对象,找到System进程,也就是目标进程。传递内容中是android.os.IFregService。

4、System进程,处理BC_TRANSACTION,返回BR_TRANSACTION

参考Andorid Binder进程间通信---FregClient和FregServer进程间通信http://blog.csdn.net/jltxgcy/article/details/28428853一文中的第4点。

通过System实体对象,读取的tr.target.ptr为System进程的本地对象的弱引用计数的地址,tr.cookie为System进程的本地对象地址(BBinder)。

~/Android/frameworks/base/libs/binder

----IPCThreadState.cpp

status_t IPCThreadState::executeCommand(int32_t cmd)
{
    BBinder* obj;
    RefBase::weakref_type* refs;
    status_t result = NO_ERROR;

    switch (cmd) {//BR_TRANSACTION
    ......
    case BR_TRANSACTION:
        {
            binder_transaction_data tr;
            result = mIn.read(&tr, sizeof(tr));//读取出传递过来的binder_transaction_data结构体
            ......
            if (result != NO_ERROR) break;

            Parcel buffer;//把数据放入buffer中
            buffer.ipcSetDataReference(
                reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                tr.data_size,
                reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
                tr.offsets_size/sizeof(size_t), freeBuffer, this);

            .....

            Parcel reply;
            .....
            if (tr.target.ptr) {//System进程的本地对象的弱引用计数的地址
                sp<BBinder> b((BBinder*)tr.cookie);//tr.cookie原来为IBinder向下转型为BBinder,System进程的本地对象地址
                const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);//code为Stub.TRANSACTION_getVal
                if (error < NO_ERROR) reply.setError(error);
            } else {
                ......
            }

            .......

            if ((tr.flags & TF_ONE_WAY) == 0) {
                .......
                sendReply(reply, 0);
            } else {
                ......
            }

            ......

        }
        break;

    ......
    return result;
}

首先,读取出传递过来的binder_transaction_data结构体,并把其中的数据放入buffer中,调用BBinder的transact方法,实现如下:

~/Android/frameworks/base/libs/binder

----Binder.cpp

status_t BBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    data.setDataPosition(0);

    status_t err = NO_ERROR;
    switch (code) {
        case PING_TRANSACTION:
            reply->writeInt32(pingBinder());
            break;
        default:
            err = onTransact(code, data, reply, flags);//code为Stub.TRANSACTION_getVal
            break;
    }   

    if (reply != NULL) {
        reply->setDataPosition(0);
    }   

    return err;
}

BBinder的onTransact方法,由于子类JavaBBinder复写了onTransact方法,所以调用该方法。实现如下:

class JavaBBinder : public BBinder
{
	JavaBBinder(JNIEnv* env, jobject object)
		: mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
	{
		......
	}

	......

	virtual status_t onTransact(
		uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
	{
		JNIEnv* env = javavm_to_jnienv(mVM);

		......

		jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
			code, (int32_t)&data, (int32_t)reply, flags);

		......

		return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
	}

	......

        JavaVM* const   mVM;
	jobject const   mObject;
};

JavaBBinder类里面的成员变量mObject就是FregService类的一个实例对象了。因此,这里通过语句:

jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
			code, (int32_t)&data, (int32_t)reply, flags);

就调用了FregService.execTransact函数,而FregService.execTransact函数继承了Binder类的execTransact函数:

~/Android/frameworks/base/core/java/android/os

----Binder.java

public class Binder implements IBinder {
	......

	// Entry point from android_util_Binder.cpp's onTransact
	private boolean execTransact(int code, int dataObj, int replyObj, int flags) {
		Parcel data = Parcel.obtain(dataObj);
		Parcel reply = Parcel.obtain(replyObj);
		// theoretically, we should call transact, which will call onTransact,
		// but all that does is rewind it, and we just got these from an IPC,
		// so we'll just call it directly.
		boolean res;
		try {
			res = onTransact(code, data, reply, flags);//data为android.os.IFregService,code为Stub.TRANSACTION_getVal
		} catch (RemoteException e) {
			reply.writeException(e);
			res = true;
		} catch (RuntimeException e) {
			reply.writeException(e);
			res = true;
		} catch (OutOfMemoryError e) {
			RuntimeException re = new RuntimeException("Out of memory", e);
			reply.writeException(re);
			res = true;
		}
		reply.recycle();
		data.recycle();
		return res;
	}
}

这里又调用了onTransact函数来作进一步处理。由于FregService类继承了IFregService.Stub类,而IFregService.Stub类实现了onTransact函数,FregService类没有实现,因此,最终调用了IFregService.Stub.onTransact函数:

~/Android/fout/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os中。

IFregService.java

public interface IFregService extends android.os.IInterface
{
	/** Local-side IPC implementation stub class. */
	public static abstract class Stub extends android.os.Binder implements android.os.IFregService
	{
		......

		@Override
		public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
		{
			switch (code)
			{
			......
			case TRANSACTION_getVal:
				{
					data.enforceInterface(DESCRIPTOR);//data为android.os.IFregService
					int _result = this.getVal();
					reply.writeNoException();
					reply.writeInt(_result);//写入reply
					return true;
				}
			}
			return super.onTransact(code, data, reply, flags);
		}

		......

	}
}

函数最终又调用了FregService.getVal函数:

public class FregService extends IFregService.Stub {
	......

	public int getVal() {
		return getVal_native();
	}

	......
	private static native int getVal_native();
}

5、System进程,发送BC_REPLY,睡眠等待。

参考Andorid Binder进程间通信---FregClient和FregServer进程间通信http://blog.csdn.net/jltxgcy/article/details/28428853一文中的第5点。

根据thread->transaction_stack->from找到目标进程,即应用程序进程。传递的数据返回值是getVal获取的值。

6、应用程序进程,处理BC_REPLY,返回BR_REPLY。

参考Andorid Binder进程间通信---FregClient和FregServer进程间通信http://blog.csdn.net/jltxgcy/article/details/28428853一文中的第6点。

7、应用程序进程进程,返回到IFregService.Stub.Proxy类的getVal方法。

最终,经过层层返回,就回到IFregService.Stub.Proxy.getVal函数中来了,从下面语句返回:

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

并将结果读出来:

_result = _reply.readInt();

最后将这个结果返回到Freg.onClick函数中。

Andorid Binder进程间通信---Java接口源代码--System和应用程序进程间通信,布布扣,bubuko.com

时间: 2024-12-16 03:06:50

Andorid Binder进程间通信---Java接口源代码--System和应用程序进程间通信的相关文章

Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了Android系统进程间通信机制Binder的原理,并且深入分析了系统提供的Binder运行库和驱动程序的 源代码.细心的读者会发现,这几篇文章分析的Binder接口都是基于C/C++语言来实现的,但是我们在编写应用程序都是基于Java语言的,那么,我 们如何使用Java语言来使用系统的Binder机

Andorid Binder进程间通信---Binder本地对象,实体对象,引用对象,代理对象的引用计数

本文参考<Android系统源代码情景分析>,作者罗升阳. 一.Binder库(libbinder)代码: ~/Android/frameworks/base/libs/binder ----BpBinder.cpp ----Parcel.cpp ----ProcessState.cpp ----Binder.cpp ----IInterface.cpp ----IPCThreadState.cpp ----IServiceManager.cpp ----Static.cpp ~/Androi

Andorid Binder进程间通信---Binder对象死亡通知机制

本文参考<Android系统源代码情景分析>,作者罗升阳. 一.Binder库(libbinder)代码: ~/Android/frameworks/base/libs/binder ----BpBinder.cpp ----Parcel.cpp ----ProcessState.cpp ----Binder.cpp ----IInterface.cpp ----IPCThreadState.cpp ----IServiceManager.cpp ----Static.cpp ~/Androi

java常用类详细介绍及总结:字符串相关类、日期时间API、比较器接口、System、Math、BigInteger与BigDecimal

一.字符串相关的类 1.String及常用方法 1.1 String的特性 String:字符串,使用一对""引起来表示. String声明为final的,不可被继承 String实现了Serializable接口:表示字符串是支持序列化的. 实现了Comparable接口:表示String可以比较大小 String内部定义了final char[] value用于存储字符串数据 String:代表不可变的字符序列.简称:不可变性. 体现: 当对字符串重新赋值时,需要重写指定内存区域赋

java接口调用——webservice就是一个RPC而已

很多新手一听到接口就蒙逼,不知道接口是什么!其实接口就是RPC,通过远程访问别的程序提供的方法,然后获得该方法执行的接口,而不需要在本地执行该方法.就是本地方法调用的升级版而已,我明天会上一篇如何通过socket实现rpc,以及服务的注册和动态上下线.这里先上一篇RPC的实现者一webservice,便于后面理解源码执行过程,框架就是在原理的基础上提供更加便捷的使用而已,协议就是基于TCP或UDP之上,服务者和调用者之间约定消息按照什么样的格式发送以及解析罢了.协议没什么高深莫测的. 原文和作者

Java接口技术

1.RMI技术 1.1 RMI技术介绍 RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网络分布式应用系统的核心解决方案之一.其实它可以被看作是RPC的Java版本.但是传统RPC并不能很好地应用于分布式对象系统.而Java RMI 则支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用. RMI目前使用Java远程消息交换协议JRMP

Java接口多线程并发测试 (二)

原文地址http://www.cnblogs.com/yezhenhan/archive/2012/01/09/2317636.html 这是一篇很不错的文章,感谢原博主的分享! JAVA多线程实现和应用总结 最近在做代码优化时学习和研究了下JAVA多线程的使用,看了菜鸟们的见解后做了下总结.1.JAVA多线程实现方式JAVA多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种

java接口相关例题

java接口相关习题 interface Graphics{  //接口里面只能用抽象方法  public abstract double area();    }//设置 平面类class PlaneGraphics1{    private String shape; //形状    //构造方法,有参数    public PlaneGraphics1(String shape)    {        this.shape=shape;    }    //无参数    public P

hadoop java接口及常用api

# java接口及常用api package com.yting.hadoop.hdfs; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.net.URI; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataInputS