Android directly communicates with RILD through Socket

Source: Internet
Author: User
Tags connection reset

1RIL_J communicates with RIL_C

The upper layer usually needs to communicate with RILD through Socket, which is implemented at the RIL_JAVA layer;

Perform the Framework -- native following this code process:

Phone -- RIL_JAVA --> RIL_CPP

Can I directly communicate with RILD (RIL_CPP?

Yes, because the rild socket used for communication can communicate with RILD through this socket;

However, in practice, reliable use is not feasible, because when RILD is created,

The design initialization determines the number of clients supported by RILD at the same time:

A single card supports only one client;

The dual-card implementation code provides two methods:

1) Two RIL clients on the dual-card correspond to an RILD server, which is distinguished by tags SUB0 and SUB1. The data flow in the RILD corresponds to two entities;

2) a ril client corresponds to an RILD server, that is, dual-card, there will be multiple RILD Processes

Due to the special nature of the Phone process, the resident process will establish a connection with RILD at startup as the RILD client.

Therefore, if you establish a connection with RILD through socket, the connection between the original Phone and RILD will be disconnected;

This may cause conflicts and exceptions, unless you delete your own Phone;

Generally, third-party dialing software is implemented based on Phone.

Because all the upper-Layer Code is processed through the Framework and then passed with the C/C ++ layer;

Some previous practices are to send requests from the underlying layer to the upper layer, call the requests through the normal process at the upper layer, and then pass the requests to the underlying layer,

This is not very reasonable, but it has to be done;

If you have such a requirement, you can test the function of the mobile phone without starting the upper layer, or directly communicate with RILD at the bottom layer.

For example, how does one implement the network communication function?

You must establish a connection with the RILD layer directly through the socket at the underlying layer C for communication;

The following describes the implementation process:

