博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android之rild进程启动源码分析
阅读量:6274 次
发布时间:2019-06-22

本文共 107077 字,大约阅读时间需要 356 分钟。

hot3.png

Android 电话系统框架介绍

android系统中rild运行在AP上,AP上的应用通过rild发送AT指令给BPBP接收到信息后又通过rild传送给AP。AP与BP之间有两种通信方式:

1.Solicited Response:ApBp发送请求,BpAp发送回复,该类型的AT指令及其回调函数以数组的形式存放在Ril_commands.h文件中:

    {数组中的索引号,请求回调函数,响应回调函数}

[plain]

  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},  

    {0, NULL, NULL},                   //none    {RIL_REQUEST_GET_SIM_STATUS, dispatchVoid, responseSimStatus},    {RIL_REQUEST_ENTER_SIM_PIN, dispatchStrings, responseInts},    {RIL_REQUEST_ENTER_SIM_PUK, dispatchStrings, responseInts},    {RIL_REQUEST_ENTER_SIM_PIN2, dispatchStrings, responseInts},    {RIL_REQUEST_ENTER_SIM_PUK2, dispatchStrings, responseInts},    {RIL_REQUEST_CHANGE_SIM_PIN, dispatchStrings, responseInts},    {RIL_REQUEST_CHANGE_SIM_PIN2, dispatchStrings, responseInts},    {RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION, dispatchStrings, responseInts},    {RIL_REQUEST_GET_CURRENT_CALLS, dispatchVoid, responseCallList},    {RIL_REQUEST_DIAL, dispatchDial, responseVoid},    {RIL_REQUEST_GET_IMSI, dispatchStrings, responseString},    {RIL_REQUEST_HANGUP, dispatchInts, responseVoid},    {RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND, dispatchVoid, responseVoid},    {RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND, dispatchVoid, responseVoid},    {RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, dispatchVoid, responseVoid},    {RIL_REQUEST_CONFERENCE, dispatchVoid, responseVoid},    {RIL_REQUEST_UDUB, dispatchVoid, responseVoid},    {RIL_REQUEST_LAST_CALL_FAIL_CAUSE, dispatchVoid, responseInts},    {RIL_REQUEST_SIGNAL_STRENGTH, dispatchVoid, responseRilSignalStrength},    {RIL_REQUEST_VOICE_REGISTRATION_STATE, dispatchVoid, responseStrings},    {RIL_REQUEST_DATA_REGISTRATION_STATE, dispatchVoid, responseStrings},    {RIL_REQUEST_OPERATOR, dispatchVoid, responseStrings},    {RIL_REQUEST_RADIO_POWER, dispatchInts, responseVoid},    {RIL_REQUEST_DTMF, dispatchString, responseVoid},    {RIL_REQUEST_SEND_SMS, dispatchStrings, responseSMS},    {RIL_REQUEST_SEND_SMS_EXPECT_MORE, dispatchStrings, responseSMS},    {RIL_REQUEST_SETUP_DATA_CALL, dispatchDataCall, responseSetupDataCall},    {RIL_REQUEST_SIM_IO, dispatchSIM_IO, responseSIM_IO},    {RIL_REQUEST_SEND_USSD, dispatchString, responseVoid},    {RIL_REQUEST_CANCEL_USSD, dispatchVoid, responseVoid},    {RIL_REQUEST_GET_CLIR, dispatchVoid, responseInts},    {RIL_REQUEST_SET_CLIR, dispatchInts, responseVoid},    {RIL_REQUEST_QUERY_CALL_FORWARD_STATUS, dispatchCallForward, responseCallForwards},    {RIL_REQUEST_SET_CALL_FORWARD, dispatchCallForward, responseVoid},    {RIL_REQUEST_QUERY_CALL_WAITING, dispatchInts, responseInts},    {RIL_REQUEST_SET_CALL_WAITING, dispatchInts, responseVoid},    {RIL_REQUEST_SMS_ACKNOWLEDGE, dispatchInts, responseVoid},    {RIL_REQUEST_GET_IMEI, dispatchVoid, responseString},    {RIL_REQUEST_GET_IMEISV, dispatchVoid, responseString},    {RIL_REQUEST_ANSWER,dispatchVoid, responseVoid},    {RIL_REQUEST_DEACTIVATE_DATA_CALL, dispatchStrings, responseVoid},    {RIL_REQUEST_QUERY_FACILITY_LOCK, dispatchStrings, responseInts},    {RIL_REQUEST_SET_FACILITY_LOCK, dispatchStrings, responseInts},    {RIL_REQUEST_CHANGE_BARRING_PASSWORD, dispatchStrings, responseVoid},    {RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE, dispatchVoid, responseInts},    {RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, dispatchVoid, responseVoid},    {RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, dispatchString, responseVoid},    {RIL_REQUEST_QUERY_AVAILABLE_NETWORKS , dispatchVoid, responseStrings},    {RIL_REQUEST_DTMF_START, dispatchString, responseVoid},    {RIL_REQUEST_DTMF_STOP, dispatchVoid, responseVoid},    {RIL_REQUEST_BASEBAND_VERSION, dispatchVoid, responseString},    {RIL_REQUEST_SEPARATE_CONNECTION, dispatchInts, responseVoid},    {RIL_REQUEST_SET_MUTE, dispatchInts, responseVoid},    {RIL_REQUEST_GET_MUTE, dispatchVoid, responseInts},    {RIL_REQUEST_QUERY_CLIP, dispatchVoid, responseInts},    {RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE, dispatchVoid, responseInts},    {RIL_REQUEST_DATA_CALL_LIST, dispatchVoid, responseDataCallList},    {RIL_REQUEST_RESET_RADIO, dispatchVoid, responseVoid},    {RIL_REQUEST_OEM_HOOK_RAW, dispatchRaw, responseRaw},    {RIL_REQUEST_OEM_HOOK_STRINGS, dispatchStrings, responseStrings},    {RIL_REQUEST_SCREEN_STATE, dispatchInts, responseVoid},    {RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION, dispatchInts, responseVoid},    {RIL_REQUEST_WRITE_SMS_TO_SIM, dispatchSmsWrite, responseInts},    {RIL_REQUEST_DELETE_SMS_ON_SIM, dispatchInts, responseVoid},    {RIL_REQUEST_SET_BAND_MODE, dispatchInts, responseVoid},    {RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE, dispatchVoid, responseInts},    {RIL_REQUEST_STK_GET_PROFILE, dispatchVoid, responseString},    {RIL_REQUEST_STK_SET_PROFILE, dispatchString, responseVoid},    {RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND, dispatchString, responseString},    {RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE, dispatchString, responseVoid},    {RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM, dispatchInts, responseVoid},    {RIL_REQUEST_EXPLICIT_CALL_TRANSFER, dispatchVoid, responseVoid},    {RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, dispatchInts, responseVoid},    {RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE, dispatchVoid, responseInts},    {RIL_REQUEST_GET_NEIGHBORING_CELL_IDS, dispatchVoid, responseCellList},    {RIL_REQUEST_SET_LOCATION_UPDATES, dispatchInts, responseVoid},    {RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE, dispatchInts, responseVoid},    {RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE, dispatchInts, responseVoid},    {RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE, dispatchVoid, responseInts},    {RIL_REQUEST_SET_TTY_MODE, dispatchInts, responseVoid},    {RIL_REQUEST_QUERY_TTY_MODE, dispatchVoid, responseInts},    {RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE, dispatchInts, responseVoid},    {RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE, dispatchVoid, responseInts},    {RIL_REQUEST_CDMA_FLASH, dispatchString, responseVoid},    {RIL_REQUEST_CDMA_BURST_DTMF, dispatchStrings, responseVoid},    {RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY, dispatchString, responseVoid},    {RIL_REQUEST_CDMA_SEND_SMS, dispatchCdmaSms, responseSMS},    {RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE, dispatchCdmaSmsAck, responseVoid},    {RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG, dispatchVoid, responseGsmBrSmsCnf},    {RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG, dispatchGsmBrSmsCnf, responseVoid},    {RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION, dispatchInts, responseVoid},    {RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG, dispatchVoid, responseCdmaBrSmsCnf},    {RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG, dispatchCdmaBrSmsCnf, responseVoid},    {RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION, dispatchInts, responseVoid},    {RIL_REQUEST_CDMA_SUBSCRIPTION, dispatchVoid, responseStrings},    {RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM, dispatchRilCdmaSmsWriteArgs, responseInts},    {RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM, dispatchInts, responseVoid},    {RIL_REQUEST_DEVICE_IDENTITY, dispatchVoid, responseStrings},    {RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, dispatchVoid, responseVoid},    {RIL_REQUEST_GET_SMSC_ADDRESS, dispatchVoid, responseString},    {RIL_REQUEST_SET_SMSC_ADDRESS, dispatchString, responseVoid},    {RIL_REQUEST_REPORT_SMS_MEMORY_STATUS, dispatchInts, responseVoid},    {RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING, dispatchVoid, responseVoid},    {RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE, dispatchCdmaSubscriptionSource, responseInts},    {RIL_REQUEST_ISIM_AUTHENTICATION, dispatchString, responseString},    {RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU, dispatchStrings, responseVoid},    {RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS, dispatchString, responseSIM_IO},    {RIL_REQUEST_VOICE_RADIO_TECH, dispatchVoiceRadioTech, responseInts},

2.unSolicited Response:Bp主动给Ap发送事件,该类型的AT指令及其回调函数以数组的形式存放在ril_unsol_commands.h文件中:

    {数组中的索引号,响应回调函数,类型}

[plain]

  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},  

    {RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, responseVoid, WAKE_PARTIAL},    {RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, responseVoid, WAKE_PARTIAL},    {RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, responseVoid, WAKE_PARTIAL},    {RIL_UNSOL_RESPONSE_NEW_SMS, responseString, WAKE_PARTIAL},    {RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT, responseString, WAKE_PARTIAL},    {RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM, responseInts, WAKE_PARTIAL},    {RIL_UNSOL_ON_USSD, responseStrings, WAKE_PARTIAL},    {RIL_UNSOL_ON_USSD_REQUEST, responseVoid, DONT_WAKE},    {RIL_UNSOL_NITZ_TIME_RECEIVED, responseString, WAKE_PARTIAL},    {RIL_UNSOL_SIGNAL_STRENGTH, responseRilSignalStrength, DONT_WAKE},    {RIL_UNSOL_DATA_CALL_LIST_CHANGED, responseDataCallList, WAKE_PARTIAL},    {RIL_UNSOL_SUPP_SVC_NOTIFICATION, responseSsn, WAKE_PARTIAL},    {RIL_UNSOL_STK_SESSION_END, responseVoid, WAKE_PARTIAL},    {RIL_UNSOL_STK_PROACTIVE_COMMAND, responseString, WAKE_PARTIAL},    {RIL_UNSOL_STK_EVENT_NOTIFY, responseString, WAKE_PARTIAL},    {RIL_UNSOL_STK_CALL_SETUP, responseInts, WAKE_PARTIAL},    {RIL_UNSOL_SIM_SMS_STORAGE_FULL, responseVoid, WAKE_PARTIAL},    {RIL_UNSOL_SIM_REFRESH, responseSimRefresh, WAKE_PARTIAL},    {RIL_UNSOL_CALL_RING, responseCallRing, WAKE_PARTIAL},    {RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, responseVoid, WAKE_PARTIAL},    {RIL_UNSOL_RESPONSE_CDMA_NEW_SMS, responseCdmaSms, WAKE_PARTIAL},    {RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS, responseRaw, WAKE_PARTIAL},    {RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL, responseVoid, WAKE_PARTIAL},    {RIL_UNSOL_RESTRICTED_STATE_CHANGED, responseInts, WAKE_PARTIAL},    {RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE, responseVoid, WAKE_PARTIAL},    {RIL_UNSOL_CDMA_CALL_WAITING, responseCdmaCallWaiting, WAKE_PARTIAL},    {RIL_UNSOL_CDMA_OTA_PROVISION_STATUS, responseInts, WAKE_PARTIAL},    {RIL_UNSOL_CDMA_INFO_REC, responseCdmaInformationRecords, WAKE_PARTIAL},    {RIL_UNSOL_OEM_HOOK_RAW, responseRaw, WAKE_PARTIAL},    {RIL_UNSOL_RINGBACK_TONE, responseInts, WAKE_PARTIAL},    {RIL_UNSOL_RESEND_INCALL_MUTE, responseVoid, WAKE_PARTIAL},    {RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, responseInts, WAKE_PARTIAL},    {RIL_UNSOL_CDMA_PRL_CHANGED, responseInts, WAKE_PARTIAL},    {RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE, responseVoid, WAKE_PARTIAL},    {RIL_UNSOL_RIL_CONNECTED, responseInts, WAKE_PARTIAL},    {RIL_UNSOL_VOICE_RADIO_TECH_CHANGED, responseInts, WAKE_PARTIAL},

