Android phone system framework introduced

inandroidSystemrildrunningAPon,APApplication byrildsendATInstructions toBPBPAfter receiving the information through therildSent toAP. There are two means of communication between the AP and BP:

1.Solicited Response:AptoBpsend request,BpgiveApSending a reply, the AT command and the type of callback functions stored in an array Ril_commands.h file:

{Array index, callback requests, in response to the callback function}

[plain] view plain copy
  1. {0, NULL, NULL},                   //none  
  2. {RIL_REQUEST_GET_SIM_STATUS, dispatchVoid, responseSimStatus},  
  3. {RIL_REQUEST_ENTER_SIM_PIN, dispatchStrings, responseInts},  
  4. {RIL_REQUEST_ENTER_SIM_PUK, dispatchStrings, responseInts},  
  5. {RIL_REQUEST_ENTER_SIM_PIN2, dispatchStrings, responseInts},  
  6. {RIL_REQUEST_ENTER_SIM_PUK2, dispatchStrings, responseInts},  
  7. {RIL_REQUEST_CHANGE_SIM_PIN, dispatchStrings, responseInts},  
  8. {RIL_REQUEST_CHANGE_SIM_PIN2, dispatchStrings, responseInts},  
  9. {RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION, dispatchStrings, responseInts},  
  10. {RIL_REQUEST_GET_CURRENT_CALLS, dispatchVoid, responseCallList},  
  11. {RIL_REQUEST_DIAL, dispatchDial, responseVoid},  
  12. {RIL_REQUEST_GET_IMSI, dispatchStrings, responseString},  
  13. {RIL_REQUEST_HANGUP, dispatchInts, responseVoid},  
  14. {RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND, dispatchVoid, responseVoid},  
  15. {RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND, dispatchVoid, responseVoid},  
  16. {RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, dispatchVoid, responseVoid},  
  17. {RIL_REQUEST_CONFERENCE, dispatchVoid, responseVoid},  
  18. {RIL_REQUEST_UDUB, dispatchVoid, responseVoid},  
  19. {RIL_REQUEST_LAST_CALL_FAIL_CAUSE, dispatchVoid, responseInts},  
  20. {RIL_REQUEST_SIGNAL_STRENGTH, dispatchVoid, responseRilSignalStrength},  
  21. {RIL_REQUEST_VOICE_REGISTRATION_STATE, dispatchVoid, responseStrings},  
  22. {RIL_REQUEST_DATA_REGISTRATION_STATE, dispatchVoid, responseStrings},  
  23. {RIL_REQUEST_OPERATOR, dispatchVoid, responseStrings},  
  24. {RIL_REQUEST_RADIO_POWER, dispatchInts, responseVoid},  
  25. {RIL_REQUEST_DTMF, dispatchString, responseVoid},  
  26. {RIL_REQUEST_SEND_SMS, dispatchStrings, responseSMS},  
  27. {RIL_REQUEST_SEND_SMS_EXPECT_MORE, dispatchStrings, responseSMS},  
  28. {RIL_REQUEST_SETUP_DATA_CALL, dispatchDataCall, responseSetupDataCall},  
  29. {RIL_REQUEST_SIM_IO, dispatchSIM_IO, responseSIM_IO},  
  30. {RIL_REQUEST_SEND_USSD, dispatchString, responseVoid},  
  31. {RIL_REQUEST_CANCEL_USSD, dispatchVoid, responseVoid},  
  32. {RIL_REQUEST_GET_CLIR, dispatchVoid, responseInts},  
  33. {RIL_REQUEST_SET_CLIR, dispatchInts, responseVoid},  
  34. {RIL_REQUEST_QUERY_CALL_FORWARD_STATUS, dispatchCallForward, responseCallForwards},  
  35. {RIL_REQUEST_SET_CALL_FORWARD, dispatchCallForward, responseVoid},  
  36. {RIL_REQUEST_QUERY_CALL_WAITING, dispatchInts, responseInts},  
  37. {RIL_REQUEST_SET_CALL_WAITING, dispatchInts, responseVoid},  
  38. {RIL_REQUEST_SMS_ACKNOWLEDGE, dispatchInts, responseVoid},  
  39. {RIL_REQUEST_GET_IMEI, dispatchVoid, responseString},  
  40. {RIL_REQUEST_GET_IMEISV, dispatchVoid, responseString},  
  41. {RIL_REQUEST_ANSWER,dispatchVoid, responseVoid},  
  42. {RIL_REQUEST_DEACTIVATE_DATA_CALL, dispatchStrings, responseVoid},  
  43. {RIL_REQUEST_QUERY_FACILITY_LOCK, dispatchStrings, responseInts},  
  44. {RIL_REQUEST_SET_FACILITY_LOCK, dispatchStrings, responseInts},  
  45. {RIL_REQUEST_CHANGE_BARRING_PASSWORD, dispatchStrings, responseVoid},  
  46. {RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE, dispatchVoid, responseInts},  
  47. {RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, dispatchVoid, responseVoid},  
  48. {RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, dispatchString, responseVoid},  
  49. {RIL_REQUEST_QUERY_AVAILABLE_NETWORKS , dispatchVoid, responseStrings},  
  50. {RIL_REQUEST_DTMF_START, dispatchString, responseVoid},  
  51. {RIL_REQUEST_DTMF_STOP, dispatchVoid, responseVoid},  
  52. {RIL_REQUEST_BASEBAND_VERSION, dispatchVoid, responseString},  
  53. {RIL_REQUEST_SEPARATE_CONNECTION, dispatchInts, responseVoid},  
  54. {RIL_REQUEST_SET_MUTE, dispatchInts, responseVoid},  
  55. {RIL_REQUEST_GET_MUTE, dispatchVoid, responseInts},  
  56. {RIL_REQUEST_QUERY_CLIP, dispatchVoid, responseInts},  
  57. {RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE, dispatchVoid, responseInts},  
  58. {RIL_REQUEST_DATA_CALL_LIST, dispatchVoid, responseDataCallList},  
  59. {RIL_REQUEST_RESET_RADIO, dispatchVoid, responseVoid},  
  60. {RIL_REQUEST_OEM_HOOK_RAW, dispatchRaw, responseRaw},  
  61. {RIL_REQUEST_OEM_HOOK_STRINGS, dispatchStrings, responseStrings},  
  62. {RIL_REQUEST_SCREEN_STATE, dispatchInts, responseVoid},  
  63. {RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION, dispatchInts, responseVoid},  
  64. {RIL_REQUEST_WRITE_SMS_TO_SIM, dispatchSmsWrite, responseInts},  
  65. {RIL_REQUEST_DELETE_SMS_ON_SIM, dispatchInts, responseVoid},  
  66. {RIL_REQUEST_SET_BAND_MODE, dispatchInts, responseVoid},  
  67. {RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE, dispatchVoid, responseInts},  
  68. {RIL_REQUEST_STK_GET_PROFILE, dispatchVoid, responseString},  
  69. {RIL_REQUEST_STK_SET_PROFILE, dispatchString, responseVoid},  
  70. {RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND, dispatchString, responseString},  
  71. {RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE, dispatchString, responseVoid},  
  72. {RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM, dispatchInts, responseVoid},  
  73. {RIL_REQUEST_EXPLICIT_CALL_TRANSFER, dispatchVoid, responseVoid},  
  74. {RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, dispatchInts, responseVoid},  
  75. {RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE, dispatchVoid, responseInts},  
  76. {RIL_REQUEST_GET_NEIGHBORING_CELL_IDS, dispatchVoid, responseCellList},  
  77. {RIL_REQUEST_SET_LOCATION_UPDATES, dispatchInts, responseVoid},  
  78. {RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE, dispatchInts, responseVoid},  
  79. {RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE, dispatchInts, responseVoid},  
  80. {RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE, dispatchVoid, responseInts},  
  81. {RIL_REQUEST_SET_TTY_MODE, dispatchInts, responseVoid},  
  82. {RIL_REQUEST_QUERY_TTY_MODE, dispatchVoid, responseInts},  
  83. {RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE, dispatchInts, responseVoid},  
  84. {RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE, dispatchVoid, responseInts},  
  85. {RIL_REQUEST_CDMA_FLASH, dispatchString, responseVoid},  
  86. {RIL_REQUEST_CDMA_BURST_DTMF, dispatchStrings, responseVoid},  
  87. {RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY, dispatchString, responseVoid},  
  88. {RIL_REQUEST_CDMA_SEND_SMS, dispatchCdmaSms, responseSMS},  
  89. {RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE, dispatchCdmaSmsAck, responseVoid},  
  90. {RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG, dispatchVoid, responseGsmBrSmsCnf},  
  91. {RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG, dispatchGsmBrSmsCnf, responseVoid},  
  92. {RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION, dispatchInts, responseVoid},  
  93. {RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG, dispatchVoid, responseCdmaBrSmsCnf},  
  94. {RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG, dispatchCdmaBrSmsCnf, responseVoid},  
  95. {RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION, dispatchInts, responseVoid},  
  96. {RIL_REQUEST_CDMA_SUBSCRIPTION, dispatchVoid, responseStrings},  
  97. {RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM, dispatchRilCdmaSmsWriteArgs, responseInts},  
  98. {RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM, dispatchInts, responseVoid},  
  99. {RIL_REQUEST_DEVICE_IDENTITY, dispatchVoid, responseStrings},  
  100. {RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, dispatchVoid, responseVoid},  
  101. {RIL_REQUEST_GET_SMSC_ADDRESS, dispatchVoid, responseString},  
  102. {RIL_REQUEST_SET_SMSC_ADDRESS, dispatchString, responseVoid},  
  103. {RIL_REQUEST_REPORT_SMS_MEMORY_STATUS, dispatchInts, responseVoid},  
  104. {RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING, dispatchVoid, responseVoid},  
  105. {RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE, dispatchCdmaSubscriptionSource, responseInts},  
  106. {RIL_REQUEST_ISIM_AUTHENTICATION, dispatchString, responseString},  
  107. {RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU, dispatchStrings, responseVoid},  
  108. {RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS, dispatchString, responseSIM_IO},  
  109. {RIL_REQUEST_VOICE_RADIO_TECH, dispatchVoiceRadioTech, responseInts},  


