rild

 

Android之rild进程启动源码分析

  1746人阅读  评论(2)  收藏  举报

目录(?)[+]

Android 电话系统框架介绍

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

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

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

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


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

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

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

不同手机厂商使用的AT命令不完全相同,为了保密,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进程,在android之Init进程启动过程源码分析一文中对init进程的启动流程进行了详细的介绍。init进程在启动过程中将读取init.rc文件来启动一些重量级的native服务,rild进程就是通过配置在init.rc中来启动的。

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

RILD进程入口函数分析

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

hardware\ril\rild\rild.c

[cpp]  view plain copy
  1. int main(int argc, char **argv)  
  2. {  
  3.     const char * rilLibPath = NULL;  
  4.     char **rilArgv;  
  5.     void *dlHandle;  
  6.     const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, intchar **);  
  7.     const RIL_RadioFunctions *funcs;  
  8.     char libPath[PROPERTY_VALUE_MAX];  
  9.     unsigned char hasLibArgs = 0;  
  10.     int i;  
  11.   umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);  
  12.   //rild启动无参数  
  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 *, intchar **))dlsym(dlHandle, "RIL_Init");  
  137.     if (rilInit == NULL) {  
  138.         fprintf(stderr, "RIL_Init not defined or exported in %s\n", rilLibPath);  
  139.         exit(-1);  
  140.     }  
  141.     if (hasLibArgs) { //false  
  142.         rilArgv = argv + i - 1;  
  143.         argc = argc -i + 1;  
  144.     } else {  
  145.         static char * newArgv[MAX_LIB_ARGS];  
  146.         static char args[PROPERTY_VALUE_MAX];  
  147.         rilArgv = newArgv;  
  148.         property_get(LIB_ARGS_PROPERTY, args, "");//通过属性系统读取"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. }  
[cpp]  view plain copy
  1. int main(int argc, char **argv)  
  2. {  
  3.     const char * rilLibPath = NULL;  
  4.     char **rilArgv;  
  5.     void *dlHandle;  
  6.     const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, intchar **);  
  7.     const RIL_RadioFunctions *funcs;  
  8.     char libPath[PROPERTY_VALUE_MAX];  
  9.     unsigned char hasLibArgs = 0;  
  10.     int i;  
  11.   umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);  
  12.   //rild启动无参数  
  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 *, intchar **))dlsym(dlHandle, "RIL_Init");  
  137.     if (rilInit == NULL) {  
  138.         fprintf(stderr, "RIL_Init not defined or exported in %s\n", rilLibPath);  
  139.         exit(-1);  
  140.     }  
  141.     if (hasLibArgs) { //false  
  142.         rilArgv = argv + i - 1;  
  143.         argc = argc -i + 1;  
  144.     } else {  
  145.         static char * newArgv[MAX_LIB_ARGS];  
  146.         static char args[PROPERTY_VALUE_MAX];  
  147.         rilArgv = newArgv;  
  148.         property_get(LIB_ARGS_PROPERTY, args, "");//通过属性系统读取"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. }  
在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]  view plain copy
  1. extern "C" void RIL_startEventLoop(void) {  
  2.     int ret;  
  3.     pthread_attr_t attr;  
  4.     /* spin up eventLoop thread and wait for it to get started */  
  5.     s_started = 0;  
  6.     pthread_mutex_lock(&s_startupMutex);  
  7.     pthread_attr_init (&attr);  
  8.   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  
  9.   //创建一个工作线程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. }  
[cpp]  view plain copy
  1. extern "C" void RIL_startEventLoop(void) {  
  2.     int ret;  
  3.     pthread_attr_t attr;  
  4.     /* spin up eventLoop thread and wait for it to get started */  
  5.     s_started = 0;  
  6.     pthread_mutex_lock(&s_startupMutex);  
  7.     pthread_attr_init (&attr);  
  8.   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);  
  9.   //创建一个工作线程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. }  
eventLoop执行时序图:


[cpp]  view plain copy
  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. }  
[cpp]  view plain copy
  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. }  
在rild中定义了event的概念,Rild 支持两种类型的事件:

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

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

事件定义如下:
[cpp]  view plain copy
  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. };  
[cpp]  view plain copy
  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. };  

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

