• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Telephony Development
2
3
4## Initializing a Modem Vendor Library
5
6
7### When to Use
8
9Initializing a modem vendor library means to implement **const HRilOps \*RilInitOps(const struct HRilReport \*reportOps)** function in the vendor library. This function is mainly used to:
10
11- Receive function pointers to event callbacks of RIL Adapter. When a service event needs to be reported, the target pointer will be called to report the event to RIL Adapter.
12
13- Create a thread for reading modem nodes. In this thread, the data reported by the modem is read cyclically and parsed as a specific service event for reporting.
14
15- Return the function pointer of the service request API to RIL Adapter.
16
17
18### Available APIs
19
20The following table describes the API for initializing a modem vendor library.
21
22  **Table  1** API for initializing a modem vendor library
23
24| Name| Description|
25| -------- | -------- |
26| const&nbsp;HRilOps&nbsp;\*RilInitOps(const&nbsp;struct&nbsp;HRilReport&nbsp;\*&nbsp;reportOps) | Function: Provides an entry for running a modem vendor library.<br>Input arguments:<br>**reportOps**: event callback function pointer passed by RIL Adapter.<br>Return value: function pointer of the service request API.|
27
28
29### How to Develop
30
31
321. Set the event callback function pointers passed by RIL Adapter through **RilInitOps**.
33
34   ```
35   // Define the callback function pointers of the modem vendor library.
36   static struct HRilReport g_reportOps = {
37       OnCallReport, // Callback function for call services
38       OnDataReport, // Callback function for cellular data services
39       OnModemReport, // Callback function for modem services
40       OnNetworkReport, // Callback function for network search services
41       OnSimReport, // Callback function for SIM card services
42       OnSmsReport // Callback function for SMS services
43   };
44   ```
45
46
471. Create the **g_reader** main thread to enable message looping.
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); // Create the g_reader thread.
54   ```
55
56
571. In the **g_eventListeners** thread, use **open()** to open a modem node and then create the **g_reader** thread to read and process messages reported by the modem.
58
59   ```
60   g_fd = open(g_devicePath, O_RDWR); // Open the device node specified by g_devicePath.
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. Return the function pointer of the service request API.
68
69   ```
70   // Structure for the service request API of the call module
71   typedef struct {
72       // Obtain the call list.
73       void (*GetCallList)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
74       // Make a call
75       void (*Dial)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
76       // End a call.
77       void (*Hangup)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
78       // Reject a call
79       void (*Reject)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
80       // Answer a call.
81       void (*Answer)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
82   } HRilCallReq;
83
84   // Callback function pointer of the call module
85   static const HRilCallReq g_callReqOps = {
86       .GetCallList = ReqGetCallList, // Obtain the call list.
87       .Dial = ReqDial,               // Make a call.
88       .Hangup = ReqHangup,           // Disconnect a call.
89       .Reject = ReqReject,           // Reject a call.
90       .Answer = ReqAnswer,           // Answer a call.
91   };
92
93   // Service request structure
94   typedef struct {
95       const HRilCallReq *callOps;       // Pointer to the structure of call service requests
96       const HRilSimReq *simOps;         // Pointer to the structure of SIM card service requests
97       const HRilSmsReq *smsOps;         // Pointer to the structure of SMS and MMS service requests
98       const HRilDataReq *dataOps;       // Pointer to the structure of cellular data service requests
99       const HRilNetworkReq *networkOps; // Pointer to the structure of network search service requests
100       const HRilModemReq *modemOps;     // Pointer to the structure of modem service requests
101   } HRilOps;
102
103   // Service request APIs
104   HRilOps g_hrilOps = {
105       .callOps = &g_callReqOps,       // API for call service requests
106       .simOps = &g_simReqOps,         // API for SIM card service requests
107       .smsOps = &g_smsReqOps,         // API for SMS and MMS service requests
108       .networkOps = &g_networkReqOps, // API for cellular data service requests
109       .dataOps = &g_dataReqOps,       // API for network search service requests
110       .modemOps = &g_modemReqOps,     // API for modem service requests
111   };
112   ```
113
114
115### Debugging and Verification
116
1171. Use the [hdc\_std](../subsystems/subsys-toolchain-hdc-guide.md#how-to-obtain) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device. For details about how to integrate a library file, see  [Integrating Modem Vendor Libraries](#integrating-modem-vendor-libraries).
118
119   ```
120   hdc_std file send libril_vendor.z.so /system/lib/
121   ```
122
1232. Reboot the debugging device.
124
125   ```
126   hdc_std shell sync
127   hdc_std shell reboot
128   ```
129
1303. Run the **hdc_std shell hilog** command to view the debug log, and check whether the **RilInitOps()** function is successfully executed. The following debug log is for reference:
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## Responding to Modem Service Requests
139
140
141### When to Use
142
143After receiving a specific telephony service request, RIL Adapter calls the target function pointer obtained in modem vendor library initialization to send a specific service request to the vendor library. Then, the vendor library processes the request based on the request ID.
144
145
146### Available APIs
147
148The following table describes the APIs for responding to modem service requests, with the dial module as an example.
149
150  **Table 2** APIs for responding to modem service requests
151
152| Name| Description|
153| -------- | -------- |
154| void&nbsp;ReqDial(ReqDataInfo&nbsp;\*requestInfo,&nbsp;const&nbsp;void&nbsp;\*data,&nbsp;size_t&nbsp;dataLen); | Function: Processes number dial requests.<br>Input arguments:<br>**requestInfo**: request type.<br>**data**: called number.<br>**dataLen**: data length.<br>Return value: none|
155| void&nbsp;(\*OnCallReport)(struct&nbsp;ReportInfo&nbsp;reportInfo,&nbsp;const&nbsp;void&nbsp;\*data,&nbsp;size_t&nbsp;dataLen); | Function: Reports the execution result of a service request to RIL Adapter.<br>Input arguments:<br>**reportInfo**: request type.<br>**data**: returned data.<br>**dataLen**: data length.<br>Return value: none|
156
157
158### How to Develop
159
1601. Implement processing of dial requests in the **ReqDial()** API.
161
162   ```
163   // Implement the API for processing dial requests.
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); // Send the AT command.
195       ......
196   }
197   ```
198
1992. After the modem executes the dial command, report the execution result to RIL Adapter via **OnCallReport()**.
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); // Invoke the callback function of the call service.
209   ```
210
211
212### Debugging and Verification
213
2141. Use the [hdc\_std](../subsystems/subsys-toolchain-hdc-guide.md#how-to-obtain) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device.
215
216   ```
217   hdc_std file send libril_vendor.z.so /system/lib/
218   ```
219
2202. Reboot the debugging device.
221
222   ```
223   hdc_std shell sync
224   hdc_std shell reboot
225   ```
226
2273. Run the **hdc_std shell** command. Then, run the **./system/bin/ril_adapter_test** command, type **1**, and enter the phone number as prompted to test the call function.
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. Open another terminal window, and run the **hdc_std shell hilog** command. Then, view the log to check whether **ReqDial()** is successfully executed. The following debug log is for reference:
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## Reporting Modem Events
256
257
258### When to Use
259
260A modem node thread reads the messages reported by the modem cyclically, parses the messages into specific events, and then reports the events to RIL Adapter.
261
262
263### Available APIs
264
265The following table describes the API for reporting modem events.
266
267  **Table 3** API for reporting modem events
268
269| Name| Description|
270| -------- | -------- |
271| void&nbsp;OnNotifyOps(const&nbsp;char&nbsp;\*s,&nbsp;const&nbsp;char&nbsp;\*smsPdu) | Function: Distributes the events reported by the modem.<br>Input arguments:<br>**s**: AT command prefix<br>**smsPdu**: PDU of the SMS message.<br>Return value: none|
272
273
274### How to Develop
275
2761. Call **OnNotifyOps()** in the g_reader thread of the modem device node to parse reported modem events. On determining the command type, call **OnXxxReport()** to report the parsed module events to the hril layer.
277
278   ```
279   // Parse the data reported by the modem as events proactively reported by the corresponding module.
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       // Determine the type of the proactively reported events based on the AT command.
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       // Report the events of each module to the hril layer.
301       ......
302   }
303   ```
304
3051. Distribute the reported events from the **hril** layer to the Telephony Service layer.
306
307   ```
308   // Report the call status proactively.
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       // Distribute events.
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### Debugging and Verification
332
3331. Use the [hdc\_std](../subsystems/subsys-toolchain-hdc-guide.md#how-to-obtain) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device.
334
335   ```
336   hdc_std file send libril_vendor.z.so /system/lib/
337   ```
338
3392. Reboot the debugging device.
340
341   ```
342   hdc_std shell sync
343   hdc_std shell reboot
344   ```
345
3463. Run the **hdc_std shell** command. Then, run the **./system/bin/ril_adapter_test** command, type **1**, and enter the phone number as prompted to test the call function.
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. Open another terminal window, and run the **hdc_std shell hilog** command. Then, view the log to check whether **OnNotifyOps()** is successfully executed. The following debug log is for reference:
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### Development Example
386
387- **Outgoing Call**
388    The following figure shows the API calling for an outgoing call.
389    **Figure 1** Time sequence of API calling for an outgoing call
390
391  ![](figures/en-us_image_0000001171507146.png)
392
393    When an application initiates an outgoing call, RIL Adapter receives a call request, and the **hril** layer invokes the **ReqDial()** function. In **ReqDial()**, the data passed by the Telephony Service is encapsulated as an AT command and sent to the modem. After executing the dial command, the modem reports the execution result to RIL Adapter through **OnCallReport()**.
394
395  ```
396  // Callback function pointer of the call module
397  static const HRilCallReq g_callReqOps = {
398      .GetCallList = ReqGetCallList, // Obtain the call list.
399      .Dial = ReqDial,               // Make a call.
400      .Hangup = ReqHangup,           // Disconnect a call.
401      .Reject = ReqReject,           // Reject a call.
402      .Answer = ReqAnswer,           // Answer a call.
403  };
404
405  // Service request APIs
406  HRilOps g_hrilOps = {
407      .callOps = &g_callReqOps,       // API for call service requests
408      .simOps = &g_simReqOps,         // API for SIM card service requests
409      .smsOps = &g_smsReqOps,         // API for SMS and MMS service requests
410      .networkOps = &g_networkReqOps, // API for cellular data service requests
411      .dataOps = &g_dataReqOps,       // API for network search service requests
412      .modemOps = &g_modemReqOps,     // API for modem service requests
413  };
414
415  // Implement the API for processing dial requests.
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); // Send the AT command.
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); // Invoke the callback function of the call service.
458      FreeResponseInfo(pResponse);
459  }
460  ```
461
462
463- **Incoming Call**
464    The following figure shows the API calling of an incoming call.
465    **Figure 2** Time sequence of API calling for an incoming call
466
467  ![](figures/en-us_image_0000001214727595.png)
468
469  The **g_reader** thread cyclically reads the messages reported by the modem. When the modem receives an incoming call event, it actively reports the information about the incoming call.
470
471    The **g_reader** thread calls **OnNotifyOps()** to parse the reported information. If the parsed data reported by the modem starts with characters such as **+CRING** or **RING**, it indicates that an incoming call event exists. In this case, the event is reported to RIL Adapter through **OnCallReport(reportInfo, NULL, 0)**.
472
473  ```
474  // Parse the data reported by the modem as events proactively reported by the corresponding module.
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      // Determine the type of the proactively reported events based on the AT command.
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);  // Invoke the callback function of the call service.
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## Integrating Modem Vendor Libraries
502
503
504### Configuring Compilation Information
505
506Compile the modem vendor library into a dynamic library by using **BUILD.gn**. Upon startup, RIL Adapter loads the dynamic library to the system in dlopen mode and then initializes the library. For details about how to implement vendor library initialization, see  [Initializing a Modem Vendor Library](#initializing-a-modem-vendor-library). The following is an example of **BUILD.gn**:
507
508
509```
510import("//build/ohos.gni")
511RIL_ADAPTER = "//base/telephony"
512ohos_shared_library("ril_vendor") { // Modem vendor library
513    sources = [// Source files to be built
514        "at_call.c",
515        "at_data.c",
516        "xxx.c",
517    ]
518    include_dirs = [// Header files
519        "$RIL_ADAPTER/ril_adapter/vendor/include",
520        "$RIL_ADAPTER/ril_adapter/interfaces/innerkits",
521        "include",
522    ]
523    deps = [// Internal dependencies
524        "//drivers/adapter/uhdf2/osal:libhdf_utils",
525        "//base/telephony/core_service/utils:libtelephony_common",
526    ]
527    external_deps = [ "hilog:libhilog" ] // External dependenc
528
529    part_name = "ril_adapter"  // Part name
530    subsystem_name = "telephony" // Subsystem name
531}
532```
533
534
535### Debugging and Verification
536
5371. Build the code.
538
5392. Check whether the **libril_vendor.z.so** file exists in the **/out/{device_name}/telephony/ril_adapter** directory. If the file exists, the integration is successful. Otherwise, correct the code error, and perform compilation and verification again.
540