2.unSolicited Response:BpInitiative toApSend event,The AT command and the type of callback functions stored in an array ofril_unsol_commands.h file:

{Array index, in response to the callback function, type}

[plain] view plain copy
  1. {RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, responseVoid, WAKE_PARTIAL},  
  2. {RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, responseVoid, WAKE_PARTIAL},  
  3. {RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, responseVoid, WAKE_PARTIAL},  
  4. {RIL_UNSOL_RESPONSE_NEW_SMS, responseString, WAKE_PARTIAL},  
  5. {RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, responseString, WAKE_PARTIAL},  
  6. {RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM, responseInts, WAKE_PARTIAL},  
  7. {RIL_UNSOL_ON_USSD, responseStrings, WAKE_PARTIAL},  
  8. {RIL_UNSOL_ON_USSD_REQUEST, responseVoid, DONT_WAKE},  
  9. {RIL_UNSOL_NITZ_TIME_RECEIVED, responseString, WAKE_PARTIAL},  
  10. {RIL_UNSOL_SIGNAL_STRENGTH, responseRilSignalStrength, DONT_WAKE},  
  11. {RIL_UNSOL_DATA_CALL_LIST_CHANGED, responseDataCallList, WAKE_PARTIAL},  
  12. {RIL_UNSOL_SUPP_SVC_NOTIFICATION, responseSsn, WAKE_PARTIAL},  
  13. {RIL_UNSOL_STK_SESSION_END, responseVoid, WAKE_PARTIAL},  
  14. {RIL_UNSOL_STK_PROACTIVE_COMMAND, responseString, WAKE_PARTIAL},  
  15. {RIL_UNSOL_STK_EVENT_NOTIFY, responseString, WAKE_PARTIAL},  
  16. {RIL_UNSOL_STK_CALL_SETUP, responseInts, WAKE_PARTIAL},  
  17. {RIL_UNSOL_SIM_SMS_STORAGE_FULL, responseVoid, WAKE_PARTIAL},  
  18. {RIL_UNSOL_SIM_REFRESH, responseSimRefresh, WAKE_PARTIAL},  
  19. {RIL_UNSOL_CALL_RING, responseCallRing, WAKE_PARTIAL},  
  20. {RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, responseVoid, WAKE_PARTIAL},  
  21. {RIL_UNSOL_RESPONSE_CDMA_NEW_SMS, responseCdmaSms, WAKE_PARTIAL},  
  22. {RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS, responseRaw, WAKE_PARTIAL},  
  23. {RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL, responseVoid, WAKE_PARTIAL},  
  24. {RIL_UNSOL_RESTRICTED_STATE_CHANGED, responseInts, WAKE_PARTIAL},  
  25. {RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE, responseVoid, WAKE_PARTIAL},  
  26. {RIL_UNSOL_CDMA_CALL_WAITING, responseCdmaCallWaiting, WAKE_PARTIAL},  
  27. {RIL_UNSOL_CDMA_OTA_PROVISION_STATUS, responseInts, WAKE_PARTIAL},  
  28. {RIL_UNSOL_CDMA_INFO_REC, responseCdmaInformationRecords, WAKE_PARTIAL},  
  29. {RIL_UNSOL_OEM_HOOK_RAW, responseRaw, WAKE_PARTIAL},  
  30. {RIL_UNSOL_RINGBACK_TONE, responseInts, WAKE_PARTIAL},  
  31. {RIL_UNSOL_RESEND_INCALL_MUTE, responseVoid, WAKE_PARTIAL},  
  32. {RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, responseInts, WAKE_PARTIAL},  
  33. {RIL_UNSOL_CDMA_PRL_CHANGED, responseInts, WAKE_PARTIAL},  
  34. {RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE, responseVoid, WAKE_PARTIAL},  
  35. {RIL_UNSOL_RIL_CONNECTED, responseInts, WAKE_PARTIAL},  
  36. {RIL_UNSOL_VOICE_RADIO_TECH_CHANGED, responseInts, WAKE_PARTIAL},  

AT mobile phone manufacturers use differentCommand is not exactly the same, in order to confidentiality,APversusBPBetween the various manufacturers to communicate through their relevant dynamic libraries.

RILModule consists ofrildDaemon,libril.solibrefrence.so three partscomposition:

  1.rildModule is compiled into an executable file, to achieve amainFunction as a wholerilEntry point of the module. Use during initializationdlopenturn onlibrefrence_ril.so, Which fetches and executesRIL_InitFunction, getRIL_RadioFunctionsPointer byRIL_register()Functions registered tolibril.soLibrary, its source code structure is as follows:

 

 2.libril.soIs a shared library, the work is mainly responsible for communication with the upper receivingrilRequest, and passed tolibrefrence_ril.soWhilelibrefrence_ril.soThe message is returned to the calling process, as shown in the source code is structured as follows:

 

3.librefrence_ril.so is achieved by the handset makers themselves, runs in rild processbydlopenWay to load, is responsible withmodemCommunication hardware, the conversion fromlibril.soThe request for theATCommand, while listeningModemFeedback tolibril.so


Android telephone system is divided into three parts, a variety of telephone related java application layer, Phone Service java layer, the upper layer was mainly the API, while communicating with a native, can be seen as a client telephone system, Native layer telephone service process RILD, is responsible for the upper layer provides services to various phone functions, to interact directly with the modem:


Android phone system design framework chart:


Because Modem Android developers to use is not the same, various instruction format, initialization sequences may be different, so in order to eliminate these differences, Android designers ril made an abstract concept of using a virtual phone, different modem-related AT commands or the communication protocol to the corresponding compiled dynamic link library .so files, Rild specific AT commands and responses by the synthesis resolver.


Android phone system code structure:



RILD frame design

In the android phone system, the native layer to achieve the service end of the telephone service, by the interaction RILD service and a modem, java layer implementation in a client calls, the paper introduces the server process RILD telephone system, the following isFIG RILD design framework:



RILD source code analysis

Followed by removal of the entire frame RILD source will be described in detail.

After the kernel startup is complete, it will start the first application process Init process, inInit process of android source code analysis process startsIn an article for the init process start the process of a detailed introduction. init.rc init process reads the file in the startup process to start some heavyweight native service, rild process is to start by configuring the init.rc.

[plain] view plain copy
  1. service ril-daemon /system/bin/rild  
  2.     class main  
  3.     socket rild stream 660 root radio  
  4.     socket rild-debug stream 660 radio system  
  5.     user root  
  6.     group radio cache inet misc audio sdcard_rw log  

RILD entry function analysis process

The next is a timing chart RILD given to start the process:

hardware\ril\rild\rild.c