[cpp]  view plain copy
  1. static struct ril_event s_commands_event;  
  2. ril_event_set (&s_commands_event, s_fdCommand, 1,processCommandsCallback, p_rs)  
  3.   
  4. static struct ril_event s_wakeupfd_event;  
  5. ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,processWakeupCallback, NULL)  
  6.   
  7. static struct ril_event s_listen_event;  
  8. ril_event_set (&s_listen_event, s_fdListen, false,listenCallback, NULL)  
  9.   
  10. static struct ril_event s_wake_timeout_event;  
  11. ril_timer_add(&(p_info->event), &myRelativeTime);  
[cpp]  view plain copy
  1. static struct ril_event s_commands_event;  
  2. ril_event_set (&s_commands_event, s_fdCommand, 1,processCommandsCallback, p_rs)  
  3.   
  4. static struct ril_event s_wakeupfd_event;  
  5. ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,processWakeupCallback, NULL)  
  6.   
  7. static struct ril_event s_listen_event;  
  8. ril_event_set (&s_listen_event, s_fdListen, false,listenCallback, NULL)  
  9.   
  10. static struct ril_event s_wake_timeout_event;  
  11. ril_timer_add(&(p_info->event), &myRelativeTime);  
[cpp]  view plain copy
  1. static struct ril_event s_debug_event;  
  2. ril_event_set (&s_debug_event, s_fdDebug, true,debugCallback, NULL)  
[cpp]  view plain copy
  1. static struct ril_event s_debug_event;  
  2. 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]  view plain copy
  1. static void rilEventAddWakeup(struct ril_event *ev) {  
  2.     ril_event_add(ev); //向监控表watch_table添加一个s_wakeupfd_event事件  
  3.     triggerEvLoop(); //向管道s_fdWakeupWrite中写入之来触发事件循环  
  4. }  
[cpp]  view plain copy
  1. static void rilEventAddWakeup(struct ril_event *ev) {  
  2.     ril_event_add(ev); //向监控表watch_table添加一个s_wakeupfd_event事件  
  3.     triggerEvLoop(); //向管道s_fdWakeupWrite中写入之来触发事件循环  
  4. }  