不同手机厂商使用的AT命令不完全相同,为了保密,APBP之间通过各厂商自己的相关动态库来通信。

RIL模块由rild守护进程、libril.solibrefrence.so三部分组成:

  1.rild模块被编译为一个可执行文件,实现一个main函数作为整个ril模块的入口点。在初始化时使用dlopen打开librefrence_ril.so,从中取出并执行RIL_Init函数,得到RIL_RadioFunctions指针,通过RIL_register()函数注册到libril.so库中,其源码结构如下:

 

 2.libril.so是共享库,主要负责同上层的通信工作,接收ril的请求,并传递给librefrence_ril.so,同时将librefrence_ril.so返回的消息送给调用进程,源码结构如下所示:

 

3.librefrence_ril.so是由各手机厂商自己实现,在rild进程运行中通过dlopen方式加载,主要负责跟modem硬件通信,转换来自libril.so的请求为AT命令,同时监听Modem的反馈信息给libril.so

Android的电话系统主要分为三个部分,java层的各种电话相关应用,java层的Phone Service,主要为上层提供API,同时与native进行通信,可以看做为电话系统的客户端,native层的电话服务进程RILD,负责为上层提供各种电话功能服务,直接与modem进行交互:

Android电话系统设计框架图:

由于Android 开发者使用的Modem 是不一样的,各种指令格式,初始化序列都可能不一样,所以为了消除这些差别,Android 设计者将ril 做了一个抽象,使用一个虚拟电话的概念,不同modem相关的AT指令或者通信协议编译成相应的动态链接库.so文件,Rild 是具体的AT 指令合成者和应答解析者。

Android电话系统代码结构图:

RILD框架设计

在android的电话系统中,在native层实现了电话服务的服务端,由RILD服务与modem的交互,在java层实现电话的客户端,本文主要介绍电话系统的服务端RILD进程,以下是RILD的设计框架图:

RILD源码分析

接下来通过源码对RILD的整个框架进行详细介绍。

在kernel启动完成后,将启动第一个应用进程Init进程,在一文中对init进程的启动流程进行了详细的介绍。init进程在启动过程中将读取init.rc文件来启动一些重量级的native服务,rild进程就是通过配置在init.rc中来启动的。

[plain]

  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  

service ril-daemon /system/bin/rild    class main    socket rild stream 660 root radio    socket rild-debug stream 660 radio system    user root    group radio cache inet misc audio sdcard_rw log

RILD进程入口函数分析

接下来给出的是RILD进程启动的时序图:

hardware\ril\rild\rild.c

[cpp]

  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 *, int, char **);  

  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启动无参数   

  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.       //通过Android属性系统读取属性"rild.libpath"的值,即lib库的存放路径   

  27.         if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {  

  28.             goto done;  

  29.         } else {  

  30.             rilLibPath = libPath;  

  31.         }  

  32.   }  

  33. ##################################################################################   

  34.                             判断是否为模拟器  

  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.         //读取/proc/cmdline文件中的内容   

  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.         //判断是否为模拟器,对于真机,此处条件为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.             //判断/proc/cmdline中的内容是否包含"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.                             动态库装载  

  124. ##################################################################################   

  125.   

  126.   switchUser();//设置Rild进程的组用户为radio   

  127.   //加载厂商自定义的库   

  128.     ①dlHandle = dlopen(rilLibPath, RTLD_NOW);  

  129.     if (dlHandle == NULL) {  

  130.         fprintf(stderr, "dlopen failed: %s\n", dlerror());  

  131.         exit(-1);  

  132.   }  

  133.   //创建客户端事件监听线程   

  134.   ②RIL_startEventLoop();  

  135.   //通过dlsym定位到RIL_Init函数的地址,并且强制转换为RIL_RadioFunctions的函数指针   

  136.     ③rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))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, "");//通过属性系统读取"rild.libargs"属性值   

  149.         argc = make_argv(args, rilArgv);  

  150.     }  

  151.     // Make sure there's a reasonable argv[0]   

  152.   rilArgv[0] = argv[0];  

  153.   //调用RIL_Init函数来初始化rild,传入参数s_rilEnv,返回RIL_RadioFunctions地址   

  154.   ④funcs = rilInit(&s_rilEnv, argc, rilArgv);  

  155.   //注册客户端事件处理接口RIL_RadioFunctions,并创建socket监听事件   

  156.     ⑤RIL_register(funcs);  

  157. done:  

  158.     while(1) {  

  159.         // sleep(UINT32_MAX) seems to return immediately on bionic   

  160.         sleep(0x00ffffff);  

  161.     }  

  162. }  

int main(int argc, char **argv){    const char * rilLibPath = NULL;    char **rilArgv;    void *dlHandle;    const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);    const RIL_RadioFunctions *funcs;    char libPath[PROPERTY_VALUE_MAX];    unsigned char hasLibArgs = 0;    int i;  umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);  //rild启动无参数    for (i = 1; i < argc ;) {        if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) {            rilLibPath = argv[i + 1];            i += 2;        } else if (0 == strcmp(argv[i], "--")) {            i++;            hasLibArgs = 1;            break;        } else {            usage(argv[0]);        }    }  if (rilLibPath == NULL) {      //通过Android属性系统读取属性"rild.libpath"的值,即lib库的存放路径        if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {            goto done;        } else {            rilLibPath = libPath;        }  }##################################################################################                            判断是否为模拟器###################################################################################if 1    {        static char*  arg_overrides[3];        static char   arg_device[32];        int           done = 0;#define  REFERENCE_RIL_PATH  "/system/lib/libreference-ril.so"        /* first, read /proc/cmdline into memory */        char          buffer[1024], *p, *q;        int           len;        int           fd = open("/proc/cmdline",O_RDONLY);        if (fd < 0) {            LOGD("could not open /proc/cmdline:%s", strerror(errno));            goto OpenLib;        }        //读取/proc/cmdline文件中的内容        do {            len = read(fd,buffer,sizeof(buffer)); }        while (len == -1 && errno == EINTR);        if (len < 0) {            LOGD("could not read /proc/cmdline:%s", strerror(errno));            close(fd);            goto OpenLib;        }        close(fd);        //判断是否为模拟器,对于真机,此处条件为false        if (strstr(buffer, "android.qemud=") != NULL)        {            int  tries = 5;#define  QEMUD_SOCKET_NAME    "qemud"            while (1) {                int  fd;                sleep(1);                fd = socket_local_client(QEMUD_SOCKET_NAME,                            ANDROID_SOCKET_NAMESPACE_RESERVED,                            SOCK_STREAM );                if (fd >= 0) {                    close(fd);                    snprintf( arg_device, sizeof(arg_device), "%s/%s",                                ANDROID_SOCKET_DIR, QEMUD_SOCKET_NAME );                    arg_overrides[1] = "-s";                    arg_overrides[2] = arg_device;                    done = 1;                    break;                }                LOGD("could not connect to %s socket: %s",QEMUD_SOCKET_NAME, strerror(errno));                if (--tries == 0)                    break;            }            if (!done) {                LOGE("could not connect to %s socket (giving up): %s",                    QEMUD_SOCKET_NAME, strerror(errno));                while(1)                    sleep(0x00ffffff);            }        }        /* otherwise, try to see if we passed a device name from the kernel */        if (!done) do { //true#define  KERNEL_OPTION  "android.ril="#define  DEV_PREFIX     "/dev/"            //判断/proc/cmdline中的内容是否包含"android.ril="            p = strstr( buffer, KERNEL_OPTION );            if (p == NULL)                break;            p += sizeof(KERNEL_OPTION)-1;            q  = strpbrk( p, " \t\n\r" );            if (q != NULL)                *q = 0;            snprintf( arg_device, sizeof(arg_device), DEV_PREFIX "%s", p );            arg_device[sizeof(arg_device)-1] = 0;            arg_overrides[1] = "-d";            arg_overrides[2] = arg_device;            done = 1;        } while (0);                if (done) { //false            argv = arg_overrides;            argc = 3;            i    = 1;            hasLibArgs = 1;            rilLibPath = REFERENCE_RIL_PATH;            LOGD("overriding with %s %s", arg_overrides[1], arg_overrides[2]);        }    }OpenLib:#endif##################################################################################                            动态库装载##################################################################################  switchUser();//设置Rild进程的组用户为radio  //加载厂商自定义的库    ①dlHandle = dlopen(rilLibPath, RTLD_NOW);    if (dlHandle == NULL) {        fprintf(stderr, "dlopen failed: %s\n", dlerror());        exit(-1);  }  //创建客户端事件监听线程  ②RIL_startEventLoop();  //通过dlsym定位到RIL_Init函数的地址,并且强制转换为RIL_RadioFunctions的函数指针    ③rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");    if (rilInit == NULL) {        fprintf(stderr, "RIL_Init not defined or exported in %s\n", rilLibPath);        exit(-1);    }    if (hasLibArgs) { //false        rilArgv = argv + i - 1;        argc = argc -i + 1;    } else {        static char * newArgv[MAX_LIB_ARGS];        static char args[PROPERTY_VALUE_MAX];        rilArgv = newArgv;        property_get(LIB_ARGS_PROPERTY, args, "");//通过属性系统读取"rild.libargs"属性值        argc = make_argv(args, rilArgv);    }    // Make sure there's a reasonable argv[0]  rilArgv[0] = argv[0];  //调用RIL_Init函数来初始化rild,传入参数s_rilEnv,返回RIL_RadioFunctions地址  ④funcs = rilInit(&s_rilEnv, argc, rilArgv);  //注册客户端事件处理接口RIL_RadioFunctions,并创建socket监听事件    ⑤RIL_register(funcs);done:    while(1) {        // sleep(UINT32_MAX) seems to return immediately on bionic        sleep(0x00ffffff);    }}

在main函数中主要完成以下工作:

1.解析命令行参数,通过判断是否为模拟器采取不同的方式来读取libreference-ril.so库的存放路径;

2.使用dlopen手动装载libreference-ril.so库;

3.启动事件循环处理;

4.从libreference-ril.so库中取得RIL_Init函数地址,并使用该函数将libril.so库中的RIL_Env接口注册到libreference-ril.so库,同时将libreference-ril.so库中的RIL_RadioFunctions接口注册到到libril.so库中,建立起libril.so库与libreference-ril.so库通信桥梁;

启动事件循环处理eventLoop工作线程

建立多路I/O驱动机制的消息队列,用来接收上层发出的命令以及往Modem发送AT指令的工作,时整个RIL系统的核心部分。创建一个事件分发线程s_tid_dispatch,线程执行体为eventLoop。

hardware\ril\libril\Ril.cpp 

[cpp]

  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.   //创建一个工作线程eventLoop   

  10.   ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);  

  11.   //确保函数返回前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. }  