2. Create a socket and connect
SendAtFd createToRildFd (void) {sendAtFd =-1; // create a socket and connect fd = socket_local_client (SOCKET_NAME_RILD, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); if (fd <0) {perror ("opening radio socket"); exit (-1) ;}// Save the FD s_send_at_fd = fd; return fd;} that communicates with RILD ;}

The socket created here is a UNIX socket, the parameter is different from the network socket,

The struct uses sockaddr_un. The field parameter should be PF_LOCAL,The communication type should be SOCK_STREAM or SOCK_DGRAM.

For more information about UNIX local sockets, see the following documents:

Http://zerocool60.blog.163.com/blog/static/35270508200772955536291/

3. Initiate a connection to RILD
SendAtErrnoType setupToRild (void) {sendAtErrnoType result = E_SUCCESS; char recvBuffer [RECV_BUFFER_LEN] = {0}; Parcel recvP; sendAtFd fd = s_send_at_fd;//Initiate a connection to RILDChar * SUB1 = "SUB1"; int res = send (fd, (const void *) SUB1, strlen (SUB1), 0); // receives RILD return, create a connection while (1) {sleep (10); // wait for receiving data from the server int recvLen = recv (fd, recvBuffer, RECV_BUFFER_HEAD_LEN, 0); if (recvLen = 0) continue;// Read LengthInt messageLength = (recvBuffer [0] & 0xff) <24) | (recvBuffer [1] & 0xff) <16) | (recvBuffer [2] & 0xff) <8) | (recvBuffer [3] & 0xff); ALOGI ("sendAt messageLength = % d", messageLength );// Read contentRecvLen = recv (fd, recvBuffer, messageLength, 0); recvP. setData (uint8_t *) recvBuffer, recvLen );// Parse dataInt type = recvP. readInt32 (); int response = recvP. readInt32 (); // type: RESPONSE_UNSOLICITED/RESPONSE_SOLICITED ALOGI ("sendAt type = % d", type); // response ID: RESPONSE_UNSOLICITED // For RESPONSE_SOLICITED may not be like this in serial, in actual parsing, two types of data formats must be differentiated. For details, refer to ALOGI ("sendAt response = % d", response) According to RIL_JAVA ); // data content ALOGI ("sendAt recvBuffer = % s", recvBuffer );// Establish a connection exit LoopBreak;} return result ;}

  You also need to receive messages transmitted by RILD. You can set up another thread to receive messages sent by RILD.

4. Send data
SendAtErrnoTypeSendDataToRild(Parcel & p) {unsigned char * sendData = NULL; uint32 sendDataLen = p. dataSize (); unsigned char dataLength [4]; int32 res =-1; sendAtErrnoType error = E_SUCCESS; sendAtFd fd = s_send_at_fd;// Parcel length in big endian converts the data length to a byte arrayDataLength [0] = dataLength [1] = 0; dataLength [2] = (unsigned char) (sendDataLen> 8) & 0xff ); dataLength [3] = (unsigned char) (sendDataLen) & 0xff); // obtain the data to be sent sendData = (unsigned char *) malloc (p. dataSize (); memcpy (sendData, p. data (), sendDataLen );// Send Data LengthRes = send (fd, (const void *) dataLength, 4,0 );// Send data contentRes = send (fd, (const void *) sendData, sendDataLen, 0); free (sendData); return error ;}

  We can see that RILD uses Parcel to parse the received data,

Therefore, the format of data transmission is still organized using Parcel;

  From the above we can see that Data Reading and data sending both start from the Data Length and then the data content

This is the data format for communication with RILD socket. For details, refer to the data format sent by RILJ.

The client that communicates with RILD socket can only use "Radio" for communication.

This is restricted in listenCallback of RIL_CPP.

However, if you change the UID to: setuid (AID_RADIO,

An error occurs when the socket is created. If you do not know how to solve the problem, you may wonder why the radio permission is the same,

Rild socket cannot be opened here.

As a test, we use include $ (BUILD_EXECUTABLE) to compile an executable file.

You can only change the permission requirements of RILD.

If the program exits immediately after the data is sent to rild, an error is reported;

Cause the server to report: ECONNRESET 104 error connection reset by peer reset connection;

Therefore, you need to perform some latency in the function and cannot end the program running immediately.

To use the Parcel class and other classes in Android, you must go to namespace android.

Namespace is an identifier of c ++ that defines a global space.

The android Code regards the entire android project as a namespace.

Therefore, it must be referenced in the same space.

5. code snippets
Int main (int argc, char * argv []) {send_at_main_init (); send_at_fight_mode (1 );// You cannot end the program immediately. Otherwise, the ECONNRESET 104 error occurs. connection reset by peer// The precision of sleep is second, and the precision of usleep is subtle sleep (3); // or prevent the program from exiting and entering the endless loop while (0) {// sleep (UINT32_MAX) seems to return immediately on bionic sleep (0x00ffffff);} return 0 ;}

The following describes the specific data transmission procedures and formats:

6. Call
Void Merge (handle * handle_params) {Parcel p; status_t status; uint32 ril_request_dial = RIL_REQUEST_DIAL; uint32 serial = 0; const char address [20] = "15816891234"; uint32 clirMode = 0; uint32 uusInfoNone = 0; // package data status = p. writeInt32 (ril_request_dial); status = p. writeInt32 (serial); // The write and read modes of the string are consistent. For details, refer to the writeStringToParcel (p, address) function in RILD; status = p. writeInt32 (clirMode); status = p. writeInt32 (uusInfoNone); // send dataSendDataToRild(P );}

7. Set the Radio status
Void Merge (send_at_request_params * handle_params) {Parcel p; status_t status; atRadioEvent * pRadioEvent = (atRadioEvent *) handle_params-> data; // package data status = p. writeInt32 (pRadioEvent-> ril_request_radio); status = p. writeInt32 (pRadioEvent-> serial); status = p. writeInt32 (pRadioEvent-> radio); status = p. writeInt32 (pRadioEvent-> on); // send dataSendDataToRild(P );}

8 compile an executable binary file

Generated to the directory:/system/bin/sendAt

Push adb to the mobile phone/system/bin directory, and change the permission to execute

# For sendAt binary# =======================LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES:= \    sendAt.c \    sendAtUtil.cpp \    sendAtEvent.cpp \    sendAtDispatch.cpp    LOCAL_SHARED_LIBRARIES := \    libutils \    libbinder \    libcutils \    libril    LOCAL_CFLAGS := \LOCAL_MODULE:= sendAtLOCAL_MODULE_TAGS := optionalinclude $(BUILD_EXECUTABLE)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.