[cpp] view plain copy
  1. int main(int argc, char **argv)  
  2. {  
  3.     const char * rilLibPath = NULL;  
  4.     char **rilArgv;  
  5.     void *dlHandle;  
  6.     const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, intchar **);  
  7.     const RIL_RadioFunctions *funcs;  
  8.     char libPath[PROPERTY_VALUE_MAX];  
  9.     unsigned char hasLibArgs = 0;  
  10.     int i;  
  11.   umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);  
  12.   // rild start without parameters  
  13.     for (i = 1; i < argc ;) {  
  14.         if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) {  
  15.             rilLibPath = argv[i + 1];  
  16.             i += 2;  
  17.         } else if (0 == strcmp(argv[i], "--")) {  
  18.             i++;  
  19.             hasLibArgs = 1;  
  20.             break;  
  21.         } else {  
  22.             usage(argv[0]);  
  23.         }  
  24.     }  
  25.   if (rilLibPath == NULL) {  
  26.       // read value "rild.libpath" attribute by attribute Android system, i.e. storage path lib library  
  27.         if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {  
  28.             goto done;  
  29.         } else {  
  30.             rilLibPath = libPath;  
  31.         }  
  32.   }  
  33. ##################################################################################  
  34. To determine whether the simulator
  35. ##################################################################################  
  36. #if 1  
  37.     {  
  38.         static char*  arg_overrides[3];  
  39.         static char   arg_device[32];  
  40.         int           done = 0;  
  41. #define  REFERENCE_RIL_PATH  "/system/lib/libreference-ril.so"  
  42.         /* first, read /proc/cmdline into memory */  
  43.         char          buffer[1024], *p, *q;  
  44.         int           len;  
  45.         int           fd = open("/proc/cmdline",O_RDONLY);  
  46.         if (fd < 0) {  
  47.             LOGD("could not open /proc/cmdline:%s", strerror(errno));  
  48.             goto OpenLib;  
  49.         }  
  50.         // read the contents of / proc / cmdline file  
  51.         do {  
  52.             len = read(fd,buffer,sizeof(buffer)); }  
  53.         while (len == -1 && errno == EINTR);  
  54.         if (len < 0) {  
  55.             LOGD("could not read /proc/cmdline:%s", strerror(errno));  
  56.             close(fd);  
  57.             goto OpenLib;  
  58.         }  
  59.         close(fd);  
  60.         // determines whether simulator, for the real machine, where the condition is false  
  61.         if (strstr(buffer, "android.qemud=") != NULL)  
  62.         {  
  63.             int  tries = 5;  
  64. #define  QEMUD_SOCKET_NAME    "qemud"  
  65.             while (1) {  
  66.                 int  fd;  
  67.                 sleep(1);  
  68.                 fd = socket_local_client(QEMUD_SOCKET_NAME,  
  69.                             ANDROID_SOCKET_NAMESPACE_RESERVED,  
  70.                             SOCK_STREAM );  
  71.                 if (fd >= 0) {  
  72.                     close(fd);  
  73.                     snprintf( arg_device, sizeof(arg_device), "%s/%s",  
  74.                                 ANDROID_SOCKET_DIR, QEMUD_SOCKET_NAME );  
  75.                     arg_overrides[1] = "-s";  
  76.                     arg_overrides[2] = arg_device;  
  77.                     done = 1;  
  78.                     break;  
  79.                 }  
  80.                 LOGD("could not connect to %s socket: %s",QEMUD_SOCKET_NAME, strerror(errno));  
  81.                 if (--tries == 0)  
  82.                     break;  
  83.             }  
  84.             if (!done) {  
  85.                 LOGE("could not connect to %s socket (giving up): %s",  
  86.                     QEMUD_SOCKET_NAME, strerror(errno));  
  87.                 while(1)  
  88.                     sleep(0x00ffffff);  
  89.             }  
  90.         }  
  91.   
  92.         /* otherwise, try to see if we passed a device name from the kernel */  
  93.         if (!done) do { //true  
  94. #define  KERNEL_OPTION  "android.ril="  
  95. #define  DEV_PREFIX     "/dev/"  
  96.             // content determination / proc / cmdline is included in "android.ril ="  
  97.             p = strstr( buffer, KERNEL_OPTION );  
  98.             if (p == NULL)  
  99.                 break;  
  100.             p += sizeof(KERNEL_OPTION)-1;  
  101.             q  = strpbrk( p, " \t\n\r" );  
  102.             if (q != NULL)  
  103.                 *q = 0;  
  104.             snprintf( arg_device, sizeof(arg_device), DEV_PREFIX "%s", p );  
  105.             arg_device[sizeof(arg_device)-1] = 0;  
  106.             arg_overrides[1] = "-d";  
  107.             arg_overrides[2] = arg_device;  
  108.             done = 1;  
  109.         } while (0);  
  110.           
  111.         if (done) { //false  
  112.             argv = arg_overrides;  
  113.             argc = 3;  
  114.             i    = 1;  
  115.             hasLibArgs = 1;  
  116.             rilLibPath = REFERENCE_RIL_PATH;  
  117.             LOGD("overriding with %s %s", arg_overrides[1], arg_overrides[2]);  
  118.         }  
  119.     }  
  120. OpenLib:  
  121. #endif  
  122. ##################################################################################  
  123. Dynamic load library
  124. ##################################################################################  
  125.   
  126.   switchUser();// set Rild process for the radio user groups  
  127.   // load library vendor-defined  
  128.     ①dlHandle = dlopen(rilLibPath, RTLD_NOW);  
  129.     if (dlHandle == NULL) {  
  130.         fprintf(stderr, "dlopen failed: %s\n", dlerror());  
  131.         exit(-1);  
  132.   }  
  133.   // Create a client event listener thread  
  134.   ②RIL_startEventLoop();  
  135.   // address by dlsym RIL_Init targeting function, and cast the function pointer RIL_RadioFunctions  
  136.     ③rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, intchar **))dlsym(dlHandle, "RIL_Init");  
  137.     if (rilInit == NULL) {  
  138.         fprintf(stderr, "RIL_Init not defined or exported in %s\n", rilLibPath);  
  139.         exit(-1);  
  140.     }  
  141.     if (hasLibArgs) { //false  
  142.         rilArgv = argv + i - 1;  
  143.         argc = argc -i + 1;  
  144.     } else {  
  145.         static char * newArgv[MAX_LIB_ARGS];  
  146.         static char args[PROPERTY_VALUE_MAX];  
  147.         rilArgv = newArgv;  
  148.         property_get(LIB_ARGS_PROPERTY, args, "");// read "rild.libargs" attribute property values ​​system  
  149.         argc = make_argv(args, rilArgv);  
  150.     }  
  151.     // Make sure there's a reasonable argv[0]  
  152.   rilArgv[0] = argv[0];  
  153.   // call the function to initialize RIL_Init rild, passing parameters s_rilEnv, return address RIL_RadioFunctions  
  154.   ④funcs = rilInit(&s_rilEnv, argc, rilArgv);  
  155.   // Register client event processing interface RIL_RadioFunctions, and create a socket listening for events  
  156.     ⑤RIL_register(funcs);  
  157. done:  
  158.     while(1) {  
  159.         // sleep(UINT32_MAX) seems to return immediately on bionic  
  160.         sleep(0x00ffffff);  
  161.     }  
  162. }  
Mainly do the following main function:

1. parse command line arguments, reads libreference-ril.so library storage path by determining whether a different approach to the simulator;

2. dlopen manual loading libreference-ril.so library;

3. Start the event loop processing;

4. RIL_Init function to obtain the address from libreference-ril.so library, using the functionlibril.so libraryRIL_Env interface registration to libreference-ril.so library, while libreference-ril.so library RIL_RadioFunctions interface registers to the library to libril.so establish libril.so library and library libreference-ril.so communication bridge;

Start event loop processing eventLoop worker

The establishment of multi-channelI/ODriving message queue for receiving a command issued by an upper layer and toModemsendATWork order, the entireRILThe core of the system. Create an event dispatch threads_tid_dispatch, thread of execution is eventLoop.

hardware\ril\libril\Ril.cpp 

[cpp] view plain copy
  1. extern "C" void RIL_startEventLoop(void) {  
  2.     int ret;  
  3.     pthread_attr_t attr;  
  4.     /* spin up eventLoop thread and wait for it to get started */  
  5.     s_started = 0;  
  6.     pthread_mutex_lock(&s_startupMutex);  
  7.     pthread_attr_init (&attr);  
  8.   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  
  9.   // Create a worker thread eventLoop  
  10.   ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);  
  11.   // make sure the function returns the thread starts running before eventLoop  
  12.     while (s_started == 0) {  
  13.         pthread_cond_wait(&s_startupCond, &s_startupMutex);  
  14.     }  
  15.     pthread_mutex_unlock(&s_startupMutex);  
  16.     if (ret < 0) {  
  17.         LOGE("Failed to create dispatch thread errno:%d", errno);  
  18.         return;  
  19.     }  
  20. }  
eventLoop FIG execution timing:


[cpp] view plain copy
  1. static void * eventLoop(void *param) {  
  2.     int ret;  
  3.     int filedes[2];  
  4.     ril_event_init(); // Initialize the request queue  
  5.     pthread_mutex_lock(&s_startupMutex);  
  6.     s_started = 1; // eventLoop thread running flag  
  7.     pthread_cond_broadcast(&s_startupCond);  
  8.   pthread_mutex_unlock(&s_startupMutex);  
  9.   // Create an anonymous pipe  
  10.     ret = pipe(filedes);  
  11.     if (ret < 0) {  
  12.         LOGE("Error in pipe() errno:%d", errno);  
  13.         return NULL;  
  14.   }  
  15.   // s_fdWakeupRead for the read end of pipe  
  16.   s_fdWakeupRead = filedes[0];  
  17.   // s_fdWakeupWrite to the write end of the pipe  
  18.   s_fdWakeupWrite = filedes[1];  
  19.   // set the read end of the pipe O_NONBLOCK nonblocking  
  20.   fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);  
  21.   // Initialize s_wakeupfd_event content structure, handle is s_fdWakeupRead, the callback function is processWakeupCallback  
  22.     ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,processWakeupCallback, NULL);  
  23.     ①rilEventAddWakeup (&s_wakeupfd_event);  
  24.     // Only returns on error  
  25.     ②ril_event_loop();  
  26.     LOGE ("error in event_loop_base errno:%d", errno);  
  27.     return NULL;  
  28. }  
