【Android架构Telephony篇】数据业务(2)RILJ 【转】

转自 https://blog.csdn.net/u013686019/article/details/49719897
 

 

一、Telephony整体流程

Telephony执行的完整流程如下:

下面自上而下,只关注主干,分层看下代码走向。

 

 

二、Telephony数据业务的RILJ层

 

1、App层

用户点击系统【设置】进行开启/关闭数据业务,调用:

 

 
  1. DataUsageSummary.java (packages\apps\settings\src\com\android\settings)

  2. private void setMobileDataEnabled(int subId, boolean enabled) {

  3. mTelephonyManager.setDataEnabled(subId, enabled);

  4. }


TelephonyManager作为"phone"系统服务的管理类,其获取方式可以:

 

 

 
  1. DataUsageSummary#onCreate()

  2. -->mTelephonyManager = TelephonyManager.from(context);

  3.  
  4. TelephonyManager.java (frameworks\base\telephony\java\android\telephony)

  5. public static TelephonyManager from(Context context) {

  6. return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

  7. }

 

 

在上图中,把"phone"系统服务获取放在了frameworks层,这是因为在frameworks中可以越过Manager类直接获取服务,如:

 

 
  1. TelephonyManager.java (frameworks\base\telephony\java\android\telephony)

  2. private ITelephony getITelephony() {

  3. return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));

  4. }

  5.  
  6. public void setDataEnabled(int subId, boolean enable) {

  7. ITelephony telephony = getITelephony();

  8. telephony.setDataEnabled(subId, enable);

  9. }


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")服务很是另类,其注册流程:

 

 
  1. PhoneApp.java (packages\services\telephony\src\com\android\phone)

  2. public class PhoneApp extends Application {}

  3. PhoneApp#onCreate()

  4. -->PhoneGlobals#onCreate()

  5. ---->PhoneInterfaceManager#init()

  6. ------>PhoneInterfaceManager#publish()

  7. -------->PhoneInterfaceManager#ServiceManager.addService("phone", this);

 

adb shell进去系统,通过service命令可以查看系统注册的所有服务:

 

 
  1. # service list

  2. Found 102 services:

  3. 1 phone: [com.android.internal.telephony.ITelephony]


(2) 继续数据业务流程

 

PhoneInterfaceManager是"phone"服务实现方,对于数据开启/关闭:

 

 
  1. PhoneInterfaceManager.java (packages\services\telephony\src\com\android\phone)

  2. /**

  3. * Set mobile data enabled

  4. * Used by the user through settings etc to turn on/off mobile data

  5. */

  6. @Override

  7. public void setDataEnabled(int subId, boolean enable) {

  8. enforceModifyPermission(); -->a

  9. int phoneId = mSubscriptionController.getPhoneId(subId); -->b

  10. Phone phone = PhoneFactory.getPhone(phoneId);

  11. phone.setDataEnabled(enable);

  12. }


这里的Phone是一个interface。在【Android架构Telephony篇】数据业务(1)总览提到,无线通信有TD-LTE/FDD-LTE/TD-SCDMA/WCDMA/EVDO/CDMA1X/GSM等等很多的网络制式,不同模块可以支持其中的一种或多种。它们之间的区别最简单的例子,比如常说的电信卡、联通卡等等。从软件层面进行抽象就是:

 

 

 

Phone的创建

 

 
  1. PhoneFactory.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)

  2. public static void makeDefaultPhone(Context context) {

  3. PhoneBase phone = null;

  4. int phoneType = TelephonyManager.getPhoneType(networkModes[i]);

  5. if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {

  6. phone = new GSMPhone(context,

  7. sCommandsInterfaces[i], sPhoneNotifier, i);

  8. } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {

  9. phone = new CDMALTEPhone(context,

  10. sCommandsInterfaces[i], sPhoneNotifier, i);

  11. }

  12. }

 

 

这里就根据type创建不同的Phone,我们以GSMPhone为例,setDataEnabled()调用的就是:

 

 
  1. GSMPhone.java (frameworks\opt\telephony\src\java\com\android\internal\telephony\gsm)

  2. public void setDataEnabled(boolean enable) {

  3. mDcTracker.setDataEnabled(enable);

  4. }


mDcTracker是一个Handler,

 

 

 

 
  1. DcTrackerBase.java (frameworks\opt\telephony\src\java\com\android\internal\telephony\dataconnection)

  2. public void setDataEnabled(boolean enable) {

  3. Message msg = obtainMessage(DctConstants.CMD_SET_USER_DATA_ENABLE);

  4. msg.arg1 = enable ? 1 : 0;

  5. sendMessage(msg);

  6. }

  7. public void handleMessage(Message msg) {

  8. switch (msg.what) {

  9. case DctConstants.CMD_SET_USER_DATA_ENABLE: {

  10. final boolean enabled = (msg.arg1 == DctConstants.ENABLED) ? true : false;

  11. onSetUserDataEnabled(enabled);

  12. break;

  13. }

  14. }

  15.  
  16. DcTrackerBase#onSetUserDataEnabled()

  17. -->DcTrackerBase#onTrySetupData()

 

DcTrackerBase发送CMD_SET_USER_DATA_ENABLE信息,并自己处理,最终调用到onTrySetupData(),实现onTrySetupData()的地方:

 

 
  1. DcTracker.java (opt\telephony\src\java\com\android\internal\telephony\dataconnection)

  2. protected boolean onTrySetupData(String reason) {

  3. setupDataOnConnectableApns(reason);

  4. return true;

  5. }


setupDataOnConnectableApns()顾名思义就是使用可用的APN建立数据连接,之后:

 

 
  1. DcTracker.java (opt\telephony\src\java\com\android\internal\telephony\dataconnection)

  2. setupDataOnConnectableApns(reason, RetryFailures.ALWAYS);

  3. -->trySetupData(apnContext, waitingApns);

  4. ---->setupData(apnContext, radioTech);

  5.  
  6. private boolean setupData(ApnContext apnContext, int radioTech) {

  7. // 用于连接DcTracker和DataConnection

  8. DcAsyncChannel dcac = null;

  9.  
  10. if (dcac == null) {

  11. // 获取/创建DcAsyncChannel对象

  12. }

  13.  
  14. // 更新apnContext

  15. apnContext.setDataConnectionAc(dcac);

  16. apnContext.setApnSetting(apnSetting);

  17. apnContext.setState(DctConstants.State.CONNECTING);

  18. mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());

  19.  
  20. // 拨号成功后发送EVENT_DATA_SETUP_COMPLETE信息

  21. Message msg = obtainMessage();

  22. msg.what = DctConstants.EVENT_DATA_SETUP_COMPLETE;

  23. msg.obj = new Pair<ApnContext, Integer>(apnContext, generation);

  24. dcac.bringUp(apnContext, getInitialMaxRetry(), profileId, radioTech,

  25. mAutoAttachOnCreation.get(), msg, generation);

  26. return true;

  27. }

 

调用DcAsyncChannel的bringUp(),向DataConnection发送建立连接消息EVENT_CONNECT:

 

 
  1. DcAsyncChannel.java (opt\telephony\src\java\com\android\internal\telephony\dataconnection)

  2. /**

  3. * Bring up a connection to the apn and return an AsyncResult in onCompletedMsg.

  4. * Used for cellular networks that use Acesss Point Names (APN) such

  5. * as GSM networks.

  6. */

  7. public void bringUp(ApnContext apnContext, int initialMaxRetry, int profileId,

  8. int rilRadioTechnology, boolean retryWhenSSChange, Message onCompletedMsg,

  9. int connectionGeneration) {

  10. sendMessage(DataConnection.EVENT_CONNECT,

  11. new ConnectionParams(apnContext, initialMaxRetry, profileId,

  12. rilRadioTechnology, retryWhenSSChange, onCompletedMsg,

  13. connectionGeneration));

  14. }

 

 

DataConnection处理EVENT_CONNECT:

 
  1. DataConnection.java (opt\telephony\src\java\com\android\internal\telephony\dataconnection)

  2. private class DcInactiveState extends State { -->a

  3. public boolean processMessage(Message msg) {

  4. case EVENT_CONNECT:

  5. ConnectionParams cp = (ConnectionParams) msg.obj;

  6. if (initConnection(cp)) { -->b

  7. onConnect(mConnectionParams); -->c

  8. transitionTo(mActivatingState);

  9. } else {

  10. log("DcInactiveState: msg.what=EVENT_CONNECT initConnection failed");

  11. notifyConnectCompleted(cp, DcFailCause.UNACCEPTABLE_NETWORK_PARAMETER,

  12. false);

  13. }

  14. retVal = HANDLED;

  15. break;

  16. }

  17. }

a, DataConnection是一个状态机,其初始状态:

 

 

 
  1. private DcInactiveState mInactiveState = new DcInactiveState();

  2. private DataConnection() {

  3. setInitialState(mInactiveState);

  4. }

所以这里调用DcInactiveState类的processMessage()处理EVENT_CONNECT信息。

 

b, 检测参数合法性