extern "C" void RIL_startEventLoop(void) {    int ret;    pthread_attr_t attr;    /* spin up eventLoop thread and wait for it to get started */    s_started = 0;    pthread_mutex_lock(&s_startupMutex);    pthread_attr_init (&attr);  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  //创建一个工作线程eventLoop  ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);  //确保函数返回前eventLoop线程启动运行    while (s_started == 0) {        pthread_cond_wait(&s_startupCond, &s_startupMutex);    }    pthread_mutex_unlock(&s_startupMutex);    if (ret < 0) {        LOGE("Failed to create dispatch thread errno:%d", errno);        return;    }}

eventLoop执行时序图:

[cpp]

  1. static void * eventLoop(void *param) {  

  2.     int ret;  

  3.     int filedes[2];  

  4.     ril_event_init(); //初始化请求队列   

  5.     pthread_mutex_lock(&s_startupMutex);  

  6.     s_started = 1; //eventLoop线程运行标志位   

  7.     pthread_cond_broadcast(&s_startupCond);  

  8.   pthread_mutex_unlock(&s_startupMutex);  

  9.   //创建匿名管道   

  10.     ret = pipe(filedes);  

  11.     if (ret < 0) {  

  12.         LOGE("Error in pipe() errno:%d", errno);  

  13.         return NULL;  

  14.   }  

  15.   //s_fdWakeupRead为管道读端   

  16.   s_fdWakeupRead = filedes[0];  

  17.   //s_fdWakeupWrite为管道写端   

  18.   s_fdWakeupWrite = filedes[1];  

  19.   //设置管道读端为O_NONBLOCK非阻塞   

  20.   fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);  

  21.   //初始化s_wakeupfd_event结构体的内容,句柄为s_fdWakeupRead,回调函数为   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. }  

static void * eventLoop(void *param) {    int ret;    int filedes[2];    ril_event_init(); //初始化请求队列    pthread_mutex_lock(&s_startupMutex);    s_started = 1; //eventLoop线程运行标志位    pthread_cond_broadcast(&s_startupCond);  pthread_mutex_unlock(&s_startupMutex);  //创建匿名管道    ret = pipe(filedes);    if (ret < 0) {        LOGE("Error in pipe() errno:%d", errno);        return NULL;  }  //s_fdWakeupRead为管道读端  s_fdWakeupRead = filedes[0];  //s_fdWakeupWrite为管道写端  s_fdWakeupWrite = filedes[1];  //设置管道读端为O_NONBLOCK非阻塞  fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);  //初始化s_wakeupfd_event结构体的内容,句柄为s_fdWakeupRead,回调函数为   processWakeupCallback    ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,processWakeupCallback, NULL);    ①rilEventAddWakeup (&s_wakeupfd_event);    // Only returns on error    ②ril_event_loop();    LOGE ("error in event_loop_base errno:%d", errno);    return NULL;}

在rild中定义了event的概念,Rild支持两种类型的事件:

1. 定时事件:根据事件的执行时间来启动执行,通过ril_timer_add添加到time_list队列中

2. Wakeup事件:这些事件的句柄fd将加入的select IO多路复用的句柄池readFDs中,当对应的fd可读时将触发这些事件。对于处于listen端的socketfd可读表示有个客户端连接,此时需要调用accept接受连接。

事件定义如下:

[cpp]

  1. struct ril_event {  

  2.     struct ril_event *next;  

  3.     struct ril_event *prev;  

  4.     int fd;  //文件句柄   

  5.     int index; //该事件在监控表中的索引    

  6.     bool persist; //如果是保持的,则不从watch_list 中删除   

  7.     struct timeval timeout; //任务执行时间   

  8.     ril_event_cb func; //回调事件处理函数   

  9.     void *param; //回调时参数   

  10. };  

struct ril_event {    struct ril_event *next;    struct ril_event *prev;    int fd;  //文件句柄    int index; //该事件在监控表中的索引     bool persist; //如果是保持的,则不从watch_list 中删除    struct timeval timeout; //任务执行时间    ril_event_cb func; //回调事件处理函数    void *param; //回调时参数};

Rild进程中的几个重要事件有

[cpp]

  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);  

static struct ril_event s_commands_event;ril_event_set (&s_commands_event, s_fdCommand, 1,processCommandsCallback, p_rs)static struct ril_event s_wakeupfd_event;ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,processWakeupCallback, NULL)static struct ril_event s_listen_event;ril_event_set (&s_listen_event, s_fdListen, false,listenCallback, NULL)static struct ril_event s_wake_timeout_event;ril_timer_add(&(p_info->event), &myRelativeTime);

[cpp]

  1. static struct ril_event s_debug_event;  

  2. ril_event_set (&s_debug_event, s_fdDebug, true,debugCallback, NULL)  

static struct ril_event s_debug_event;ril_event_set (&s_debug_event, s_fdDebug, true,debugCallback, NULL)

在RILD中定义了三个事件队列,用于处理不同的事件:

/事件监控队列

static struct ril_event * watch_table[MAX_FD_EVENTS];

//定时事件队列

static struct ril_event timer_list;

//处理事件队列

static struct ril_event pending_list; //待处理事件队列,事件已经触发,需要所回调处理的事件

添加事件

1.添加Wakeup 事件

 

[cpp]

  1. static void rilEventAddWakeup(struct ril_event *ev) {  

  2.     ril_event_add(ev); //向监控表watch_table添加一个s_wakeupfd_event事件   

  3.     triggerEvLoop(); //向管道s_fdWakeupWrite中写入之来触发事件循环   

  4. }  

static void rilEventAddWakeup(struct ril_event *ev) {    ril_event_add(ev); //向监控表watch_table添加一个s_wakeupfd_event事件    triggerEvLoop(); //向管道s_fdWakeupWrite中写入之来触发事件循环}

[cpp]

  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++) { //遍历监控表watch_table   

  6.         if (watch_table[i] == NULL) { //从监控表中查找空闲的索引,然后把该任务加入到监控表中   

  7.             watch_table[i] = ev; //向监控表中添加事件   

  8.             ev->index = i; //事件的索引设置为在监控表中的索引   

  9.             dlog("~~~~ added at %d ~~~~", i);  

  10.             dump_event(ev);  

  11.             FD_SET(ev->fd, &readFds); //将添加的事件对应的句柄添加到句柄池readFds中   

  12.             if (ev->fd >= nfds) nfds = ev->fd+1; //修改句柄最大值   

  13.             dlog("~~~~ nfds = %d ~~~~", nfds);  

  14.             break;  

  15.         }  

  16.     }  

  17.     MUTEX_RELEASE();  

  18.     dlog("~~~~ -ril_event_add ~~~~");  

  19. }  