defines the concept of the event in rild, Rild It supports two types of events:

1. Timed Events: based on the execution time of the event to start the execution, byril_timer_addadd totime_listQueue

2. WakeupEvent: handle these eventsfdWill join theselect IOMultiplexed handle poolreadFDsWhen the correspondingfdThese events will trigger readable. For inlistenEnd ofsocketfdReadable expressed client connections, at this time need to callacceptAccept the connection.

event is defined as follows:
[cpp] view plain copy
  1. struct ril_event {  
  2.     struct ril_event *next;  
  3.     struct ril_event *prev;  
  4.     int fd;  // file handle  
  5.     int index; // The index in the event monitor table  
  6.     bool persist; // If it is held, is not removed from the watch_list  
  7.     struct timeval timeout; // task execution time  
  8.     ril_event_cb func; // callback event handler  
  9.     void *param; // callback parameters  
  10. };  

inRildIn the process of several important events

[cpp] view plain copy
  1. static struct ril_event s_commands_event;  
  2. ril_event_set (&s_commands_event, s_fdCommand, 1,processCommandsCallback, p_rs)  
  3.   
  4. static struct ril_event s_wakeupfd_event;  
  5. ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,processWakeupCallback, NULL)  
  6.   
  7. static struct ril_event s_listen_event;  
  8. ril_event_set (&s_listen_event, s_fdListen, false,listenCallback, NULL)  
  9.   
  10. static struct ril_event s_wake_timeout_event;  
  11. ril_timer_add(&(p_info->event), &myRelativeTime);  
[cpp] view plain copy
  1. static struct ril_event s_debug_event;  
  2. ril_event_set (&s_debug_event, s_fdDebug, true,debugCallback, NULL)  

It defined three event queue in the RILD for handling different events:

/Event Monitoring queue

static struct ril_event * watch_table[MAX_FD_EVENTS];

//Timed event queue

static struct ril_event timer_list;

//Processing the event queue

static struct ril_event pending_list; //Pending event queue, the event has been triggered, the callback handler needs event


Add an event

1. Add Wakeup Event
 
[cpp] view plain copy
  1. static void rilEventAddWakeup(struct ril_event *ev) {  
  2.     ril_event_add(ev); // add an event to the monitoring tables watch_table s_wakeupfd_event  
  3.     triggerEvLoop(); // write the pipeline to be triggered in the event loop s_fdWakeupWrite  
  4. }  

[cpp] view plain copy
  1. void ril_event_add(struct ril_event * ev)  
  2. {  
  3.     dlog("~~~~ +ril_event_add ~~~~");  
  4.     MUTEX_ACQUIRE();  
  5.     for (int i = 0; i < MAX_FD_EVENTS; i++) { // Traverse monitoring table watch_table  
  6.         if (watch_table[i] == NULL) { // Find the index free from the monitoring list, then the task was added to the monitoring list  
  7.             watch_table[i] = ev; // add events to monitor table  
  8.             ev->index = i; // set index for the event in the monitoring tables index  
  9.             dlog("~~~~ added at %d ~~~~", i);  
  10.             dump_event(ev);  
  11.             FD_SET(ev->fd, &readFds); Corresponding to the event handler // add a handler added to the pool readFds  
  12.             if (ev->fd >= nfds) nfds = ev->fd+1; // handle to modify the maximum  
  13.             dlog("~~~~ nfds = %d ~~~~", nfds);  
  14.             break;  
  15.         }  
  16.     }  
  17.     MUTEX_RELEASE();  
  18.     dlog("~~~~ -ril_event_add ~~~~");  
  19. }  

2. Add timed events
[cpp] view plain copy
  1. void ril_timer_add(struct ril_event * ev, struct timeval * tv)  
  2. {  
  3.     dlog("~~~~ +ril_timer_add ~~~~");  
  4.     MUTEX_ACQUIRE();  
  5.     struct ril_event * list;  
  6.     if (tv != NULL) {  
  7.         list = timer_list.next;  
  8.         ev->fd = -1; // make sure fd is invalid  
  9.         struct timeval now;  
  10.         getNow(&now);  
  11.         timeradd(&now, tv, &ev->timeout);  
  12.         // keep list sorted  
  13.         while (timercmp(&list->timeout, &ev->timeout, < ) && (list != &timer_list)) {  
  14.             list = list->next;  
  15.         }  
  16.         // list now points to the first event older than ev  
  17.         addToList(ev, list);  
  18.     }  
  19.     MUTEX_RELEASE();  
  20.     dlog("~~~~ -ril_timer_add ~~~~");  
  21. }  

trigger event

[cpp] view plain copy
  1. static void triggerEvLoop() {  
  2.     int ret;  
  3.   if (!pthread_equal(pthread_self(), s_tid_dispatch)) { // If the current thread ID is not equal to the event dispatch thread eventLoop thread ID  
  4.       do {  
  5.             ret = write (s_fdWakeupWrite, " ", 1); // write end of the pipe 1 to write a value to the trigger event loop eventLoop  
  6.          } while (ret < 0 && errno == EINTR);  
  7.     }  
  8. }  

Handling Events

[cpp] view plain copy
  1. void ril_event_loop()  
  2. {  
  3.     int n;  
  4.     fd_set rfds;  
  5.     struct timeval tv;  
  6.     struct timeval * ptv;  
  7.     for (;;) {  
  8.         memcpy(&rfds, &readFds, sizeof(fd_set));  
  9.         if (-1 == calcNextTimeout(&tv)) {  
  10.             dlog("~~~~ no timers; blocking indefinitely ~~~~");  
  11.             ptv = NULL;  
  12.         } else {  
  13.             dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec);  
  14.             ptv = &tv;  
  15.         }  
  16.         // wait to use the select function on the FDS, as long as the FDS data recording apparatus soon, it will select the corresponding flag bit and returns. readFDS records all events related to the device handle. readFDS the handle is in the AddEvent added.  
  17.         printReadies(&rfds);  
  18.         n = select(nfds, &rfds, NULL, NULL, ptv);   
  19.         printReadies(&rfds);  
  20.         dlog("~~~~ %d events fired ~~~~", n);  
  21.         if (n < 0) {  
  22.             if (errno == EINTR) continue;  
  23.             LOGE("ril_event: select error (%d)", errno);  
  24.             return;  
  25.         }  
  26.         processTimeouts(); // query execution time has come to the event from timer_list and added to the pending_list  
  27.         processReadReadies(&rfds, n); // query data readable event from watch_table and added to pending_list in to deal with, if the event is not long-lasting event, it is deleted from the watch_table  
  28.         // Traverse pending_list, call an event handler callback function to handle all events  
  29.         firePending();  
  30.     }  
  31. }  


In eventLoop worker thread event loop processing incoming event and the timer expires, the entire processing flow as shown below:

First by Linux in select multi-channel I / O multiplexing handles handles all pool monitor when there is an event coming select returns otherwise blocked. When select returns, expressed an arrival event to handle the timeout events by calling processTimeouts function approach is traversing time_list list to check out events, and moved out event to pending_list the list, then call processReadReadies function to handle events triggered event handling is traversing watch_table list of queries trigger event, and trigger the move to pending_list the list, if the event is not long-lasting event, also need to be removed from the list watch_table, when the event finished two kinds of queries to be processed and after put into pending_list the list, call the function firePending be treated in the event centralized treatment, treatment to traverse the list, call the callback function for each event.

