1 /*
2  * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "vendor_report.h"
17 
18 #include "at_call.h"
19 #include "at_sms.h"
20 #include "vendor_adapter.h"
21 
22 #include "hril_notification.h"
23 
24 static const struct HRilReport *g_reportOps = NULL;
25 static const size_t ZERO_RESPONSE_LEN = 0;
26 
OnModemReport(int32_t slotId,struct ReportInfo reportInfo,const uint8_t * response,size_t responseLen)27 void OnModemReport(int32_t slotId, struct ReportInfo reportInfo, const uint8_t *response, size_t responseLen)
28 {
29     if (g_reportOps != NULL) {
30         g_reportOps->OnModemReport(slotId, reportInfo, response, responseLen);
31     } else {
32         TELEPHONY_LOGE("g_reportOps is NULL");
33     }
34 }
35 
OnCallReport(int32_t slotId,struct ReportInfo reportInfo,const uint8_t * response,size_t responseLen)36 void OnCallReport(int32_t slotId, struct ReportInfo reportInfo, const uint8_t *response, size_t responseLen)
37 {
38     if (g_reportOps != NULL) {
39         g_reportOps->OnCallReport(slotId, reportInfo, response, responseLen);
40     } else {
41         TELEPHONY_LOGE("g_reportOps is NULL");
42     }
43 }
44 
OnDataReport(int32_t slotId,struct ReportInfo reportInfo,const uint8_t * response,size_t responseLen)45 void OnDataReport(int32_t slotId, struct ReportInfo reportInfo, const uint8_t *response, size_t responseLen)
46 {
47     if (g_reportOps != NULL) {
48         g_reportOps->OnDataReport(slotId, reportInfo, response, responseLen);
49     } else {
50         TELEPHONY_LOGE("g_reportOps is NULL");
51     }
52 }
53 
OnSmsReport(int32_t slotId,struct ReportInfo reportInfo,const uint8_t * response,size_t responseLen)54 void OnSmsReport(int32_t slotId, struct ReportInfo reportInfo, const uint8_t *response, size_t responseLen)
55 {
56     if (g_reportOps != NULL) {
57         g_reportOps->OnSmsReport(slotId, reportInfo, response, responseLen);
58     } else {
59         TELEPHONY_LOGE("g_reportOps is NULL");
60     }
61 }
62 
OnNetworkReport(int32_t slotId,struct ReportInfo reportInfo,const uint8_t * response,size_t responseLen)63 void OnNetworkReport(int32_t slotId, struct ReportInfo reportInfo, const uint8_t *response, size_t responseLen)
64 {
65     if (g_reportOps != NULL) {
66         g_reportOps->OnNetworkReport(slotId, reportInfo, response, responseLen);
67     } else {
68         TELEPHONY_LOGE("g_reportOps is NULL");
69     }
70 }
71 
OnSimReport(int32_t slotId,struct ReportInfo reportInfo,const uint8_t * response,size_t responseLen)72 void OnSimReport(int32_t slotId, struct ReportInfo reportInfo, const uint8_t *response, size_t responseLen)
73 {
74     if (g_reportOps != NULL) {
75         g_reportOps->OnSimReport(slotId, reportInfo, response, responseLen);
76     } else {
77         TELEPHONY_LOGE("g_reportOps is NULL");
78     }
79 }
80 
OnTimerCallback(HRilCallbackFun func,uint8_t * param,const struct timeval * tv)81 void OnTimerCallback(HRilCallbackFun func, uint8_t *param, const struct timeval *tv)
82 {
83     if (g_reportOps != NULL) {
84         g_reportOps->OnTimerCallback(func, param, tv);
85     } else {
86         TELEPHONY_LOGE("g_reportOps is NULL");
87     }
88 }
89 
CreateReportInfo(const ReqDataInfo * requestInfo,int32_t err,uint32_t type,int32_t notifyId)90 struct ReportInfo CreateReportInfo(const ReqDataInfo *requestInfo, int32_t err, uint32_t type, int32_t notifyId)
91 {
92     struct ReportInfo reportInfo = {(ReqDataInfo *)requestInfo, notifyId, type, err, {0, 0}};
93     return reportInfo;
94 }
95 
SetReportOps(const struct HRilReport * reportOps)96 void SetReportOps(const struct HRilReport *reportOps)
97 {
98     g_reportOps = reportOps;
99 }
100 
ReportCBMOrCSCB(struct ReportInfo * reportInfo)101 static void ReportCBMOrCSCB(struct ReportInfo *reportInfo)
102 {
103     if (reportInfo == NULL) {
104         TELEPHONY_LOGE("reportInfo is null");
105         return;
106     }
107     static int32_t testCount = 0;
108     char *tempData = NULL;
109     char *testDataStr =
110         ("01a41f51101102ea3030a830ea30a230e130fc30eb914d4fe130c630b930c8000d000a305330"
111          "8c306f8a669a137528306e30e130c330bb30fc30b8306730593002000d000aff0800320030003"
112          "10033002f00310031002f003252ea300037002000310035003a00340034ff09000d000aff0830"
113          "a830ea30a25e02ff0900000000000000000000000000000000000000"
114          "000000000000000000000000000000000000000000000000000000000022");
115     char *testDataTmp =
116         ("C0000032401174747A0E4ACF41E8B0BCFD76E741EF39685C66B34162F93B4C1E87E77410BD3CA7836EC2341D440ED3C321");
117     if (testCount == 0) {
118         tempData = testDataStr;
119         testCount++;
120     } else {
121         tempData = testDataTmp;
122         testCount = 0;
123     }
124     HRilCBConfigReportInfo response = {0};
125     reportInfo->notifyId = HNOTI_CB_CONFIG_REPORT;
126     int32_t ret = ProcessCellBroadcast("+CBM:100", &response);
127     if (ret > 1) {
128         response.data = (char *)tempData;
129     } else {
130         response.pdu = (char *)tempData;
131     }
132     OnSmsReport(GetSlotId(NULL), *reportInfo, (const uint8_t *)&response, sizeof(HRilCBConfigReportInfo));
133 }
134 
SmsStatus(const char * smsPdu,struct ReportInfo * reportInfo)135 static void SmsStatus(const char *smsPdu, struct ReportInfo *reportInfo)
136 {
137     if (smsPdu == NULL || reportInfo == NULL) {
138         TELEPHONY_LOGE("reportInfo is NULL");
139         return;
140     }
141     int32_t size = (smsPdu != NULL) ? strlen(smsPdu) : 0;
142     reportInfo->notifyId = HNOTI_SMS_STATUS_REPORT;
143     OnSmsReport(GetSlotId(NULL), *reportInfo, (const uint8_t *)smsPdu, size);
144 }
145 
ReportInfoInit(struct ReportInfo * reportInfo)146 static void ReportInfoInit(struct ReportInfo *reportInfo)
147 {
148     if (reportInfo == NULL) {
149         TELEPHONY_LOGE("reportInfo is NULL");
150         return;
151     }
152     reportInfo->error = HRIL_ERR_SUCCESS;
153     reportInfo->type = HRIL_NOTIFICATION;
154 }
155 
CdmaSmsNotifyMock(const char * s,HRilSmsResponse * smsResponse)156 static int32_t CdmaSmsNotifyMock(const char *s, HRilSmsResponse *smsResponse)
157 {
158     if (s == NULL || smsResponse == NULL) {
159         return 0;
160     }
161     char *testDataStr = ("0101020004081300031008d00106102c2870e1420801c00c01c0");
162     char *testDataTmp =
163         ("0000021002040602448d159e240601fc081b0003200010010910461c58d8b266a9180306211024102051080100");
164     if (ReportStrWith(s, "+CMMS:")) {
165         smsResponse->pdu = testDataTmp;
166     } else if (ReportStrWith(s, "+CSDH:")) {
167         smsResponse->pdu = testDataStr;
168     } else {
169         return 0;
170     }
171     return HNOTI_SMS_NEW_CDMA_SMS;
172 }
173 
WapPushNotifyMock(const char * s,HRilSmsResponse * smsResponse)174 static int32_t WapPushNotifyMock(const char *s, HRilSmsResponse *smsResponse)
175 {
176     if (s == NULL || smsResponse == NULL) {
177         return 0;
178     }
179     char *testDataStr =
180         ("0891683108200105f04408a0015608860104216092902512236e0605040b8423f0120601ae020"
181          "56a0045c60c033231312e3133362e3130372e37382f646f776e2e7068703f703d413063303026"
182          "733d383500080103e68e8ce68fa1e882a1e5b882e58588e69cbaefbc8ce6aca2e8bf8ee4bdbfe"
183          "794a8e6898be69cbae8af81e588b8e38082000101");
184     char *testDataTmp =
185         ("0041000B915121551532F400042E0B05040B84C0020003F001010A060403B0"
186          "81EA02066A008509036D6F62696C65746964696E67732E636F6D2F0001");
187     if (ReportStrWith(s, "+CMGF:")) {
188         smsResponse->pdu = testDataStr;
189     } else if (ReportStrWith(s, "+CSMP:")) {
190         smsResponse->pdu = testDataTmp;
191     } else {
192         return 0;
193     }
194     return HNOTI_SMS_NEW_SMS;
195 }
196 
ProcessNotifyMock(const char * s,struct ReportInfo reportInfo)197 static void ProcessNotifyMock(const char *s, struct ReportInfo reportInfo)
198 {
199     HRilSmsResponse response = {0};
200     if ((reportInfo.notifyId = CdmaSmsNotifyMock(s, &response)) > 0) {
201         OnSmsReport(GetSlotId(NULL), reportInfo, (const uint8_t *)&response, sizeof(HRilSmsResponse));
202     }
203     if ((reportInfo.notifyId = WapPushNotifyMock(s, &response)) > 0) {
204         OnSmsReport(GetSlotId(NULL), reportInfo, (const uint8_t *)&response, strlen(response.pdu));
205     }
206     return;
207 }
208 
OnNotifyOps(const char * s,const char * smsPdu)209 void OnNotifyOps(const char *s, const char *smsPdu)
210 {
211     if (s == NULL) {
212         return;
213     }
214     char *str = NULL;
215     struct ReportInfo reportInfo = {0};
216     ReportInfoInit(&reportInfo);
217     if (GetRadioState() == HRIL_RADIO_POWER_STATE_UNAVAILABLE) {
218         return;
219     }
220     str = strdup(s);
221     if (str == NULL) {
222         return;
223     }
224     if (IsCallNoticeCmd(s)) {
225         CallReportInfoProcess(s);
226     } else if (ReportStrWith(s, "+CMT:")) {
227         HRilSmsResponse smsResponse = {};
228         smsResponse.pdu = (char *)smsPdu;
229         reportInfo.notifyId = HNOTI_SMS_NEW_SMS;
230         OnSmsReport(GetSlotId(NULL), reportInfo, (const uint8_t *)&smsResponse, strlen(smsResponse.pdu));
231     } else if (ReportStrWith(s, "+CDS:")) {
232         SmsStatus(smsPdu, &reportInfo);
233     } else if (ReportStrWith(s, "+CBM:") || ReportStrWith(s, "+CSCB:")) {
234         ReportCBMOrCSCB(&reportInfo);
235         ReportCBMOrCSCB(&reportInfo); // The test requires send twice
236     } else if (ReportStrWith(s, "+COPS: (")) {
237         char *copsStr = strdup(s);
238         ProcessOperListToUse(copsStr);
239         free(copsStr);
240     } else if (ReportStrWith(s, "^SIMST:")) {
241         reportInfo.notifyId = HNOTI_SIM_STATUS_CHANGED;
242         OnSimReport(GetSlotId(NULL), reportInfo, NULL, 0);
243     } else if (ReportStrWith(s, "^MONSC:")) {
244         ProcessCurrentCellList(reportInfo, str);
245     } else if (ReportStrWith(s, "^DATACONNECT") || ReportStrWith(s, "^DATADISCONN")) {
246         PdpContextListUpdate();
247     } else if (OnNotifyStkOps(s, str)) {
248         TELEPHONY_LOGI("STK notify completed.");
249     } else {
250         ProcessNotifyMock(s, reportInfo);
251         OnNotifyNetWorksOps(s, str);
252     }
253     free(str);
254 }
255 
ParseStkResponseStr(const char * s,char ** cmdResponseInfo)256 static int32_t ParseStkResponseStr(const char *s, char **cmdResponseInfo)
257 {
258     char *str = (char *)s;
259     if (str == NULL) {
260         TELEPHONY_LOGE("ProcessStkNotify, s or cmdResponse param is null");
261         return HRIL_ERR_NULL_POINT;
262     }
263     int32_t err = SkipATPrefix(&str);
264     if (err != VENDOR_SUCCESS) {
265         TELEPHONY_LOGE("ProcessStkNotify, invalid response");
266         return HRIL_ERR_INVALID_RESPONSE;
267     }
268     err = NextStr(&str, cmdResponseInfo);
269     TELEPHONY_LOGD("ParseStkResponseStr, cmdResponse: %{public}s", *cmdResponseInfo);
270     if (err != 0) {
271         return HRIL_ERR_INVALID_PARAMETER;
272     }
273     return VENDOR_SUCCESS;
274 }
275 
OnNotifyStkOps(const char * s,const char * strInfo)276 bool OnNotifyStkOps(const char *s, const char *strInfo)
277 {
278     bool isStkNotify = true;
279     struct ReportInfo reportInfo = {0};
280     reportInfo.error = HRIL_ERR_SUCCESS;
281     reportInfo.type = HRIL_NOTIFICATION;
282     if (ReportStrWith(s, "SoftwareVersion:")) {
283         reportInfo.notifyId = HNOTI_SIM_STK_SESSION_END_NOTIFY;
284         OnSimReport(GetSlotId(NULL), reportInfo, NULL, ZERO_RESPONSE_LEN);
285     } else if (ReportStrWith(s, "HardwareVersion:")) {
286         reportInfo.notifyId = HNOTI_SIM_STK_PROACTIVE_NOTIFY;
287         char *cmdResponse = (char *)strInfo;
288         int32_t ret = ParseStkResponseStr(s, &cmdResponse);
289         if (ret != VENDOR_SUCCESS) {
290             reportInfo.error = ret;
291         }
292         if (cmdResponse == NULL) {
293             TELEPHONY_LOGE("cmdResponse is NULL");
294             OnSimReport(GetSlotId(NULL), reportInfo, NULL, ZERO_RESPONSE_LEN);
295         } else {
296             TELEPHONY_LOGD("OnNotifyStkOps, cmdResponse: %{public}s", cmdResponse);
297             OnSimReport(GetSlotId(NULL), reportInfo, (const uint8_t *)cmdResponse, sizeof(char));
298         }
299     } else if (ReportStrWith(s, "+CGMM:")) {
300         reportInfo.notifyId = HNOTI_SIM_STK_ALPHA_NOTIFY;
301         OnSimReport(GetSlotId(NULL), reportInfo, NULL, ZERO_RESPONSE_LEN);
302     } else {
303         isStkNotify = false;
304     }
305     return isStkNotify;
306 }
307 
OnCsRegStatusNotify(struct ReportInfo reportInfo,int32_t ret,char * str,const char * s)308 static void OnCsRegStatusNotify(struct ReportInfo reportInfo, int32_t ret, char *str, const char *s)
309 {
310     reportInfo.notifyId = HNOTI_NETWORK_CS_REG_STATUS_UPDATED;
311     HRilRegStatusInfo regStatusInfo;
312     ret = ProcessRegStatus(str, &regStatusInfo);
313     if (ret == 0) {
314         OnNetworkReport(GetSlotId(NULL), reportInfo, (const uint8_t *)(&regStatusInfo), sizeof(HRilRegStatusInfo));
315     } else {
316         TELEPHONY_LOGW("CREG notify str format  unexpected: %{public}s", s);
317     }
318 }
319 
RadioTurnNotify(struct ReportInfo reportInfo,char * str)320 static void RadioTurnNotify(struct ReportInfo reportInfo, char *str)
321 {
322     HRilRadioState radioState = HRIL_RADIO_POWER_STATE_UNAVAILABLE;
323     if (ReportStrWith(str, "^RADIO: 1")) {
324         radioState = HRIL_RADIO_POWER_STATE_ON;
325     } else if (ReportStrWith(str, "^RADIO: 0")) {
326         radioState = HRIL_RADIO_POWER_STATE_OFF;
327     } else {
328         TELEPHONY_LOGW("^RADIO notify str format  unexpected: %{public}s", str);
329     }
330     if (radioState != HRIL_RADIO_POWER_STATE_UNAVAILABLE) {
331         reportInfo.error = HRIL_ERR_SUCCESS;
332         reportInfo.type = HRIL_NOTIFICATION;
333         reportInfo.notifyId = HNOTI_MODEM_RADIO_STATE_UPDATED;
334         OnModemReport(GetSlotId(NULL), reportInfo, (const uint8_t *)&radioState, sizeof(HRilRadioState));
335     }
336 }
337 
DsdsModeNotify(struct ReportInfo reportInfo,char * str)338 static void DsdsModeNotify(struct ReportInfo reportInfo, char *str)
339 {
340     HRilDsdsMode dsdsMode = HRIL_DSDS_MODE_V2;
341     reportInfo.error = HRIL_ERR_SUCCESS;
342     reportInfo.type = HRIL_NOTIFICATION;
343     reportInfo.notifyId = HNOTI_MODEM_DSDS_MODE_UPDATED;
344     OnModemReport(GetSlotId(NULL), reportInfo, (const uint8_t *)&dsdsMode, sizeof(HRilDsdsMode));
345 }
346 
OnPsRegStatusNotify(struct ReportInfo reportInfo,int32_t ret,char * str,const char * s)347 static void OnPsRegStatusNotify(struct ReportInfo reportInfo, int32_t ret, char *str, const char *s)
348 {
349     reportInfo.notifyId = HNOTI_NETWORK_PS_REG_STATUS_UPDATED;
350     HRilRegStatusInfo regStatusInfo;
351     ret = ProcessRegStatus(str, &regStatusInfo);
352     if (ret == 0) {
353         OnNetworkReport(GetSlotId(NULL), reportInfo, (const uint8_t *)(&regStatusInfo), sizeof(HRilRegStatusInfo));
354     } else {
355         TELEPHONY_LOGW("CGREG notify str format  unexpected: %{public}s", s);
356     }
357 }
358 
OnNotifyNetWorksOpsJudgeTwo(struct ReportInfo reportInfo,const char * infoStr,char * responseData[MAX_REG_INFO_ITEM])359 static void OnNotifyNetWorksOpsJudgeTwo(
360     struct ReportInfo reportInfo, const char *infoStr, char *responseData[MAX_REG_INFO_ITEM])
361 {
362     reportInfo.notifyId = HNOTI_NETWORK_TIME_UPDATED;
363     char *time[DEFAULT_INDEX] = {""};
364     if (GenerateCommand((char *)time, DEFAULT_INDEX, "^TIME:\"20%s", infoStr + DEFAULT_ADD_NUM) < 0) {
365         TELEPHONY_LOGE("GenerateCommand is failed!");
366         OnNetworkReport(GetSlotId(NULL), reportInfo, (const uint8_t *)responseData, MAX_REG_INFO_ITEM * sizeof(char));
367         return;
368     }
369     TELEPHONY_LOGW("Report TIME: %{public}s", (char *)time);
370     OnNetworkReport(GetSlotId(NULL), reportInfo, (const uint8_t *)time, MAX_REG_INFO_ITEM * sizeof(char));
371 }
372 
SignalStrengthNotify(struct ReportInfo reportInfo,int32_t ret,char * str,const char * s)373 static void SignalStrengthNotify(struct ReportInfo reportInfo, int32_t ret, char *str, const char *s)
374 {
375     HRilRssi response = {0};
376     reportInfo.notifyId = HNOTI_NETWORK_SIGNAL_STRENGTH_UPDATED;
377     TELEPHONY_LOGD("start report SignalStrengthNotify ");
378     ret = ProcessParamSignalStrengthNotify(str, &response);
379     if (ret == 0) {
380         OnNetworkReport(GetSlotId(NULL), reportInfo, (const uint8_t *)(&response), sizeof(HRilRssi));
381     } else {
382         TELEPHONY_LOGW("HCSQ notify str format  unexpected: %{public}s", s);
383     }
384 }
385 
VoiceRadioInfoNotify(struct ReportInfo reportInfo,int32_t ret,char * str,const char * s)386 static void VoiceRadioInfoNotify(struct ReportInfo reportInfo, int32_t ret, char *str, const char *s)
387 {
388     HRilVoiceRadioInfo voiceRadioInfo = {0};
389     ret = ProcessVoiceRadioInfo(str, &voiceRadioInfo);
390     if (ret != 0) {
391         TELEPHONY_LOGE("ProcessVoiceRadioInfo format  unexpected: %{public}s", s);
392         return;
393     }
394     reportInfo.notifyId = HNOTI_MODEM_VOICE_TECH_UPDATED;
395     OnModemReport(GetSlotId(NULL), reportInfo, (const uint8_t *)(&voiceRadioInfo), sizeof(HRilVoiceRadioInfo));
396 }
397 
OnNotifyNetWorksOps(const char * s,const char * infoStr)398 void OnNotifyNetWorksOps(const char *s, const char *infoStr)
399 {
400     int32_t ret = 0;
401     char *str = (char *)infoStr;
402     char *responseData[MAX_REG_INFO_ITEM] = {""};
403     struct ReportInfo reportInfo = {0};
404     reportInfo.error = HRIL_ERR_SUCCESS;
405     reportInfo.type = HRIL_NOTIFICATION;
406     if (ReportStrWith(s, "+CREG:")) {
407         OnCsRegStatusNotify(reportInfo, ret, str, s);
408     } else if (ReportStrWith(s, "+CGREG:")) {
409         OnPsRegStatusNotify(reportInfo, ret, str, s);
410     } else if (ReportStrWith(s, "^TIME:")) {
411         OnNotifyNetWorksOpsJudgeTwo(reportInfo, infoStr, responseData);
412     } else if (ReportStrWith(s, "+CTZV:")) {
413         reportInfo.notifyId = HNOTI_NETWORK_TIME_ZONE_UPDATED;
414         OnNetworkReport(GetSlotId(NULL), reportInfo, (const uint8_t *)responseData, MAX_REG_INFO_ITEM * sizeof(char));
415     } else if (ReportStrWith(s, "^HCSQ:")) {
416         SignalStrengthNotify(reportInfo, ret, str, s);
417     } else if (ReportStrWith(s, "^RADIO:")) {
418         RadioTurnNotify(reportInfo, str);
419     } else if (ReportStrWith(s, "^PHYCHLCFG:")) {
420         ProcessPhyChnlCfgNotify(reportInfo, str);
421     } else if (ReportStrWith(s, "^SYSINFOEX:")) {
422         VoiceRadioInfoNotify(reportInfo, ret, str, s);
423     } else if (ReportStrWith(s, "^DSDS:")) {
424         DsdsModeNotify(reportInfo, str);
425     } else if (ReportStrWith(s, "^PLMN:")) {
426         ResidentNetworkUpdated(reportInfo, str);
427     } else {
428         TELEPHONY_LOGW("enter to  is unrecognized command");
429     }
430 }
431