void ril_event_add(struct ril_event * ev){    dlog("~~~~ +ril_event_add ~~~~");    MUTEX_ACQUIRE();    for (int i = 0; i < MAX_FD_EVENTS; i++) { //遍历监控表watch_table        if (watch_table[i] == NULL) { //从监控表中查找空闲的索引,然后把该任务加入到监控表中            watch_table[i] = ev; //向监控表中添加事件            ev->index = i; //事件的索引设置为在监控表中的索引            dlog("~~~~ added at %d ~~~~", i);            dump_event(ev);            FD_SET(ev->fd, &readFds); //将添加的事件对应的句柄添加到句柄池readFds中            if (ev->fd >= nfds) nfds = ev->fd+1; //修改句柄最大值            dlog("~~~~ nfds = %d ~~~~", nfds);            break;        }    }    MUTEX_RELEASE();    dlog("~~~~ -ril_event_add ~~~~");}

2.添加定时事件

[cpp]

  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. }  

void ril_timer_add(struct ril_event * ev, struct timeval * tv){    dlog("~~~~ +ril_timer_add ~~~~");    MUTEX_ACQUIRE();    struct ril_event * list;    if (tv != NULL) {        list = timer_list.next;        ev->fd = -1; // make sure fd is invalid        struct timeval now;        getNow(&now);        timeradd(&now, tv, &ev->timeout);        // keep list sorted        while (timercmp(&list->timeout, &ev->timeout, < ) && (list != &timer_list)) {            list = list->next;        }        // list now points to the first event older than ev        addToList(ev, list);    }    MUTEX_RELEASE();    dlog("~~~~ -ril_timer_add ~~~~");}

触发事件

[cpp]

  1. static void triggerEvLoop() {  

  2.     int ret;  

  3.   if (!pthread_equal(pthread_self(), s_tid_dispatch)) { //如果当前线程ID不等于事件分发线程eventLoop的线程ID   

  4.       do {  

  5.             ret = write (s_fdWakeupWrite, " ", 1); //向管道写端写入值1来触发eventLoop事件循环   

  6.          } while (ret < 0 && errno == EINTR);  

  7.     }  

  8. }  

static void triggerEvLoop() {    int ret;  if (!pthread_equal(pthread_self(), s_tid_dispatch)) { //如果当前线程ID不等于事件分发线程eventLoop的线程ID      do {            ret = write (s_fdWakeupWrite, " ", 1); //向管道写端写入值1来触发eventLoop事件循环         } while (ret < 0 && errno == EINTR);    }}

处理事件

[cpp]

  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.         //使用select 函数等待在FDS 上,只要FDS 中记录的设备有数据到来,select 就会设置相应的标志位并返回。readFDS 记录了所有的事件相关设备句柄。readFDS 中句柄是在在AddEvent 加入的。   

  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(); //从timer_list中查询执行时间已到的事件,并添加到pending_list中   

  27.         processReadReadies(&rfds, n); //从watch_table中查询数据可读的事件,并添加到pending_list中去处理,如果该事件不是持久事件,则同时从watch_table中删除   

  28.         //遍历pending_list,调用事件处理回调函数处理所有事件   

  29.         firePending();  

  30.     }  

  31. }  

void ril_event_loop(){    int n;    fd_set rfds;    struct timeval tv;    struct timeval * ptv;    for (;;) {        memcpy(&rfds, &readFds, sizeof(fd_set));        if (-1 == calcNextTimeout(&tv)) {            dlog("~~~~ no timers; blocking indefinitely ~~~~");            ptv = NULL;        } else {            dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec);            ptv = &tv;        }        //使用select 函数等待在FDS 上,只要FDS 中记录的设备有数据到来,select 就会设置相应的标志位并返回。readFDS 记录了所有的事件相关设备句柄。readFDS 中句柄是在在AddEvent 加入的。        printReadies(&rfds);        n = select(nfds, &rfds, NULL, NULL, ptv);         printReadies(&rfds);        dlog("~~~~ %d events fired ~~~~", n);        if (n < 0) {            if (errno == EINTR) continue;            LOGE("ril_event: select error (%d)", errno);            return;        }        processTimeouts(); //从timer_list中查询执行时间已到的事件,并添加到pending_list中        processReadReadies(&rfds, n); //从watch_table中查询数据可读的事件,并添加到pending_list中去处理,如果该事件不是持久事件,则同时从watch_table中删除        //遍历pending_list,调用事件处理回调函数处理所有事件        firePending();    }}

在eventLoop工作线程中,循环处理到来的事件及定时结束事件,整个处理流程如下图所示:

首先通过Linux中的select多路I/O复用对句柄池中的所有句柄进行监控,当有事件到来时select返回,否则阻塞。当select返回时,表示有事件的到来,通过调用processTimeouts函数来处理超时事件,处理方式是遍历time_list链表以查询超时事件,并将超时事件移入到pending_list链表中,接着调用processReadReadies函数来处理触发的事件,处理方式为遍历watch_table列表以查询触发的事件,并将触发的事件移入到pending_list链表中,如果该事件不是持久事件,还需要从watch_table列表中移除,当查询完两种待处理的事件并放入到pending_list链表中后,调用firePending函数对待处理的事件进行集中处理,处理方式为遍历链表,调用每一个事件的回调函数。

 1.超时事件查询

[cpp]

  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); //获取当前时间   

  9.   dlog("~~~~ Looking for timers <= %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec);  

  10.   //如果当前时间大于事件的超时时间,则将该事件从timer_list中移除,添加到pending_list   

  11.     while ((tev != &timer_list) && (timercmp(&now, &tev->timeout, >))) {  

  12.         dlog("~~~~ firing timer ~~~~");  

  13.         next = tev->next;  

  14.         removeFromList(tev); //从timer_list中移除事件   

  15.         addToList(tev, &pending_list); //将事件添加到pending_list   

  16.         tev = next;  

  17.     }  

  18.     MUTEX_RELEASE();  

  19.     dlog("~~~~ -processTimeouts ~~~~");  

  20. }  

static void processTimeouts(){    dlog("~~~~ +processTimeouts ~~~~");    MUTEX_ACQUIRE();    struct timeval now;    struct ril_event * tev = timer_list.next;    struct ril_event * next;    getNow(&now); //获取当前时间  dlog("~~~~ Looking for timers <= %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec);  //如果当前时间大于事件的超时时间,则将该事件从timer_list中移除,添加到pending_list    while ((tev != &timer_list) && (timercmp(&now, &tev->timeout, >))) {        dlog("~~~~ firing timer ~~~~");        next = tev->next;        removeFromList(tev); //从timer_list中移除事件        addToList(tev, &pending_list); //将事件添加到pending_list        tev = next;    }    MUTEX_RELEASE();    dlog("~~~~ -processTimeouts ~~~~");}
2.可读事件查询

[cpp]

  1. static void processReadReadies(fd_set * rfds, int n)  

  2. {  

  3.     dlog("~~~~ +processReadReadies (%d) ~~~~", n);  

  4.   MUTEX_ACQUIRE();   

  5.   //遍历watch_table数组,根据select返回的句柄n查找对应的事件   

  6.     for (int i = 0; (i < MAX_FD_EVENTS) && (n > 0); i++) {  

  7.         struct ril_event * rev = watch_table[i]; //得到相应的事件   

  8.         if (rev != NULL && FD_ISSET(rev->fd, rfds)) {  

  9.             addToList(rev, &pending_list); //将该事件添加到pending_list中   

  10.             if (rev->persist == false) { //如果该事件不是持久事件还要从watch_table中移除   

  11.                 removeWatch(rev, i);  

  12.             }  

  13.             n--;  

  14.         }  

  15.     }  

  16.     MUTEX_RELEASE();  

  17.     dlog("~~~~ -processReadReadies (%d) ~~~~", n);  

  18. }  

static void processReadReadies(fd_set * rfds, int n){    dlog("~~~~ +processReadReadies (%d) ~~~~", n);  MUTEX_ACQUIRE();   //遍历watch_table数组,根据select返回的句柄n查找对应的事件    for (int i = 0; (i < MAX_FD_EVENTS) && (n > 0); i++) {        struct ril_event * rev = watch_table[i]; //得到相应的事件        if (rev != NULL && FD_ISSET(rev->fd, rfds)) {            addToList(rev, &pending_list); //将该事件添加到pending_list中            if (rev->persist == false) { //如果该事件不是持久事件还要从watch_table中移除                removeWatch(rev, i);            }            n--;        }    }    MUTEX_RELEASE();    dlog("~~~~ -processReadReadies (%d) ~~~~", n);}
3.事件处理

[cpp]

  1. static void firePending()  

  2. {  

  3.     dlog("~~~~ +firePending ~~~~");  

  4.     struct ril_event * ev = pending_list.next;  

  5.     while (ev != &pending_list) { //遍历pending_list链表,处理链表中的所有事件   

  6.         struct ril_event * next = ev->next;  

  7.         removeFromList(ev); //将处理完的事件从pending_list中移除   

  8.         ev->func(ev->fd, 0, ev->param); //调用事件处理的回调函数   

  9.         ev = next;  

  10.     }  

  11.     dlog("~~~~ -firePending ~~~~");  

  12. }  

static void firePending(){    dlog("~~~~ +firePending ~~~~");    struct ril_event * ev = pending_list.next;    while (ev != &pending_list) { //遍历pending_list链表,处理链表中的所有事件        struct ril_event * next = ev->next;        removeFromList(ev); //将处理完的事件从pending_list中移除        ev->func(ev->fd, 0, ev->param); //调用事件处理的回调函数        ev = next;    }    dlog("~~~~ -firePending ~~~~");}

RIL_Env定义

hardware\ril\include\telephony\ril.h

[cpp]

  1. struct RIL_Env {  

  2.     //动态库完成请求后通知处理结果的接口   

  3.   void (*OnRequestComplete)(RIL_Token t, RIL_Errno e,void *response, size_t responselen);  

  4.     //动态库unSolicited Response通知接口   

  5.   void (*OnUnsolicitedResponse)(int unsolResponse, const void *data,size_t datalen);  

  6.     //向Rild提交一个超时任务的接口   

  7.     void (*RequestTimedCallback) (RIL_TimedCallback callback,void *param, const struct timeval *relativeTime);  

  8. };  

struct RIL_Env {    //动态库完成请求后通知处理结果的接口  void (*OnRequestComplete)(RIL_Token t, RIL_Errno e,void *response, size_t responselen);    //动态库unSolicited Response通知接口  void (*OnUnsolicitedResponse)(int unsolResponse, const void *data,size_t datalen);    //向Rild提交一个超时任务的接口    void (*RequestTimedCallback) (RIL_TimedCallback callback,void *param, const struct timeval *relativeTime);};

hardware\ril\rild\rild.c

s_rilEnv变量定义:

[cpp]

  1. static struct RIL_Env s_rilEnv = {  

  2.     RIL_onRequestComplete,  

  3.     RIL_onUnsolicitedResponse,  

  4.     RIL_requestTimedCallback  

  5. };  

static struct RIL_Env s_rilEnv = {    RIL_onRequestComplete,    RIL_onUnsolicitedResponse,    RIL_requestTimedCallback};

在hardware\ril\libril\ril.cpp中实现了RIL_Env的各个接口函数

1.RIL_onRequestComplete

[cpp]

  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. }  

extern "C" void RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen) {    RequestInfo *pRI;    int ret;    size_t errorOffset;    pRI = (RequestInfo *)t;    if (!checkAndDequeueRequestInfo(pRI)) {        LOGE ("RIL_onRequestComplete: invalid RIL_Token");        return;    }    if (pRI->local > 0) {        // Locally issued command...void only!        // response does not go back up the command socket        LOGD("C[locl]< %s", requestToString(pRI->pCI->requestNumber));        goto done;    }    appendPrintBuf("[%04d]< %s",pRI->token, requestToString(pRI->pCI->requestNumber));    if (pRI->cancelled == 0) {        Parcel p;        p.writeInt32 (RESPONSE_SOLICITED);        p.writeInt32 (pRI->token);        errorOffset = p.dataPosition();        p.writeInt32 (e);        if (response != NULL) {            // there is a response payload, no matter success or not.            ret = pRI->pCI->responseFunction(p, response, responselen);            /* if an error occurred, rewind and mark it */            if (ret != 0) {                p.setDataPosition(errorOffset);                p.writeInt32 (ret);            }        }        if (e != RIL_E_SUCCESS) {            appendPrintBuf("%s fails by %s", printBuf, failCauseToString(e));        }        if (s_fdCommand < 0) {            LOGD ("RIL onRequestComplete: Command channel closed");        }        sendResponse(p);    }done:    free(pRI);}

通过调用responseXXX将底层响应传给客户进程

2.RIL_onUnsolicitedResponse

[cpp]

  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. }  

extern "C" void RIL_onUnsolicitedResponse(int unsolResponse, void *data,                                size_t datalen){    int unsolResponseIndex;    int ret;    int64_t timeReceived = 0;    bool shouldScheduleTimeout = false;    if (s_registerCalled == 0) {        // Ignore RIL_onUnsolicitedResponse before RIL_register        LOGW("RIL_onUnsolicitedResponse called before RIL_register");        return;    }    unsolResponseIndex = unsolResponse - RIL_UNSOL_RESPONSE_BASE;    if ((unsolResponseIndex < 0)        || (unsolResponseIndex >= (int32_t)NUM_ELEMS(s_unsolResponses))) {        LOGE("unsupported unsolicited response code %d", unsolResponse);        return;    }    // Grab a wake lock if needed for this reponse,    // as we exit we'll either release it immediately    // or set a timer to release it later.    switch (s_unsolResponses[unsolResponseIndex].wakeType) {        case WAKE_PARTIAL:            grabPartialWakeLock();            shouldScheduleTimeout = true;        break;        case DONT_WAKE:        default:            // No wake lock is grabed so don't set timeout            shouldScheduleTimeout = false;            break;    }    // Mark the time this was received, doing this    // after grabing the wakelock incase getting    // the elapsedRealTime might cause us to goto    // sleep.    if (unsolResponse == RIL_UNSOL_NITZ_TIME_RECEIVED) {        timeReceived = elapsedRealtime();    }    appendPrintBuf("[UNSL]< %s", requestToString(unsolResponse));    Parcel p;    p.writeInt32 (RESPONSE_UNSOLICITED);    p.writeInt32 (unsolResponse);    ret = s_unsolResponses[unsolResponseIndex].responseFunction(p, data, datalen);    if (ret != 0) {        // Problem with the response. Don't continue;        goto error_exit;    }    // some things get more payload    switch(unsolResponse) {        case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:            p.writeInt32(s_callbacks.onStateRequest());            appendPrintBuf("%s {%s}", printBuf,                radioStateToString(s_callbacks.onStateRequest()));        break;        case RIL_UNSOL_NITZ_TIME_RECEIVED:            // Store the time that this was received so the            // handler of this message can account for            // the time it takes to arrive and process. In            // particular the system has been known to sleep            // before this message can be processed.            p.writeInt64(timeReceived);        break;    }    ret = sendResponse(p);    if (ret != 0 && unsolResponse == RIL_UNSOL_NITZ_TIME_RECEIVED) {        // Unfortunately, NITZ time is not poll/update like everything        // else in the system. So, if the upstream client isn't connected,        // keep a copy of the last NITZ response (with receive time noted        // above) around so we can deliver it when it is connected        if (s_lastNITZTimeData != NULL) {            free (s_lastNITZTimeData);            s_lastNITZTimeData = NULL;        }        s_lastNITZTimeData = malloc(p.dataSize());        s_lastNITZTimeDataSize = p.dataSize();        memcpy(s_lastNITZTimeData, p.data(), p.dataSize());    }    // For now, we automatically go back to sleep after TIMEVAL_WAKE_TIMEOUT    // FIXME The java code should handshake here to release wake lock    if (shouldScheduleTimeout) {        // Cancel the previous request        if (s_last_wake_timeout_info != NULL) {            s_last_wake_timeout_info->userParam = (void *)1;        }        s_last_wake_timeout_info= internalRequestTimedCallback(wakeTimeoutCallback, NULL,                                            &TIMEVAL_WAKE_TIMEOUT);    }    return;error_exit:    if (shouldScheduleTimeout) {        releaseWakeLock();    }}

这个函数处理modem从网络端接收到的各种事件,如网络信号变化,拨入的电话,收到短信等。然后传给客户进程。

3.RIL_requestTimedCallback

[cpp]

  1. extern "C" void RIL_requestTimedCallback (RIL_TimedCallback callback, void *param,  

  2.                                 const struct timeval *relativeTime) {  

  3.     internalRequestTimedCallback (callback, param, relativeTime);  

  4. }  

extern "C" void RIL_requestTimedCallback (RIL_TimedCallback callback, void *param,                                const struct timeval *relativeTime) {    internalRequestTimedCallback (callback, param, relativeTime);}

[cpp]

  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. }  

static UserCallbackInfo *internalRequestTimedCallback (RIL_TimedCallback callback, void *param,                                const struct timeval *relativeTime){    struct timeval myRelativeTime;    UserCallbackInfo *p_info;    p_info = (UserCallbackInfo *) malloc (sizeof(UserCallbackInfo));    p_info->p_callback = callback;    p_info->userParam = param;    if (relativeTime == NULL) {        /* treat null parameter as a 0 relative time */        memset (&myRelativeTime, 0, sizeof(myRelativeTime));    } else {        /* FIXME I think event_add's tv param is really const anyway */        memcpy (&myRelativeTime, relativeTime, sizeof(myRelativeTime));    }    ril_event_set(&(p_info->event), -1, false, userTimerCallback, p_info);    ril_timer_add(&(p_info->event), &myRelativeTime);    triggerEvLoop();    return p_info;}

RIL_RadioFunctions定义

客户端向Rild发送请求的接口,由各手机厂商实现。

hardware\ril\include\telephony\Ril.h 

[cpp]

  1. typedef struct {  

  2.     int version; //Rild版本   

  3.     RIL_RequestFunc onRequest; //AP请求接口   

  4.     RIL_RadioStateRequest onStateRequest;//BP状态查询   

  5.     RIL_Supports supports;  

  6.     RIL_Cancel onCancel;  

  7.     RIL_GetVersion getVersion;//动态库版本   

  8. } RIL_RadioFunctions;  

typedef struct {    int version; //Rild版本    RIL_RequestFunc onRequest; //AP请求接口    RIL_RadioStateRequest onStateRequest;//BP状态查询    RIL_Supports supports;    RIL_Cancel onCancel;    RIL_GetVersion getVersion;//动态库版本} RIL_RadioFunctions;

变量定义:

[cpp]

  1. static const RIL_RadioFunctions s_callbacks = {  

  2.     RIL_VERSION,  

  3.     onRequest,  

  4.     currentState,  

  5.     onSupports,  

  6.     onCancel,  

  7.     getVersion  

  8. };  

static const RIL_RadioFunctions s_callbacks = {    RIL_VERSION,    onRequest,    currentState,    onSupports,    onCancel,    getVersion};

在hardware\ril\reference-ril\reference-ril.c中实现了RIL_RadioFunctions的各个接口函数

1.onRequest

[cpp]

  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. }  

static void onRequest (int request, void *data, size_t datalen, RIL_Token t){    ATResponse *p_response;    int err;    LOGD("onRequest: %s", requestToString(request));    /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS     * when RADIO_STATE_UNAVAILABLE.     */    if (sState == RADIO_STATE_UNAVAILABLE        && request != RIL_REQUEST_GET_SIM_STATUS    ) {        RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);        return;    }    /* Ignore all non-power requests when RADIO_STATE_OFF     * (except RIL_REQUEST_GET_SIM_STATUS)     */    if (sState == RADIO_STATE_OFF&& !(request == RIL_REQUEST_RADIO_POWER            || request == RIL_REQUEST_GET_SIM_STATUS)    ) {        RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);        return;    }    switch (request) {        case RIL_REQUEST_GET_SIM_STATUS: {            RIL_CardStatus *p_card_status;            char *p_buffer;            int buffer_size;            int result = getCardStatus(&p_card_status);            if (result == RIL_E_SUCCESS) {                p_buffer = (char *)p_card_status;                buffer_size = sizeof(*p_card_status);            } else {                p_buffer = NULL;                buffer_size = 0;            }            RIL_onRequestComplete(t, result, p_buffer, buffer_size);            freeCardStatus(p_card_status);            break;        }        case RIL_REQUEST_GET_CURRENT_CALLS:            requestGetCurrentCalls(data, datalen, t);            break;        case RIL_REQUEST_DIAL:            requestDial(data, datalen, t);            break;        case RIL_REQUEST_HANGUP:            requestHangup(data, datalen, t);            break;        case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:            // 3GPP 22.030 6.5.5            // "Releases all held calls or sets User Determined User Busy            //  (UDUB) for a waiting call."            at_send_command("AT+CHLD=0", NULL);            /* success or failure is ignored by the upper layer here.               it will call GET_CURRENT_CALLS and determine success that way */            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);            break;        case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:            // 3GPP 22.030 6.5.5            // "Releases all active calls (if any exist) and accepts            //  the other (held or waiting) call."            at_send_command("AT+CHLD=1", NULL);            /* success or failure is ignored by the upper layer here.               it will call GET_CURRENT_CALLS and determine success that way */            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);            break;        case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:            // 3GPP 22.030 6.5.5            // "Places all active calls (if any exist) on hold and accepts            //  the other (held or waiting) call."            at_send_command("AT+CHLD=2", NULL);#ifdef WORKAROUND_ERRONEOUS_ANSWER            s_expectAnswer = 1;#endif /* WORKAROUND_ERRONEOUS_ANSWER */            /* success or failure is ignored by the upper layer here.               it will call GET_CURRENT_CALLS and determine success that way */            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);            break;        case RIL_REQUEST_ANSWER:            at_send_command("ATA", NULL);#ifdef WORKAROUND_ERRONEOUS_ANSWER            s_expectAnswer = 1;#endif /* WORKAROUND_ERRONEOUS_ANSWER */            /* success or failure is ignored by the upper layer here.               it will call GET_CURRENT_CALLS and determine success that way */            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);            break;        case RIL_REQUEST_CONFERENCE:            // 3GPP 22.030 6.5.5            // "Adds a held call to the conversation"            at_send_command("AT+CHLD=3", NULL);            /* success or failure is ignored by the upper layer here.               it will call GET_CURRENT_CALLS and determine success that way */            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);            break;        case RIL_REQUEST_UDUB:            /* user determined user busy */            /* sometimes used: ATH */            at_send_command("ATH", NULL);            /* success or failure is ignored by the upper layer here.               it will call GET_CURRENT_CALLS and determine success that way */            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);            break;        case RIL_REQUEST_SEPARATE_CONNECTION:            {                char  cmd[12];                int   party = ((int*)data)[0];                // Make sure that party is in a valid range.                // (Note: The Telephony middle layer imposes a range of 1 to 7.                // It's sufficient for us to just make sure it's single digit.)                if (party > 0 && party < 10) {                    sprintf(cmd, "AT+CHLD=2%d", party);                    at_send_command(cmd, NULL);                    RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);                } else {                    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);                }            }            break;        case RIL_REQUEST_SIGNAL_STRENGTH:            requestSignalStrength(data, datalen, t);            break;        case RIL_REQUEST_REGISTRATION_STATE:        case RIL_REQUEST_GPRS_REGISTRATION_STATE:            requestRegistrationState(request, data, datalen, t);            break;        case RIL_REQUEST_OPERATOR:            requestOperator(data, datalen, t);            break;        case RIL_REQUEST_RADIO_POWER:            requestRadioPower(data, datalen, t);            break;        case RIL_REQUEST_DTMF: {            char c = ((char *)data)[0];            char *cmd;            asprintf(&cmd, "AT+VTS=%c", (int)c);            at_send_command(cmd, NULL);            free(cmd);            RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);            break;        }        case RIL_REQUEST_SEND_SMS:            requestSendSMS(data, datalen, t);            break;        case RIL_REQUEST_SETUP_DATA_CALL:            requestSetupDataCall(data, datalen, t);            break;        case RIL_REQUEST_SMS_ACKNOWLEDGE:            requestSMSAcknowledge(data, datalen, t);            break;        case RIL_REQUEST_GET_IMSI:            p_response = NULL;            err = at_send_command_numeric("AT+CIMI", &p_response);            if (err < 0 || p_response->success == 0) {                RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);            } else {                RIL_onRequestComplete(t, RIL_E_SUCCESS,                    p_response->p_intermediates->line, sizeof(char *));            }            at_response_free(p_response);            break;        case RIL_REQUEST_GET_IMEI:            p_response = NULL;            err = at_send_command_numeric("AT+CGSN", &p_response);            if (err < 0 || p_response->success == 0) {                RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);            } else {                RIL_onRequestComplete(t, RIL_E_SUCCESS,                    p_response->p_intermediates->line, sizeof(char *));            }            at_response_free(p_response);            break;        case RIL_REQUEST_SIM_IO:            requestSIM_IO(data,datalen,t);            break;        case RIL_REQUEST_SEND_USSD:            requestSendUSSD(data, datalen, t);            break;        case RIL_REQUEST_CANCEL_USSD:            p_response = NULL;            err = at_send_command_numeric("AT+CUSD=2", &p_response);            if (err < 0 || p_response->success == 0) {                RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);            } else {                RIL_onRequestComplete(t, RIL_E_SUCCESS,                    p_response->p_intermediates->line, sizeof(char *));            }            at_response_free(p_response);            break;        case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:            at_send_command("AT+COPS=0", NULL);            break;        case RIL_REQUEST_DATA_CALL_LIST:            requestDataCallList(data, datalen, t);            break;        case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:            requestQueryNetworkSelectionMode(data, datalen, t);            break;        case RIL_REQUEST_OEM_HOOK_RAW:            // echo back data            RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);            break;        case RIL_REQUEST_OEM_HOOK_STRINGS: {            int i;            const char ** cur;            LOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen);            for (i = (datalen / sizeof (char *)), cur = (const char **)data ;                    i > 0 ; cur++, i --) {                LOGD("> '%s'", *cur);            }            // echo back strings            RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);            break;        }        case RIL_REQUEST_WRITE_SMS_TO_SIM:            requestWriteSmsToSim(data, datalen, t);            break;        case RIL_REQUEST_DELETE_SMS_ON_SIM: {            char * cmd;            p_response = NULL;            asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]);            err = at_send_command(cmd, &p_response);            free(cmd);            if (err < 0 || p_response->success == 0) {                RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);            } else {                RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);            }            at_response_free(p_response);            break;        }        case RIL_REQUEST_ENTER_SIM_PIN:        case RIL_REQUEST_ENTER_SIM_PUK:        case RIL_REQUEST_ENTER_SIM_PIN2:        case RIL_REQUEST_ENTER_SIM_PUK2:        case RIL_REQUEST_CHANGE_SIM_PIN:        case RIL_REQUEST_CHANGE_SIM_PIN2:            requestEnterSimPin(data, datalen, t);            break;        case RIL_REQUEST_GSM_SMS_BROADCAST_ACTIVATION:            requestSmsBroadcastActivation(0,data, datalen, t);            break;        case RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG:             LOGD("onRequest RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG");            requestSetSmsBroadcastConfig(0,data, datalen, t);            break;        case RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG:            requestGetSmsBroadcastConfig(0,data, datalen, t);            break;        default:            RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);            break;    }}

对每一个RIL_REQUEST_XXX请求转化成相应的ATcommand,发送给modem,然后睡眠等待,当收到ATcommand的最终响应后,线程被唤醒,将响应传给客户端进程。

2.currentState

[cpp]

  1. static RIL_RadioState currentState()  

  2. {  

  3.     return sState;  

  4. }  

static RIL_RadioState currentState(){    return sState;}

3.onSupports

[cpp]

  1. static int onSupports (int requestCode)  

  2. {  

  3.     //@@@ todo   

  4.     return 1;  

  5. }  

static int onSupports (int requestCode){    //@@@ todo    return 1;}

4.onCancel

[cpp]

  1. static void onCancel (RIL_Token t)  

  2. {  

  3.     //@@   

  4. }  

static void onCancel (RIL_Token t){    //@@@todo}

5.getVersion

[cpp]

  1. static const char * getVersion(void)  

  2. {  

  3.     return "android reference-ril 1.0";  

  4. }  

static const char * getVersion(void){    return "android reference-ril 1.0";}

注册RIL_Env接口

由于各手机厂商的AT指令差异,因此与modem交互层需要各手机厂商实现,以动态库的形式提供。作为介于modem与上层的中间层,即要与底层交互也要与上层通信,因此就需要定义一个接口来衔接RILD与动态库,RIL_Env和RIL_RadioFunctions接口就是libril.so与librefrence.so通信的桥梁。Rild架构中用于隔离通用代码和厂商代码的接口,RIL_Env由通用代码实现,而RIL_RadioFunctions则是由厂商代码实现。

RIL_Init的主要任务:

1. 向librefrence.so注册libril.so提供的接口RIL_Env;

2. 创建一个mainLoop工作线程,用于初始化AT模块,并监控AT模块的状态,一旦AT被关闭,则重新打开并初始化AT

3. AT被打开后,mainLoop工作线程将向Rild提交一个定时事件,并触发eventLoop来完成对modem的初始化;

4. 创建一个readLoop工作线程,用于从AT串口中读取数据;

5.返回librefrence.so提供的接口RIL_RadioFunctions;

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

[cpp]

  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; //将ril.cpp中定义的RIL_Env注册到reference-ril.c中的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.   //创建一个mainLoop线程   

  39.   ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);  

  40.   //将reference-ril.c中定义的RIL_RadioFunctions返回并注册到ril.cpp中的s_callbacks   

  41.     return &s_callbacks;  

  42. }  

const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv){    int ret;    int fd = -1;    int opt;    pthread_attr_t attr;  s_rilenv = env; //将ril.cpp中定义的RIL_Env注册到reference-ril.c中的s_rilenv    while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {        switch (opt) {            case 'p':                s_port = atoi(optarg);                if (s_port == 0) {                    usage(argv[0]);                    return NULL;                }                LOGI("Opening loopback port %d\n", s_port);            break;            case 'd':                s_device_path = optarg;                LOGI("Opening tty device %s\n", s_device_path);            break;            case 's':                s_device_path   = optarg;                s_device_socket = 1;                LOGI("Opening socket %s\n", s_device_path);            break;            default:                usage(argv[0]);                return NULL;        }    }    if (s_port < 0 && s_device_path == NULL) {        usage(argv[0]);        return NULL;    }    pthread_attr_init (&attr);  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  //创建一个mainLoop线程  ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);  //将reference-ril.c中定义的RIL_RadioFunctions返回并注册到ril.cpp中的s_callbacks    return &s_callbacks;}

mainLoop工作线程是用来初始化并监控AT模块的,一旦AT模块被关闭,就自动打开。

[cpp]

  1. static void * mainLoop(void *param)  

  2. {  

  3.     int fd;  

  4.     int ret;  

  5.   AT_DUMP("== ", "entering mainLoop()", -1 );  

  6.   //为AT模块设置回调函数   

  7.     at_set_on_reader_closed(onATReaderClosed);  

  8.     at_set_on_timeout(onATTimeout);  

  9.     for (;;) {  

  10.         fd = -1;  

  11.         while  (fd < 0) { //获得串口AT模块的设备文件描述符   

  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.         //打开AT模块,创建AT读取线程s_tid_reader,fd为modem设备文件句柄   

  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.         //向Rild提交超时任务   

  54.         RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);  

  55.         sleep(1);  

  56.         //如果AT模块被关闭,则waitForClose返回,重新打开AT,如果AT已打开,则阻塞   

  57.         waitForClose();  

  58.         LOGI("Re-opening after close");  

  59.     }  

  60. }  

static void * mainLoop(void *param){    int fd;    int ret;  AT_DUMP("== ", "entering mainLoop()", -1 );  //为AT模块设置回调函数    at_set_on_reader_closed(onATReaderClosed);    at_set_on_timeout(onATTimeout);    for (;;) {        fd = -1;        while  (fd < 0) { //获得串口AT模块的设备文件描述符            if (s_port > 0) {                fd = socket_loopback_client(s_port, SOCK_STREAM);            } else if (s_device_socket) {                if (!strcmp(s_device_path, "/dev/socket/qemud")) {                    /* Qemu-specific control socket */                    fd = socket_local_client( "qemud",                 ANDROID_SOCKET_NAMESPACE_RESERVED,SOCK_STREAM );                    if (fd >= 0 ) {                        char  answer[2];                        if ( write(fd, "gsm", 3) != 3 ||read(fd, answer, 2) != 2 ||                             memcmp(answer, "OK", 2) != 0)                        {                            close(fd);                            fd = -1;                        }                   }                }                else                    fd = socket_local_client( s_device_path,    ANDROID_SOCKET_NAMESPACE_FILESYSTEM,SOCK_STREAM );            } else if (s_device_path != NULL) {                fd = open (s_device_path, O_RDWR);                if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {                    /* disable echo on serial ports */                    struct termios  ios;                    tcgetattr( fd, &ios );                    ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */                    tcsetattr( fd, TCSANOW, &ios );                }            }            if (fd < 0) {                perror ("opening AT interface. retrying...");                sleep(10);            }        }        s_closed = 0;        //打开AT模块,创建AT读取线程s_tid_reader,fd为modem设备文件句柄        ret = at_open(fd, onUnsolicited);        if (ret < 0) {            LOGE ("AT error %d on at_open\n", ret);            return 0;        }        //向Rild提交超时任务        RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);        sleep(1);        //如果AT模块被关闭,则waitForClose返回,重新打开AT,如果AT已打开,则阻塞        waitForClose();        LOGI("Re-opening after close");    }}

1.打开AT模块

通过at_open打开文件描述符为fdAT串口设备,并注册回调函数ATUnsolHandler 

[cpp]

  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.   //创建readerLoop工作线程,该线程用于从串口读取数据   

  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. }  

int at_open(int fd, ATUnsolHandler h){    int ret;    pthread_t tid;    pthread_attr_t attr;    s_fd = fd;    s_unsolHandler = h;    s_readerClosed = 0;    s_responsePrefix = NULL;    s_smsPDU = NULL;    sp_response = NULL;    /* Android power control ioctl */#ifdef HAVE_ANDROID_OS#ifdef OMAP_CSMI_POWER_CONTROL    ret = ioctl(fd, OMAP_CSMI_TTY_ENABLE_ACK);    if(ret == 0) {        int ack_count;		int read_count;        int old_flags;        char sync_buf[256];        old_flags = fcntl(fd, F_GETFL, 0);        fcntl(fd, F_SETFL, old_flags | O_NONBLOCK);        do {            ioctl(fd, OMAP_CSMI_TTY_READ_UNACKED, &ack_count);			read_count = 0;            do {                ret = read(fd, sync_buf, sizeof(sync_buf));				if(ret > 0)					read_count += ret;            } while(ret > 0 || (ret < 0 && errno == EINTR));            ioctl(fd, OMAP_CSMI_TTY_ACK, &ack_count);         } while(ack_count > 0 || read_count > 0);        fcntl(fd, F_SETFL, old_flags);        s_readCount = 0;        s_ackPowerIoctl = 1;    }    else        s_ackPowerIoctl = 0;#else // OMAP_CSMI_POWER_CONTROL        s_ackPowerIoctl = 0;#endif // OMAP_CSMI_POWER_CONTROL#endif /*HAVE_ANDROID_OS*/    pthread_attr_init (&attr);  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  //创建readerLoop工作线程,该线程用于从串口读取数据    ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);    if (ret < 0) {        perror ("pthread_create");        return -1;    }    return 0;}

2.添加定时事件RIL_requestTimedCallback

[cpp]

  1. RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);  

  2.   

  3. #define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)  

RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);#define RIL_requestTimedCallback(a,b,c) s_rilenv->RequestTimedCallback(a,b,c)

向定时事件队列中添加一个定时事件,该事件的处理函数为initializeCallback,用于发送一些AT指令来初始化BPmodem

3.readLoop工作线程

Read loop 解析从Modem 发过来的回应。如果遇到URC 则通过handleUnsolicited 上报的RIL_JAVA。如果是命令的应答,则通过handleFinalResponse 通知send_at_command 有应答结果。

[cpp]

  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)) { //判断是否是SMS 通知   

  10.             char *line1;  

  11.             const char *line2;  

  12.             line1 = strdup(line);  

  13.             line2 = readline();  

  14.             if (line2 == NULL) {  

  15.                 break;  

  16.             }  

  17.             if (s_unsolHandler != NULL) {  

  18.                 s_unsolHandler (line1, line2); //回调通知SMS   

  19.             }  

  20.             free(line1);  

  21.         } else {  

  22.             processLine(line); //处理接收到的数据,根据line中的指令调用不同的回调函数   

  23.         }  

  24. #ifdef HAVE_ANDROID_OS   

  25.         if (s_ackPowerIoctl > 0) {  

  26.             /* acknowledge that bytes have been read and processed */  

  27.             ioctl(s_fd, OMAP_CSMI_TTY_ACK, &s_readCount);  

  28.             s_readCount = 0;  

  29.         }  

  30. #endif /*HAVE_ANDROID_OS*/   

  31.     }  

  32.     onReaderClosed();  

  33.     return NULL;  

  34. }  

static void *readerLoop(void *arg){    for (;;) {        const char * line;        line = readline();        if (line == NULL) {            break;        }        if(isSMSUnsolicited(line)) { //判断是否是SMS 通知            char *line1;            const char *line2;            line1 = strdup(line);            line2 = readline();            if (line2 == NULL) {                break;            }            if (s_unsolHandler != NULL) {                s_unsolHandler (line1, line2); //回调通知SMS            }            free(line1);        } else {            processLine(line); //处理接收到的数据,根据line中的指令调用不同的回调函数        }#ifdef HAVE_ANDROID_OS        if (s_ackPowerIoctl > 0) {            /* acknowledge that bytes have been read and processed */            ioctl(s_fd, OMAP_CSMI_TTY_ACK, &s_readCount);            s_readCount = 0;        }#endif /*HAVE_ANDROID_OS*/    }    onReaderClosed();    return NULL;}

注册RIL_RadioFunctions接口

hardware\ril\libril\ril.cpp

[cpp]

  1. extern "C" void RIL_register (const RIL_RadioFunctions *callbacks) {  

  2.     int ret;  

  3.   int flags;  

  4.   //版本验证   

  5.     if (callbacks == NULL || ((callbacks->version != RIL_VERSION)&& (callbacks->version < 2))) {   

  6.         return;  

  7.     }  

  8.     if (callbacks->version < RIL_VERSION) {  

  9.         LOGE ("RIL_register: upgrade RIL to version %d current version=%d",  

  10.               RIL_VERSION, callbacks->version);  

  11.     }  

  12.     if (s_registerCalled > 0) {  

  13.         LOGE("RIL_register has been called more than once. "Subsequent call ignored");  

  14.         return;  

  15.   }  

  16.     //将reference-ril.c中定义的RIL_RadioFunctions注册到ril.cpp中   

  17.     memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));  

  18.     s_registerCalled = 1;  

  19.     for (int i = 0; i < (int)NUM_ELEMS(s_commands); i++) {  

  20.         assert(i == s_commands[i].requestNumber); //序号验证   

  21.     }  

  22.     for (int i = 0; i < (int)NUM_ELEMS(s_unsolResponses); i++) {  

  23.         assert(i + RIL_UNSOL_RESPONSE_BASE== s_unsolResponses[i].requestNumber);  

  24.     }  

  25.     // old standalone impl wants it here.   

  26.     if (s_started == 0) {  

  27.         RIL_startEventLoop();  

  28.     }  

  29.   // 得到名为rild的socket句柄   

  30.   s_fdListen = android_get_control_socket(SOCKET_NAME_RIL);  

  31.     if (s_fdListen < 0) {  

  32.         LOGE("Failed to get socket '" SOCKET_NAME_RIL "'");  

  33.         exit(-1);  

  34.   }  

  35.   // 监听该socket   

  36.     ret = listen(s_fdListen, 4);  

  37.     if (ret < 0) {  

  38.         LOGE("Failed to listen on control socket '%d': %s",s_fdListen, strerror(errno));  

  39.         exit(-1);  

  40.     }  

  41.     /* 设置s_listen_event事件,一旦有客户端连接,即s_fdListen可读就会导致eventLoop工作线程中的select返回,因为该事件不是持久的,因此调用为listenCallback处理完后,将从watch_table移除该事件,所以Rild只支持一个客户端连接*/  

  42.   ril_event_set (&s_listen_event, s_fdListen, false,listenCallback, NULL);  

  43.     /* 添加s_listen_event事件,并触发eventLoop工作线程 */  

  44.     rilEventAddWakeup (&s_listen_event);  

  45. #if 1   

  46.     // 得到调试socket的句柄rild-debug   

  47.     s_fdDebug = android_get_control_socket(SOCKET_NAME_RIL_DEBUG);  

  48.     if (s_fdDebug < 0) {  

  49.         LOGE("Failed to get socket '" SOCKET_NAME_RIL_DEBUG "' errno:%d", errno);  

  50.         exit(-1);  

  51.   }  

  52.   //监听该socket   

  53.     ret = listen(s_fdDebug, 4);  

  54.     if (ret < 0) {  

  55.         LOGE("Failed to listen on ril debug socket '%d': %s",s_fdDebug, strerror(errno));  

  56.         exit(-1);  

  57.   }  

  58.     /* 设置s_debug_event事件 */  

  59.     ril_event_set (&s_debug_event, s_fdDebug, true,debugCallback, NULL);  

  60.     /* 添加s_debug_event事件,并触发eventLoop工作线程  */  

  61.     rilEventAddWakeup (&s_debug_event);  

  62. #endif   

  63. }  

extern "C" void RIL_register (const RIL_RadioFunctions *callbacks) {    int ret;  int flags;  //版本验证    if (callbacks == NULL || ((callbacks->version != RIL_VERSION)&& (callbacks->version < 2))) {         return;    }    if (callbacks->version < RIL_VERSION) {        LOGE ("RIL_register: upgrade RIL to version %d current version=%d",              RIL_VERSION, callbacks->version);    }    if (s_registerCalled > 0) {        LOGE("RIL_register has been called more than once. "Subsequent call ignored");        return;  }    //将reference-ril.c中定义的RIL_RadioFunctions注册到ril.cpp中    memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));    s_registerCalled = 1;    for (int i = 0; i < (int)NUM_ELEMS(s_commands); i++) {        assert(i == s_commands[i].requestNumber); //序号验证    }    for (int i = 0; i < (int)NUM_ELEMS(s_unsolResponses); i++) {        assert(i + RIL_UNSOL_RESPONSE_BASE== s_unsolResponses[i].requestNumber);    }    // old standalone impl wants it here.    if (s_started == 0) {        RIL_startEventLoop();    }  // 得到名为rild的socket句柄  s_fdListen = android_get_control_socket(SOCKET_NAME_RIL);    if (s_fdListen < 0) {        LOGE("Failed to get socket '" SOCKET_NAME_RIL "'");        exit(-1);  }  // 监听该socket    ret = listen(s_fdListen, 4);    if (ret < 0) {        LOGE("Failed to listen on control socket '%d': %s",s_fdListen, strerror(errno));        exit(-1);    }    /* 设置s_listen_event事件,一旦有客户端连接,即s_fdListen可读就会导致eventLoop工作线程中的select返回,因为该事件不是持久的,因此调用为listenCallback处理完后,将从watch_table移除该事件,所以Rild只支持一个客户端连接*/  ril_event_set (&s_listen_event, s_fdListen, false,listenCallback, NULL);    /* 添加s_listen_event事件,并触发eventLoop工作线程 */    rilEventAddWakeup (&s_listen_event);#if 1    // 得到调试socket的句柄rild-debug    s_fdDebug = android_get_control_socket(SOCKET_NAME_RIL_DEBUG);    if (s_fdDebug < 0) {        LOGE("Failed to get socket '" SOCKET_NAME_RIL_DEBUG "' errno:%d", errno);        exit(-1);  }  //监听该socket    ret = listen(s_fdDebug, 4);    if (ret < 0) {        LOGE("Failed to listen on ril debug socket '%d': %s",s_fdDebug, strerror(errno));        exit(-1);  }    /* 设置s_debug_event事件 */    ril_event_set (&s_debug_event, s_fdDebug, true,debugCallback, NULL);    /* 添加s_debug_event事件,并触发eventLoop工作线程  */    rilEventAddWakeup (&s_debug_event);#endif}

打开监听端口,接收来自客户端进程的命令请求,当与客户进程连接建立时调用listenCallback函数,创建单独线程监视并处理所有事件源。

1.客户端连接处理

s_listen_event事件用于处理上层客户端的socket连接,当得到socket连接请求时,eventLoop工作线程里的select返回并自动调用listenCallback回调函数进行处理:

[cpp]

  1. tatic void listenCallback (int fd, short flags, void *param) {  

  2.     int ret;  

  3.     int err;  

  4.     int is_phone_socket;  

  5.     RecordStream *p_rs;  

  6.     commthread_data_t *user_data = NULL;  

  7.     user_data =(commthread_data_t *)malloc(sizeof(commthread_data_t));  

  8.     struct sockaddr_un peeraddr;  

  9.     socklen_t socklen = sizeof (peeraddr);  

  10.     struct ucred creds;  

  11.     socklen_t szCreds = sizeof(creds);  

  12.     struct passwd *pwd = NULL;  

  13.     assert (s_fdCommand < 0);  

  14.   assert (fd == s_fdListen);  

  15.   //接收一个客户端的连接,并将该socket连接保存在变量s_fdCommand中   

  16.     s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);  

  17.     if (s_fdCommand < 0 ) {  

  18.         LOGE("Error on accept() errno:%d", errno);  

  19.         /* start listening for new connections again */  

  20.         rilEventAddWakeup(&s_listen_event);  

  21.           return;  

  22.     }  

  23.     /* 对客户端权限判断,判断是否是进程组ID为radio的进程发起的连接*/  

  24.     errno = 0;  

  25.     is_phone_socket = 0;  

  26.     err = getsockopt(s_fdCommand, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);  

  27.     if (err == 0 && szCreds > 0) {  

  28.         errno = 0;  

  29.         pwd = getpwuid(creds.uid);  

  30.         if (pwd != NULL) {  

  31.             if (strcmp(pwd->pw_name, PHONE_PROCESS) == 0) {  

  32.                 is_phone_socket = 1;  

  33.             } else {  

  34.                 LOGE("RILD can't accept socket from process %s", pwd->pw_name);  

  35.             }  

  36.         } else {  

  37.             LOGE("Error on getpwuid() errno: %d", errno);  

  38.         }  

  39.     } else {  

  40.         LOGD("Error on getsockopt() errno: %d", errno);  

  41.     }  

  42.       

  43.     if ( !is_phone_socket ) {  

  44.       LOGE("RILD must accept socket from %s", PHONE_PROCESS);  

  45.       close(s_fdCommand);  

  46.       s_fdCommand = -1;  

  47.       onCommandsSocketClosed();  

  48.       /* start listening for new connections again */  

  49.       rilEventAddWakeup(&s_listen_event);  

  50.       return;  

  51.     }  

  52. #if 0   

  53.     if(s_dualSimMode) {  

  54.         if(s_sim_num == 0) {  

  55.             property_get(SIM_POWER_PROPERTY, prop, "0");  

  56.             if(!strcmp(prop, "0")) {  

  57.                 property_set(SIM_POWER_PROPERTY, "1");  

  58.                 s_callbacks.powerSIM(NULL);  

  59.             }  

  60.         } else if(s_sim_num == 1) {  

  61.             property_get(SIM_POWER_PROPERTY1, prop, "0");  

  62.             if(!strcmp(prop, "0")) {  

  63.                 property_set(SIM_POWER_PROPERTY1, "1");  

  64.                 s_callbacks.powerSIM(NULL);  

  65.             }  

  66.         }  

  67.     } else {  

  68.         property_get(SIM_POWER_PROPERTY, prop, "0");  

  69.         if(!strcmp(prop, "0")) {  

  70.             property_set(SIM_POWER_PROPERTY, "1");  

  71.             s_callbacks.powerSIM(NULL);  

  72.         }  

  73.     }  

  74. #endif   

  75.     //p_rs为RecordStream类型,它内部会分配一个缓冲区来存储客户端发送过来的数据   

  76.   p_rs = record_stream_new(s_fdCommand, MAX_COMMAND_BYTES);  

  77.   //添加一个针对接收到的客户端连接的处理事件,从而在eventLoop工作线程中处理该客户端的各种请求   

  78.     ril_event_set (&s_commands_event, s_fdCommand, 1,processCommandsCallback, p_rs);  

  79.     rilEventAddWakeup (&s_commands_event);  

  80.     onNewCommandConnect();  

  81. }  

tatic void listenCallback (int fd, short flags, void *param) {    int ret;    int err;    int is_phone_socket;    RecordStream *p_rs;    commthread_data_t *user_data = NULL;    user_data =(commthread_data_t *)malloc(sizeof(commthread_data_t));    struct sockaddr_un peeraddr;    socklen_t socklen = sizeof (peeraddr);    struct ucred creds;    socklen_t szCreds = sizeof(creds);    struct passwd *pwd = NULL;    assert (s_fdCommand < 0);  assert (fd == s_fdListen);  //接收一个客户端的连接,并将该socket连接保存在变量s_fdCommand中    s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);    if (s_fdCommand < 0 ) {        LOGE("Error on accept() errno:%d", errno);        /* start listening for new connections again */        rilEventAddWakeup(&s_listen_event);	      return;    }    /* 对客户端权限判断,判断是否是进程组ID为radio的进程发起的连接*/    errno = 0;    is_phone_socket = 0;    err = getsockopt(s_fdCommand, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);    if (err == 0 && szCreds > 0) {        errno = 0;        pwd = getpwuid(creds.uid);        if (pwd != NULL) {            if (strcmp(pwd->pw_name, PHONE_PROCESS) == 0) {                is_phone_socket = 1;            } else {                LOGE("RILD can't accept socket from process %s", pwd->pw_name);            }        } else {            LOGE("Error on getpwuid() errno: %d", errno);        }    } else {        LOGD("Error on getsockopt() errno: %d", errno);    }        if ( !is_phone_socket ) {      LOGE("RILD must accept socket from %s", PHONE_PROCESS);      close(s_fdCommand);      s_fdCommand = -1;      onCommandsSocketClosed();      /* start listening for new connections again */      rilEventAddWakeup(&s_listen_event);      return;    }#if 0    if(s_dualSimMode) {        if(s_sim_num == 0) {            property_get(SIM_POWER_PROPERTY, prop, "0");            if(!strcmp(prop, "0")) {                property_set(SIM_POWER_PROPERTY, "1");                s_callbacks.powerSIM(NULL);            }        } else if(s_sim_num == 1) {            property_get(SIM_POWER_PROPERTY1, prop, "0");            if(!strcmp(prop, "0")) {                property_set(SIM_POWER_PROPERTY1, "1");                s_callbacks.powerSIM(NULL);            }        }    } else {        property_get(SIM_POWER_PROPERTY, prop, "0");        if(!strcmp(prop, "0")) {            property_set(SIM_POWER_PROPERTY, "1");            s_callbacks.powerSIM(NULL);        }    }#endif    //p_rs为RecordStream类型,它内部会分配一个缓冲区来存储客户端发送过来的数据  p_rs = record_stream_new(s_fdCommand, MAX_COMMAND_BYTES);  //添加一个针对接收到的客户端连接的处理事件,从而在eventLoop工作线程中处理该客户端的各种请求    ril_event_set (&s_commands_event, s_fdCommand, 1,processCommandsCallback, p_rs);    rilEventAddWakeup (&s_commands_event);    onNewCommandConnect();}

2.客户端通信处理

在listenCallback中首先接收客户端的连接请求,并验证客户端的权限,同时将该客户端以事件的形式添加到eventLoop工作线程中进行监控,当该客户端有数据请求时,eventLoop工作线程从select中返回,并自动调用processCommandsCallback回调函数:

[cpp]

  1. static void processCommandsCallback(int fd, short flags, void *param) {  

  2.     RecordStream *p_rs;  

  3.     void *p_record;  

  4.     size_t recordlen;  

  5.     int ret;  

  6.     assert(fd == s_fdCommand);  

  7.     p_rs = (RecordStream *)param;  

  8.   for (;;) { //循环处理客户端发送过来的AT命令   

  9.       //读取一条AT命令   

  10.         ret = record_stream_get_next(p_rs, &p_record, &recordlen);  

  11.         if (ret == 0 && p_record == NULL) {  

  12.             break;  

  13.         } else if (ret < 0) {  

  14.             break;  

  15.         } else if (ret == 0) { /* && p_record != NULL */  

  16.             //处理客户端发送过来的AT命令   

  17.             processCommandBuffer(p_record, recordlen);  

  18.         }  

  19.     }  

  20.     if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {  

  21.         if (ret != 0) {  

  22.             LOGE("error on reading command socket errno:%d\n", errno);  

  23.         } else {  

  24.             LOGW("EOS.  Closing command socket.");  

  25.         }  

  26.         close(s_fdCommand);  

  27.         s_fdCommand = -1;  

  28.         ril_event_del(&s_commands_event);  

  29.         record_stream_free(p_rs);  

  30.         rilEventAddWakeup(&s_listen_event);  

  31.         onCommandsSocketClosed();  

  32.     }  

  33. }  

static void processCommandsCallback(int fd, short flags, void *param) {    RecordStream *p_rs;    void *p_record;    size_t recordlen;    int ret;    assert(fd == s_fdCommand);    p_rs = (RecordStream *)param;  for (;;) { //循环处理客户端发送过来的AT命令      //读取一条AT命令        ret = record_stream_get_next(p_rs, &p_record, &recordlen);        if (ret == 0 && p_record == NULL) {            break;        } else if (ret < 0) {            break;        } else if (ret == 0) { /* && p_record != NULL */            //处理客户端发送过来的AT命令            processCommandBuffer(p_record, recordlen);        }    }    if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {        if (ret != 0) {            LOGE("error on reading command socket errno:%d\n", errno);        } else {            LOGW("EOS.  Closing command socket.");        }        close(s_fdCommand);        s_fdCommand = -1;        ril_event_del(&s_commands_event);        record_stream_free(p_rs);        rilEventAddWakeup(&s_listen_event);        onCommandsSocketClosed();    }}

通过processCommandBuffer函数来处理每一条AT命令:

[cpp]

  1. static int processCommandBuffer(void *buffer, size_t buflen) {  

  2.     Parcel p;  

  3.     status_t status;  

  4.     int32_t request;  

  5.     int32_t token;  

  6.     RequestInfo *pRI;  

  7.     int ret;  

  8.     p.setData((uint8_t *) buffer, buflen);  

  9.     // status checked at end   

  10.     status = p.readInt32(&request);  

  11.     status = p.readInt32 (&token);  

  12.     if (status != NO_ERROR) {  

  13.         LOGE("invalid request block");  

  14.         return 0;  

  15.     }  

  16.     if (request < 1 || request >= (int32_t)NUM_ELEMS(s_commands)) {  

  17.         LOGE("unsupported request code %d token %d", request, token);  

  18.         return 0;  

  19.     }  

  20.     pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo));  

  21.     pRI->token = token; //AT命令标号   

  22.     pRI->pCI = &(s_commands[request]); //根据request找到s_commands命令数组中的指定AT命令   

  23.     ret = pthread_mutex_lock(&s_pendingRequestsMutex);  

  24.     assert (ret == 0);  

  25.     pRI->p_next = s_pendingRequests;  

  26.     s_pendingRequests = pRI;  

  27.     ret = pthread_mutex_unlock(&s_pendingRequestsMutex);  

  28.   assert (ret == 0);  

  29.   //调用指定AT命令的dispatch函数,根据接收来自客户进程的命令和参数,调用onRequest进行处理。   

  30.     pRI->pCI->dispatchFunction(p, pRI);  

  31.     return 0;  

  32. }  

static int processCommandBuffer(void *buffer, size_t buflen) {    Parcel p;    status_t status;    int32_t request;    int32_t token;    RequestInfo *pRI;    int ret;    p.setData((uint8_t *) buffer, buflen);    // status checked at end    status = p.readInt32(&request);    status = p.readInt32 (&token);    if (status != NO_ERROR) {        LOGE("invalid request block");        return 0;    }    if (request < 1 || request >= (int32_t)NUM_ELEMS(s_commands)) {        LOGE("unsupported request code %d token %d", request, token);        return 0;    }    pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo));    pRI->token = token; //AT命令标号    pRI->pCI = &(s_commands[request]); //根据request找到s_commands命令数组中的指定AT命令    ret = pthread_mutex_lock(&s_pendingRequestsMutex);    assert (ret == 0);    pRI->p_next = s_pendingRequests;    s_pendingRequests = pRI;    ret = pthread_mutex_unlock(&s_pendingRequestsMutex);  assert (ret == 0);  //调用指定AT命令的dispatch函数,根据接收来自客户进程的命令和参数,调用onRequest进行处理。    pRI->pCI->dispatchFunction(p, pRI);    return 0;}

打电话的AT命令:{

RIL_REQUEST_DIALdispatchDialresponseVoid},

发短信的AT命令:{

RIL_REQUEST_SEND_SMSdispatchStrings, responseSMS},

3.电话拨打流程

[cpp]

  1. static void dispatchDial (Parcel &p, RequestInfo *pRI) {  

  2.   RIL_Dial dial; //RIL_Dial存储了打电话的所有信息   

  3.     RIL_UUS_Info uusInfo;   

  4.     int32_t sizeOfDial;  

  5.     int32_t t;  

  6.     .................. //初始化dial变量     

  7.   s_callbacks.onRequest(pRI->pCI->requestNumber, &dial, sizeOfDial, pRI);  

  8.   .................  

  9.     return;  

  10. }  

static void dispatchDial (Parcel &p, RequestInfo *pRI) {  RIL_Dial dial; //RIL_Dial存储了打电话的所有信息    RIL_UUS_Info uusInfo;     int32_t sizeOfDial;    int32_t t;    .................. //初始化dial变量    s_callbacks.onRequest(pRI->pCI->requestNumber, &dial, sizeOfDial, pRI);  .................    return;}

s_callbacks.onRequest其实就是调用RIL_RadioFunctions中的函数,该函数在前面已介绍过了。

[cpp]

  1. static void onRequest (int request, void *data, size_t datalen, RIL_Token t)  

  2. {  

  3.     switch (request) {  

  4.         case RIL_REQUEST_DIAL:  

  5.             requestDial(data, datalen, t);  

  6.             break;  

  7.     }  

  8. }  

static void onRequest (int request, void *data, size_t datalen, RIL_Token t){    switch (request) {        case RIL_REQUEST_DIAL:            requestDial(data, datalen, t);            break;    }}

[cpp]

  1. static void requestDial(void *data, size_t datalen, RIL_Token t)  

  2. {  

  3.     RIL_Dial *p_dial;  

  4.     char *cmd;  

  5.     const char *clir;  

  6.     int ret;  

  7.     p_dial = (RIL_Dial *)data;  

  8.     switch (p_dial->clir) {  

  9.         case 1: clir = "I"; break;  /*invocation*/  

  10.         case 2: clir = "i"; break;  /*suppression*/  

  11.         default:  

  12.         case 0: clir = ""; break;   /*subscription default*/  

  13.   }  

  14.   //向串口发送AT指令   

  15.     ret = at_send_command(cmd, NULL);  

  16.   free(cmd);  

  17.   //通知请求结果   

  18.     RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);  

  19. }  

static void requestDial(void *data, size_t datalen, RIL_Token t){    RIL_Dial *p_dial;    char *cmd;    const char *clir;    int ret;    p_dial = (RIL_Dial *)data;    switch (p_dial->clir) {        case 1: clir = "I"; break;  /*invocation*/        case 2: clir = "i"; break;  /*suppression*/        default:        case 0: clir = ""; break;   /*subscription default*/  }  //向串口发送AT指令    ret = at_send_command(cmd, NULL);  free(cmd);  //通知请求结果    RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);}

AT发送完拨号指令后,通过RIL_onRequestComplete返回处理结果,RIL_onRequestComplete实际上是RIL_Env中的函数,在前面我们也介绍过了

[cpp]

  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.   //该请求已经处理,需要从请求队列中移除该请求   

  7.     if (!checkAndDequeueRequestInfo(pRI)) {  

  8.         LOGE ("RIL_onRequestComplete: invalid RIL_Token");  

  9.         return;  

  10.     }  

  11.     if (pRI->local > 0) {  

  12.         ...........  

  13.         sendResponse(p);  

  14.     }  

  15. done:  

  16.     free(pRI);  

  17. }  

extern "C" void RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen) {    RequestInfo *pRI;    int ret;    size_t errorOffset;  pRI = (RequestInfo *)t;  //该请求已经处理,需要从请求队列中移除该请求    if (!checkAndDequeueRequestInfo(pRI)) {        LOGE ("RIL_onRequestComplete: invalid RIL_Token");        return;    }    if (pRI->local > 0) {        ...........        sendResponse(p);    }done:    free(pRI);}

[cpp]

  1. static int sendResponse (Parcel &p) {  

  2.     return sendResponseRaw(p.data(), p.dataSize()); //将结果发送给JAVA RIL客户端   

  3. }  

static int sendResponse (Parcel &p) {    return sendResponseRaw(p.data(), p.dataSize()); //将结果发送给JAVA RIL客户端}

[cpp]

  1. static int sendResponseRaw (const void *data, size_t dataSize) {  

  2.     int fd = s_fdCommand;  

  3.     int ret;  

  4.     uint32_t header;  

  5.     if (s_fdCommand < 0) {  

  6.         return -1;  

  7.     }  

  8.     if (dataSize > MAX_COMMAND_BYTES) {  

  9.         return -1;  

  10.     }  

  11.     pthread_mutex_lock(&s_writeMutex);  

  12.     header = htonl(dataSize);  

  13.     ret = blockingWrite(fd, (void *)&header, sizeof(header));  

  14.     if (ret < 0) {  

  15.         pthread_mutex_unlock(&s_writeMutex);  

  16.         return ret;  

  17.     }  

  18.     ret = blockingWrite(fd, data, dataSize);  

  19.     if (ret < 0) {  

  20.         pthread_mutex_unlock(&s_writeMutex);  

  21.         return ret;  

  22.     }  

  23.     pthread_mutex_unlock(&s_writeMutex);  

  24.     return 0;  

  25. }  

static int sendResponseRaw (const void *data, size_t dataSize) {    int fd = s_fdCommand;    int ret;    uint32_t header;    if (s_fdCommand < 0) {        return -1;    }    if (dataSize > MAX_COMMAND_BYTES) {        return -1;    }    pthread_mutex_lock(&s_writeMutex);    header = htonl(dataSize);    ret = blockingWrite(fd, (void *)&header, sizeof(header));    if (ret < 0) {        pthread_mutex_unlock(&s_writeMutex);        return ret;    }    ret = blockingWrite(fd, data, dataSize);    if (ret < 0) {        pthread_mutex_unlock(&s_writeMutex);        return ret;    }    pthread_mutex_unlock(&s_writeMutex);    return 0;}

拨打电话的时序图如下:

Rild通过onRequest向动态库提交一个请求,然后返回,动态库处理完请求后,处理结果通过回调接口通知客户端

转载于:https://my.oschina.net/u/586684/blog/199643

你可能感兴趣的文章
浅谈MVC3自定义分页
查看>>
.net中ashx文件有什么用?功能有那些,一般用在什么情况下?
查看>>
select、poll、epoll之间的区别总结[整理]【转】
查看>>
CSS基础知识(上)
查看>>
PHP中常见的面试题2(附答案)
查看>>
26.Azure备份服务器(下)
查看>>
mybatis学习
查看>>
LCD的接口类型详解
查看>>
Spring Boot Unregistering JMX-exposed beans on shutdown
查看>>
poi 导入导出的api说明(大全)
查看>>
Mono for Android 优势与劣势
查看>>
将图片转成base64字符串并在JSP页面显示的Java代码
查看>>
js 面试题
查看>>
sqoop数据迁移(基于Hadoop和关系数据库服务器之间传送数据)
查看>>
腾讯云下安装 nodejs + 实现 Nginx 反向代理
查看>>
试水区块链出版?纽约时报在招人了
查看>>
拥抱PostgreSQL,红帽再表态:SSPL的MongoDB坚决不用
查看>>
QCon演讲速递:异步处理在分布式系统中的优化作用
查看>>
Javascript 中的 Array 操作
查看>>
YARN的AsyncDispatcher原理
查看>>