1. timeout event query
[cpp] view plain copy
  1. static void processTimeouts()  
  2. {  
  3.     dlog("~~~~ +processTimeouts ~~~~");  
  4.     MUTEX_ACQUIRE();  
  5.     struct timeval now;  
  6.     struct ril_event * tev = timer_list.next;  
  7.     struct ril_event * next;  
  8.     getNow(&now); // Get the current time  
  9.   dlog("~~~~ Looking for timers <= %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec);  
  10.   // If the current time is greater than the timeout time of the event, then the event is removed from the timer_list added to pending_list  
  11.     while ((tev != &timer_list) && (timercmp(&now, &tev->timeout, >))) {  
  12.         dlog("~~~~ firing timer ~~~~");  
  13.         next = tev->next;  
  14.         removeFromList(tev); // remove the event from the timer_list  
  15.         addToList(tev, &pending_list); // add the event to pending_list  
  16.         tev = next;  
  17.     }  
  18.     MUTEX_RELEASE();  
  19.     dlog("~~~~ -processTimeouts ~~~~");  
  20. }  
2. A readable event query
[cpp] view plain copy
  1. static void processReadReadies(fd_set * rfds, int n)  
  2. {  
  3.     dlog("~~~~ +processReadReadies (%d) ~~~~", n);  
  4.   MUTEX_ACQUIRE();   
  5.   // Traverse watch_table array, according to the n select returns a handle to find the corresponding event  
  6.     for (int i = 0; (i < MAX_FD_EVENTS) && (n > 0); i++) {  
  7.         struct ril_event * rev = watch_table[i]; // get the corresponding event  
  8.         if (rev != NULL && FD_ISSET(rev->fd, rfds)) {  
  9.             addToList(rev, &pending_list); // add the event to the pending_list  
  10.             if (rev->persist == false) { // If the event is not persistent in the event also removed from watch_table  
  11.                 removeWatch(rev, i);  
  12.             }  
  13.             n--;  
  14.         }  
  15.     }  
  16.     MUTEX_RELEASE();  
  17.     dlog("~~~~ -processReadReadies (%d) ~~~~", n);  
  18. }  
3. Event Processing
[cpp] view plain copy
  1. static void firePending()  
  2. {  
  3.     dlog("~~~~ +firePending ~~~~");  
  4.     struct ril_event * ev = pending_list.next;  
  5.     while (ev != &pending_list) { // Traverse pending_list list, all events are processed in a linked list  
  6.         struct ril_event * next = ev->next;  
  7.         removeFromList(ev); // event processed removed from the pending_list  
  8.         ev->func(ev->fd, 0, ev->param); // Call the event handler callback function  
  9.         ev = next;  
  10.     }  
  11.     dlog("~~~~ -firePending ~~~~");  
  12. }  

RIL_Env defined

hardware\ril\include\telephony\ril.h

[cpp] view plain copy
  1. struct RIL_Env {  
  2.     // notify the processing result after the completion of the request interface DLL  
  3.   void (*OnRequestComplete)(RIL_Token t, RIL_Errno e,void *response, size_t responselen);  
  4.     // dynamic library unSolicited Response notification interface  
  5.   void (*OnUnsolicitedResponse)(int unsolResponse, const void *data,size_t datalen);  
  6.     // submit a timeout task to Rild Interface  
  7.     void (*RequestTimedCallback) (RIL_TimedCallback callback,void *param, const struct timeval *relativeTime);  
  8. };  

hardware\ril\rild\rild.c

s_rilEnv variable definitions:

[cpp] view plain copy
  1. static struct RIL_Env s_rilEnv = {  
  2.     RIL_onRequestComplete,  
  3.     RIL_onUnsolicitedResponse,  
  4.     RIL_requestTimedCallback  
  5. };  

Implement the various interface functions RIL_Env in hardware \ ril \ libril \ ril.cpp in

1.RIL_onRequestComplete

[cpp] view plain copy
  1. extern "C" void RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen) {  
  2.     RequestInfo *pRI;  
  3.     int ret;  
  4.     size_t errorOffset;  
  5.     pRI = (RequestInfo *)t;  
  6.     if (!checkAndDequeueRequestInfo(pRI)) {  
  7.         LOGE ("RIL_onRequestComplete: invalid RIL_Token");  
  8.         return;  
  9.     }  
  10.     if (pRI->local > 0) {  
  11.         // Locally issued command...void only!  
  12.         // response does not go back up the command socket  
  13.         LOGD("C[locl]< %s", requestToString(pRI->pCI->requestNumber));  
  14.         goto done;  
  15.     }  
  16.     appendPrintBuf("[%04d]< %s",pRI->token, requestToString(pRI->pCI->requestNumber));  
  17.     if (pRI->cancelled == 0) {  
  18.         Parcel p;  
  19.         p.writeInt32 (RESPONSE_SOLICITED);  
  20.         p.writeInt32 (pRI->token);  
  21.         errorOffset = p.dataPosition();  
  22.         p.writeInt32 (e);  
  23.         if (response != NULL) {  
  24.             // there is a response payload, no matter success or not.  
  25.             ret = pRI->pCI->responseFunction(p, response, responselen);  
  26.             /* if an error occurred, rewind and mark it */  
  27.             if (ret != 0) {  
  28.                 p.setDataPosition(errorOffset);  
  29.                 p.writeInt32 (ret);  
  30.             }  
  31.         }  
  32.         if (e != RIL_E_SUCCESS) {  
  33.             appendPrintBuf("%s fails by %s", printBuf, failCauseToString(e));  
  34.         }  
  35.         if (s_fdCommand < 0) {  
  36.             LOGD ("RIL onRequestComplete: Command channel closed");  
  37.         }  
  38.         sendResponse(p);  
  39.     }  
  40. done:  
  41.     free(pRI);  
  42. }  

By calling responseXXXThe underlying passed in response to the client process

2.RIL_onUnsolicitedResponse

[cpp] view plain copy
  1. extern "C" void RIL_onUnsolicitedResponse(int unsolResponse, void *data,  
  2.                                 size_t datalen)  
  3. {  
  4.     int unsolResponseIndex;  
  5.     int ret;  
  6.     int64_t timeReceived = 0;  
  7.     bool shouldScheduleTimeout = false;  
  8.     if (s_registerCalled == 0) {  
  9.         // Ignore RIL_onUnsolicitedResponse before RIL_register  
  10.         LOGW("RIL_onUnsolicitedResponse called before RIL_register");  
  11.         return;  
  12.     }  
  13.     unsolResponseIndex = unsolResponse - RIL_UNSOL_RESPONSE_BASE;  
  14.     if ((unsolResponseIndex < 0)  
  15.         || (unsolResponseIndex >= (int32_t)NUM_ELEMS(s_unsolResponses))) {  
  16.         LOGE("unsupported unsolicited response code %d", unsolResponse);  
  17.         return;  
  18.     }  
  19.     // Grab a wake lock if needed for this reponse,  
  20.     // as we exit we'll either release it immediately  
  21.     // or set a timer to release it later.  
  22.     switch (s_unsolResponses[unsolResponseIndex].wakeType) {  
  23.         case WAKE_PARTIAL:  
  24.             grabPartialWakeLock();  
  25.             shouldScheduleTimeout = true;  
  26.         break;  
  27.         case DONT_WAKE:  
  28.         default:  
  29.             // No wake lock is grabed so don't set timeout  
  30.             shouldScheduleTimeout = false;  
  31.             break;  
  32.     }  
  33.     // Mark the time this was received, doing this  
  34.     // after grabing the wakelock incase getting  
  35.     // the elapsedRealTime might cause us to goto  
  36.     // sleep.  
  37.     if (unsolResponse == RIL_UNSOL_NITZ_TIME_RECEIVED) {  
  38.         timeReceived = elapsedRealtime();  
  39.     }  
  40.     appendPrintBuf("[UNSL]< %s", requestToString(unsolResponse));  
  41.     Parcel p;  
  42.     p.writeInt32 (RESPONSE_UNSOLICITED);  
  43.     p.writeInt32 (unsolResponse);  
  44.     ret = s_unsolResponses[unsolResponseIndex].responseFunction(p, data, datalen);  
  45.     if (ret != 0) {  
  46.         // Problem with the response. Don't continue;  
  47.         goto error_exit;  
  48.     }  
  49.     // some things get more payload  
  50.     switch(unsolResponse) {  
  51.         case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:  
  52.             p.writeInt32(s_callbacks.onStateRequest());  
  53.             appendPrintBuf("%s {%s}", printBuf,  
  54.                 radioStateToString(s_callbacks.onStateRequest()));  
  55.         break;  
  56.         case RIL_UNSOL_NITZ_TIME_RECEIVED:  
  57.             // Store the time that this was received so the  
  58.             // handler of this message can account for  
  59.             // the time it takes to arrive and process. In  
  60.             // particular the system has been known to sleep  
  61.             // before this message can be processed.  
  62.             p.writeInt64(timeReceived);  
  63.         break;  
  64.     }  
  65.     ret = sendResponse(p);  
  66.     if (ret != 0 && unsolResponse == RIL_UNSOL_NITZ_TIME_RECEIVED) {  
  67.         // Unfortunately, NITZ time is not poll/update like everything  
  68.         // else in the system. So, if the upstream client isn't connected,  
  69.         // keep a copy of the last NITZ response (with receive time noted  
  70.         // above) around so we can deliver it when it is connected  
  71.         if (s_lastNITZTimeData != NULL) {  
  72.             free (s_lastNITZTimeData);  
  73.             s_lastNITZTimeData = NULL;  
  74.         }  
  75.         s_lastNITZTimeData = malloc(p.dataSize());  
  76.         s_lastNITZTimeDataSize = p.dataSize();  
  77.         memcpy(s_lastNITZTimeData, p.data(), p.dataSize());  
  78.     }  
  79.     // For now, we automatically go back to sleep after TIMEVAL_WAKE_TIMEOUT  
  80.     // FIXME The java code should handshake here to release wake lock  
  81.     if (shouldScheduleTimeout) {  
  82.         // Cancel the previous request  
  83.         if (s_last_wake_timeout_info != NULL) {  
  84.             s_last_wake_timeout_info->userParam = (void *)1;  
  85.         }  
  86.         s_last_wake_timeout_info= internalRequestTimedCallback(wakeTimeoutCallback, NULL,  
  87.                                             &TIMEVAL_WAKE_TIMEOUT);  
  88.     }  
  89.     return;  
  90. error_exit:  
  91.     if (shouldScheduleTimeout) {  
  92.         releaseWakeLock();  
  93.     }  
  94. }  

