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 "cdma_sms_sender.h"
17
18 #include <cinttypes>
19
20 #include "cdma_sms_message.h"
21 #include "core_manager_inner.h"
22 #include "radio_event.h"
23 #include "securec.h"
24 #include "sms_hisysevent.h"
25 #include "string_utils.h"
26 #include "telephony_log_wrapper.h"
27
28 namespace OHOS {
29 namespace Telephony {
30 using namespace std;
31 static constexpr uint32_t CDMASMS_MESSAGE_ID_MAX = 65536;
32 static constexpr uint8_t CDMASMS_SEQ_NUM_MAX = 64;
33
CdmaSmsSender(int32_t slotId,function<void (shared_ptr<SmsSendIndexer>)> sendRetryFun)34 CdmaSmsSender::CdmaSmsSender(int32_t slotId, function<void(shared_ptr<SmsSendIndexer>)> sendRetryFun)
35 : SmsSender(slotId, sendRetryFun)
36 {}
37
~CdmaSmsSender()38 CdmaSmsSender::~CdmaSmsSender() {}
39
TextBasedSmsDelivery(const string & desAddr,const string & scAddr,const string & text,const sptr<ISendShortMessageCallback> & sendCallback,const sptr<IDeliveryShortMessageCallback> & deliveryCallback)40 void CdmaSmsSender::TextBasedSmsDelivery(const string &desAddr, const string &scAddr, const string &text,
41 const sptr<ISendShortMessageCallback> &sendCallback,
42 const sptr<IDeliveryShortMessageCallback> &deliveryCallback)
43 {
44 if (isImsNetDomain_ && imsSmsCfg_) {
45 TextBasedSmsDeliveryViaIms(desAddr, scAddr, text, sendCallback, deliveryCallback);
46 return;
47 }
48 CdmaSmsMessage message;
49 DataCodingScheme codingType;
50 std::vector<struct SplitInfo> splits;
51 std::string addr;
52 message.SplitMessage(splits, text, CheckForce7BitEncodeType(), codingType, false, addr);
53 if (splits.size() > MAX_SEGMENT_NUM) {
54 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
55 TELEPHONY_LOGE("message exceed the limit.");
56 SmsHiSysEvent::WriteSmsSendFaultEvent(slotId_, SmsMmsMessageType::SMS_SHORT_MESSAGE,
57 SmsMmsErrorCode::SMS_ERROR_EXCEED_MAX_SEGMENT_NUM, "text sms cdma message exceed the limit");
58 return;
59 }
60 bool bStatusReport = (deliveryCallback == nullptr) ? false : true;
61 std::unique_ptr<CdmaTransportMsg> transMsg =
62 message.CreateSubmitTransMsg(desAddr, scAddr, text, bStatusReport, codingType);
63 if (transMsg == nullptr) {
64 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
65 TELEPHONY_LOGE("CreateSubmitTransMsg nullptr fail.");
66 return;
67 }
68 /* 1. Set Reply sequence number. */
69 uint8_t msgRef8bit = GetSeqNum();
70 transMsg->data.p2p.replySeq = msgRef8bit;
71 /* 2. Set msg ID. */
72 uint16_t msgId = GetSubmitMsgId();
73 transMsg->data.p2p.telesvcMsg.data.submit.msgId.msgId = msgId;
74 chrono::system_clock::duration timePoint = chrono::system_clock::now().time_since_epoch();
75 long timeStamp = chrono::duration_cast<chrono::seconds>(timePoint).count();
76 TextBasedSmsSplitDelivery(
77 desAddr, scAddr, splits, std::move(transMsg), msgRef8bit, msgId, timeStamp, sendCallback, deliveryCallback);
78 }
79
TextBasedSmsSplitDelivery(const std::string & desAddr,const std::string & scAddr,std::vector<struct SplitInfo> splits,std::unique_ptr<CdmaTransportMsg> transMsg,uint8_t msgRef8bit,uint16_t msgId,long timeStamp,const sptr<ISendShortMessageCallback> & sendCallback,const sptr<IDeliveryShortMessageCallback> & deliveryCallback)80 void CdmaSmsSender::TextBasedSmsSplitDelivery(const std::string &desAddr, const std::string &scAddr,
81 std::vector<struct SplitInfo> splits, std::unique_ptr<CdmaTransportMsg> transMsg, uint8_t msgRef8bit,
82 uint16_t msgId, long timeStamp, const sptr<ISendShortMessageCallback> &sendCallback,
83 const sptr<IDeliveryShortMessageCallback> &deliveryCallback)
84 {
85 shared_ptr<bool> hasCellFailed = make_shared<bool>(false);
86 if (hasCellFailed == nullptr) {
87 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
88 return;
89 }
90 for (std::size_t i = 0; i < splits.size(); i++) {
91 (void)memset_s(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data,
92 sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data), 0x00,
93 sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data));
94 if (splits[i].encodeData.size() > sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data)) {
95 TELEPHONY_LOGE("data length invalid");
96 return;
97 }
98 int value = memcpy_s(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data,
99 sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data), splits[i].encodeData.data(),
100 splits[i].encodeData.size());
101 if (value != EOK) {
102 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
103 return;
104 }
105 std::string segmentText;
106 segmentText.append((char *)(splits[i].encodeData.data()), splits[i].encodeData.size());
107 auto indexer = make_shared<SmsSendIndexer>(desAddr, scAddr, segmentText, sendCallback, deliveryCallback);
108 if (indexer == nullptr) {
109 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
110 return;
111 }
112 indexer->SetDcs(splits[i].encodeType);
113 SetPduSeqInfo(indexer, splits.size(), transMsg, i, msgRef8bit);
114 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.length =
115 static_cast<int>(splits[i].encodeData.size());
116 /* encode msg data */
117 std::unique_ptr<std::vector<uint8_t>> pdu = EncodeMsg(*transMsg.get());
118 if (pdu == nullptr) {
119 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
120 return;
121 }
122 indexer->SetEncodePdu(*pdu);
123 indexer->SetMsgRefId(msgRef8bit);
124 indexer->SetNetWorkType(NET_TYPE_CDMA);
125 indexer->SetUnSentCellCount(splits.size());
126 indexer->SetHasCellFailed(hasCellFailed);
127 indexer->SetTimeStamp(timeStamp);
128 indexer->SetMsgId(msgId);
129 SendSmsToRil(indexer);
130 }
131 }
132
TextBasedSmsDeliveryViaIms(const string & desAddr,const string & scAddr,const string & text,const sptr<ISendShortMessageCallback> & sendCallback,const sptr<IDeliveryShortMessageCallback> & deliveryCallback)133 void CdmaSmsSender::TextBasedSmsDeliveryViaIms(const string &desAddr, const string &scAddr, const string &text,
134 const sptr<ISendShortMessageCallback> &sendCallback, const sptr<IDeliveryShortMessageCallback> &deliveryCallback)
135 {
136 DataCodingScheme codingType;
137 GsmSmsMessage gsmSmsMessage;
138 std::vector<struct SplitInfo> cellsInfos;
139 gsmSmsMessage.SetSmsCodingNationalType(GetSmsCodingNationalType(slotId_));
140 std::string addr;
141 gsmSmsMessage.SplitMessage(cellsInfos, text, CheckForce7BitEncodeType(), codingType, false, addr);
142 bool isStatusReport = (deliveryCallback == nullptr) ? false : true;
143 std::shared_ptr<struct SmsTpdu> tpdu =
144 gsmSmsMessage.CreateDefaultSubmitSmsTpdu(desAddr, scAddr, text, isStatusReport, codingType);
145 int cellsInfosSize = static_cast<int>(cellsInfos.size());
146 shared_ptr<uint8_t> unSentCellCount = make_shared<uint8_t>(cellsInfosSize);
147 shared_ptr<bool> hasCellFailed = make_shared<bool>(false);
148 if (TpduNullOrSmsPageOverNormalOrSmsEncodeFail(cellsInfos, tpdu, unSentCellCount, hasCellFailed, sendCallback)) {
149 return;
150 }
151
152 std::unique_lock<std::mutex> lock(mutex_);
153 uint8_t msgRef8bit = GetMsgRef8Bit();
154 TELEPHONY_LOGI("cdma text msgRef8bit = %{public}d", msgRef8bit);
155 for (int i = 0; i < cellsInfosSize; i++) {
156 SendSmsForEveryIndexer(i, cellsInfos, desAddr, scAddr, tpdu, gsmSmsMessage, unSentCellCount, hasCellFailed,
157 codingType, msgRef8bit, sendCallback, deliveryCallback);
158 }
159 return;
160 }
161
SendSmsForEveryIndexer(int & i,std::vector<struct SplitInfo> cellsInfos,const string & desAddr,const string & scAddr,std::shared_ptr<struct SmsTpdu> tpdu,GsmSmsMessage gsmSmsMessage,shared_ptr<uint8_t> unSentCellCount,shared_ptr<bool> hasCellFailed,DataCodingScheme codingType,uint8_t msgRef8bit,const sptr<ISendShortMessageCallback> & sendCallback,const sptr<IDeliveryShortMessageCallback> & deliveryCallback)162 void CdmaSmsSender::SendSmsForEveryIndexer(int &i, std::vector<struct SplitInfo> cellsInfos, const string &desAddr,
163 const string &scAddr, std::shared_ptr<struct SmsTpdu> tpdu, GsmSmsMessage gsmSmsMessage,
164 shared_ptr<uint8_t> unSentCellCount, shared_ptr<bool> hasCellFailed, DataCodingScheme codingType,
165 uint8_t msgRef8bit, const sptr<ISendShortMessageCallback> &sendCallback,
166 const sptr<IDeliveryShortMessageCallback> &deliveryCallback)
167 {
168 std::string segmentText;
169 segmentText.append((char *)(cellsInfos[i].encodeData.data()), cellsInfos[i].encodeData.size());
170 std::shared_ptr<SmsSendIndexer> indexer =
171 make_shared<SmsSendIndexer>(desAddr, scAddr, segmentText, sendCallback, deliveryCallback);
172 if (indexer == nullptr) {
173 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
174 return;
175 }
176 indexer->SetDcs(cellsInfos[i].encodeType);
177 (void)memset_s(tpdu->data.submit.userData.data, MAX_USER_DATA_LEN + 1, 0x00, MAX_USER_DATA_LEN + 1);
178
179 if (cellsInfos[i].encodeData.size() > MAX_USER_DATA_LEN + 1) {
180 return;
181 }
182 if (memcpy_s(tpdu->data.submit.userData.data, MAX_USER_DATA_LEN + 1, &cellsInfos[i].encodeData[0],
183 cellsInfos[i].encodeData.size()) != EOK) {
184 SendResultCallBack(indexer, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
185 return;
186 }
187
188 tpdu->data.submit.userData.length = cellsInfos[i].encodeData.size();
189 tpdu->data.submit.userData.data[cellsInfos[i].encodeData.size()] = 0;
190 tpdu->data.submit.msgRef = msgRef8bit;
191 int headerCnt = 0;
192 bool isMore = false;
193 bool isStatusReport = false;
194 isStatusReport = (deliveryCallback == nullptr) ? false : true;
195
196 int cellsInfosSize = static_cast<int>(cellsInfos.size());
197 if (cellsInfosSize > 1) {
198 indexer->SetIsConcat(true);
199 SmsConcat concat;
200 concat.is8Bits = true;
201 concat.msgRef = msgRef8bit;
202 concat.totalSeg = static_cast<uint16_t>(cellsInfosSize);
203 concat.seqNum = static_cast<uint16_t>(i + 1);
204 indexer->SetSmsConcat(concat);
205 headerCnt += gsmSmsMessage.SetHeaderConcat(headerCnt, concat);
206 }
207
208 /* Set User Data Header for Alternate Reply Address */
209 headerCnt += gsmSmsMessage.SetHeaderReply(headerCnt);
210 /* Set User Data Header for National Language Single Shift */
211 headerCnt += gsmSmsMessage.SetHeaderLang(headerCnt, codingType, cellsInfos[i].langId);
212 indexer->SetLangId(cellsInfos[i].langId);
213 tpdu->data.submit.userData.headerCnt = headerCnt;
214 tpdu->data.submit.bHeaderInd = (headerCnt > 0) ? true : false;
215
216 if (cellsInfosSize > 1 && i < (cellsInfosSize - 1)) {
217 tpdu->data.submit.bStatusReport = false;
218 isMore = true;
219 } else {
220 tpdu->data.submit.bStatusReport = isStatusReport;
221 }
222 ReadySendSms(gsmSmsMessage, scAddr, isMore, indexer, msgRef8bit, unSentCellCount, hasCellFailed);
223 }
224
ReadySendSms(GsmSmsMessage gsmSmsMessage,const string & scAddr,bool isMore,std::shared_ptr<SmsSendIndexer> indexer,uint8_t msgRef8bit,shared_ptr<uint8_t> unSentCellCount,shared_ptr<bool> hasCellFailed)225 void CdmaSmsSender::ReadySendSms(GsmSmsMessage gsmSmsMessage, const string &scAddr, bool isMore,
226 std::shared_ptr<SmsSendIndexer> indexer, uint8_t msgRef8bit, shared_ptr<uint8_t> unSentCellCount,
227 shared_ptr<bool> hasCellFailed)
228 {
229 std::shared_ptr<struct EncodeInfo> encodeInfo = gsmSmsMessage.GetSubmitEncodeInfo(scAddr, isMore);
230 if (encodeInfo == nullptr) {
231 SendResultCallBack(indexer, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
232 TELEPHONY_LOGE("create encodeInfo encodeInfo nullptr error.");
233 return;
234 }
235
236 SetSendIndexerInfo(indexer, encodeInfo, msgRef8bit);
237 indexer->SetUnSentCellCount(*unSentCellCount);
238 indexer->SetHasCellFailed(hasCellFailed);
239 indexer->SetImsSmsForCdma(true);
240 SendSmsToRil(indexer);
241 }
242
TpduNullOrSmsPageOverNormalOrSmsEncodeFail(std::vector<struct SplitInfo> cellsInfos,std::shared_ptr<struct SmsTpdu> tpdu,shared_ptr<uint8_t> unSentCellCount,shared_ptr<bool> hasCellFailed,const sptr<ISendShortMessageCallback> & sendCallback)243 bool CdmaSmsSender::TpduNullOrSmsPageOverNormalOrSmsEncodeFail(std::vector<struct SplitInfo> cellsInfos,
244 std::shared_ptr<struct SmsTpdu> tpdu, shared_ptr<uint8_t> unSentCellCount, shared_ptr<bool> hasCellFailed,
245 const sptr<ISendShortMessageCallback> &sendCallback)
246 {
247 if (tpdu == nullptr) {
248 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
249 TELEPHONY_LOGE("TextBasedSmsDelivery tpdu nullptr error.");
250 return true;
251 }
252
253 int cellsInfosSize = static_cast<int>(cellsInfos.size());
254 if (cellsInfosSize > MAX_SEGMENT_NUM) {
255 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
256 TELEPHONY_LOGE("message exceed the limit.");
257 return true;
258 }
259
260 bool isStatusReport = tpdu->data.submit.bStatusReport;
261 TELEPHONY_LOGI("TextBasedSmsDelivery isStatusReport= %{public}d", isStatusReport);
262 if (unSentCellCount == nullptr || hasCellFailed == nullptr) {
263 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
264 return true;
265 }
266 return false;
267 }
268
SetSendIndexerInfo(const std::shared_ptr<SmsSendIndexer> & indexer,const std::shared_ptr<struct EncodeInfo> & encodeInfo,uint8_t msgRef8bit)269 void CdmaSmsSender::SetSendIndexerInfo(const std::shared_ptr<SmsSendIndexer> &indexer,
270 const std::shared_ptr<struct EncodeInfo> &encodeInfo, uint8_t msgRef8bit)
271 {
272 if (encodeInfo == nullptr || indexer == nullptr) {
273 TELEPHONY_LOGE("CdmaSmsSender::SetSendIndexerInfo encodeInfo nullptr");
274 return;
275 }
276
277 std::vector<uint8_t> smca(encodeInfo->smcaData_, encodeInfo->smcaData_ + encodeInfo->smcaLen);
278 std::vector<uint8_t> pdu(encodeInfo->tpduData_, encodeInfo->tpduData_ + encodeInfo->tpduLen);
279 chrono::system_clock::duration timePoint = chrono::system_clock::now().time_since_epoch();
280 long timeStamp = chrono::duration_cast<chrono::seconds>(timePoint).count();
281 indexer->SetTimeStamp(timeStamp);
282 indexer->SetEncodeSmca(std::move(smca));
283 indexer->SetEncodePdu(std::move(pdu));
284 indexer->SetHasMore(encodeInfo->isMore_);
285 indexer->SetMsgRefId(msgRef8bit);
286 indexer->SetNetWorkType(NET_TYPE_CDMA);
287 }
288
SetPduSeqInfo(const std::shared_ptr<SmsSendIndexer> & smsIndexer,const std::size_t size,const std::unique_ptr<CdmaTransportMsg> & transMsg,const std::size_t index,const uint8_t msgRef8bit)289 void CdmaSmsSender::SetPduSeqInfo(const std::shared_ptr<SmsSendIndexer> &smsIndexer, const std::size_t size,
290 const std::unique_ptr<CdmaTransportMsg> &transMsg, const std::size_t index, const uint8_t msgRef8bit)
291 {
292 if (size > 1) {
293 smsIndexer->SetIsConcat(true);
294 SmsConcat smsConcat;
295 transMsg->data.p2p.teleserviceId = static_cast<uint16_t>(SmsTransTelsvcId::WEMT);
296 transMsg->data.p2p.telesvcMsg.data.submit.msgId.headerInd = true;
297 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.headerCnt = 1;
298 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udhType = UDH_CONCAT_8BIT;
299 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udh.concat8bit.msgRef = msgRef8bit;
300 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udh.concat8bit.totalSeg =
301 static_cast<uint8_t>(size);
302 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udh.concat8bit.seqNum = index + 1;
303 smsConcat.msgRef = msgRef8bit;
304 smsConcat.seqNum = index + 1;
305 smsConcat.totalSeg = static_cast<uint8_t>(size);
306 smsConcat.is8Bits = true;
307 smsIndexer->SetSmsConcat(smsConcat);
308 }
309 }
310
DataBasedSmsDelivery(const string & desAddr,const string & scAddr,int32_t port,const uint8_t * data,uint32_t dataLen,const sptr<ISendShortMessageCallback> & sendCallback,const sptr<IDeliveryShortMessageCallback> & deliveryCallback)311 void CdmaSmsSender::DataBasedSmsDelivery(const string &desAddr, const string &scAddr, int32_t port, const uint8_t *data,
312 uint32_t dataLen, const sptr<ISendShortMessageCallback> &sendCallback,
313 const sptr<IDeliveryShortMessageCallback> &deliveryCallback)
314 {
315 if (isImsNetDomain_ && imsSmsCfg_) {
316 DataBasedSmsDeliveryViaIms(desAddr, scAddr, port, data, dataLen, sendCallback, deliveryCallback);
317 return;
318 }
319 CdmaSmsMessage message;
320 DataCodingScheme codingType;
321 std::vector<struct SplitInfo> splits;
322 std::string text((char *)data, dataLen);
323 std::string addr;
324 message.SplitMessage(splits, text, false, codingType, true, addr);
325 if (splits.size() == 0) {
326 TELEPHONY_LOGE("splits fail.");
327 return;
328 }
329 std::unique_ptr<CdmaTransportMsg> transMsg = nullptr;
330 bool bStatusReport = (deliveryCallback == nullptr) ? false : true;
331 transMsg = message.CreateSubmitTransMsg(desAddr, scAddr, port, data, dataLen, bStatusReport);
332 if (transMsg == nullptr) {
333 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
334 TELEPHONY_LOGE("CreateSubmitTransMsg nullptr fail.");
335 return;
336 }
337 /* Set Reply sequence number. */
338 uint8_t msgRef8bit = GetSeqNum();
339 transMsg->data.p2p.replySeq = msgRef8bit;
340 /* Set msg ID. */
341 uint16_t msgId = GetSubmitMsgId();
342 transMsg->data.p2p.telesvcMsg.data.submit.msgId.msgId = msgId;
343 /* while user data header isn't exist, headerInd must be set false. */
344 transMsg->data.p2p.telesvcMsg.data.submit.msgId.headerInd = true;
345 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.length = static_cast<int>(splits[0].encodeData.size());
346 if (splits[0].encodeData.size() > sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data)) {
347 TELEPHONY_LOGE("DataBasedSmsDelivery data length invalid.");
348 return;
349 }
350 if (memcpy_s(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data,
351 sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data), splits[0].encodeData.data(),
352 splits[0].encodeData.size()) != EOK) {
353 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
354 TELEPHONY_LOGE("memcpy_s return error.");
355 return;
356 }
357 std::shared_ptr<SmsSendIndexer> indexer = make_shared<SmsSendIndexer>(desAddr, scAddr, port,
358 splits[0].encodeData.data(), splits[0].encodeData.size(), sendCallback, deliveryCallback);
359 EncodeMsgData(std::move(transMsg), indexer, msgRef8bit, sendCallback);
360 }
361
EncodeMsgData(std::unique_ptr<CdmaTransportMsg> transMsg,std::shared_ptr<SmsSendIndexer> indexer,uint8_t msgRef8bit,const sptr<ISendShortMessageCallback> & sendCallback)362 void CdmaSmsSender::EncodeMsgData(std::unique_ptr<CdmaTransportMsg> transMsg, std::shared_ptr<SmsSendIndexer> indexer,
363 uint8_t msgRef8bit, const sptr<ISendShortMessageCallback> &sendCallback)
364 {
365 /* encode msg data */
366 SmsWriteBuffer pduBuffer;
367 std::unique_ptr<CdmaSmsTransportMessage> msg = CdmaSmsTransportMessage::CreateTransportMessage(*transMsg.get());
368 if (msg == nullptr || msg->IsEmpty() || !msg->Encode(pduBuffer)) {
369 TELEPHONY_LOGE("EncodeMsg Error");
370 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
371 SmsHiSysEvent::WriteSmsSendFaultEvent(slotId_, SmsMmsMessageType::SMS_SHORT_MESSAGE,
372 SmsMmsErrorCode::SMS_ERROR_PDU_ENCODEING_FAIL, "cdma encode msg error");
373 return;
374 }
375
376 const uint8_t segmentCount = 1;
377 shared_ptr<uint8_t> unSentCellCount = make_shared<uint8_t>(segmentCount);
378 shared_ptr<bool> hasCellFailed = make_shared<bool>(false);
379 std::unique_ptr<std::vector<uint8_t>> pdu = pduBuffer.GetPduBuffer();
380 if (indexer == nullptr || unSentCellCount == nullptr || hasCellFailed == nullptr || pdu == nullptr) {
381 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
382 TELEPHONY_LOGE("Init SmsSend Indexer Error.");
383 return;
384 }
385 indexer->SetEncodePdu(*pdu);
386 indexer->SetMsgRefId(msgRef8bit);
387 indexer->SetNetWorkType(NET_TYPE_CDMA);
388 indexer->SetUnSentCellCount(*unSentCellCount);
389 indexer->SetHasCellFailed(hasCellFailed);
390 chrono::system_clock::duration timePoint = chrono::system_clock::now().time_since_epoch();
391 long timeStamp = chrono::duration_cast<chrono::seconds>(timePoint).count();
392 indexer->SetTimeStamp(timeStamp);
393 uint16_t msgId = GetSubmitMsgId();
394 indexer->SetMsgId(msgId);
395 SendSmsToRil(indexer);
396 }
397
DataBasedSmsDeliveryViaIms(const string & desAddr,const string & scAddr,int32_t port,const uint8_t * data,uint32_t dataLen,const sptr<ISendShortMessageCallback> & sendCallback,const sptr<IDeliveryShortMessageCallback> & deliveryCallback)398 void CdmaSmsSender::DataBasedSmsDeliveryViaIms(const string &desAddr, const string &scAddr, int32_t port,
399 const uint8_t *data, uint32_t dataLen, const sptr<ISendShortMessageCallback> &sendCallback,
400 const sptr<IDeliveryShortMessageCallback> &deliveryCallback)
401 {
402 GsmSmsMessage gsmSmsMessage;
403 std::vector<struct SplitInfo> cellsInfos;
404 DataCodingScheme codingType;
405 std::string dataStr;
406 CharArrayToString(data, dataLen, dataStr);
407 gsmSmsMessage.SetSmsCodingNationalType(GetSmsCodingNationalType(slotId_));
408 gsmSmsMessage.SplitMessage(cellsInfos, dataStr, CheckForce7BitEncodeType(), codingType, true, desAddr);
409 uint8_t msgRef8bit = GetMsgRef8Bit();
410 TELEPHONY_LOGI("cdma data msgRef8bit = %{public}d", msgRef8bit);
411 std::shared_ptr<struct SmsTpdu> tpdu = gsmSmsMessage.CreateDataSubmitSmsTpdu(
412 desAddr, scAddr, port, data, dataLen, msgRef8bit, codingType, (deliveryCallback == nullptr) ? false : true);
413 if (tpdu == nullptr) {
414 SendResultCallBack(sendCallback, ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
415 TELEPHONY_LOGE("tpdu nullptr error.");
416 return;
417 }
418 DataBasedSmsDeliverySplitPage(
419 gsmSmsMessage, cellsInfos, tpdu, msgRef8bit, desAddr, scAddr, port, sendCallback, deliveryCallback);
420 }
421
StatusReportAnalysis(const AppExecFwk::InnerEvent::Pointer & event)422 void CdmaSmsSender::StatusReportAnalysis(const AppExecFwk::InnerEvent::Pointer &event)
423 {
424 if (event == nullptr) {
425 TELEPHONY_LOGE("cdma_sms_sender: StatusReportAnalysis event nullptr error.");
426 return;
427 }
428 std::shared_ptr<SmsReceiveIndexer> statusInfo = event->GetSharedObject<SmsReceiveIndexer>();
429 if (statusInfo == nullptr) {
430 TELEPHONY_LOGE("cdma_sms_sender: StatusReportAnalysis statusInfo nullptr error.");
431 return;
432 }
433 std::string pdu = StringUtils::StringToHex(statusInfo->GetPdu());
434 std::shared_ptr<CdmaSmsMessage> message = CdmaSmsMessage::CreateMessage(pdu);
435 if (message == nullptr) {
436 TELEPHONY_LOGE("message is nullptr.");
437 return;
438 }
439 sptr<IDeliveryShortMessageCallback> deliveryCallback = nullptr;
440 auto oldIndexer = reportList_.begin();
441 while (oldIndexer != reportList_.end()) {
442 auto iter = oldIndexer++;
443 if (*iter != nullptr) {
444 if (message->GetMsgRef() == (*iter)->GetMsgRefId()) {
445 // save the message to db, or updata to db msg state(success or fail)
446 deliveryCallback = (*iter)->GetDeliveryCallback();
447 reportList_.erase(iter);
448 }
449 }
450 }
451 if (deliveryCallback != nullptr) {
452 std::string ackpdu = StringUtils::StringToHex(message->GetRawPdu());
453 deliveryCallback->OnSmsDeliveryResult(StringUtils::ToUtf16(ackpdu));
454 TELEPHONY_LOGI("gsm_sms_sender: StatusReportAnalysis %{private}s", pdu.c_str());
455 }
456 }
457
SendSmsToRil(const shared_ptr<SmsSendIndexer> & smsIndexer)458 void CdmaSmsSender::SendSmsToRil(const shared_ptr<SmsSendIndexer> &smsIndexer)
459 {
460 if (smsIndexer == nullptr) {
461 TELEPHONY_LOGE("cdma_sms_sender: SendSms smsIndexer nullptr");
462 return;
463 }
464 if ((!isImsNetDomain_ && voiceServiceState_ != static_cast<int32_t>(RegServiceState::REG_STATE_IN_SERVICE))) {
465 SendResultCallBack(smsIndexer, ISendShortMessageCallback::SEND_SMS_FAILURE_SERVICE_UNAVAILABLE);
466 TELEPHONY_LOGE("cdma_sms_sender: SendSms not in service");
467 SmsHiSysEvent::WriteSmsSendFaultEvent(slotId_, SmsMmsMessageType::SMS_SHORT_MESSAGE,
468 SmsMmsErrorCode::SMS_ERROR_SENDSMS_NOT_IN_SERVICE, "cdma send sms not in service");
469 return;
470 }
471 int64_t refId = GetMsgRef64Bit();
472 TELEPHONY_LOGI("cdma refId = %{public}" PRId64 "", refId);
473 if (!SendCacheMapAddItem(refId, smsIndexer)) {
474 TELEPHONY_LOGE("SendCacheMapAddItem Error!!");
475 }
476
477 std::string pdu = StringUtils::StringToHex(smsIndexer->GetEncodePdu());
478 bool sendImsSMS = smsIndexer->IsImsSmsForCdma();
479 if (smsIndexer->GetPsResendCount() < MAX_SEND_RETRIES) {
480 sendImsSMS = true;
481 }
482
483 if (sendImsSMS) {
484 SendImsSms(smsIndexer, refId, pdu);
485 } else {
486 SendCsSms(smsIndexer, refId, pdu);
487 }
488 }
489
SendCsSms(const shared_ptr<SmsSendIndexer> & smsIndexer,int64_t & refId,std::string & pdu)490 void CdmaSmsSender::SendCsSms(const shared_ptr<SmsSendIndexer> &smsIndexer, int64_t &refId, std::string &pdu)
491 {
492 lastSmsDomain_ = CS_DOMAIN;
493 CoreManagerInner::GetInstance().SendCdmaSms(
494 slotId_, RadioEvent::RADIO_SEND_CDMA_SMS, pdu, refId, shared_from_this());
495 TELEPHONY_LOGI("SendCsSms pdu = %{private}s", pdu.c_str());
496 }
497
SendImsSms(const shared_ptr<SmsSendIndexer> & smsIndexer,int64_t & refId,std::string & pdu)498 void CdmaSmsSender::SendImsSms(const shared_ptr<SmsSendIndexer> &smsIndexer, int64_t &refId, std::string &pdu)
499 {
500 TELEPHONY_LOGI("ims network domain send sms interface.!");
501 auto smsClient = DelayedSingleton<ImsSmsClient>::GetInstance();
502 if (smsClient == nullptr) {
503 TELEPHONY_LOGE("SendImsSms return, ImsSmsClient is nullptr.");
504 return;
505 }
506 lastSmsDomain_ = IMS_DOMAIN;
507 ImsMessageInfo imsMessageInfo;
508 imsMessageInfo.refId = refId;
509 imsMessageInfo.smscPdu = "";
510 imsMessageInfo.pdu = pdu;
511 imsMessageInfo.tech = SMS_RADIO_TECH_3GPP;
512 int32_t reply = smsClient->ImsSendMessage(slotId_, imsMessageInfo);
513 TELEPHONY_LOGI("SendImsSms reply = %{public}d", reply);
514 }
515
IsImsSmsSupported(int32_t slotId,bool & isSupported)516 int32_t CdmaSmsSender::IsImsSmsSupported(int32_t slotId, bool &isSupported)
517 {
518 auto smsClient = DelayedSingleton<ImsSmsClient>::GetInstance();
519 if (smsClient == nullptr) {
520 TELEPHONY_LOGE("IsImsSmsSupported return, ImsSmsClient is nullptr.");
521 return TELEPHONY_ERR_LOCAL_PTR_NULL;
522 }
523 std::unique_lock<std::mutex> lck(ctx_);
524 resIsSmsReady_ = false;
525 int32_t reply = smsClient->ImsGetSmsConfig(slotId);
526 TELEPHONY_LOGI("IsImsSmsSupported reply = %{public}d", reply);
527 while (resIsSmsReady_) {
528 TELEPHONY_LOGI("IsImsSmsSupported::wait(), resIsSmsReady_ = false");
529 if (cv_.wait_for(lck, std::chrono::seconds(WAIT_TIME_SECOND)) == std::cv_status::timeout) {
530 break;
531 }
532 }
533 TELEPHONY_LOGI("CdmaSmsSender::IsImsSmsSupported(), imsSmsCfg_:%{public}d", imsSmsCfg_);
534 isSupported = (imsSmsCfg_ == IMS_SMS_ENABLE);
535 return TELEPHONY_ERR_SUCCESS;
536 }
537
StatusReportSetImsSms(const AppExecFwk::InnerEvent::Pointer & event)538 void CdmaSmsSender::StatusReportSetImsSms(const AppExecFwk::InnerEvent::Pointer &event)
539 {
540 if (event == nullptr) {
541 TELEPHONY_LOGE("cdma_sms_sender: StatusReportSetImsSms event nullptr error.");
542 return;
543 }
544 std::shared_ptr<RadioResponseInfo> imsResponseInfo = event->GetSharedObject<RadioResponseInfo>();
545
546 if (imsResponseInfo->error != ErrType::NONE) {
547 imsSmsCfg_ = IMS_SMS_DISABLE;
548 }
549 }
550
StatusReportGetImsSms(const AppExecFwk::InnerEvent::Pointer & event)551 void CdmaSmsSender::StatusReportGetImsSms(const AppExecFwk::InnerEvent::Pointer &event)
552 {
553 if (event == nullptr) {
554 TELEPHONY_LOGE("CdmaSmsSender: StatusReportGetImsSms event nullptr error.");
555 return;
556 }
557 std::shared_ptr<int32_t> imsSmsInfo = event->GetSharedObject<int32_t>();
558 if (imsSmsInfo == nullptr) {
559 TELEPHONY_LOGE("CdmaSmsSender: StatusReportGetImsSms imsSmsInfo nullptr error.");
560 return;
561 }
562 imsSmsCfg_ = *imsSmsInfo;
563 }
564
Init()565 void CdmaSmsSender::Init() {}
566
ReceiveStatusReport(const std::shared_ptr<SmsReceiveIndexer> & smsIndexer)567 void CdmaSmsSender::ReceiveStatusReport(const std::shared_ptr<SmsReceiveIndexer> &smsIndexer)
568 {
569 SendEvent(RadioEvent::RADIO_SMS_STATUS, smsIndexer);
570 }
571
RegisterImsHandler()572 void CdmaSmsSender::RegisterImsHandler()
573 {
574 if (isImsCdmaHandlerRegistered) {
575 return;
576 }
577 auto smsClient = DelayedSingleton<ImsSmsClient>::GetInstance();
578 if (smsClient == nullptr) {
579 TELEPHONY_LOGE("RegisterHandler return, ImsSmsClient is nullptr.");
580 return;
581 }
582 smsClient->RegisterImsSmsCallbackHandler(slotId_, shared_from_this());
583 TELEPHONY_LOGE("RegisterHandler gsm ImsSmsClient successs");
584 isImsCdmaHandlerRegistered = true;
585 }
586
GetSeqNum()587 uint8_t CdmaSmsSender::GetSeqNum()
588 {
589 msgSeqNum_ = ((msgSeqNum_ + 1) % CDMASMS_SEQ_NUM_MAX);
590 return msgSeqNum_;
591 }
592
GetSubmitMsgId()593 uint8_t CdmaSmsSender::GetSubmitMsgId()
594 {
595 msgSubmitId_ = ((msgSubmitId_ + 1) % CDMASMS_MESSAGE_ID_MAX);
596 return msgSubmitId_;
597 }
598
EncodeMsg(CdmaTransportMsg & transMsg)599 std::unique_ptr<std::vector<uint8_t>> CdmaSmsSender::EncodeMsg(CdmaTransportMsg &transMsg)
600 {
601 std::unique_ptr<CdmaSmsTransportMessage> msg = CdmaSmsTransportMessage::CreateTransportMessage(transMsg);
602 SmsWriteBuffer pduBuffer;
603 if (msg == nullptr || msg->IsEmpty() || !msg->Encode(pduBuffer)) {
604 TELEPHONY_LOGE("encode msg error");
605 return nullptr;
606 }
607 return pduBuffer.GetPduBuffer();
608 }
609
ResendTextDelivery(const std::shared_ptr<SmsSendIndexer> & smsIndexer)610 void CdmaSmsSender::ResendTextDelivery(const std::shared_ptr<SmsSendIndexer> &smsIndexer)
611 {
612 if (smsIndexer == nullptr) {
613 TELEPHONY_LOGE("smsIndexer is nullptr!!");
614 return;
615 }
616 CdmaSmsMessage message;
617 DataCodingScheme codingType = smsIndexer->GetDcs();
618 std::unique_ptr<CdmaTransportMsg> transMsg = nullptr;
619 bool bStatusReport = (smsIndexer->GetDeliveryCallback() == nullptr) ? false : true;
620 transMsg = message.CreateSubmitTransMsg(
621 smsIndexer->GetDestAddr(), smsIndexer->GetSmcaAddr(), smsIndexer->GetText(), bStatusReport, codingType);
622 if (transMsg == nullptr) {
623 SendResultCallBack(smsIndexer->GetSendCallback(), ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
624 TELEPHONY_LOGE("CreateSubmitTransMsg nullptr fail.");
625 return;
626 }
627 /* 1. Set Reply sequence number. */
628 uint8_t msgRef8bit = smsIndexer->GetMsgRefId();
629 transMsg->data.p2p.replySeq = msgRef8bit;
630 /* 2. Set msg ID. */
631 transMsg->data.p2p.telesvcMsg.data.submit.msgId.msgId = smsIndexer->GetMsgId();
632 chrono::system_clock::duration timePoint = chrono::system_clock::now().time_since_epoch();
633 long timeStamp = chrono::duration_cast<chrono::seconds>(timePoint).count();
634 smsIndexer->SetTimeStamp(timeStamp);
635 transMsg->data.p2p.telesvcMsg.data.submit.userData.encodeType = SmsEncodingType::OCTET;
636 (void)memset_s(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data,
637 sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data), 0x00,
638 sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data));
639 if (smsIndexer->GetText().length() > sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data)) {
640 TELEPHONY_LOGE("ResendTextDelivery data length invalid.");
641 return;
642 }
643 if (memcpy_s(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data,
644 sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data), smsIndexer->GetText().data(),
645 smsIndexer->GetText().length()) != EOK) {
646 SendResultCallBack(smsIndexer->GetSendCallback(), ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
647 return;
648 }
649 SetConcact(smsIndexer, transMsg);
650 /* encode msg data */
651 std::unique_ptr<std::vector<uint8_t>> pdu = EncodeMsg(*transMsg.get());
652 if (pdu == nullptr) {
653 SendResultCallBack(smsIndexer->GetSendCallback(), ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
654 return;
655 }
656 smsIndexer->SetEncodePdu(*pdu);
657 smsIndexer->SetNetWorkType(NET_TYPE_CDMA);
658 smsIndexer->SetTimeStamp(timeStamp);
659 SendSmsToRil(smsIndexer);
660 }
661
ResendDataDelivery(const std::shared_ptr<SmsSendIndexer> & smsIndexer)662 void CdmaSmsSender::ResendDataDelivery(const std::shared_ptr<SmsSendIndexer> &smsIndexer)
663 {
664 if (smsIndexer == nullptr) {
665 TELEPHONY_LOGI("ResendDataDelivery::smsIndexer is nullptr error.");
666 return;
667 }
668
669 CdmaSmsMessage message;
670 std::unique_ptr<CdmaTransportMsg> transMsg = nullptr;
671 bool bStatusReport = (smsIndexer->GetDeliveryCallback() == nullptr) ? false : true;
672 transMsg = message.CreateSubmitTransMsg(smsIndexer->GetDestAddr(), smsIndexer->GetSmcaAddr(),
673 smsIndexer->GetDestPort(), smsIndexer->GetData().data(), smsIndexer->GetData().size(), bStatusReport);
674 if (transMsg == nullptr) {
675 SendResultCallBack(smsIndexer->GetSendCallback(), ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
676 TELEPHONY_LOGE("CreateSubmitTransMsg nullptr fail.");
677 return;
678 }
679 /* Set Reply sequence number. */
680 uint8_t msgRef8bit = smsIndexer->GetMsgRefId();
681 transMsg->data.p2p.replySeq = msgRef8bit;
682 /* Set msg ID. */
683 transMsg->data.p2p.telesvcMsg.data.submit.msgId.msgId = smsIndexer->GetMsgId();
684 /* while user data header isn't exist, headerInd must be set false. */
685 transMsg->data.p2p.telesvcMsg.data.submit.msgId.headerInd = true;
686
687 chrono::system_clock::duration timePoint = chrono::system_clock::now().time_since_epoch();
688 long timeStamp = chrono::duration_cast<chrono::seconds>(timePoint).count();
689 transMsg->data.p2p.telesvcMsg.data.submit.userData.encodeType = SmsEncodingType::OCTET;
690 if (smsIndexer->GetData().size() > sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data)) {
691 TELEPHONY_LOGE("ResendDataDelivery data length invalid.");
692 return;
693 }
694 if (memcpy_s(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data,
695 sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data), smsIndexer->GetData().data(),
696 smsIndexer->GetData().size()) != EOK) {
697 SendResultCallBack(smsIndexer->GetSendCallback(), ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
698 return;
699 }
700
701 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.length = static_cast<int>(smsIndexer->GetData().size());
702 /* encode msg data */
703 std::unique_ptr<std::vector<uint8_t>> pdu = EncodeMsg(*transMsg.get());
704 if (pdu == nullptr) {
705 SendResultCallBack(smsIndexer->GetSendCallback(), ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
706 return;
707 }
708 smsIndexer->SetEncodePdu(*pdu);
709 smsIndexer->SetNetWorkType(NET_TYPE_CDMA);
710 smsIndexer->SetTimeStamp(timeStamp);
711 SendSmsToRil(smsIndexer);
712 }
713
SetConcact(const std::shared_ptr<SmsSendIndexer> & smsIndexer,const std::unique_ptr<CdmaTransportMsg> & transMsg)714 void CdmaSmsSender::SetConcact(
715 const std::shared_ptr<SmsSendIndexer> &smsIndexer, const std::unique_ptr<CdmaTransportMsg> &transMsg)
716 {
717 if (smsIndexer->GetIsConcat()) {
718 SmsConcat smsConcat = smsIndexer->GetSmsConcat();
719 transMsg->data.p2p.teleserviceId = static_cast<uint16_t>(SmsTransTelsvcId::WEMT);
720 transMsg->data.p2p.telesvcMsg.data.submit.msgId.headerInd = true;
721 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.headerCnt = 1;
722 if (smsConcat.is8Bits) {
723 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udhType = UDH_CONCAT_8BIT;
724 } else {
725 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udhType = UDH_CONCAT_16BIT;
726 }
727 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udh.concat8bit.msgRef = smsConcat.msgRef;
728 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udh.concat8bit.totalSeg =
729 smsConcat.totalSeg;
730 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udh.concat8bit.seqNum = smsConcat.seqNum;
731 }
732 }
733 } // namespace Telephony
734 } // namespace OHOS
735