In advance, this article is based on AOSP and basically from the perspective of RILJ. I am also a beginner, if there is something wrong, please give me some advice
1. Concept
- RIL is required to interact with the underlying modem. RIL is divided into two parts: RILJ and RILC
- RILJ is responsible for interacting with the upper layer (java). He is in the same process as the phone. For example, the request of the upper layer will be sent to RILC through RILJ. This process is socket communication.
- In the rild process, RILC is responsible for docking with RILJ (C + +) upward and modem downward.
- HIDL is the communication interface between RILJ and RILC
In order to better understand HIDL, take an example. For example, PC, you think that playing games is not suck, maybe CPU or GPU has bottlenecks, so you can change the corresponding modules at this time. This is because PCs have universal interfaces. If you are not satisfied with one piece, you can change one piece alone. There is no need to change the whole piece. But the mobile phone suck, and the game is not powerful. No matter CPU or GPU, you have to change the whole machine because there is no universal interface.
2. Interaction
There are two kinds of interaction, one is the active query of the upper layer, and the other is the active report of the lower layer.
Active query is divided into request and modem solicited response:
- Most of the code for executing query operations is in RIL Java inside
- The codes that receive sol response are in radioresponse In Java
unsolicited msg:
- The corresponding codes are in radioindication In Java
HIDL:
- The code is in hardware/interfaces/radio, and different versions are distinguished. There is iRadio under each version hal,IRadioIndication.hal,IRadioResponse.hal,types.hal these files basically correspond to the above
- The corresponding code of RILC may be under hardware/ril/libril /, and their code is C++
3. Examples
- Active query:
private void handleRadioAvailable() { mCi.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE)); mCi.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE)); mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY)); mCi.areUiccApplicationsEnabled(obtainMessage(EVENT_GET_UICC_APPS_ENABLEMENT_DONE)); startLceAfterRadioIsAvailable(); }
1. In gsmcdmaphone In handleradioavailable, in line 2, first call obtainMessage to create a Message object. There are two key points in this place:
- obtainMessage is a handler method, that is, GsmCdmaPhone is a handler. There will also be corresponding handleMessage rewriting and corresponding event processing
- obtainMessage is a handler method, that is, GsmCdmaPhone is a handler. There will also be corresponding handleMessage rewriting and corresponding event processing
- Event is EVENT_GET_BASEBAND_VERSION_DONE
@Override public void getBasebandVersion(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_BASEBAND_VERSION, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getBasebandVersion(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getBasebandVersion", e); } } }
2. Call getBasebandVersion to process the generated Message
- In line 5, use obtainRequest to generate a RILRequest from the incoming Message and put it into a list. Its position in the list is mSerial
- The number of this RILRequest is RIL_REQUEST_BASEBAND_VERSION
- In line 11, use the HIDL interface to notify RILC to query BASEBAND_VERSION and pass the previously obtained mSerial to RILC
public void getBasebandVersionResponse(RadioResponseInfo responseInfo, String version) { responseString(responseInfo, version); } private void responseString(RadioResponseInfo responseInfo, String str) { RILRequest rr = mRil.processResponse(responseInfo); if (rr != null) { if (responseInfo.error == RadioError.NONE) { sendMessageResponse(rr.mResult, str); } mRil.processResponseDone(rr, responseInfo, str); } }
3. When the modem finds the result and returns the result to RILJ through RILC, call the HIDL interface getBasebandVersionResponse to notify
- In line 2, the received information is directly passed to responseString for processing
- In line 6, get the RILRequest created before through the mSerial passed to RILC
- In line 9, rr Mrresult is the Message created at the beginning. Find the original handler (GsmCdmaPhone) through Message, and return the Message and the obtained response (String) to the handler in the form of AsyncResult
- After receiving the Message, the handler uses the handleMessage function to process the corresponding MSG What is the event when the Message was created before_ GET_ BASEBAND_ VERSION_ DONE
- modem actively reports:
private void responseDataCallListChanged(int indicationType, List<?> dcList) { mRil.processIndication(indicationType); if (RIL.RILJ_LOGD) mRil.unsljLogRet(RIL_UNSOL_DATA_CALL_LIST_CHANGED, dcList); ArrayList<DataCallResponse> response = RIL.convertDataCallResultList(dcList); mRil.mDataCallListChangedRegistrants.notifyRegistrants( new AsyncResult(null, response, null)); }
1. The unsol message can be simpler, that is, the upper layer does not need to trigger the request, and the lower layer directly calls the HIDL interface to report
2. After parsing the data response in line 6, notify all subscribers through notify registrants in line 7
3. For specific subscribers, you can look at the place of the add member in mdatcalllistchanged registers, that is, the place where registerForDataCallListChanged is called
4. The method of notifying the subscriber is to traverse the list and take out each registry. This data structure is also a bit similar to Message. When it is created, it saves the corresponding handler and other information. Through the handler, the corresponding event and the result returned by the modem are sent to the handler for processing. For example, the event to be processed by the handler is EVENT_RECEIVE_NETWORK_SCAN_RESULT