This function handles modemVarious events received at the network, such as network signal changes from incoming calls, receive text messages and so on. Then passed to the client process.

3.RIL_requestTimedCallback

[cpp] view plain copy
  1. extern "C" void RIL_requestTimedCallback (RIL_TimedCallback callback, void *param,  
  2.                                 const struct timeval *relativeTime) {  
  3.     internalRequestTimedCallback (callback, param, relativeTime);  
  4. }  

[cpp] view plain copy
  1. static UserCallbackInfo *internalRequestTimedCallback (RIL_TimedCallback callback, void *param,  
  2.                                 const struct timeval *relativeTime)  
  3. {  
  4.     struct timeval myRelativeTime;  
  5.     UserCallbackInfo *p_info;  
  6.     p_info = (UserCallbackInfo *) malloc (sizeof(UserCallbackInfo));  
  7.     p_info->p_callback = callback;  
  8.     p_info->userParam = param;  
  9.     if (relativeTime == NULL) {  
  10.         /* treat null parameter as a 0 relative time */  
  11.         memset (&myRelativeTime, 0, sizeof(myRelativeTime));  
  12.     } else {  
  13.         /* FIXME I think event_add's tv param is really const anyway */  
  14.         memcpy (&myRelativeTime, relativeTime, sizeof(myRelativeTime));  
  15.     }  
  16.     ril_event_set(&(p_info->event), -1, false, userTimerCallback, p_info);  
  17.     ril_timer_add(&(p_info->event), &myRelativeTime);  
  18.     triggerEvLoop();  
  19.     return p_info;  
  20. }  

RIL_RadioFunctions defined

Client toRildRequest transmission interface,Achieved by each mobile phone manufacturers.

hardware\ril\include\telephony\Ril.h 

[cpp] view plain copy
  1. typedef struct {  
  2.     int version; // Rild version  
  3.     RIL_RequestFunc onRequest; // AP Request Interface  
  4.     RIL_RadioStateRequest onStateRequest;// BP Status  
  5.     RIL_Supports supports;  
  6.     RIL_Cancel onCancel;  
  7.     RIL_GetVersion getVersion;// dynamic library version  
  8. } RIL_RadioFunctions;  
variable definitions:
[cpp] view plain copy
  1. static const RIL_RadioFunctions s_callbacks = {  
  2.     RIL_VERSION,  
  3.     onRequest,  
  4.     currentState,  
  5.     onSupports,  
  6.     onCancel,  
  7.     getVersion  
  8. };  

RIL_RadioFunctions implement various interface functions in hardware \ ril \ reference-ril \ reference-ril.c in

1.onRequest