[cpp]  view plain copy
  1. void ril_event_add(struct ril_event * ev)  
  2. {  
  3.     dlog("~~~~ +ril_event_add ~~~~");  
  4.     MUTEX_ACQUIRE();  
  5.     for (int i = 0; i < MAX_FD_EVENTS; i++) { //遍历监控表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. }  
[cpp]  view plain copy
  1. void ril_event_add(struct ril_event * ev)  
  2. {  
  3.     dlog("~~~~ +ril_event_add ~~~~");  
  4.     MUTEX_ACQUIRE();  
  5.     for (int i = 0; i < MAX_FD_EVENTS; i++) { //遍历监控表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. }  

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

触发事件

[cpp]  view plain copy
  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. }  
[cpp]  view plain copy
  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. }  

处理事件

[cpp]  view plain copy
  1. void ril_event_loop()  
  2. {  
  3.     int n;  
  4.     fd_set rfds;  
  5.     struct timeval tv;  
  6.     struct timeval * ptv;  
  7.     for (;;) {  
  8.         memcpy(&rfds, &readFds, sizeof(fd_set));  
  9.         if (-1 == calcNextTimeout(&tv)) {  
  10.             dlog("~~~~ no timers; blocking indefinitely ~~~~");  
  11.             ptv = NULL;  
  12.         } else {  
  13.             dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec);  
  14.             ptv = &tv;  
  15.         }  
  16.         //使用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. }  
[cpp]  view plain copy
  1. void ril_event_loop()  
  2. {  
  3.     int n;  
  4.     fd_set rfds;  
  5.     struct timeval tv;  
  6.     struct timeval * ptv;  
  7.     for (;;) {  
  8.         memcpy(&rfds, &readFds, sizeof(fd_set));  
  9.         if (-1 == calcNextTimeout(&tv)) {  
  10.             dlog("~~~~ no timers; blocking indefinitely ~~~~");  
  11.             ptv = NULL;  
  12.         } else {  
  13.             dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec);  
  14.             ptv = &tv;  
  15.         }  
  16.         //使用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. }  


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

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

 1.超时事件查询
[cpp]  view plain copy
  1. static void processTimeouts()  
  2. {  
  3.     dlog("~~~~ +processTimeouts ~~~~");  
  4.     MUTEX_ACQUIRE();  
  5.     struct timeval now;  
  6.     struct ril_event * tev = timer_list.next;  
  7.     struct ril_event * next;  
  8.     getNow(&now); //获取当前时间  
  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. }  
[cpp]  view plain copy
  1. static void processTimeouts()  
  2. {  
  3.     dlog("~~~~ +processTimeouts ~~~~");  
  4.     MUTEX_ACQUIRE();  
  5.     struct timeval now;  
  6.     struct ril_event * tev = timer_list.next;  
  7.     struct ril_event * next;  
  8.     getNow(&now); //获取当前时间  
  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. }  
2.可读事件查询
[cpp]  view plain copy
  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. }  
[cpp]  view plain copy
  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. }  
3.事件处理
[cpp]  view plain copy
  1. static void firePending()  
  2. {  
  3.     dlog("~~~~ +firePending ~~~~");  
  4.     struct ril_event * ev = pending_list.next;  
  5.     while (ev != &pending_list) { //遍历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. }  
[cpp]  view plain copy
  1. static void firePending()  
  2. {  
  3.     dlog("~~~~ +firePending ~~~~");  
  4.     struct ril_event * ev = pending_list.next;  
  5.     while (ev != &pending_list) { //遍历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. }  

RIL_Env定义

hardware\ril\include\telephony\ril.h

[cpp]  view plain copy
  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. };  
[cpp]  view plain copy
  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. };  

hardware\ril\rild\rild.c

s_rilEnv变量定义:

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

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

1.RIL_onRequestComplete

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

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

2.RIL_onUnsolicitedResponse

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

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

3.RIL_requestTimedCallback

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

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

RIL_RadioFunctions定义

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

hardware\ril\include\telephony\Ril.h 

[cpp]  view plain copy
  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;  
[cpp]  view plain copy
  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;  
变量定义:
[cpp]  view plain copy
  1. static const RIL_RadioFunctions s_callbacks = {  
  2.     RIL_VERSION,  
  3.     onRequest,  
  4.     currentState,  
  5.     onSupports,  
  6.     onCancel,  
  7.     getVersion  
  8. };  
[cpp]  view plain copy
  1. static const RIL_RadioFunctions s_callbacks = {  
  2.     RIL_VERSION,  
  3.     onRequest,  
  4.     currentState,  
  5.     onSupports,  
  6.     onCancel,  
  7.     getVersion  
  8. };  

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

1.onRequest

[cpp]  view plain copy
  1. static void onRequest (int request, void *data, size_t datalen, RIL_Token t)  
  2. {  
  3.     ATResponse *p_response;  
  4.     int err;  
  5.     LOGD("onRequest: %s", requestToString(request));  
  6.     /* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS 
  7.      * when RADIO_STATE_UNAVAILABLE. 
  8.      */  
  9.     if (sState == RADIO_STATE_UNAVAILABLE  
  10.         && request != RIL_REQUEST_GET_SIM_STATUS  
  11.     ) {  
  12.         RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);  
  13.         return;  
  14.     }  
  15.     /* Ignore all non-power requests when RADIO_STATE_OFF 
  16.      * (except RIL_REQUEST_GET_SIM_STATUS) 
  17.      */  
  18.     if (sState == RADIO_STATE_OFF&& !(request == RIL_REQUEST_RADIO_POWER  
  19.             || request == RIL_REQUEST_GET_SIM_STATUS)  
  20.     ) {  
  21.         RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);  
  22.         return;  
  23.     }  
  24.     switch (request) {  
  25.         case RIL_REQUEST_GET_SIM_STATUS: {  
  26.             RIL_CardStatus *p_card_status;  
  27.             char *p_buffer;  
  28.             int buffer_size;  
  29.             int result = getCardStatus(&p_card_status);  
  30.             if (result == RIL_E_SUCCESS) {  
  31.                 p_buffer = (char *)p_card_status;  
  32.                 buffer_size = sizeof(*p_card_status);  
  33.             } else {  
  34.                 p_buffer = NULL;  
  35.                 buffer_size = 0;  
  36.             }  
  37.             RIL_onRequestComplete(t, result, p_buffer, buffer_size);  
  38.             freeCardStatus(p_card_status);  

你可能感兴趣的:(rild)