1、创建
Android9.0 开启关闭移动数据流程帖子中,提到了数据的打开过程,会调用DcAsyncChannel的bringUp方法。
@DcTracker
private boolean setupData(ApnContext apnContext, int radioTech, boolean unmeteredUseOnly) {
//用于连接DcTracker和DataConnection
DcAsyncChannel dcac = null;
...
if (dcac == null) {
...
//判断能否复用dataConnection
dcac = findFreeDataConnection();
if (dcac == null) {
//不能复用创建新的DataConnection和DcAsyncChannel
dcac = createDataConnection();
}
}
...
apnContext.setDataConnectionAc(dcac);
apnContext.setApnSetting(apnSetting);
apnContext.setState(DctConstants.State.CONNECTING);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
Message msg = obtainMessage();
msg.what = DctConstants.EVENT_DATA_SETUP_COMPLETE;
msg.obj = new Pair<ApnContext, Integer>(apnContext, generation);
dcac.bringUp(apnContext, profileId, radioTech, unmeteredUseOnly, msg, generation);
}
这里我们详细看一下createDataConnection方法。
private DcAsyncChannel createDataConnection() {
DataConnection conn = DataConnection.makeDataConnection(mPhone, id, this,
mDataServiceManager, mDcTesterFailBringUpAll, mDcc);
mDataConnections.put(id, conn);
if (status == AsyncChannel.STATUS_SUCCESSFUL) {
mDataConnectionAcHashMap.put(dcac.getDataConnectionIdSync(), dcac);
} else {
loge("createDataConnection: Could not connect to dcac=" + dcac + " status=" + status);
}
return dcac;
}
这里首先创建DcAsyncChannel实例,并调用fullyConnectSync方法,目的是完成DcTracker与DataConnection之间handle的绑定,为什么这样绑定,后续介绍。
即:传递的参数this把DcTracker自己传递给AsyncChannel与DataConnection的getHandler获取handle进行绑定
在DataConnection中,当数据连接成功时,就会在DataConnection中进入DcActiveState的状态机,然后就会创建数据连接随想DcNetworkAgent。
@DataConnection.java
private class DcActiveState extends State {
@Override
...
updateNetworkInfo();
...
if (DBG) log("mRestrictedNetworkOverride = " + mRestrictedNetworkOverride);
mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(),
"DcNetworkAgent", mNetworkInfo, getNetworkCapabilities(), mLinkProperties,
50, misc);
...
}
}
这里创建DcNetworkAgent实例,DcNetworkAgent是NetworkAgent的子类,初始化DcNetworkAgent时就会初始化NetworkAgent
所以进入NetworkAgent类
@NetworkAgent.java
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
super(looper);
LOG_TAG = logTag;
mContext = context;
if (ni == null || nc == null || lp == null) {
throw new IllegalArgumentException();
}
if (VDBG) log("Registering NetworkAgent");
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
}
在NetworkAgent的初始化时,只做了一件事,就是将其注册到ConnectivityService中。
至此 , DcAsyncChannel,DcNetworkAgent,NetworkAgent,ConnectivityManager都初始化完了
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkMisc networkMisc) {
enforceConnectivityInternalPermission();
lp.ensureDirectlyConnectedRoutes();
// TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
// satisfies mDefaultRequest.
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
new Network(reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore,
mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
// Make sure the network capabilities reflect what the agent info says.
nai.networkCapabilities = mixInCapabilities(nai, nc);
synchronized (this) {
nai.networkMonitor.systemReady = mSystemReady;
}
final String extraInfo = networkInfo.getExtraInfo();
final String name = TextUtils.isEmpty(extraInfo)
? nai.networkCapabilities.getSSID() : extraInfo;
addValidationLogs(nai.networkMonitor.getValidationLogs(), nai.network, name);
if (DBG) log("registerNetworkAgent " + nai);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
return nai.network.netId;
}
@Override
public void handleMessage(Message msg) {
...
case EVENT_REGISTER_NETWORK_AGENT: {
handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);
break;
}
...
}
if (VDBG) log("Got NetworkAgent Messenger");
mNetworkAgentInfos.put(nai.messenger, nai);
synchronized (mNetworkForNetId) {
mNetworkForNetId.put(nai.network.netId, nai);
}
nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);
NetworkInfo networkInfo = nai.networkInfo;
nai.networkInfo = null;
updateNetworkInfo(nai, networkInfo);
updateUids(nai, null, nai.networkCapabilities);
}
switch (msg.what) {
default:
return false;
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
handleAsyncChannelHalfConnect(msg);
break;
}
...
}
return true;
}
...
}
private void handleAsyncChannelHalfConnect(Message msg) {
AsyncChannel ac = (AsyncChannel) msg.obj;
if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
...
} else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (VDBG) log("NetworkAgent connected");
// A network agent has requested a connection. Establish the connection.
mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
} else {
...
}
}
}
上面代码可以看到,当ConnectivityService与NetworkAgent之间单向通道建立完成后,又发起了双向通道的请求,此时在NetworkAgent端,将会收到CMD_CHANNEL_FULL_CONNECTION的请求消息:
@NetworkAgent.java
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
if (mAsyncChannel != null) {
log("Received new connection while already connected!");
} else {
if (VDBG) log("NetworkAgent fully connected");
AsyncChannel ac = new AsyncChannel();
ac.connected(null, this, msg.replyTo);
//连接建立成功
ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
AsyncChannel.STATUS_SUCCESSFUL);
synchronized (mPreConnectedQueue) {
mAsyncChannel = ac;
for (Message m : mPreConnectedQueue) {
ac.sendMessage(m);
}
mPreConnectedQueue.clear();
}
}
break;
}
...
}
从上面的代码可以看出,NetworkAgent收到请求之后就发送了建立成功的消息,然后检测消息队列,如果有消息就及时向ConnectivityService传递。
至此,NetworkAgent与ConnectivityService建立连接完成。别忘了NetworkAgent是通过DataConnection在onConnection连接成功后创建的,
所以,DataConnection通过调用DcNetworkAgent(NetworkAgent)方法,例如sendNetworkInfo()方法,NetworkAgent通过建立的AsyncChannel连接调用sendMessage发送给ConnectivityService。
最后看一下最开始mark的位置。
DcTracker在创建DataConnection时,调用
根据AsyncChannel规则,服务端会收到CMD_CHANNEL_FULL_CONNECTION连接通知:
@DataConnection.java
private class DcDefaultState extends State {
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
if (mAc != null) {
if (VDBG) log("Disconnecting to previous connection mAc=" + mAc);
mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED);
} else {
mAc = new AsyncChannel();
mAc. connected(null, getHandler(), msg.replyTo);
if (VDBG) log("DcDefaultState: FULL_CONNECTION reply connected");
mAc. replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
AsyncChannel.STATUS_SUCCESSFUL, mId, "hi");
}
break;
}
...
}
}
从上面代码可以看到,DataConnection在最开始的状态机DcDefaultState中就处理了CMD_CHANNEL_FULL_CONNECTION通知,并且和NetworkAgent与ConnectivityService建立的连接一样,
首先创建AsyncChannel,返回连接建立成功的消息。所以DcTracker与DataConnection也是双向连接。
至此,DcTracker调用DcAsyncChannel的bingUp方法,就是DcTracker通过AsyncChannel连接,调用sendMessage方法发送给DataConnection。
来源:oschina
链接:https://my.oschina.net/u/2288619/blog/3178289