[cpp] view plain copy
  1. static void onRequest (int request, void *data, size_t datalen, RIL_Token t)  
  2. {  
  3.     ATResponse *p_response;  
  4.     int err;  
  5.     LOGD("onRequest: %s", requestToString(request));  
  6.     /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS 
  7.      * when RADIO_STATE_UNAVAILABLE. 
  8.      */  
  9.     if (sState == RADIO_STATE_UNAVAILABLE  
  10.         && request != RIL_REQUEST_GET_SIM_STATUS  
  11.     ) {  
  12.         RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);  
  13.         return;  
  14.     }  
  15.     /* Ignore all non-power requests when RADIO_STATE_OFF 
  16.      * (except RIL_REQUEST_GET_SIM_STATUS) 
  17.      */  
  18.     if (sState == RADIO_STATE_OFF&& !(request == RIL_REQUEST_RADIO_POWER  
  19.             || request == RIL_REQUEST_GET_SIM_STATUS)  
  20.     ) {  
  21.         RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);  
  22.         return;  
  23.     }  
  24.     switch (request) {  
  25.         case RIL_REQUEST_GET_SIM_STATUS: {  
  26.             RIL_CardStatus *p_card_status;  
  27.             char *p_buffer;  
  28.             int buffer_size;  
  29.             int result = getCardStatus(&p_card_status);  
  30.             if (result == RIL_E_SUCCESS) {  
  31.                 p_buffer = (char *)p_card_status;  
  32.                 buffer_size = sizeof(*p_card_status);  
  33.             } else {  
  34.                 p_buffer = NULL;  
  35.                 buffer_size = 0;  
  36.             }  
  37.             RIL_onRequestComplete(t, result, p_buffer, buffer_size);  
  38.             freeCardStatus(p_card_status);  
  39.             break;  
  40.         }  
  41.         case RIL_REQUEST_GET_CURRENT_CALLS:  
  42.             requestGetCurrentCalls(data, datalen, t);  
  43.             break;  
  44.         case RIL_REQUEST_DIAL:  
  45.             requestDial(data, datalen, t);  
  46.             break;  
  47.         case RIL_REQUEST_HANGUP:  
  48.             requestHangup(data, datalen, t);  
  49.             break;  
  50.         case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:  
  51.             // 3GPP 22.030 6.5.5  
  52.             // "Releases all held calls or sets User Determined User Busy  
  53.             //  (UDUB) for a waiting call."  
  54.             at_send_command("AT+CHLD=0", NULL);  
  55.             /* success or failure is ignored by the upper layer here. 
  56.                it will call GET_CURRENT_CALLS and determine success that way */  
  57.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);  
  58.             break;  
  59.         case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:  
  60.             // 3GPP 22.030 6.5.5  
  61.             // "Releases all active calls (if any exist) and accepts  
  62.             //  the other (held or waiting) call."  
  63.             at_send_command("AT+CHLD=1", NULL);  
  64.             /* success or failure is ignored by the upper layer here. 
  65.                it will call GET_CURRENT_CALLS and determine success that way */  
  66.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);  
  67.             break;  
  68.         case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:  
  69.             // 3GPP 22.030 6.5.5  
  70.             // "Places all active calls (if any exist) on hold and accepts  
  71.             //  the other (held or waiting) call."  
  72.             at_send_command("AT+CHLD=2", NULL);  
  73.   
  74. #ifdef WORKAROUND_ERRONEOUS_ANSWER  
  75.             s_expectAnswer = 1;  
  76. #endif /* WORKAROUND_ERRONEOUS_ANSWER */  
  77.             /* success or failure is ignored by the upper layer here. 
  78.                it will call GET_CURRENT_CALLS and determine success that way */  
  79.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);  
  80.             break;  
  81.         case RIL_REQUEST_ANSWER:  
  82.             at_send_command("ATA", NULL);  
  83. #ifdef WORKAROUND_ERRONEOUS_ANSWER  
  84.             s_expectAnswer = 1;  
  85. #endif /* WORKAROUND_ERRONEOUS_ANSWER */  
  86.             /* success or failure is ignored by the upper layer here. 
  87.                it will call GET_CURRENT_CALLS and determine success that way */  
  88.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);  
  89.             break;  
  90.         case RIL_REQUEST_CONFERENCE:  
  91.             // 3GPP 22.030 6.5.5  
  92.             // "Adds a held call to the conversation"  
  93.             at_send_command("AT+CHLD=3", NULL);  
  94.             /* success or failure is ignored by the upper layer here. 
  95.                it will call GET_CURRENT_CALLS and determine success that way */  
  96.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);  
  97.             break;  
  98.         case RIL_REQUEST_UDUB:  
  99.             /* user determined user busy */  
  100.             /* sometimes used: ATH */  
  101.             at_send_command("ATH", NULL);  
  102.             /* success or failure is ignored by the upper layer here. 
  103.                it will call GET_CURRENT_CALLS and determine success that way */  
  104.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);  
  105.             break;  
  106.         case RIL_REQUEST_SEPARATE_CONNECTION:  
  107.             {  
  108.                 char  cmd[12];  
  109.                 int   party = ((int*)data)[0];  
  110.                 // Make sure that party is in a valid range.  
  111.                 // (Note: The Telephony middle layer imposes a range of 1 to 7.  
  112.                 // It's sufficient for us to just make sure it's single digit.)  
  113.                 if (party > 0 && party < 10) {  
  114.                     sprintf(cmd, "AT+CHLD=2%d", party);  
  115.                     at_send_command(cmd, NULL);  
  116.                     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);  
  117.                 } else {  
  118.                     RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);  
  119.                 }  
  120.             }  
  121.             break;  
  122.         case RIL_REQUEST_SIGNAL_STRENGTH:  
  123.             requestSignalStrength(data, datalen, t);  
  124.             break;  
  125.         case RIL_REQUEST_REGISTRATION_STATE:  
  126.         case RIL_REQUEST_GPRS_REGISTRATION_STATE:  
  127.             requestRegistrationState(request, data, datalen, t);  
  128.             break;  
  129.         case RIL_REQUEST_OPERATOR:  
  130.             requestOperator(data, datalen, t);  
  131.             break;  
  132.         case RIL_REQUEST_RADIO_POWER:  
  133.             requestRadioPower(data, datalen, t);  
  134.             break;  
  135.         case RIL_REQUEST_DTMF: {  
  136.             char c = ((char *)data)[0];  
  137.             char *cmd;  
  138.             asprintf(&cmd, "AT+VTS=%c", (int)c);  
  139.             at_send_command(cmd, NULL);  
  140.             free(cmd);  
  141.             RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);  
  142.             break;  
  143.         }  
  144.         case RIL_REQUEST_SEND_SMS:  
  145.             requestSendSMS(data, datalen, t);  
  146.             break;  
  147.         case RIL_REQUEST_SETUP_DATA_CALL:  
  148.             requestSetupDataCall(data, datalen, t);  
  149.             break;  
  150.         case RIL_REQUEST_SMS_ACKNOWLEDGE:  
  151.             requestSMSAcknowledge(data, datalen, t);  
  152.             break;  
  153.         case RIL_REQUEST_GET_IMSI:  
  154.             p_response = NULL;  
  155.             err = at_send_command_numeric("AT+CIMI", &p_response);  
  156.             if (err < 0 || p_response->success == 0) {  
  157.                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);  
  158.             } else {  
  159.                 RIL_onRequestComplete(t, RIL_E_SUCCESS,  
  160.                     p_response->p_intermediates->line, sizeof(char *));  
  161.             }  
  162.             at_response_free(p_response);  
  163.             break;  
  164.         case RIL_REQUEST_GET_IMEI:  
  165.             p_response = NULL;  
  166.             err = at_send_command_numeric("AT+CGSN", &p_response);  
  167.   
  168.             if (err < 0 || p_response->success == 0) {  
  169.                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);  
  170.             } else {  
  171.                 RIL_onRequestComplete(t, RIL_E_SUCCESS,  
  172.                     p_response->p_intermediates->line, sizeof(char *));  
  173.             }  
  174.             at_response_free(p_response);  
  175.             break;  
  176.         case RIL_REQUEST_SIM_IO:  
  177.             requestSIM_IO(data,datalen,t);  
  178.             break;  
  179.         case RIL_REQUEST_SEND_USSD:  
  180.             requestSendUSSD(data, datalen, t);  
  181.             break;  
  182.         case RIL_REQUEST_CANCEL_USSD:  
  183.             p_response = NULL;  
  184.             err = at_send_command_numeric("AT+CUSD=2", &p_response);  
  185.             if (err < 0 || p_response->success == 0) {  
  186.                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);  
  187.             } else {  
  188.                 RIL_onRequestComplete(t, RIL_E_SUCCESS,  
  189.                     p_response->p_intermediates->line, sizeof(char *));  
  190.             }  
  191.             at_response_free(p_response);  
  192.             break;  
  193.         case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:  
  194.             at_send_command("AT+COPS=0", NULL);  
  195.             break;  
  196.         case RIL_REQUEST_DATA_CALL_LIST:  
  197.             requestDataCallList(data, datalen, t);  
  198.             break;  
  199.         case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:  
  200.             requestQueryNetworkSelectionMode(data, datalen, t);  
  201.             break;  
  202.         case RIL_REQUEST_OEM_HOOK_RAW:  
  203.             // echo back data  
  204.             RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);  
  205.             break;  
  206.         case RIL_REQUEST_OEM_HOOK_STRINGS: {  
  207.             int i;  
  208.             const char ** cur;  
  209.             LOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen);  
  210.             for (i = (datalen / sizeof (char *)), cur = (const char **)data ;  
  211.                     i > 0 ; cur++, i --) {  
  212.                 LOGD("> '%s'", *cur);  
  213.             }  
  214.             // echo back strings  
  215.             RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);  
  216.             break;  
  217.         }  
  218.         case RIL_REQUEST_WRITE_SMS_TO_SIM:  
  219.             requestWriteSmsToSim(data, datalen, t);  
  220.             break;  
  221.         case RIL_REQUEST_DELETE_SMS_ON_SIM: {  
  222.             char * cmd;  
  223.             p_response = NULL;  
  224.             asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]);  
  225.             err = at_send_command(cmd, &p_response);  
  226.             free(cmd);  
  227.             if (err < 0 || p_response->success == 0) {  
  228.                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);  
  229.             } else {  
  230.                 RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);  
  231.             }  
  232.             at_response_free(p_response);  
  233.             break;  
  234.         }  
  235.         case RIL_REQUEST_ENTER_SIM_PIN:  
  236.         case RIL_REQUEST_ENTER_SIM_PUK:  
  237.         case RIL_REQUEST_ENTER_SIM_PIN2:  
  238.         case RIL_REQUEST_ENTER_SIM_PUK2:  
  239.         case RIL_REQUEST_CHANGE_SIM_PIN:  
  240.         case RIL_REQUEST_CHANGE_SIM_PIN2:  
  241.             requestEnterSimPin(data, datalen, t);  
  242.             break;  
  243.         case RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION:  
  244.             requestSmsBroadcastActivation(0,data, datalen, t);  
  245.             break;  
  246.         case RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG:  
  247.              LOGD("onRequest RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG");  
  248.             requestSetSmsBroadcastConfig(0,data, datalen, t);  
  249.             break;  
  250.         case RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG:  
  251.             requestGetSmsBroadcastConfig(0,data, datalen, t);  
  252.             break;  
  253.         default:  
  254.             RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);  
  255.             break;  
  256.     }  
  257. }  

For each RIL_REQUEST_XXXConverted to the corresponding requestATcommand,send tomodemAnd then wait for sleep, when receivedATcommandAfter the final response, the thread wakes up, the response to the client process.

2.currentState

[cpp] view plain copy
  1. static RIL_RadioState currentState()  
  2. {  
  3.     return sState;  
  4. }  

3.onSupports

[cpp] view plain copy
  1. static int onSupports (int requestCode)  
  2. {  
  3.     //@@@ todo  
  4.     return 1;  
  5. }  

4.onCancel

[cpp] view plain copy
  1. static void onCancel (RIL_Token t)  
  2. {  
  3.     //@@@todo  
  4. }  

5.getVersion

[cpp] view plain copy
  1. static const char * getVersion(void)  
  2. {  
  3.     return "android reference-ril 1.0";  
  4. }  

Registration RIL_Env Interface



Since the AT command differences among mobile phone manufacturers, mobile phone manufacturers therefore need to achieve interaction with the modem layer, provided in the form of a dynamic library. As an intermediate layer between the modem and the upper layer, i.e., to interact with the bottom also communicate with the upper layer, so it is necessary to define an interface adapter RILD a dynamic library,RIL_Env andInterface is RIL_RadioFunctionslibril.so andBridge librefrence.so communication.YesRildIsolated interface architecture for generic code and manufacturer code,RIL_EnvRealized by a common code, andRIL_RadioFunctionsIt is the code of vendor implementations.


RIL_InitThe main tasks:

1. tolibrefrence.so registrationlibril.so interface providedRIL_Env;

2. CreatemainLoopWorker, used to initializeATModule, and monitorATStatus of the module, onceATIt is closed, then reopened and initializeAT

3. whenATAfter being opened,mainLoopWorker willRildSubmit a timed events, and triggerseventLoopTo complete themodemInitialization;

4. CreatereadLoopWorker thread for theATSerial read data;

5.returnlibrefrence.so interface providedRIL_RadioFunctions;

hardware\ril\reference-ril\reference-ril.c

[cpp] view plain copy
  1. const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)  
  2. {  
  3.     int ret;  
  4.     int fd = -1;  
  5.     int opt;  
  6.     pthread_attr_t attr;  
  7.   s_rilenv = env; // will be defined ril.cpp RIL_Env registered to the reference-ril.c in s_rilenv  
  8.     while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {  
  9.         switch (opt) {  
  10.             case 'p':  
  11.                 s_port = atoi(optarg);  
  12.                 if (s_port == 0) {  
  13.                     usage(argv[0]);  
  14.                     return NULL;  
  15.                 }  
  16.                 LOGI("Opening loopback port %d\n", s_port);  
  17.             break;  
  18.             case 'd':  
  19.                 s_device_path = optarg;  
  20.                 LOGI("Opening tty device %s\n", s_device_path);  
  21.             break;  
  22.             case 's':  
  23.                 s_device_path   = optarg;  
  24.                 s_device_socket = 1;  
  25.                 LOGI("Opening socket %s\n", s_device_path);  
  26.             break;  
  27.             default:  
  28.                 usage(argv[0]);  
  29.                 return NULL;  
  30.         }  
  31.     }  
  32.     if (s_port < 0 && s_device_path == NULL) {  
  33.         usage(argv[0]);  
  34.         return NULL;  
  35.     }  
  36.     pthread_attr_init (&attr);  
  37.   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  
  38.   // Create a thread mainLoop  
  39.   ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);  
  40.   // The RIL_RadioFunctions reference-ril.c defined return and register ril.cpp in s_callbacks  
  41.     return &s_callbacks;  
  42. }  

