I was recently talking with a colleague about the RIL Proxy and it occurred to me that this component isn’t well known and is pretty confusing. I’ve been digging into the RIL Proxy for a little while now so I’ve become pretty comfortable with it, so I thought I’d write a blog that introduces RIL Proxy, then build up to more in-depth blogs on how to debug radio problems using RIL Proxy logging. This first article is just the high level introduction targeted at people who may have heard of RIL Proxy but haven’t worked with it.
Overview of RIL
The Radio Interface Layer (RIL) is an abstraction layer that enables clients to interact with the cellular radio on Windows Mobile (WM) devices. The RIL is split into two main components: the RIL Proxy (Ril.dll), and the RIL Driver (he filename of the driver changes from BSP to BSP, but the default name is RilGsm.dll or RilCdma.dll). The RIL Driver is device specific, so clients should avoid calling directly into the driver. The RIL Proxy layer sits on top of the RIL Driver and provides standard APIs that a client can use to interact with the hardware.
The RIL Proxy is a pass through layer who’s main jobs are to provide notifications of cellular radio changes and coordinate cellular radio related requests from multiple clients. Since the it’s just a pass through layer, the RIL Proxy doesn’t store any state information about the radio or maintain any hardware configurations. There are several components that sit on top of RIL Proxy and abstract radio functionality even further to simplify specific tasks. For example, the SIM Manager provides APIs for reading and writing contact information from/to a SIM card. However, these components are outside the scope of this document; for more information on the components built on top of the RIL Proxy, consult the “RIL Architecture” section of the Windows Mobile 6.0 documentation.
RIL Proxy is a notification based component. To enable RIL Proxy to communicate with an application, each application must register with the RIL Proxy by calling RIL_Initialize(). This API creates a unique instance of a RIL client which the app can interact with directly. An application can create multiple RIL clients by calling RIL_Initialize() multiple times, but there’s no real benefit to doing this so it’s rarely done. When a RIL client is initialized, the application passes the client two callback functions and subscribes to specific classes of notifications.
The first callback function registered with RIL Proxy client is used to receive and process unsolicited notifications. These notifications are generated by the RIL Proxy when the radio or cellular states change. A notification for a particular state change is only sent to a client if the client has subscribed to receive that class of notifications. For example, if the client has registered to receive the RIL_NCLASS_NETWORK class of notifications, then it will receive the notification RIL_NOTIFY_REGSTATUSCHANGED when the cellular radio registers or deregisters on a cellular network.
Async Results Callback
The second callback function registered with the client is response callback. This callback is used to asynchronously pass data to the application. A majority of the functions exported by the RIL Proxy are asynchronous, so no actual data is returned by the API. Instead, the API queues a command with the RIL Driver and returns a command ID. After the command has been processed by the driver, the response callback function is called and given the HRESULT of the command, the command ID, and any requested data. Apps can have multiple commands outstanding and they can differentiate between the responses by matching the command ID for each response, but, for simplicity, most apps issue RIL requests serially so the command ID isn’t necessary in these cases.