6.4 Client端调用Java系统服务的方法
6.3 节中分析了服务代理对象的获取过程,该服务对象最终封装到PowerManager中供Client端调用,本节分析调用服务的方法。
以PowerManager的isScreenOn方法为例,代码如下:
public boolean isScreenOn()
{
try{
//mService为IPowerManager.Stub.Proxy
return mService.isScreenOn();
}catch(RemoteException e){
return false;
}
}
可见调用PowerManager的isScreenOn方法是调用IPowerManager.Stub.Proxy的isScreenOn方法,其代码如下:
private static class Proxy implements android.os.IPowerManager{
private android.os.IBinder mRemote;//mRemote存储BinderProxy
……
public boolean isScreenOn()throws android.os.RemoteException{
android.os.Parcel_data=android.os.Parcel.obtain();
android.os.Parcel_reply=android.os.Parcel.obtain();
boolean_result;
try{
_data.writeInterfaceToken(DESCRIPTOR);
//调用BinderProxy的transact方法
mRemote.transact(Stub.TRANSACTION_isScreenOn,_data,_reply,0);
_reply.readException();
_result=(0!=_reply.readInt());//读取返回结果
}finally{
_reply.recycle();
_data.recycle();
}
return_result;
}
……
BinderProxy的transact方法会调用其Native层对等的BpBinder的transact方法,参与进程间通信,这之后的过程与Native层的处理流程是一样的,请参考第5章的内容。
进程间通信的结果是,Binder驱动将Client端的Stub.TRANSACTION_isScreenOn请求转发给BBinder的transact方法,在该方法中调用其onTransact方法处理请求。
onTransact方法由BBinder的子类JavaBBinder(上文中写入ServiceManager的便是该类型的对象)覆盖,其代码如下:
class JavaBBinder:public BBinder
{
virtual status_t onTransact(
uint32_t code, const Parcel&data, Parcel*reply, uint32_t flags=0)
{
JNIEnv*env=javavm_to_jnienv(mVM);
……
//mObject指向Java系统服务,通过JNI函数调用系统服务的execTransact
jboolean res=env->CallBooleanMethod(mObject,
gBinderOffsets.mExecTransact, code,
(int32_t)&data,(int32_t)reply, flags);
jthrowable excep=env->ExceptionOccurred();
if(excep){
……//处理异常
}
……
if(code==SYSPROPS_TRANSACTION){
BBinder:onTransact(code, data, reply, flags);
}
return res!=JNI_FALSE?NO_ERROR:UNKNOWN_TRANSACTION;
}
onTransact方法中需要根据gBinderOffsets.mExecTransact中保存的Binder类(Java层)的Method ID找到并调用mObject对象的execTransact方法。
在本例中,mObject即PowerManagerService,继承自Binder类(Java层),其execTransact方法如下:
public class Binder implements IBinder{
……
private boolean execTransact(int code, int dataObj, int replyObj, int flags){
Parcel data=Parcel.obtain(dataObj);
Parcel reply=Parcel.obtain(replyObj);
boolean res;
try{
res=onTransact(code, data, reply, flags);
}catch(RemoteException e){
reply.setDataPosition(0);
reply.writeException(e);
res=true;
}catch(RuntimeException e){
reply.setDataPosition(0);
reply.writeException(e);
res=true;
}catch(OutOfMemoryError e){
RuntimeException re=new RuntimeException("Out of memory",e);
reply.setDataPosition(0);
reply.writeException(re);
res=true;
}
reply.recycle();
data.recycle();
return res;
}
可见execTransact方法调用onTransact方法,该方法由Binder的子类覆盖。
PowerManager Service中并没有定义onTransact方法,但PowerManagerService继承自IPowerManager.Stub,而IPowerManager.Stub又继承了android.os.Binder, IPowerManager.Stub中覆盖了Binder的onTransact方法,因此这里调用的是PowerManagerService从IPowerManager.Stub中继承的onTransact方法。onTransact方法的代码如下:
public interface IPowerManager extends android.os.IInterface{
public static abstract class Stub extends android.os.Binder implements
android.os.IPowerManager{
public boolean onTransact(int code, android.os.Parcel data,
android.os.Parcel reply, int flags)
throws android.os.RemoteException{
switch(code){
……
//根据Client端发送的code匹配当前对象的相应处理方法
case TRANSACTION_isScreenOn:{
data.enforceInterface(DESCRIPTOR);
//调用子类的isScreenOn实现方法
boolean_result=this.isScreenOn();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
……
}
return super.onTransact(code, data, reply, flags);
}
……
可见,在IPowerManager.Stub的onTransact方法中,会根据Client端传入的请求code,匹配当前对象的对应方法处理请求。
在本例中,对应TRANSACTION_isScreenOn请求码的Server端处理方法是isScreenOn方法。由于PowerManagerService继承自IPowerManager.Stub,因此运行时将调用子类PowerManagerService的isScreenOn方法,该方法代码如下:
public boolean isScreenOn(){
synchronized(mLocks){
return(mPowerState&SCREEN_ON_BIT)!=0;
}
}
在PowerManagerService的isScreenOn方法中,判断其内部成员变量mPowerState的标记位是否设置为SCREEN_ON_BIT,然后返回结果。该结果会被写入reply中,由Binder驱动返回给Client。