您的位置:首页 > 移动开发 > Android开发

Android Telephony系统 之 DataConnectionTracker与MobileDataStateTracker之间的通信

2013-07-28 22:11 357 查看
我们知道DataConnectionTracker是跑在com.android.phone进程中,而MobileDataStateTracker是跑在system_server进程中,那么两者是如何通信的
在DataConnectionTracker的派生类GsmDataConnectionTracker的构造函数的最后一行:
public GsmDataConnectionTracker(PhoneBase p)
broadcastMessenger();//调用父类DataConnectiontracker的方法
DataConnectionTracker.java
protected void broadcastMessenger()
Intent intent = new Intent(DctConstants.ACTION_DATA_CONNECTION_TRACKER_MESSENGER);
intent.putExtra(DctConstants.EXTRA_MESSENGER, new Messenger(this));

mPhone.getContext().sendBroadcast(intent); //构造一个Messenger,通过intent发送出去
这个intent,会被MobileDataStateTracker收到,而正是这个Messenger(信使),搭建起了二者通信的桥梁。
既然是进程间通信,必然会存在一个Messenger.aidl接口,那么来看Messenger.aidl的实现:
package android.os;
parcelable Messenger; //这意味Messgenger可以通过parcelable的方式在进程间传输。

那么在一个进程里面,怎么给另外一个进程的Handler发消息,就像那个Handler在自己进程里面跑一样呢。
答案就是IMessenger.aidl接口,看IMessenger.aidl的实现
package android.os;

import android.os.Message;

/** @hide */

oneway interface IMessenger {

void send(in Message msg); //那么send接口可以跨进程调用

}

IMessenger的Stub代码,理所应当的在Handler.java中实现。
private final class MessengerImpl extends IMessenger.Stub {

public void send(Message msg) {

Handler.this.sendMessage(msg); //对方的进程,调用send,就是相当于调用本进程的Handler的sendMessage
}

}

那么怎么才能调用到这个接口呢,就是Messenger,Messeger对send接口进行的包装,看Messenger的构造方法实现
public Messenger(Handler target) {

mTarget = target.getIMessenger();

}

现在,可以来看MobileDataStateTracker的onReceiver方法
if (intent.getAction().equals(DctConstants
.ACTION_DATA_CONNECTION_TRACKER_MESSENGER)) {

if (VDBG) log(mApnType + " got ACTION_DATA_CONNECTION_TRACKER_MESSENGER");

mMessenger =

intent.getParcelableExtra(DctConstants.EXTRA_MESSENGER); //取出Messager实例

AsyncChannel ac = new AsyncChannel();

ac.connect(mContext, MobileDataStateTracker.this.mHandler, mMessenger); //构造一个AsyncChannel,把自己的Handler与Messenger联系起来,也就是跟DataConnectionTracker联系起来。
}

在来看AsyncChannel的connect实现:
framework/base/core/java/com/android/internal/util/AsyncChannel.java
public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger)
connected(srcContext, srcHandler, dstMessenger); //构造一个srcMessenger,与MobileDataStateTracker绑定起来
replyHalfConnected(STATUS_SUCCESSFUL); //给MoblieDataStateTracker发一个,告诉MobileDataStateTracker,我们已经连接一半了

那么MoblieDataStateTracker收到这个CMD之后,是怎么处理的。
public void handleMessage(Message msg)
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (VDBG) {

mMdst.log("MdstHandler connected");

}

mMdst.mDataConnectionTrackerAc = (AsyncChannel) msg.obj; //这个obj其实就是刚在构造的AsyncChannel

}
那么这个通道已经建立起来了。

当ConnectivityService调用MoblieDataStateTracker的setUserDataEnable方法的时候(用户在设置里面把移动数据取消勾选)
MobileDataStateTracker.java
public void setUserDataEnable(boolean enabled)
final AsyncChannel channel = mDataConnectionTrackerAc;
channel.sendMessage(DctConstants.CMD_SET_USER_DATA_ENABLE,
enabled ? DctConstants.ENABLED : DctConstants.DISABLED); //构造一个DctConstants.CMD_SET_USER_DATA_ENABLE消息

看AsyncChannel怎么处理
public void sendMessage(Message msg)
msg.replyTo = mSrcMessenger;
mDstMessenger.send(msg); //这里看出,把那个消息发给了DataConnecionTracker。

再来看DataConnectionTracker是如何处理的
public void handleMessage(Message msg)
case DctConstants.CMD_SET_USER_DATA_ENABLE: {
final boolean enabled = (msg.arg1 == DctConstants.ENABLED) ? true : false;

onSetUserDataEnabled(enabled); //这里做开启数据,断开数据的操作

break;

}


可以看出,正是Handler的跨进程传输特型,才让AsyncChannel能够将两个进程的Handler联系起来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: