Radiointerfacelayer Ril_woker Init分析
加载radiointerfacelayer.js,
获取ro.moz.ril.numclients ,system/build.prop ro.moz.ril.numclients=2 在build.prop 文件中定义。
具体代码如下:
// Initialize shared preference "ril.numRadioInterfaces" according to system // property. try { Services.prefs.setIntPref(kPrefRilNumRadioInterfaces, (function() { // When Gonk property "ro.moz.ril.numclients" is not set, return 1; if // explicitly set to any number larger-equal than 0, return num; else, return // 1 for compatibility. try { let numString = libcutils.property_get("ro.moz.ril.numclients","1"); let num = parseInt(numString, 10); if (num >= 0) { return num; } } catch (e) {}
return1; })()); }catch (e) {} |
在RadioInterfaceLayer 定义numRadioInterfaces:
XPCOMUtils.defineLazyGetter(RadioInterfaceLayer.prototype, "numRadioInterfaces",function() { try { return Services.prefs.getIntPref(kPrefRilNumRadioInterfaces); } catch(e) {}
return1; }); |
function RadioInterfaceLayer() { let workerMessenger = new WorkerMessenger(); workerMessenger.init();
let numIfaces = this.numRadioInterfaces; if (DEBUG) debug(numIfaces + " interfaces"); this.radioInterfaces = []; for (let clientId = 0; clientId < numIfaces; clientId++) { this.radioInterfaces.push(new RadioInterface(clientId, workerMessenger)); } Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
gMessageManager.init(this); gRadioEnabledController.init(this); gDataConnectionManager.init(this); } |
WorkerMessenger 构造函数:
function WorkerMessenger() { // Initial owning attributes. this.radioInterfaces = []; this.tokenCallbackMap = {};
this.worker = new ChromeWorker("resource://gre/modules/ril_worker.js"); this.worker.onerror = this.onerror.bind(this); this.worker.onmessage = this.onmessage.bind(this); } |
a) 在WorkerMessenger构造函数中,创建radioInterfaces,创建tokenCallbackMap
b) 创建chromeworker,加载ril_worker.js
在ril_worker.js中,定义ContextPool对象,并且通过onmessage/onerror 获取WorkerMessenger的消息
c) 创建ChromeWorker,绑定onmessage/onerror函数,处理ril_worker消息
Webworker 的相关介绍如下:
http://www.cnblogs.com/_franky/archive/2010/11/23/1885773.html
https://developer.mozilla.org/en-US/docs/Web/API/ChromeWorker
Init函数设置参数options,通过this.send(null,"setInitialOptions", options); 发送到ril_worker.js
在ril_worker.js 中,通过onmessage 函数接收,radiointerface消息。
当前clientID = null,会调用method.call(this, aMessage);
此时method = setInitialOptions,调用ContextPool对象的
setInitialOptions 函数,设置全局属性。
根据this.numRadioInterfaces;创建radiointerface对象,并将rdiointerface对象加入radioInterfaces
RadioInterface 的构造函数主要功能:
1) Radiointerface.clientId 属性初始化
2) Radiointerface.workerMessenger 对象初始化
i. 将Radiointerface.workerMessenger 的send方法与radiointerfacelayer对象中的WorkerMessenger.send方法进行绑定。并添加radiointerface aClientId参数
ii. 将Radiointerface.workerMessenger的sendWithIPCMessage 方法与radiointerfacelayer对象中的WorkerMessenger. sendWithIPCMessage方法进行绑定。并添加radiointerface aClientId参数
3) 调用aWorkerMessenger 的registerClient方法
registerClient: function(aClientId, aRadioInterface) { if (DEBUG) this.debug(aClientId, "Starting RIL Worker");
// Keep a reference so that we can dispatch unsolicited messages to it. this.radioInterfaces[aClientId] = aRadioInterface;
this.send(null, "registerClient", { clientId: aClientId }); gSystemWorkerManager.registerRilWorker(aClientId, this.worker); },
|
主要功能:
i. 保存radiointerface对象
ii. 向ril_worker 发送registerClient 消息
在ril_worker.js 的ContextPool的registerClient函数,处理如下:
registerClient: function(aOptions) { let clientId = aOptions.clientId; this._contexts[clientId] = new Context(clientId); }, |
创建context对象,并加入this._contexts[clientId],其中
this= ContextPool。
Context构造函数如下:
function Context(aClientId) { this.clientId = aClientId;
this.Buf = new BufObject(this); this.Buf.init();
this.RIL = new RilObject(this); this.RIL.initRILState(); } |
保存aClientId
为context对象创建Buf对象并初始化。
为context对象创建RIL对象并初始化。
iii. 调用gSystemWorkerManager.registerRilWorker方法
具体实现在:
B2G/gecko/dom/system/gonk/SystemWorkerManager.cpp中
gSystemWorkerManager registerRilWorker 主要功能:
(一) 获取跨线程的分发对象wctd。
(二) 调用RilConsumer::Register
其中RilConsumer::Register的具体实现在:
B2G/gecko/ipc/ril/Ril.cpp中。
该函数功能如下:
A. 创建ConnectWorkerToRIL 对象并调用PostTask,将当前的ConnectWorkerToRIL消息队列里面,即启动task
其中,ConnectWorkerToRIL 使用:
JS_DefineFunction(aCx,workerGlobal,
"postRILMessage",PostToRIL,2, 0);
将ril_worker 中的postRILMessage 和
ConnectWorkerToRIL中的PostToRIL 进行绑定。而PostToRIL函数实现了向RILProxy socket发送数据。
B. 创建RilConsumer对象,并存放到
sRilConsumers[aClientId]中,其中RilConsumer 构造函数实现了连接rilproxy socket。并通过ReceiveSocketData读取socket数据。
当接收到rilproxy socket消息时,通过ReceiveSocketData函数,new DispatchRILEvent。并将DispatchRILEvent加入消息队列。
其中DispatchRILEvent 的runtask 中,实现了 ril_worker.js中的onRILMessage 函数。
4) 通过getSupportedNetworkTypes获取当前支持的网络类型。
5) 创建rilcontext对象
6) 创建voicemailInfo对象
7) 获取settings的相应配置项, 并在radiointerface对象的handle函数中处理。
let lock = gSettingsService.createLock();
// Read the "time.clock.automatic-update.enabled" setting to see if // we need to adjust the system clock time by NITZ or SNTP. lock.get(kSettingsClockAutoUpdateEnabled, this);
// Read the "time.timezone.automatic-update.enabled" setting to see if // we need to adjust the system timezone by NITZ. lock.get(kSettingsTimezoneAutoUpdateEnabled, this);
// Set "time.clock.automatic-update.available" to false when starting up. this.setClockAutoUpdateAvailable(false);
// Set "time.timezone.automatic-update.available" to false when starting up. this.setTimezoneAutoUpdateAvailable(false);
// Read the Cell Broadcast Search List setting, string of integers or integer // ranges separated by comma, to set listening channels. lock.get(kSettingsCellBroadcastSearchList, this); |
8) 添加监听,在radiointerface对象的observe函数中进行处理。
Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false); Services.obs.addObserver(this, kSysClockChangeObserverTopic, false); Services.obs.addObserver(this, kScreenStateChangedTopic, false);
Services.obs.addObserver(this, kNetworkConnStateChangedTopic, false); Services.prefs.addObserver(kPrefCellBroadcastDisabled, this,false);
|
9) 其他
this.portAddressedSmsApps = {}; this.portAddressedSmsApps[WAP.WDP_PORT_PUSH] = this.handleSmsWdpPortPush.bind(this);
this._receivedSmsSegmentsMap = {};
this._sntp = new Sntp(this.setClockBySntp.bind(this), Services.prefs.getIntPref("network.sntp.maxRetryCount"), Services.prefs.getIntPref("network.sntp.refreshPeriod"), Services.prefs.getIntPref("network.sntp.timeout"), Services.prefs.getCharPref("network.sntp.pools").split(";") Services.prefs.getIntPref("network.sntp.port")); |
/** * nsIObserver interface methods. */
observe: function(subject, topic, data) { switch (topic) { case NS_XPCOM_SHUTDOWN_OBSERVER_ID: for (let radioInterface of this.radioInterfaces) { radioInterface.shutdown(); } this.radioInterfaces = null; Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); break; } }, |
gMessageManager 对象主要用于和rilcontenthelper通信。使用ppmm对象监听cpmm的消息。
init: function(ril) { this.ril = ril;
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); Services.obs.addObserver(this, kSysMsgListenerReadyObserverTopic, false); this._registerMessageListeners(); },
|
在gMessageManager init函数中,主要有以下功能:
1. 获取当前的radiointerfacelayer对象。
2. 注册监听,并在gMessageManager 的Observe函数中进行处理
3. 注册消息处理。其中_registerMessageListeners的具体实现如下:
_registerMessageListeners: function() { ppmm.addMessageListener("child-process-shutdown",this); for (let msgname of RIL_IPC_MOBILECONNECTION_MSG_NAMES) { ppmm.addMessageListener(msgname, this); } for (let msgname of RIL_IPC_MOBILENETWORK_MSG_NAMES) { ppmm.addMessageListener(msgname, this); } for (let msgName of RIL_IPC_ICCMANAGER_MSG_NAMES) { ppmm.addMessageListener(msgName, this); } for (let msgname of RIL_IPC_VOICEMAIL_MSG_NAMES) { ppmm.addMessageListener(msgname, this); } for (let msgname of RIL_IPC_CELLBROADCAST_MSG_NAMES) { ppmm.addMessageListener(msgname, this); } }, |
具体的处理函数在gMessageManager对象的receiveMessage中。
init: function(ril) { _ril = ril; }, |
gRadioEnabledController 函数比较简单,保存当前的ril对象。
具体作用还要研究。
获取settings有关数据的设置,在handle函数进行处理。
监听settings 有关数据的设置,在observe函数中进行处理。
init: function(ril) { if (!ril) { return; }
this._connectionHandlers = []; for (let clientId = 0; clientId < ril.numRadioInterfaces; clientId++) { let radioInterface = ril.getRadioInterface(clientId); this._connectionHandlers.push( new DataConnectionHandler(clientId, radioInterface)); } let lock = gSettingsService.createLock(); // Read the APN data from the settings DB. lock.get("ril.data.apnSettings",this); // Read the data enabled setting from DB. lock.get("ril.data.enabled",this); lock.get("ril.data.roaming_enabled",this); // Read the default client id for data call. lock.get("ril.data.defaultServiceId",this);
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false); Services.obs.addObserver(this, kNetworkInterfaceStateChangedTopic, false); }, |