mainLoopWorker thread is used to initialize and monitorATModule, onceATModule is turned off, it opens automatically.

[cpp] view plain copy
  1. static void * mainLoop(void *param)  
  2. {  
  3.     int fd;  
  4.     int ret;  
  5.   AT_DUMP("== ""entering mainLoop()", -1 );  
  6.   // Set a callback function to AT module  
  7.     at_set_on_reader_closed(onATReaderClosed);  
  8.     at_set_on_timeout(onATTimeout);  
  9.     for (;;) {  
  10.         fd = -1;  
  11.         while  (fd < 0) { // Get device descriptor AT Serial Module  
  12.             if (s_port > 0) {  
  13.                 fd = socket_loopback_client(s_port, SOCK_STREAM);  
  14.             } else if (s_device_socket) {  
  15.                 if (!strcmp(s_device_path, "/dev/socket/qemud")) {  
  16.                     /* Qemu-specific control socket */  
  17.                     fd = socket_local_client( "qemud",  
  18.                  ANDROID_SOCKET_NAMESPACE_RESERVED,SOCK_STREAM );  
  19.                     if (fd >= 0 ) {  
  20.                         char  answer[2];  
  21.                         if ( write(fd, "gsm", 3) != 3 ||read(fd, answer, 2) != 2 ||  
  22.                              memcmp(answer, "OK", 2) != 0)  
  23.                         {  
  24.                             close(fd);  
  25.                             fd = -1;  
  26.                         }  
  27.                    }  
  28.                 }  
  29.                 else  
  30.                     fd = socket_local_client( s_device_path,    ANDROID_SOCKET_NAMESPACE_FILESYSTEM,SOCK_STREAM );  
  31.             } else if (s_device_path != NULL) {  
  32.                 fd = open (s_device_path, O_RDWR);  
  33.                 if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {  
  34.                     /* disable echo on serial ports */  
  35.                     struct termios  ios;  
  36.                     tcgetattr( fd, &ios );  
  37.                     ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */  
  38.                     tcsetattr( fd, TCSANOW, &ios );  
  39.                 }  
  40.             }  
  41.             if (fd < 0) {  
  42.                 perror ("opening AT interface. retrying...");  
  43.                 sleep(10);  
  44.             }  
  45.         }  
  46.         s_closed = 0;  
  47.         // open the AT module, create a thread to read AT s_tid_reader, fd as a modem device file handle  
  48.         ret = at_open(fd, onUnsolicited);  
  49.         if (ret < 0) {  
  50.             LOGE ("AT error %d on at_open\n", ret);  
  51.             return 0;  
  52.         }  
  53.         // submit timeout task to Rild  
  54.         RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);  
  55.         sleep(1);  
  56.         // If the AT module is turned off, the waitForClose return, re-open the AT, if AT is open, blocking  
  57.         waitForClose();  
  58.         LOGI("Re-opening after close");  
  59.     }  
  60. }  

1. Open AT module

byat_openOpen the file descriptorfdofATSerial devices, and register a callback functionATUnsolHandler 

[cpp] view plain copy
  1. int at_open(int fd, ATUnsolHandler h)  
  2. {  
  3.     int ret;  
  4.     pthread_t tid;  
  5.     pthread_attr_t attr;  
  6.     s_fd = fd;  
  7.     s_unsolHandler = h;  
  8.     s_readerClosed = 0;  
  9.     s_responsePrefix = NULL;  
  10.     s_smsPDU = NULL;  
  11.     sp_response = NULL;  
  12.     /* Android power control ioctl */  
  13. #ifdef HAVE_ANDROID_OS  
  14. #ifdef OMAP_CSMI_POWER_CONTROL  
  15.     ret = ioctl(fd, OMAP_CSMI_TTY_ENABLE_ACK);  
  16.     if(ret == 0) {  
  17.         int ack_count;  
  18.         int read_count;  
  19.         int old_flags;  
  20.         char sync_buf[256];  
  21.         old_flags = fcntl(fd, F_GETFL, 0);  
  22.         fcntl(fd, F_SETFL, old_flags | O_NONBLOCK);  
  23.         do {  
  24.             ioctl(fd, OMAP_CSMI_TTY_READ_UNACKED, &ack_count);  
  25.             read_count = 0;  
  26.             do {  
  27.                 ret = read(fd, sync_buf, sizeof(sync_buf));  
  28.                 if(ret > 0)  
  29.                     read_count += ret;  
  30.             } while(ret > 0 || (ret < 0 && errno == EINTR));  
  31.             ioctl(fd, OMAP_CSMI_TTY_ACK, &ack_count);  
  32.          } while(ack_count > 0 || read_count > 0);  
  33.         fcntl(fd, F_SETFL, old_flags);  
  34.         s_readCount = 0;  
  35.         s_ackPowerIoctl = 1;  
  36.     }  
  37.     else  
  38.         s_ackPowerIoctl = 0;  
  39. #else // OMAP_CSMI_POWER_CONTROL  
  40.         s_ackPowerIoctl = 0;  
  41. #endif // OMAP_CSMI_POWER_CONTROL  
  42. #endif /*HAVE_ANDROID_OS*/  
  43.     pthread_attr_init (&attr);  
  44.   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  
  45.   // Create readerLoop work thread that is used to read data from the serial port  
  46.     ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);  
  47.     if (ret < 0) {  
  48.         perror ("pthread_create");  
  49.         return -1;  
  50.     }  
  51.     return 0;  
  52. }  

2.Add timed events RIL_requestTimedCallback

[cpp] view plain copy
  1. RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);  
  2.   
  3. #define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)  

The timing to add a timer event in the event queue, the event handler is initializeCallback, for transmitting some of the ATCommand to initializeBPofmodem

3.readLoop worker

Read loop parsing hair came from Modem response. If you encounter URC handleUnsolicited reported RIL_JAVA through. If you answered command, then there is a response by handleFinalResponse notice send_at_command results.


[cpp] view plain copy
  1. static void *readerLoop(void *arg)  
  2. {  
  3.     for (;;) {  
  4.         const char * line;  
  5.         line = readline();  
  6.         if (line == NULL) {  
  7.             break;  
  8.         }  
  9.         if(isSMSUnsolicited(line)) { // determine whether the SMS notification  
  10.             char *line1;  
  11.             const char *line2;  
  12.             line1 = strdup(line);  
  13.             line2 = readline();

Intelligent Recommendation

Building Shadowsocks in the Android phone system

Building Shadowsocks in the Android phone system In some special production work environments, we sometimes need to use a mobile device to build a proxy to provide connectivity to other devices. The r...

Android phone system permission processing

This article mainly introduces the handling method of Android mobile phone system permissions. Foreword With the widespread use of Android devices, Google is paying more and more attention to the secu...

Android system phone startup process

2019 Unicorn Enterprise Heavy Gold Recruitment Python Engineer Standard >>> Part III: Android Launch The Android startup process starts with the process init, so it is the ancestor process of...

Android system phone development notes

Connected phone code road vendor/commons/carriers/Extension/apps/Dialer/ Main interface: dialtacts_activity.xml DialtactsActivity.java ListsFragment.java This is the interface fragment of the communic...

Open the Android phone system calls

In this paper, personal Guangdong shopping when suddenly thought of before ... have to write several blog about opening the phone, so go home after just fired off letters to write out a release main.x...

More Recommendation

Android Bluetooth phone management system

Introduction: recently encountered a need to write a APP on-board system, you need to control your calls on your phone. Previously had contact with Bluetooth, so a little bit to understand. first car ...

Android modify phone system resolution

Directory device/mediatek/common/aapt_config.mk...

Android get phone system information

The finishing part has been marked with notes as follows:  ...

Android phone replacement system application

In development, we generally use the debug apk package, but sometimes we need to install the Release package. If it is a normal application, it can be deleted directly, but if it is a system applicati...

Install Linux system on Android phone

I have only heard of Linux before but have never been exposed to it, so I also referred to the tutorials of my predecessors before installing it. Refer to the blog: https://blog.csdn.net/qq_36513794/a...

Copyright  DMCA © 2018-2026 - All Rights Reserved - www.programmersought.com  User Notice

Top