1/*
2 * Copyright (C) 2021-2023 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 "gsm_sms_sender.h"
17
18#include <cinttypes>
19
20#include "core_manager_inner.h"
21#include "radio_event.h"
22#include "satellite_sms_client.h"
23#include "securec.h"
24#include "sms_hisysevent.h"
25#include "telephony_log_wrapper.h"
26
27namespace OHOS {
28namespace Telephony {
29using namespace std;
30GsmSmsSender::GsmSmsSender(int32_t slotId, function<void(std::shared_ptr<SmsSendIndexer>)> sendRetryFun)
31    : SmsSender(slotId, sendRetryFun)
32{}
33
34GsmSmsSender::~GsmSmsSender() {}
35
36void GsmSmsSender::Init()
37{
38    if (!RegisterHandler()) {
39        TELEPHONY_LOGI("GsmSmsSender::Init Register RADIO_SMS_STATUS fail.");
40    }
41}
42
43void GsmSmsSender::TextBasedSmsDelivery(const string &desAddr, const string &scAddr, const string &text,
44    const sptr<ISendShortMessageCallback> &sendCallback,
45    const sptr<IDeliveryShortMessageCallback> &deliveryCallback, uint16_t dataBaseId, bool isMmsApp)
46{
47    DataCodingScheme codingType;
48    GsmSmsMessage gsmSmsMessage;
49    std::vector<struct SplitInfo> cellsInfos;
50    gsmSmsMessage.SetSmsCodingNationalType(GetSmsCodingNationalType(slotId_));
51    std::string addr;
52    gsmSmsMessage.SplitMessage(cellsInfos, text, CheckForce7BitEncodeType(), codingType, false, addr);
53    bool isStatusReport = (deliveryCallback == nullptr) ? false : true;
54    std::shared_ptr<struct SmsTpdu> tpdu =
55        gsmSmsMessage.CreateDefaultSubmitSmsTpdu(desAddr, scAddr, text, isStatusReport, codingType);
56    if (tpdu == nullptr) {
57        SendCallbackExceptionCase(sendCallback, "TextBasedSmsDelivery");
58        return;
59    }
60    int cellsInfosSize = static_cast<int>(cellsInfos.size());
61    if (cellsInfosSize > MAX_SEGMENT_NUM) {
62        SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
63        TELEPHONY_LOGE("message exceed the limit.");
64        SmsHiSysEvent::WriteSmsSendFaultEvent(slotId_, SmsMmsMessageType::SMS_SHORT_MESSAGE,
65            SmsMmsErrorCode::SMS_ERROR_EXCEED_MAX_SEGMENT_NUM, "text sms gsm message cellsInfosSize exceed the limit");
66        return;
67    }
68    isStatusReport = tpdu->data.submit.bStatusReport;
69
70    TELEPHONY_LOGI("TextBasedSmsDelivery isStatusReport= %{public}d", isStatusReport);
71    std::unique_lock<std::mutex> lock(mutex_);
72    TextBasedSmsSplitDelivery(desAddr, scAddr, cellsInfos, codingType, isStatusReport, tpdu,
73        gsmSmsMessage, sendCallback, deliveryCallback, dataBaseId, isMmsApp);
74}
75
76void GsmSmsSender::TextBasedSmsSplitDelivery(const std::string &desAddr, const std::string &scAddr,
77    std::vector<struct SplitInfo> cellsInfos, DataCodingScheme codingType, bool isStatusReport,
78    std::shared_ptr<struct SmsTpdu> tpdu, GsmSmsMessage &gsmSmsMessage,
79    const sptr<ISendShortMessageCallback> &sendCallback, const sptr<IDeliveryShortMessageCallback> &deliveryCallback,
80    uint16_t dataBaseId, bool isMmsApp)
81{
82    int cellsInfosSize = static_cast<int>(cellsInfos.size());
83    unsigned char msgRef8bit = GetMsgRef8Bit();
84    shared_ptr<uint8_t> unSentCellCount = make_shared<uint8_t>(cellsInfosSize);
85    shared_ptr<bool> hasCellFailed = make_shared<bool>(false);
86    if (unSentCellCount == nullptr || hasCellFailed == nullptr) {
87        SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
88        return;
89    }
90    for (int i = 0; i < cellsInfosSize; i++) {
91        std::shared_ptr<SmsSendIndexer> indexer = nullptr;
92        std::string segmentText;
93        segmentText.append((char *)(cellsInfos[i].encodeData.data()), cellsInfos[i].encodeData.size());
94        indexer = make_shared<SmsSendIndexer>(desAddr, scAddr, segmentText, sendCallback, deliveryCallback);
95        if (indexer == nullptr) {
96            SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
97            return;
98        }
99        indexer->SetDcs(cellsInfos[i].encodeType);
100        indexer->SetDataBaseId(dataBaseId);
101        indexer->SetIsMmsApp(isMmsApp);
102        (void)memset_s(tpdu->data.submit.userData.data, MAX_USER_DATA_LEN + 1, 0x00, MAX_USER_DATA_LEN + 1);
103        if (cellsInfos[i].encodeData.size() > MAX_USER_DATA_LEN + 1) {
104            TELEPHONY_LOGE("TextBasedSmsDelivery data length invalid.");
105            return;
106        }
107        int ret = memcpy_s(tpdu->data.submit.userData.data, MAX_USER_DATA_LEN + 1, &cellsInfos[i].encodeData[0],
108            cellsInfos[i].encodeData.size());
109        if (ret != EOK) {
110            SendResultCallBack(indexer, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
111            return;
112        }
113        tpdu->data.submit.userData.length = cellsInfos[i].encodeData.size();
114        tpdu->data.submit.userData.data[cellsInfos[i].encodeData.size()] = 0;
115        tpdu->data.submit.msgRef = msgRef8bit;
116        int headerCnt = 0;
117        if (cellsInfosSize > 1) {
118            indexer->SetIsConcat(true);
119            SmsConcat concat;
120            concat.msgRef = msgRef8bit;
121            concat.totalSeg = static_cast<uint16_t>(cellsInfosSize);
122            concat.seqNum = static_cast<uint16_t>(i + 1);
123            indexer->SetSmsConcat(concat);
124            headerCnt += gsmSmsMessage.SetHeaderConcat(headerCnt, concat);
125            concat.is8Bits = true;
126        }
127        /* Set User Data Header for Alternate Reply Address */
128        headerCnt += gsmSmsMessage.SetHeaderReply(headerCnt);
129        /* Set User Data Header for National Language Single Shift */
130        headerCnt += gsmSmsMessage.SetHeaderLang(headerCnt, codingType, cellsInfos[i].langId);
131        indexer->SetLangId(cellsInfos[i].langId);
132        tpdu->data.submit.userData.headerCnt = headerCnt;
133        tpdu->data.submit.bHeaderInd = (headerCnt > 0) ? true : false;
134        bool isMore = false;
135        if (cellsInfosSize > 1 && i < (cellsInfosSize - 1)) {
136            isMore = true;
137            tpdu->data.submit.bStatusReport = false;
138        } else {
139            tpdu->data.submit.bStatusReport = isStatusReport;
140            isMore = false;
141        }
142        std::shared_ptr<struct EncodeInfo> encodeInfo = gsmSmsMessage.GetSubmitEncodeInfo(scAddr, isMore);
143        if (encodeInfo == nullptr) {
144            SendResultCallBack(indexer, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
145            TELEPHONY_LOGE("create encodeInfo encodeInfo nullptr error.");
146            continue;
147        }
148        SetSendIndexerInfo(indexer, encodeInfo, msgRef8bit);
149        indexer->SetUnSentCellCount(*unSentCellCount);
150        indexer->SetHasCellFailed(hasCellFailed);
151        SendSmsToRil(indexer);
152    }
153}
154
155void GsmSmsSender::DataBasedSmsDelivery(const std::string &desAddr, const std::string &scAddr, int32_t port,
156    const uint8_t *data, uint32_t dataLen, const sptr<ISendShortMessageCallback> &sendCallback,
157    const sptr<IDeliveryShortMessageCallback> &deliveryCallback)
158{
159    GsmSmsMessage gsmSmsMessage;
160    std::vector<struct SplitInfo> cellsInfos;
161    DataCodingScheme codingType;
162    std::string dataStr;
163    CharArrayToString(data, dataLen, dataStr);
164    gsmSmsMessage.SetSmsCodingNationalType(GetSmsCodingNationalType(slotId_));
165    gsmSmsMessage.SplitMessage(cellsInfos, dataStr, CheckForce7BitEncodeType(), codingType, true, desAddr);
166    uint8_t msgRef8bit = GetMsgRef8Bit();
167    TELEPHONY_LOGI("gsm data msgRef8bit = %{public}d", msgRef8bit);
168    std::shared_ptr<struct SmsTpdu> tpdu = gsmSmsMessage.CreateDataSubmitSmsTpdu(
169        desAddr, scAddr, port, data, dataLen, msgRef8bit, codingType, (deliveryCallback == nullptr) ? false : true);
170    if (tpdu == nullptr) {
171        SendCallbackExceptionCase(sendCallback, "DataBasedSmsDelivery");
172        return;
173    }
174    DataBasedSmsDeliverySplitPage(
175        gsmSmsMessage, cellsInfos, tpdu, msgRef8bit, desAddr, scAddr, port, sendCallback, deliveryCallback);
176}
177
178void GsmSmsSender::SendSmsToRil(const shared_ptr<SmsSendIndexer> &smsIndexer)
179{
180    if (smsIndexer == nullptr) {
181        SendResultCallBack(smsIndexer, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
182        TELEPHONY_LOGE("gsm_sms_sender: SendSms smsIndexer nullptr");
183        return;
184    }
185    auto &satelliteSmsClient = SatelliteSmsClient::GetInstance();
186    if (!satelliteSmsClient.IsSatelliteEnabled()) {
187        if (!isImsNetDomain_ && (voiceServiceState_ != static_cast<int32_t>(RegServiceState::REG_STATE_IN_SERVICE))) {
188            SendResultCallBack(smsIndexer, ISendShortMessageCallback::SEND_SMS_FAILURE_SERVICE_UNAVAILABLE);
189            TELEPHONY_LOGE("gsm_sms_sender: SendSms not in service");
190            SmsHiSysEvent::WriteSmsSendFaultEvent(slotId_, SmsMmsMessageType::SMS_SHORT_MESSAGE,
191                SmsMmsErrorCode::SMS_ERROR_SENDSMS_NOT_IN_SERVICE, "gsm send sms not in service");
192            return;
193        }
194    }
195
196    int64_t refId = GetMsgRef64Bit();
197    TELEPHONY_LOGI("gsm refId = %{public}" PRId64 "", refId);
198    if (!SendCacheMapAddItem(refId, smsIndexer)) {
199        TELEPHONY_LOGE("SendCacheMapAddItem Error!!");
200        return;
201    }
202
203    GsmSimMessageParam smsData;
204    smsData.refId = refId;
205    smsData.smscPdu = StringUtils::StringToHex(smsIndexer->GetEncodeSmca());
206    smsData.pdu = StringUtils::StringToHex(smsIndexer->GetEncodePdu());
207
208    if (satelliteSmsClient.IsSatelliteEnabled()) {
209        TELEPHONY_LOGI("send sms through satellite");
210        SendSatelliteSms(smsIndexer, smsData);
211        return;
212    }
213
214    bool sendCsSMS = false;
215    if ((!isImsNetDomain_ || !imsSmsCfg_) || (smsIndexer->GetPsResendCount() == MAX_SEND_RETRIES)) {
216        sendCsSMS = true;
217    }
218    if (sendCsSMS) {
219        SendCsSms(smsIndexer, smsData);
220    } else {
221        SendImsSms(smsIndexer, smsData);
222    }
223}
224
225void GsmSmsSender::SendCsSms(const shared_ptr<SmsSendIndexer> &smsIndexer, GsmSimMessageParam smsData)
226{
227    uint8_t tryCount = smsIndexer->GetCsResendCount();
228    lastSmsDomain_ = CS_DOMAIN;
229    if (tryCount > 0) {
230        smsIndexer->UpdatePduForResend();
231    }
232    if (tryCount == 0 && smsIndexer->GetHasMore()) {
233        TELEPHONY_LOGI("SendSmsMoreMode pdu len = %{public}zu", smsIndexer->GetEncodePdu().size());
234        CoreManagerInner::GetInstance().SendSmsMoreMode(
235            slotId_, RadioEvent::RADIO_SEND_SMS_EXPECT_MORE, smsData, shared_from_this());
236    } else {
237        TELEPHONY_LOGI("SendSms pdu len = %{public}zu", smsIndexer->GetEncodePdu().size());
238        CoreManagerInner::GetInstance().SendGsmSms(slotId_, RadioEvent::RADIO_SEND_SMS, smsData, shared_from_this());
239    }
240}
241
242void GsmSmsSender::SendSatelliteSms(const shared_ptr<SmsSendIndexer> &smsIndexer, GsmSimMessageParam smsData)
243{
244    auto &satelliteSmsClient = SatelliteSmsClient::GetInstance();
245    uint8_t tryCount = smsIndexer->GetCsResendCount();
246    lastSmsDomain_ = CS_DOMAIN;
247    if (tryCount > 0) {
248        smsIndexer->UpdatePduForResend();
249    }
250    TELEPHONY_LOGI("satellite SendSms tryCount = %{public}d", tryCount);
251    if (tryCount == 0 && smsIndexer->GetHasMore()) {
252        TELEPHONY_LOGI("satellite SendSmsMoreMode pdu len = %{public}zu", smsIndexer->GetEncodePdu().size());
253        satelliteSmsClient.SendSmsMoreMode(slotId_, RadioEvent::RADIO_SEND_SMS_EXPECT_MORE, smsData);
254    } else {
255        TELEPHONY_LOGI("satellite SendSms pdu len = %{public}zu", smsIndexer->GetEncodePdu().size());
256        satelliteSmsClient.SendSms(slotId_, RadioEvent::RADIO_SEND_SMS, smsData);
257    }
258}
259
260void GsmSmsSender::SendImsSms(const shared_ptr<SmsSendIndexer> &smsIndexer, GsmSimMessageParam smsData)
261{
262    auto smsClient = DelayedSingleton<ImsSmsClient>::GetInstance();
263    TELEPHONY_LOGI("ims network domain send sms interface.!");
264    if (smsClient == nullptr) {
265        TELEPHONY_LOGE("SendSmsToRil return, ImsSmsClient is nullptr.");
266        return;
267    }
268    lastSmsDomain_ = IMS_DOMAIN;
269    ImsMessageInfo imsMessageInfo;
270    imsMessageInfo.refId = smsData.refId;
271    imsMessageInfo.smscPdu = smsData.smscPdu;
272    imsMessageInfo.pdu = smsData.pdu;
273    imsMessageInfo.tech = SMS_RADIO_TECH_3GPP;
274    int32_t reply = smsClient->ImsSendMessage(slotId_, imsMessageInfo);
275    TELEPHONY_LOGI("SendImsSms reply = %{public}d", reply);
276}
277
278int32_t GsmSmsSender::IsImsSmsSupported(int32_t slotId, bool &isSupported)
279{
280    auto smsClient = DelayedSingleton<ImsSmsClient>::GetInstance();
281    if (smsClient == nullptr) {
282        TELEPHONY_LOGE("GetImsSmsConfig return, ImsSmsClient is nullptr.");
283        return TELEPHONY_ERR_LOCAL_PTR_NULL;
284    }
285    std::unique_lock<std::mutex> lck(ctx_);
286    resIsSmsReady_ = false;
287    int32_t reply = smsClient->ImsGetSmsConfig(slotId);
288    TELEPHONY_LOGI("GetImsSms reply = %{public}d", reply);
289    while (resIsSmsReady_) {
290        TELEPHONY_LOGI("GetImsSmsConfig::wait(), resIsSmsReady_ = false");
291        if (cv_.wait_for(lck, std::chrono::seconds(WAIT_TIME_SECOND)) == std::cv_status::timeout) {
292            break;
293        }
294    }
295    TELEPHONY_LOGI("GsmSmsSender::IsImsSmsSupported() imsSmsCfg_:%{public}d", imsSmsCfg_);
296    isSupported = (imsSmsCfg_ == IMS_SMS_ENABLE);
297    return TELEPHONY_ERR_SUCCESS;
298}
299
300void GsmSmsSender::StatusReportAnalysis(const AppExecFwk::InnerEvent::Pointer &event)
301{
302    if (event == nullptr) {
303        TELEPHONY_LOGE("GsmSmsSender: StatusReportAnalysis event nullptr error.");
304        return;
305    }
306
307    std::shared_ptr<SmsMessageInfo> statusInfo = event->GetSharedObject<SmsMessageInfo>();
308    if (statusInfo == nullptr) {
309        TELEPHONY_LOGE("GsmSmsSender: StatusReportAnalysis statusInfo nullptr error.");
310        return;
311    }
312
313    std::string pdu = StringUtils::StringToHex(statusInfo->pdu);
314    TELEPHONY_LOGI("StatusReport pdu size == %{public}zu", pdu.length());
315    std::shared_ptr<GsmSmsMessage> message = GsmSmsMessage::CreateMessage(pdu);
316    if (message == nullptr) {
317        TELEPHONY_LOGE("GsmSmsSender: StatusReportAnalysis message nullptr error.");
318        return;
319    }
320    sptr<IDeliveryShortMessageCallback> deliveryCallback = nullptr;
321    auto oldIndexer = reportList_.begin();
322    while (oldIndexer != reportList_.end()) {
323        auto iter = oldIndexer++;
324        if (*iter != nullptr && (message->GetMsgRef() == (*iter)->GetMsgRefId())) {
325            // save the message to db, or updata to db msg state(success or failed)
326            TELEPHONY_LOGI("StatusReport %{public}d", message->GetMsgRef());
327            deliveryCallback = (*iter)->GetDeliveryCallback();
328            reportList_.erase(iter);
329        }
330    }
331    auto &satelliteSmsClient = SatelliteSmsClient::GetInstance();
332    if (satelliteSmsClient.GetSatelliteCapability() > 0 && satelliteSmsClient.IsSatelliteEnabled()) {
333        TELEPHONY_LOGI("send sms ack through satellite");
334        satelliteSmsClient.SendSmsAck(slotId_, 0, AckIncomeCause::SMS_ACK_PROCESSED, true);
335    } else {
336        CoreManagerInner::GetInstance().SendSmsAck(slotId_, 0, AckIncomeCause::SMS_ACK_PROCESSED, true, nullptr);
337    }
338    if (deliveryCallback != nullptr) {
339        std::string ackpdu = StringUtils::StringToHex(message->GetRawPdu());
340        deliveryCallback->OnSmsDeliveryResult(StringUtils::ToUtf16(ackpdu));
341    }
342}
343
344void GsmSmsSender::StatusReportSetImsSms(const AppExecFwk::InnerEvent::Pointer &event)
345{
346    if (event == nullptr) {
347        TELEPHONY_LOGE("GsmSmsSender: StatusReportSetImsSms event nullptr error.");
348        return;
349    }
350    std::shared_ptr<RadioResponseInfo> imsResponseInfo = event->GetSharedObject<RadioResponseInfo>();
351
352    if (imsResponseInfo == nullptr) {
353        return;
354    }
355
356    if (imsResponseInfo->error != ErrType::NONE) {
357        imsSmsCfg_ = IMS_SMS_DISABLE;
358    }
359}
360
361void GsmSmsSender::StatusReportGetImsSms(const AppExecFwk::InnerEvent::Pointer &event)
362{
363    if (event == nullptr) {
364        TELEPHONY_LOGE("GsmSmsSender: StatusReportGetImsSms event nullptr error.");
365        return;
366    }
367    std::shared_ptr<int32_t> imsSmsInfo = event->GetSharedObject<int32_t>();
368    if (imsSmsInfo == nullptr) {
369        TELEPHONY_LOGE("GsmSmsSender: StatusReportGetImsSms imsSmsInfo nullptr error.");
370        return;
371    }
372    imsSmsCfg_ = *imsSmsInfo;
373}
374
375void GsmSmsSender::SetSendIndexerInfo(const std::shared_ptr<SmsSendIndexer> &indexer,
376    const std::shared_ptr<struct EncodeInfo> &encodeInfo, unsigned char msgRef8bit)
377{
378    if (encodeInfo == nullptr || indexer == nullptr) {
379        TELEPHONY_LOGE("CreateSendIndexer encodeInfo nullptr");
380        return;
381    }
382
383    std::vector<uint8_t> smca(encodeInfo->smcaData_, encodeInfo->smcaData_ + encodeInfo->smcaLen);
384    std::vector<uint8_t> pdu(encodeInfo->tpduData_, encodeInfo->tpduData_ + encodeInfo->tpduLen);
385    chrono::system_clock::duration timePoint = chrono::system_clock::now().time_since_epoch();
386    int64_t timeStamp = chrono::duration_cast<chrono::seconds>(timePoint).count();
387    indexer->SetTimeStamp(timeStamp);
388    indexer->SetEncodeSmca(std::move(smca));
389    indexer->SetEncodePdu(std::move(pdu));
390    indexer->SetHasMore(encodeInfo->isMore_);
391    TELEPHONY_LOGI("gsm text msgRef8bit = %{public}d", msgRef8bit);
392    indexer->SetMsgRefId(msgRef8bit);
393    indexer->SetNetWorkType(NET_TYPE_GSM);
394}
395
396bool GsmSmsSender::RegisterHandler()
397{
398    auto &satelliteSmsClient = SatelliteSmsClient::GetInstance();
399    if (satelliteSmsClient.GetSatelliteSupported()) {
400        satelliteSmsClient.AddSendHandler(slotId_, std::static_pointer_cast<TelEventHandler>(shared_from_this()));
401    }
402    CoreManagerInner::GetInstance().RegisterCoreNotify(
403        slotId_, shared_from_this(), RadioEvent::RADIO_SMS_STATUS, nullptr);
404
405    return true;
406}
407
408void GsmSmsSender::RegisterSatelliteCallback()
409{
410    auto &satelliteSmsClient = SatelliteSmsClient::GetInstance();
411    if (satelliteSmsClient.GetSatelliteSupported()) {
412        TELEPHONY_LOGI("gsm sender register satellite notify");
413        satelliteCallback_ =
414            std::make_unique<SatelliteSmsCallback>(std::static_pointer_cast<TelEventHandler>(shared_from_this()))
415                .release();
416        satelliteSmsClient.RegisterSmsNotify(slotId_, RadioEvent::RADIO_SMS_STATUS, satelliteCallback_);
417        satelliteSmsClient.RegisterSmsNotify(slotId_, RadioEvent::RADIO_SEND_SMS, satelliteCallback_);
418        satelliteSmsClient.RegisterSmsNotify(slotId_, RadioEvent::RADIO_SEND_SMS_EXPECT_MORE, satelliteCallback_);
419    }
420}
421
422void GsmSmsSender::UnregisterSatelliteCallback()
423{
424    auto &satelliteSmsClient = SatelliteSmsClient::GetInstance();
425    if (satelliteSmsClient.GetSatelliteSupported()) {
426        TELEPHONY_LOGI("gsm sender unregister satellite notify");
427        satelliteCallback_ = nullptr;
428    }
429}
430
431void GsmSmsSender::RegisterImsHandler()
432{
433    if (isImsGsmHandlerRegistered) {
434        return;
435    }
436    auto smsClient = DelayedSingleton<ImsSmsClient>::GetInstance();
437    if (smsClient == nullptr) {
438        TELEPHONY_LOGE("RegisterHandler return, ImsSmsClient is nullptr.");
439        return;
440    }
441
442    smsClient->RegisterImsSmsCallbackHandler(slotId_, shared_from_this());
443    TELEPHONY_LOGE("RegisterHandler  gsm ImsSmsClient successs");
444    isImsGsmHandlerRegistered = true;
445}
446
447void GsmSmsSender::ResendTextDelivery(const std::shared_ptr<SmsSendIndexer> &smsIndexer)
448{
449    if (smsIndexer == nullptr) {
450        TELEPHONY_LOGE("ResendTextDelivery smsIndexer == nullptr");
451        return;
452    }
453    GsmSmsMessage gsmSmsMessage;
454    bool isMore = false;
455    if (!SetPduInfo(smsIndexer, gsmSmsMessage, isMore)) {
456        TELEPHONY_LOGE("SetPduInfo fail.");
457        return;
458    }
459
460    std::shared_ptr<struct EncodeInfo> encodeInfo = nullptr;
461    encodeInfo = gsmSmsMessage.GetSubmitEncodeInfo(smsIndexer->GetSmcaAddr(), isMore);
462    if (encodeInfo == nullptr) {
463        SendResultCallBack(smsIndexer, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
464        TELEPHONY_LOGE("create encodeInfo indexer == nullptr\r\n");
465        return;
466    }
467    SetSendIndexerInfo(smsIndexer, encodeInfo, smsIndexer->GetMsgRefId());
468    std::unique_lock<std::mutex> lock(mutex_);
469    SendSmsToRil(smsIndexer);
470}
471
472void GsmSmsSender::ResendDataDelivery(const std::shared_ptr<SmsSendIndexer> &smsIndexer)
473{
474    if (smsIndexer == nullptr) {
475        TELEPHONY_LOGE("DataBasedSmsDelivery ResendDataDelivery smsIndexer nullptr");
476        return;
477    }
478
479    bool isStatusReport = false;
480    unsigned char msgRef8bit = 0;
481    msgRef8bit = smsIndexer->GetMsgRefId();
482    isStatusReport = (smsIndexer->GetDeliveryCallback() == nullptr) ? false : true;
483
484    GsmSmsMessage gsmSmsMessage;
485    std::shared_ptr<struct SmsTpdu> tpdu = nullptr;
486    tpdu = gsmSmsMessage.CreateDataSubmitSmsTpdu(smsIndexer->GetDestAddr(), smsIndexer->GetSmcaAddr(),
487        smsIndexer->GetDestPort(), smsIndexer->GetData().data(), smsIndexer->GetData().size(), msgRef8bit,
488        smsIndexer->GetDcs(), isStatusReport);
489
490    std::shared_ptr<struct EncodeInfo> encodeInfo = nullptr;
491    encodeInfo = gsmSmsMessage.GetSubmitEncodeInfo(smsIndexer->GetSmcaAddr(), false);
492    if (encodeInfo == nullptr || tpdu == nullptr) {
493        SendResultCallBack(smsIndexer, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
494        TELEPHONY_LOGE("DataBasedSmsDelivery encodeInfo or tpdu nullptr");
495        return;
496    }
497    std::vector<uint8_t> smca(encodeInfo->smcaData_, encodeInfo->smcaData_ + encodeInfo->smcaLen);
498    std::vector<uint8_t> pdu(encodeInfo->tpduData_, encodeInfo->tpduData_ + encodeInfo->tpduLen);
499    std::shared_ptr<uint8_t> unSentCellCount = make_shared<uint8_t>(1);
500    if (unSentCellCount == nullptr) {
501        SendResultCallBack(smsIndexer, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
502        TELEPHONY_LOGE("DataBasedSmsDelivery unSentCellCount nullptr");
503        return;
504    }
505    std::shared_ptr<bool> hasCellFailed = make_shared<bool>(false);
506    if (hasCellFailed == nullptr) {
507        SendResultCallBack(smsIndexer, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
508        TELEPHONY_LOGE("DataBasedSmsDelivery hasCellFailed nullptr");
509        return;
510    }
511    chrono::system_clock::duration timePoint = chrono::system_clock::now().time_since_epoch();
512    int64_t timeStamp = chrono::duration_cast<chrono::seconds>(timePoint).count();
513
514    smsIndexer->SetUnSentCellCount(*unSentCellCount);
515    smsIndexer->SetHasCellFailed(hasCellFailed);
516    smsIndexer->SetEncodeSmca(std::move(smca));
517    smsIndexer->SetEncodePdu(std::move(pdu));
518    smsIndexer->SetHasMore(encodeInfo->isMore_);
519    smsIndexer->SetMsgRefId(msgRef8bit);
520    smsIndexer->SetNetWorkType(NET_TYPE_GSM);
521    smsIndexer->SetTimeStamp(timeStamp);
522    std::unique_lock<std::mutex> lock(mutex_);
523    SendSmsToRil(smsIndexer);
524}
525
526bool GsmSmsSender::SetPduInfo(
527    const std::shared_ptr<SmsSendIndexer> &smsIndexer, GsmSmsMessage &gsmSmsMessage, bool &isMore)
528{
529    bool ret = false;
530    if (smsIndexer == nullptr) {
531        TELEPHONY_LOGE("Indexer is nullptr");
532        return ret;
533    }
534    DataCodingScheme codingType = smsIndexer->GetDcs();
535    std::shared_ptr<struct SmsTpdu> tpdu = nullptr;
536    tpdu = gsmSmsMessage.CreateDefaultSubmitSmsTpdu(smsIndexer->GetDestAddr(), smsIndexer->GetSmcaAddr(),
537        smsIndexer->GetText(), (smsIndexer->GetDeliveryCallback() == nullptr) ? false : true, codingType);
538    if (tpdu == nullptr) {
539        SendResultCallBack(smsIndexer, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
540        TELEPHONY_LOGE("ResendTextDelivery CreateDefaultSubmitSmsTpdu err.");
541        return ret;
542    }
543    (void)memset_s(tpdu->data.submit.userData.data, MAX_USER_DATA_LEN + 1, 0x00, MAX_USER_DATA_LEN + 1);
544    if (smsIndexer->GetText().length() > MAX_USER_DATA_LEN + 1) {
545        TELEPHONY_LOGE("SetPduInfo data length invalid.");
546        return ret;
547    }
548    if (memcpy_s(tpdu->data.submit.userData.data, MAX_USER_DATA_LEN + 1, smsIndexer->GetText().c_str(),
549        smsIndexer->GetText().length()) != EOK) {
550        SendResultCallBack(smsIndexer, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
551        TELEPHONY_LOGE("TextBasedSmsDelivery memcpy_s error.");
552        return ret;
553    }
554    int headerCnt = 0;
555    tpdu->data.submit.userData.length = static_cast<int>(smsIndexer->GetText().length());
556    tpdu->data.submit.userData.data[smsIndexer->GetText().length()] = 0;
557    tpdu->data.submit.msgRef = smsIndexer->GetMsgRefId();
558    if (smsIndexer->GetIsConcat()) {
559        headerCnt += gsmSmsMessage.SetHeaderConcat(headerCnt, smsIndexer->GetSmsConcat());
560    }
561    /* Set User Data Header for Alternate Reply Address */
562    headerCnt += gsmSmsMessage.SetHeaderReply(headerCnt);
563    /* Set User Data Header for National Language Single Shift */
564    headerCnt += gsmSmsMessage.SetHeaderLang(headerCnt, codingType, smsIndexer->GetLangId());
565    tpdu->data.submit.userData.headerCnt = headerCnt;
566    tpdu->data.submit.bHeaderInd = (headerCnt > 0) ? true : false;
567
568    unsigned char totalSeg = smsIndexer->GetSmsConcat().totalSeg;
569    if ((totalSeg > 1) && (smsIndexer->GetSmsConcat().seqNum < totalSeg)) {
570        tpdu->data.submit.bStatusReport = false;
571        isMore = true;
572    } else {
573        tpdu->data.submit.bStatusReport = (smsIndexer->GetDeliveryCallback() == nullptr) ? false : true;
574        isMore = false;
575    }
576    return true;
577}
578} // namespace Telephony
579} // namespace OHOS
580