【Android架构Telephony篇】数据业务(2)RILJ 【转】
转自 https://blog.csdn.net/u013686019/article/details/49719897
一、Telephony整体流程
Telephony执行的完整流程如下:
下面自上而下,只关注主干,分层看下代码走向。
二、Telephony数据业务的RILJ层
1、App层
用户点击系统【设置】进行开启/关闭数据业务,调用:
-
DataUsageSummary.java (packages\apps\settings\src\com\android\settings) -
private void setMobileDataEnabled(int subId, boolean enabled) { -
mTelephonyManager.setDataEnabled(subId, enabled); -
}
TelephonyManager作为"phone"系统服务的管理类,其获取方式可以:
-
DataUsageSummary#onCreate() -
-->mTelephonyManager = TelephonyManager.from(context); -
TelephonyManager.java (frameworks\base\telephony\java\android\telephony) -
public static TelephonyManager from(Context context) { -
return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); -
}
在上图中,把"phone"系统服务获取放在了frameworks层,这是因为在frameworks中可以越过Manager类直接获取服务,如:
-
TelephonyManager.java (frameworks\base\telephony\java\android\telephony) -
private ITelephony getITelephony() { -
return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE)); -
} -
public void setDataEnabled(int subId, boolean enable) { -
ITelephony telephony = getITelephony(); -
telephony.setDataEnabled(subId, enable); -
}
Telephony提供的操作无线模组的方法可以通过ITelephony.aidl文件查看:
frameworks/base/telephony/java/com/android/internal/telephony/ITelephony.aidl
2、Framework层
(1)"phone"系统服务注册
系统服务绝大部分都在frameworks/base/services/java/com/android/server/SystemServer.java文件中统一注册,但TELEPHONY_SERVICE("phone")服务很是另类,其注册流程:
-
PhoneApp.java (packages\services\telephony\src\com\android\phone) -
public class PhoneApp extends Application {} -
PhoneApp#onCreate() -
-->PhoneGlobals#onCreate() -
---->PhoneInterfaceManager#init() -
------>PhoneInterfaceManager#publish() -
-------->PhoneInterfaceManager#ServiceManager.addService("phone", this);
adb shell进去系统,通过service命令可以查看系统注册的所有服务:
-
# service list -
Found 102 services: -
1 phone: [com.android.internal.telephony.ITelephony]
(2) 继续数据业务流程
PhoneInterfaceManager是"phone"服务实现方,对于数据开启/关闭:
-
PhoneInterfaceManager.java (packages\services\telephony\src\com\android\phone) -
/** -
* Set mobile data enabled -
* Used by the user through settings etc to turn on/off mobile data -
*/ -
@Override -
public void setDataEnabled(int subId, boolean enable) { -
enforceModifyPermission(); -->a -
int phoneId = mSubscriptionController.getPhoneId(subId); -->b -
Phone phone = PhoneFactory.getPhone(phoneId); -
phone.setDataEnabled(enable); -
}
这里的Phone是一个interface。在【Android架构Telephony篇】数据业务(1)总览提到,无线通信有TD-LTE/FDD-LTE/TD-SCDMA/WCDMA/EVDO/CDMA1X/GSM等等很多的网络制式,不同模块可以支持其中的一种或多种。它们之间的区别最简单的例子,比如常说的电信卡、联通卡等等。从软件层面进行抽象就是:
Phone的创建:
-
PhoneFactory.java (frameworks\opt\telephony\src\java\com\android\internal\telephony) -
public static void makeDefaultPhone(Context context) { -
PhoneBase phone = null; -
int phoneType = TelephonyManager.getPhoneType(networkModes[i]); -
if (phoneType == PhoneConstants.PHONE_TYPE_GSM) { -
phone = new GSMPhone(context, -
sCommandsInterfaces[i], sPhoneNotifier, i); -
} else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) { -
phone = new CDMALTEPhone(context, -
sCommandsInterfaces[i], sPhoneNotifier, i); -
} -
}
这里就根据type创建不同的Phone,我们以GSMPhone为例,setDataEnabled()调用的就是:
-
GSMPhone.java (frameworks\opt\telephony\src\java\com\android\internal\telephony\gsm) -
public void setDataEnabled(boolean enable) { -
mDcTracker.setDataEnabled(enable); -
}
mDcTracker是一个Handler,
-
DcTrackerBase.java (frameworks\opt\telephony\src\java\com\android\internal\telephony\dataconnection) -
public void setDataEnabled(boolean enable) { -
Message msg = obtainMessage(DctConstants.CMD_SET_USER_DATA_ENABLE); -
msg.arg1 = enable ? 1 : 0; -
sendMessage(msg); -
} -
public void handleMessage(Message msg) { -
switch (msg.what) { -
case DctConstants.CMD_SET_USER_DATA_ENABLE: { -
final boolean enabled = (msg.arg1 == DctConstants.ENABLED) ? true : false; -
onSetUserDataEnabled(enabled); -
break; -
} -
} -
DcTrackerBase#onSetUserDataEnabled() -
-->DcTrackerBase#onTrySetupData()
DcTrackerBase发送CMD_SET_USER_DATA_ENABLE信息,并自己处理,最终调用到onTrySetupData(),实现onTrySetupData()的地方:
-
DcTracker.java (opt\telephony\src\java\com\android\internal\telephony\dataconnection) -
protected boolean onTrySetupData(String reason) { -
setupDataOnConnectableApns(reason); -
return true; -
}
setupDataOnConnectableApns()顾名思义就是使用可用的APN建立数据连接,之后:
-
DcTracker.java (opt\telephony\src\java\com\android\internal\telephony\dataconnection) -
setupDataOnConnectableApns(reason, RetryFailures.ALWAYS); -
-->trySetupData(apnContext, waitingApns); -
---->setupData(apnContext, radioTech); -
private boolean setupData(ApnContext apnContext, int radioTech) { -
// 用于连接DcTracker和DataConnection -
DcAsyncChannel dcac = null; -
if (dcac == null) { -
// 获取/创建DcAsyncChannel对象 -
} -
// 更新apnContext -
apnContext.setDataConnectionAc(dcac); -
apnContext.setApnSetting(apnSetting); -
apnContext.setState(DctConstants.State.CONNECTING); -
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType()); -
// 拨号成功后发送EVENT_DATA_SETUP_COMPLETE信息 -
Message msg = obtainMessage(); -
msg.what = DctConstants.EVENT_DATA_SETUP_COMPLETE; -
msg.obj = new Pair(apnContext, generation); -
dcac.bringUp(apnContext, getInitialMaxRetry(), profileId, radioTech, -
mAutoAttachOnCreation.get(), msg, generation); -
return true; -
}
调用DcAsyncChannel的bringUp(),向DataConnection发送建立连接消息EVENT_CONNECT:
-
DcAsyncChannel.java (opt\telephony\src\java\com\android\internal\telephony\dataconnection) -
/** -
* Bring up a connection to the apn and return an AsyncResult in onCompletedMsg. -
* Used for cellular networks that use Acesss Point Names (APN) such -
* as GSM networks. -
*/ -
public void bringUp(ApnContext apnContext, int initialMaxRetry, int profileId, -
int rilRadioTechnology, boolean retryWhenSSChange, Message onCompletedMsg, -
int connectionGeneration) { -
sendMessage(DataConnection.EVENT_CONNECT, -
new ConnectionParams(apnContext, initialMaxRetry, profileId, -
rilRadioTechnology, retryWhenSSChange, onCompletedMsg, -
connectionGeneration)); -
}
DataConnection处理EVENT_CONNECT:
-
DataConnection.java (opt\telephony\src\java\com\android\internal\telephony\dataconnection) -
private class DcInactiveState extends State { -->a -
public boolean processMessage(Message msg) { -
case EVENT_CONNECT: -
ConnectionParams cp = (ConnectionParams) msg.obj; -
if (initConnection(cp)) { -->b -
onConnect(mConnectionParams); -->c -
transitionTo(mActivatingState); -
} else { -
log("DcInactiveState: msg.what=EVENT_CONNECT initConnection failed"); -
notifyConnectCompleted(cp, DcFailCause.UNACCEPTABLE_NETWORK_PARAMETER, -
false); -
} -
retVal = HANDLED; -
break; -
} -
}
a, DataConnection是一个状态机,其初始状态:
-
private DcInactiveState mInactiveState = new DcInactiveState(); -
private DataConnection() { -
setInitialState(mInactiveState); -
}
所以这里调用DcInactiveState类的processMessage()处理EVENT_CONNECT信息。
b, 检测参数合法性
c, 调用onConnect()启动连接建立
-
/** -
* Begin setting up a data connection, calls setupDataCall -
* and the ConnectionParams will be returned with the -
* EVENT_SETUP_DATA_CONNECTION_DONE AsyncResul.userObj. -
*/ -
private void onConnect(ConnectionParams cp) { -
// msg.obj will be returned in AsyncResult.userObj; -
Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp); -
msg.obj = cp; -
mPhone.mCi.setupDataCall( -
Integer.toString(cp.mRilRat + 2), -
Integer.toString(cp.mProfileId), -
mApnSetting.apn, mApnSetting.user, mApnSetting.password, -
Integer.toString(authType), -
protocol, msg); -
}
mCi是一个CommandsInterface,实现它的是RIL:
-
RIL.java (opt\telephony\src\java\com\android\internal\telephony) -
public final class RIL extends BaseCommands implements CommandsInterface { -
}
这里,就来到了开篇流程图中的“RILJ”,在继续下去之前,稍微提下Android中本地socket通信。
(3)socket进程间通信
Linux中的socket除了可以用于不同机器之间的网络通信,还可以用于同一台机器的进程间通信。以Telephony为例,RILJ的java进程和RILC的c守护进程之间就是通过"/dev/socket/rild"这个socket进行通信的。
a, socket建立
-
RIL.java (opt\telephony\src\java\com\android\internal\telephony) -
LocalSocket mSocket; -
String rilSocket = "rild"; -
s = new LocalSocket(); -
l = new LocalSocketAddress(rilSocket, LocalSocketAddress.Namespace.RESERVED); -
s.connect(l); -
mSocket = s;
b, 数据发送
-
RIL.java (opt\telephony\src\java\com\android\internal\telephony) -
class RILSender extends Handler implements Runnable { -
@Override public void handleMessage(Message msg) { -
switch (msg.what) { -
case EVENT_SEND: -
try { -
LocalSocket s; -
s = mSocket; -
synchronized (mRequestList) { -
mRequestList.append(rr.mSerial, rr); -
} -
byte[] data; -
data = rr.mParcel.marshall(); -
rr.mParcel.recycle(); -
rr.mParcel = null; -
// parcel length in big endian -
dataLength[0] = dataLength[1] = 0; -
dataLength[2] = (byte)((data.length >> 8) & 0xff); -
dataLength[3] = (byte)((data.length) & 0xff); -
s.getOutputStream().write(dataLength); -
s.getOutputStream().write(data); -
} -
} -
}
c, 数据接收
-
RIL.java (opt\telephony\src\java\com\android\internal\telephony) -
class RILReceiver implements Runnable { -
try { -
InputStream is = mSocket.getInputStream(); -
for (;;) { -
Parcel p; -
length = readRilMessage(is, buffer); -
if (length < 0) { -
// End-of-stream reached -
break; -
} -
p = Parcel.obtain(); -
p.unmarshall(buffer, 0, length); -
p.setDataPosition(0); -
processResponse(p); // 数据处理 -
p.recycle(); -
} -
} -
}
有了这个知识,RILJ就容易理解了。
(4)RILJ
-
RIL.java (opt\telephony\src\java\com\android\internal\telephony) -
@Override -
public void setupDataCall(String radioTechnology, String profile, String apn, -
String user, String password, String authType, String protocol, -
Message result) { -
RILRequest rr -
= RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result); -
rr.mParcel.writeInt(7); -
rr.mParcel.writeString(radioTechnology); -
rr.mParcel.writeString(profile); -
rr.mParcel.writeString(apn); -
rr.mParcel.writeString(user); -
rr.mParcel.writeString(password); -
rr.mParcel.writeString(authType); -
rr.mParcel.writeString(protocol); -
send(rr); -
} -
private void send(RILRequest rr) { -
Message msg; -
if (mSocket == null) { -
rr.onError(RADIO_NOT_AVAILABLE, null); -
rr.release(); -
return; -
} -
msg = mSender.obtainMessage(EVENT_SEND, rr); -
acquireWakeLock(); -
msg.sendToTarget(); -
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