c, 调用onConnect()启动连接建立

 

 
  1. /**

  2. * Begin setting up a data connection, calls setupDataCall

  3. * and the ConnectionParams will be returned with the

  4. * EVENT_SETUP_DATA_CONNECTION_DONE AsyncResul.userObj.

  5. */

  6. private void onConnect(ConnectionParams cp) {

  7.  
  8. // msg.obj will be returned in AsyncResult.userObj;

  9. Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);

  10. msg.obj = cp;

  11.  
  12. mPhone.mCi.setupDataCall(

  13. Integer.toString(cp.mRilRat + 2),

  14. Integer.toString(cp.mProfileId),

  15. mApnSetting.apn, mApnSetting.user, mApnSetting.password,

  16. Integer.toString(authType),

  17. protocol, msg);

  18. }


mCi是一个CommandsInterface,实现它的是RIL:

 

 

 
  1. RIL.java (opt\telephony\src\java\com\android\internal\telephony)

  2. public final class RIL extends BaseCommands implements CommandsInterface {

  3. }


这里,就来到了开篇流程图中的“RILJ”,在继续下去之前,稍微提下Android中本地socket通信

 

(3)socket进程间通信

Linux中的socket除了可以用于不同机器之间的网络通信,还可以用于同一台机器的进程间通信。以Telephony为例,RILJ的java进程和RILC的c守护进程之间就是通过"/dev/socket/rild"这个socket进行通信的。

a, socket建立

 

 
  1. RIL.java (opt\telephony\src\java\com\android\internal\telephony)

  2. LocalSocket mSocket;

  3. String rilSocket = "rild";

  4. s = new LocalSocket();

  5. l = new LocalSocketAddress(rilSocket, LocalSocketAddress.Namespace.RESERVED);

  6. s.connect(l);

  7.  
  8. mSocket = s;

 

 

b, 数据发送

 

 
  1. RIL.java (opt\telephony\src\java\com\android\internal\telephony)

  2. class RILSender extends Handler implements Runnable {

  3. @Override public void handleMessage(Message msg) {

  4. switch (msg.what) {

  5. case EVENT_SEND:

  6. try {

  7. LocalSocket s;

  8. s = mSocket;

  9.  
  10. synchronized (mRequestList) {

  11. mRequestList.append(rr.mSerial, rr);

  12. }

  13.  
  14. byte[] data;

  15.  
  16. data = rr.mParcel.marshall();

  17. rr.mParcel.recycle();

  18. rr.mParcel = null;

  19.  
  20. // parcel length in big endian

  21. dataLength[0] = dataLength[1] = 0;

  22. dataLength[2] = (byte)((data.length >> 8) & 0xff);

  23. dataLength[3] = (byte)((data.length) & 0xff);

  24.  
  25. s.getOutputStream().write(dataLength);

  26. s.getOutputStream().write(data);

  27. }

  28. }

  29. }


c, 数据接收

 

 

 

 
  1. RIL.java (opt\telephony\src\java\com\android\internal\telephony)

  2. class RILReceiver implements Runnable {

  3. try {

  4. InputStream is = mSocket.getInputStream();

  5. for (;;) {

  6. Parcel p;

  7. length = readRilMessage(is, buffer);

  8. if (length < 0) {

  9. // End-of-stream reached

  10. break;

  11. }

  12.  
  13. p = Parcel.obtain();

  14. p.unmarshall(buffer, 0, length);

  15. p.setDataPosition(0);

  16. processResponse(p); // 数据处理

  17. p.recycle();

  18. }

  19. }

  20. }


有了这个知识,RILJ就容易理解了。

 

(4)RILJ

 

 
  1. RIL.java (opt\telephony\src\java\com\android\internal\telephony)

  2. @Override

  3. public void setupDataCall(String radioTechnology, String profile, String apn,

  4. String user, String password, String authType, String protocol,

  5. Message result) {

  6. RILRequest rr

  7. = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);

  8.  
  9. rr.mParcel.writeInt(7);

  10.  
  11. rr.mParcel.writeString(radioTechnology);

  12. rr.mParcel.writeString(profile);

  13. rr.mParcel.writeString(apn);

  14. rr.mParcel.writeString(user);

  15. rr.mParcel.writeString(password);

  16. rr.mParcel.writeString(authType);

  17. rr.mParcel.writeString(protocol);

  18.  
  19. send(rr);

  20. }

  21.  
  22. private void send(RILRequest rr) {

  23. Message msg;

  24.  
  25. if (mSocket == null) {

  26. rr.onError(RADIO_NOT_AVAILABLE, null);

  27. rr.release();

  28. return;

  29. }

  30.  
  31. msg = mSender.obtainMessage(EVENT_SEND, rr);

  32.  
  33. acquireWakeLock();

  34.  
  35. msg.sendToTarget();

  36. }

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值