1# 电话服务开发指导 2 3 4## Modem厂商库初始化开发指导 5 6 7### 场景介绍 8 9Modem厂商库初始化是指在厂商库里实现const HRilOps \*RilInitOps(const struct HRilReport \*reportOps)函数,在该函数里处理三个重要的功能: 10 11- 接收RIL Adapter事件回调的函数指针,当Modem有业务事件上报时,调用对应的函数指针,把事件上报给RIL Adapter。 12 13- 创建读取Modem设备节点的线程,在该线程里会循环地读取Modem上报的事件,并把接收的Modem信息解析为具体业务相关的事件进行上报。 14 15- 返回业务请求接口的函数指针给RIL Adapter。 16 17 18### 接口说明 19 20Modem厂商库初始化接口。 21 22 **表1** Modem厂商库初始化接口功能介绍 23 24| 接口名 | 描述 | 25| -------- | -------- | 26| const HRilOps \*RilInitOps(const struct HRilReport \* reportOps) | 接口功能:Modem厂商库运行的入口。<br/>参数reportOps:RIL Adapter传入的事件回调函数指针。<br/>返回值:业务请求接口的函数指针。 | 27 28 29### 开发步骤 30 31 321. RilInitOps接口中设置RIL Adapter传入的事件回调函数指针。 33 34 ``` 35 // 定义Modem厂商库回调函数指针 36 static struct HRilReport g_reportOps = { 37 OnCallReport, // 通话相关业务回调函数 38 OnDataReport, // 蜂窝数据相关业务回调函数 39 OnModemReport, // Modem相关业务回调函数 40 OnNetworkReport, // 搜网相关业务回调函数 41 OnSimReport, // SIM卡相关业务回调函数 42 OnSmsReport // 短信相关业务回调函数 43 }; 44 ``` 45 46 471. 创建主线程g_reader,开启消息循环。 48 49 ``` 50 pthread_attr_t t; 51 pthread_attr_init(&t); 52 pthread_attr_setdetachstate(&t, PTHREAD_CREATE_DETACHED); 53 ret = pthread_create(&g_reader, &t, ReaderLoop, &t); // 创建线程 54 ``` 55 56 571. 在g_eventListeners线程用open()打开Modem设备节点,并创建g_reader线程循环读取处理Modem上报的消息。 58 59 ``` 60 g_fd = open(g_devicePath, O_RDWR); // 打开设备节点,入参g_devicePath是Modem设备节点 61 pthread_attr_init(&attr); 62 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 63 ret = pthread_create(&g_eventListeners, &attr, EventListeners, NULL); 64 ``` 65 66 671. 返回业务请求接口的函数指针。 68 69 ``` 70 // call模块业务请求接口结构体 71 typedef struct { 72 // 获取呼叫列表 73 void (*GetCallList)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); 74 // 拨打电话 75 void (*Dial)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); 76 // 挂断电话 77 void (*Hangup)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); 78 // 拒接来电 79 void (*Reject)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); 80 // 接听来电 81 void (*Answer)(ReqDataInfo *requestInfo, const void *data, size_t dataLen); 82 } HRilCallReq; 83 84 // call模块回调函数指针 85 static const HRilCallReq g_callReqOps = { 86 .GetCallList = ReqGetCallList, // 获取呼叫列表接口 87 .Dial = ReqDial, // 拨打电话接口 88 .Hangup = ReqHangup, // 挂断电话接口 89 .Reject = ReqReject, // 拒接来电接口 90 .Answer = ReqAnswer, // 接听来电接口 91 }; 92 93 // 业务请求结构体 94 typedef struct { 95 const HRilCallReq *callOps; // 通话相关业务请求结构体指针 96 const HRilSimReq *simOps; // SIM卡相关业务请求结构体指针 97 const HRilSmsReq *smsOps; // 短彩信相关业务请求结构体指针 98 const HRilDataReq *dataOps; // 蜂窝数据相关业务请求结构体指针 99 const HRilNetworkReq *networkOps; // 搜网相关业务请求结构体指针 100 const HRilModemReq *modemOps; // Modem相关业务请求结构体指针 101 } HRilOps; 102 103 // 业务请求接口定义 104 HRilOps g_hrilOps = { 105 .callOps = &g_callReqOps, // 定义通话业务请求接口 106 .simOps = &g_simReqOps, // 定义SIM卡业务请求接口 107 .smsOps = &g_smsReqOps, // 定义短彩信业务请求接口 108 .networkOps = &g_networkReqOps, // 定义蜂窝数据业务请求接口 109 .dataOps = &g_dataReqOps, // 定义搜网业务请求接口 110 .modemOps = &g_modemReqOps, // 定义Modem业务请求接口 111 }; 112 ``` 113 114 115### 调测验证 116 1171. 用[hdc_std工具](../subsystems/subsys-toolchain-hdc-guide.md#环境准备)连接调试设备,把编译生成的libril_vendor.z.so库文件(参见[Modem厂商库集成指导](#modem厂商库集成指导))通过以下命令推到/system/lib/目录下。 118 119 ``` 120 hdc_std file send libril_vendor.z.so /system/lib/ 121 ``` 122 1232. 执行hdc_std shell sync,hdc_std shell reboot重启设备。 124 125 ``` 126 hdc_std shell sync 127 hdc_std shell reboot 128 ``` 129 1303. 执行hdc_std shell hilog,根据日志查看函数RilInitOps()是否正确执行完成。如下调测验证日志供参考: 131 132 ``` 133 09-02 07:40:47.807 455 455 I 01f08/HrilHdf: [LoadVendor-(hril_hdf.c:148)] RilInit LoadVendor start with rilLibPath:libril_vendor.z.so 134 09-02 07:40:47.830 455 455 I 01f08/HrilHdf: [LoadVendor-(hril_hdf.c:163)] HRilRegOps completed 135 ``` 136 137 138## Modem业务请求及响应开发指导 139 140 141### 场景介绍 142 143Modem业务请求及响应是指RIL Adapter收到电话服务具体业务请求后,调用Modem厂商库初始化获得的函数指针,把具体业务请求发送给厂商库,厂商库根据业务请求ID做相应的业务处理。 144 145 146### 接口说明 147 148Modem业务请求及响应接口。 149 150 **表2** Modem业务请求及响应接口功能介绍(以拨号功能模块为例) 151 152| 接口名 | 描述 | 153| -------- | -------- | 154| void ReqDial(ReqDataInfo \*requestInfo, const void \*data, size_t dataLen); | 接口功能:对拨号请求进行处理。<br/>参数requestInfo:请求类型信息。<br/>参数data:被叫号码信息。<br/>参数dataLen:数据长度。<br/>返回值:无。 | 155| void (\*OnCallReport)(struct ReportInfo reportInfo, const void \*data, size_t dataLen); | 接口功能:对通话业务执行结果进行响应,即当请求业务执行完成后,Modem将该请求执行的结果上报给RIL Adapter。<br/>参数reportInfo:返回类型信息。<br/>参数data:返回数据。<br/>参数dataLen:数据长度。<br/>返回值:无。 | 156 157 158### 开发步骤 159 1601. 在ReqDial()接口中对拨号请求进行处理。 161 162 ``` 163 // 拨号请求接口实现 164 void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen) 165 { 166 HRilDial *pDial = NULL; 167 char cmd[MAX_BUFF_SIZE] = {0}; 168 const char *clir = NULL; 169 int ret; 170 int err = HRIL_ERR_SUCCESS; 171 struct ReportInfo reportInfo = {}; 172 ResponseInfo *pResponse = NULL; 173 if (data == NULL) { 174 TELEPHONY_LOGE("data is null!!!"); 175 err = HRIL_ERR_INVALID_PARAMETER; 176 reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); 177 OnCallReport(reportInfo, NULL, 0); 178 return; 179 } 180 pDial = (HRilDial *)data; 181 switch (pDial->clir) { 182 case CALL_CLIR_INVOCATION: 183 clir = "I"; 184 break; /* invocation */ 185 case CALL_CLIR_SUPPRESSION: 186 clir = "i"; 187 break; /* suppression */ 188 case CALL_CLIR_SUBSCRIPTION_DEFUALT: 189 default: 190 clir = ""; 191 break; /* subscription default */ 192 } 193 (void)sprintf_s(cmd, MAX_BUFF_SIZE, "ATD%s%s;", pDial->address, clir); 194 ret = SendCommandLock(cmd, NULL, 0, &pResponse); // 发送AT指令 195 ...... 196 } 197 ``` 198 1992. 在Modem执行完拨号命令后,调用OnCallReport()回调函数,把该请求执行的结果上报给RIL Adapter。 200 201 ``` 202 ret = SendCommandLock(cmd, NULL, 0, &pResponse); 203 if (ret != 0 || (pResponse != NULL && pResponse->success == 0)) { 204 TELEPHONY_LOGE("ATD send failed"); 205 err = HRIL_ERR_GENERIC_FAILURE; 206 } 207 reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); 208 OnCallReport(reportInfo, NULL, 0); // 调用通话相关回调函数 209 ``` 210 211 212### 调测验证 213 2141. 用[hdc_std工具](../subsystems/subsys-toolchain-hdc-guide.md#环境准备)工具连接调试设备,把编译生成的libril_vendor.z.so库文件通过以下命令推到/system/lib/目录下。 215 216 ``` 217 hdc_std file send libril_vendor.z.so /system/lib/ 218 ``` 219 2202. 执行hdc_std shell sync,hdc_std shell reboot重启设备。 221 222 ``` 223 hdc_std shell sync 224 hdc_std shell reboot 225 ``` 226 2273. hdc_std shell后执行./system/bin/ril_adapter_test,输入编号1,根据提示输入电话号码,测试拨打电话功能。 228 229 ``` 230 hdc_std shell 231 # ./system/bin/ril_adapter_test 232 ----> Test Enter --------->Call--------------------- 233 234 1----> RilUnitTest::OnRequestCallDialTest 235 2----> RilUnitTest:: OnRequestCallHangupTest 236 3----> RilUnitTest:: OnRequestCallAnswerTest 237 4----> RilUnitTest::OnRequestCallGetCurrentCallsStatusTest 238 5----> RilUnitTest::OnRequestRefusedCallTest 239 240 1 241 ``` 242 2434. 另开一个终端窗口,执行hdc_std shell hilog,通过日志查看函数ReqDial()是否正确执行完成。如下调测验证日志供参考: 244 245 ``` 246 09-02 07:55:09.073 455 2059 I 01f08/RilVendor: [SendCommandLock-(at_support.c:226)] command ATD18675231804;, NeedATPause:0, atCmd:AT 247 09-02 07:55:09.099 455 2053 I 01f08/Rilvendor: [ProcessResponse-(at_support.c:159)] processLine line = OK 248 09-02 07:55:09.100 455 2053 E 01f08/RilVendor: [ReportStrWith-(vendor_util.c:63)] str or prefix parameter is null. 249 09-02 07:55:09.100 455 2053 E 01f08/RilVendor: [ProcessLastResponse-(vendor_channel.c:77)] g_bufferCur endLine is null 250 09-02 07:55:09.100 455 2059 I 01f08/RilVendor: [SendCommandLock-(at_support.c:243)] err = 0 251 09-02 07:55:09.100 455 2053 I 01f08/RilVendor: [ProcessResponse-(at_support.c:159)] processLine line = ^ORIG:1,0 252 ``` 253 254 255## Modem事件上报开发指导 256 257 258### 场景介绍 259 260Modem事件上报是指在厂商库的Modem设备节点读取线程,循环读取到Modem主动上报的消息后,对Modem上报事件进行解析,然后上报给RIL Adapter。 261 262 263### 接口说明 264 265Modem事件上报接口。 266 267 **表3** Modem事件上报接口功能介绍 268 269| 接口名 | 描述 | 270| -------- | -------- | 271| void OnNotifyOps(const char \*s, const char \*smsPdu) | 接口功能:对Modem上报的事件进行分发处理。<br/>参数s:AT指令前缀。<br/>参数smsPdu:短信PDU信息。<br/>返回值:无。 | 272 273 274### 开发步骤 275 2761. 在Modem设备节点读取线程g_reader里调用OnNotifyOps()解析具体的Modem上报事件,判断命令类型,并调用OnXxxReport()把解析得到的各模块事件上报给hril业务层。 277 278 ``` 279 // 将Modem上报数据解析为对应模块的主动上报事件 280 void OnNotifyOps(const char *s, const char *smsPdu) 281 { 282 int ret = 0; 283 struct ReportInfo reportInfo = {0}; 284 reportInfo.error = HRIL_ERR_SUCCESS; 285 reportInfo.type = HRIL_NOTIFICATION; 286 if (GetRadioState() == HRIL_RADIO_POWER_STATE_UNAVAILABLE) { 287 return; 288 } 289 TELEPHONY_LOGD("enter to [%{public}s]:%{public}s", s, smsPdu); 290 // 通过AT指令判断主动上报命令类型 291 if (ReportStrWith(s, "+CRING:") || ReportStrWith(s, "RING") || ReportStrWith(s, "IRING") || 292 ReportStrWith(s, "NO CARRIER") || ReportStrWith(s, "+CCWA") || ReportStrWith(s, "^CCALLSTATE") || 293 ReportStrWith(s, "^CEND") || ReportStrWith(s, "^CCWA")) { 294 reportInfo.notifyId = HNOTI_CALL_STATE_UPDATED; 295 OnCallReport(reportInfo, NULL, 0); 296 } else if (ReportStrWith(s, "+CMT:")) { 297 reportInfo.notifyId = HNOTI_SMS_NEW_SMS; 298 OnSmsReport(reportInfo, (void *)smsPdu, strlen(smsPdu)); 299 } 300 // 将各模块事件上报给hril业务层 301 ...... 302 } 303 ``` 304 3051. hril业务层将上报事件分发给Telephony Service。 306 307 ``` 308 // 呼叫状态主动上报 309 int32_t HRilCall::CallStateUpdated( 310 int32_t slotId, int32_t notifyType, const HRilErrno e, const void *response, size_t responseLen) 311 { 312 struct HdfSBuf *dataSbuf = HdfSBufTypedObtain(SBUF_IPC); 313 if (serviceCallbackNotify_ == nullptr) { 314 TELEPHONY_LOGE("RilAdapter serviceCallbackNotify_ is null"); 315 HdfSBufRecycle(dataSbuf); 316 return HDF_FAILURE; 317 } 318 // 分发处理 319 int32_t ret = serviceCallbackNotify_->dispatcher->Dispatch( 320 serviceCallbackNotify_, HNOTI_CALL_STATE_UPDATED, dataSbuf, nullptr); 321 if (ret != HDF_SUCCESS) { 322 HdfSBufRecycle(dataSbuf); 323 return HDF_FAILURE; 324 } 325 HdfSBufRecycle(dataSbuf); 326 return HDF_SUCCESS; 327 } 328 ``` 329 330 331### 调测验证 332 3331. 用[hdc_std工具](../subsystems/subsys-toolchain-hdc-guide.md#环境准备)工具连接调试设备,把编译生成的libril_vendor.z.so库文件通过以下命令推到/system/lib/目录下。 334 335 ``` 336 hdc_std file send libril_vendor.z.so /system/lib/ 337 ``` 338 3392. 执行hdc_std shell sync,hdc_std shell reboot重启设备。 340 341 ``` 342 hdc_std shell sync 343 hdc_std shell reboot 344 ``` 345 3463. hdc_std shell后执行./system/bin/ril_adapter_test,输入编号1,根据提示输入电话号码,测试拨打电话功能。 347 348 ``` 349 hdc_std shell 350 # ./system/bin/ril_adapter_test 351 ----> Test Enter --------->Call--------------------- 352 353 1----> RilUnitTest::OnRequestCallDialTest 354 2----> RilUnitTest:: OnRequestCallHangupTest 355 3----> RilUnitTest:: OnRequestCallAnswerTest 356 4----> RilUnitTest::OnRequestCallGetCurrentCallsStatusTest 357 5----> RilUnitTest::OnRequestRefusedCallTest 358 359 1 360 ``` 361 3624. 另开一个终端窗口,执行hdc_std shell hilog,通过日志查看函数OnNotifyOps()是否正确执行完成。如下调测验证日志供参考: 363 364 ``` 365 01-01 00:08:01.334 546 551 D 02b01/TelRilTest: [DialResponse-(tel_ril_call.cpp:280)] DialResponse --> radioResponseInfo->serial:2, radioResponseInfo->error:0 366 01-01 00:08:01.334 546 557 D 02b01/TelRilTest: [ProcessEvent-(tel_ril_test.cpp:1262)] TelRilTest::DemoHandler::ProcessEvent --> eventId:101 367 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:93)] g_bufferCur : 368 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: ^ORIG:1,0 369 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:108)] AT< ^ORIG:1,0 370 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:137)] processLine line = ^ORIG:1,0 371 01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:126)] enter to [^ORIG:1,0]:(null) 372 01-01 00:08:01.335 143 512 W 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:167)] enter to is unrecognized command: ^ORIG:1,0 373 01-01 00:08:01.335 143 512 D 02b01/Rilvendor: [ProcessLastResponse-(channel.c:37)] last data more than one line , FindEndOfLine g_bufferCur: 374 01-01 00:08:01.335 143 512 E 02b01/Rilvendor: [ProcessLastResponse-(channel.c:39)] g_bufferCur endLine is null 375 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:93)] g_bufferCur : 376 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: ^CCALLSTATE: 1,0,1 377 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:108)] AT< ^CCALLSTATE: 1,0,1 378 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:137)] processLine line = ^CCALLSTATE: 1,0,1 379 01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:126)] enter to [^CCALLSTATE: 1,0,1]:(null) 380 01-01 00:08:01.336 546 551 D 02b01/CoreService: [OnRemoteRequest-(tel_ril_manager.cpp:80)] RilManager OnRemoteRequest code:1001 381 01-01 00:08:01.336 546 551 D 02b01/CoreService: [NotifyObserver-(observer_handler.cpp:76)] handler->SendEvent:8 382 ``` 383 384 385### 开发实例 386 387- **去电开发实例** 388 去电的调用流程示例如下图所示: 389 **图1** 去电调用时序图 390 391 ![zh-cn_image_0000001171507146](figures/zh-cn_image_0000001171507146.png) 392 393 当应用触发去电动作时,RIL Adapter会接收到拨打电话的请求,hril调用对应的拨打电话的接口ReqDial()。在该接口里会把电话服务传过来的数据封装为对应的AT指令发送到Modem,Modem执行完拨号命令后通过OnCallReport()接口把响应结果上报给RIL Adapter。 394 395 ``` 396 // call模块回调函数指针 397 static const HRilCallReq g_callReqOps = { 398 .GetCallList = ReqGetCallList, // 获取呼叫列表接口 399 .Dial = ReqDial, // 拨打电话接口 400 .Hangup = ReqHangup, // 挂断电话接口 401 .Reject = ReqReject, // 拒接来电接口 402 .Answer = ReqAnswer, // 接听来电接口 403 }; 404 405 // 系统业务请求接口定义 406 HRilOps g_hrilOps = { 407 .callOps = &g_callReqOps, // 定义通话业务请求接口 408 .simOps = &g_simReqOps, // 定义SIM卡业务请求接口 409 .smsOps = &g_smsReqOps, // 定义短彩信业务请求接口 410 .networkOps = &g_networkReqOps, // 定义蜂窝数据业务请求接口 411 .dataOps = &g_dataReqOps, // 定义搜网业务请求接口 412 .modemOps = &g_modemReqOps, // 定义Modem业务请求接口 413 }; 414 415 // 拨号请求接口实现 416 void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen) 417 { 418 HRilDial *pDial = NULL; 419 char cmd[MAX_BUFF_SIZE] = {0}; 420 const char *clir = NULL; 421 int ret; 422 int err = HRIL_ERR_SUCCESS; 423 struct ReportInfo reportInfo = {}; 424 ResponseInfo *pResponse = NULL; 425 if (data == NULL) { 426 TELEPHONY_LOGE("data is null!!!"); 427 err = HRIL_ERR_INVALID_PARAMETER; 428 reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); 429 OnCallReport(reportInfo, NULL, 0); 430 return; 431 } 432 pDial = (HRilDial *)data; 433 switch (pDial->clir) { 434 case CALL_CLIR_INVOCATION: 435 clir = "I"; 436 break; /* invocation */ 437 case CALL_CLIR_SUPPRESSION: 438 clir = "i"; 439 break; /* suppression */ 440 case CALL_CLIR_SUBSCRIPTION_DEFUALT: 441 default: 442 clir = ""; 443 break; /* subscription default */ 444 } 445 (void)sprintf_s(cmd, MAX_BUFF_SIZE, "ATD%s%s;", pDial->address, clir); 446 ret = SendCommandLock(cmd, NULL, 0, &pResponse); // 发送AT命令 447 if (ret != 0) { 448 err = HRIL_ERR_CMD_SEND_FAILURE; 449 TELEPHONY_LOGE("ATD send failed"); 450 } else { 451 if (pResponse != NULL && pResponse->success == 0) { 452 TELEPHONY_LOGE("ReqDial return ERROR"); 453 err = HRIL_ERR_CMD_NO_CARRIER; 454 } 455 } 456 reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); 457 OnCallReport(reportInfo, NULL, 0); // 调用通话相关业务回调函数 458 FreeResponseInfo(pResponse); 459 } 460 ``` 461 462 463- **来电开发实例** 464 来电的调用流程示例如下图所示: 465 **图2** 来电调用时序图 466 467 ![zh-cn_image_0000001214727595](figures/zh-cn_image_0000001214727595.png) 468 469 Modem设备节点读取线程g_reader会循环读取Modem上报的消息,当Modem接收到来电时会主动上报来电相关的信息; 470 471 当该线程通过调用OnNotifyOps()解析到Modem上报的数据是以"+CRING"、"RING"等字符开头时,表示有来电事件,然后通过OnCallReport(reportInfo, NULL, 0)上报给RIL Adapter完成来电事件上报。 472 473 ``` 474 // 将Modem上报数据解析为对应模块的主动上报事件 475 void OnNotifyOps(const char *s, const char *smsPdu) 476 { 477 int ret = 0; 478 struct ReportInfo reportInfo = {0}; 479 reportInfo.error = HRIL_ERR_SUCCESS; 480 reportInfo.type = HRIL_NOTIFICATION; 481 if (GetRadioState() == HRIL_RADIO_POWER_STATE_UNAVAILABLE) { 482 return; 483 } 484 TELEPHONY_LOGD("enter to [%{public}s]:%{public}s", s, smsPdu); 485 // 通过AT指令判断主动上报命令类型 486 if (ReportStrWith(s, "+CRING:") || ReportStrWith(s, "RING") || ReportStrWith(s, "IRING") || 487 ReportStrWith(s, "NO CARRIER") || ReportStrWith(s, "+CCWA") || ReportStrWith(s, "^CCALLSTATE") || 488 ReportStrWith(s, "^CEND") || ReportStrWith(s, "^CCWA")) { 489 reportInfo.notifyId = HNOTI_CALL_STATE_UPDATED; 490 OnCallReport(reportInfo, NULL, 0); // 调用通话相关业务回调函数 491 } else if (ReportStrWith(s, "+CMT:")) { 492 reportInfo.notifyId = HNOTI_SMS_NEW_SMS; 493 OnSmsReport(reportInfo, (void *)smsPdu, strlen(smsPdu)); 494 } 495 // add your codes 496 ...... 497 } 498 ``` 499 500 501## Modem厂商库集成指导 502 503 504### 编译设置 505 506Modem厂商库可通过BUILD.gn编译为一个动态库,在RIL Adapter启动时用dlopen方式加载到系统中,然后执行厂商库的初始化操作(参见[Modem厂商库初始化开发指导](#modem厂商库初始化开发指导)),BUILD.gn编写示例如下: 507 508 509``` 510import("//build/ohos.gni") 511RIL_ADAPTER = "//base/telephony" 512ohos_shared_library("ril_vendor") { // Modem厂商库名称 513 sources = [ // 编译源文件 514 "at_call.c", 515 "at_data.c", 516 "xxx.c", 517 ] 518 include_dirs = [ // 包含的头文件目录 519 "$RIL_ADAPTER/ril_adapter/vendor/include", 520 "$RIL_ADAPTER/ril_adapter/interfaces/innerkits", 521 "include", 522 ] 523 deps = [ // 内部依赖 524 "//drivers/adapter/uhdf2/osal:libhdf_utils", 525 "//base/telephony/core_service/utils:libtelephony_common", 526 ] 527 external_deps = [ "hilog:libhilog" ] // 外部依赖 528 529 part_name = "ril_adapter" // 部件名称 530 subsystem_name = "telephony" // 子系统名称 531} 532``` 533 534 535### 调测验证 536 5371. 编译代码。 538 5392. 查看/out/{device_name}/telephony/ril_adapter目录是否存在libril_vendor.z.so,存在证明集成成功。否则检查代码,重新编译验证。 540