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 if (imsResponseInfo == nullptr) {
546 TELEPHONY_LOGE("imsResponseInfo is nullptr error.");
547 return;
548 }
549 if (imsResponseInfo->error != ErrType::NONE) {
550 imsSmsCfg_ = IMS_SMS_DISABLE;
551 }
552 }
553
StatusReportGetImsSms(const AppExecFwk::InnerEvent::Pointer & event)554 void CdmaSmsSender::StatusReportGetImsSms(const AppExecFwk::InnerEvent::Pointer &event)
555 {
556 if (event == nullptr) {
557 TELEPHONY_LOGE("CdmaSmsSender: StatusReportGetImsSms event nullptr error.");
558 return;
559 }
560 std::shared_ptr<int32_t> imsSmsInfo = event->GetSharedObject<int32_t>();
561 if (imsSmsInfo == nullptr) {
562 TELEPHONY_LOGE("CdmaSmsSender: StatusReportGetImsSms imsSmsInfo nullptr error.");
563 return;
564 }
565 imsSmsCfg_ = *imsSmsInfo;
566 }
567
Init()568 void CdmaSmsSender::Init() {}
569
ReceiveStatusReport(const std::shared_ptr<SmsReceiveIndexer> & smsIndexer)570 void CdmaSmsSender::ReceiveStatusReport(const std::shared_ptr<SmsReceiveIndexer> &smsIndexer)
571 {
572 SendEvent(RadioEvent::RADIO_SMS_STATUS, smsIndexer);
573 }
574
RegisterImsHandler()575 void CdmaSmsSender::RegisterImsHandler()
576 {
577 if (isImsCdmaHandlerRegistered) {
578 return;
579 }
580 auto smsClient = DelayedSingleton<ImsSmsClient>::GetInstance();
581 if (smsClient == nullptr) {
582 TELEPHONY_LOGE("RegisterHandler return, ImsSmsClient is nullptr.");
583 return;
584 }
585 smsClient->RegisterImsSmsCallbackHandler(slotId_, shared_from_this());
586 TELEPHONY_LOGE("RegisterHandler gsm ImsSmsClient successs");
587 isImsCdmaHandlerRegistered = true;
588 }
589
GetSeqNum()590 uint8_t CdmaSmsSender::GetSeqNum()
591 {
592 msgSeqNum_ = ((msgSeqNum_ + 1) % CDMASMS_SEQ_NUM_MAX);
593 return msgSeqNum_;
594 }
595
GetSubmitMsgId()596 uint8_t CdmaSmsSender::GetSubmitMsgId()
597 {
598 msgSubmitId_ = ((msgSubmitId_ + 1) % CDMASMS_MESSAGE_ID_MAX);
599 return msgSubmitId_;
600 }
601
EncodeMsg(CdmaTransportMsg & transMsg)602 std::unique_ptr<std::vector<uint8_t>> CdmaSmsSender::EncodeMsg(CdmaTransportMsg &transMsg)
603 {
604 std::unique_ptr<CdmaSmsTransportMessage> msg = CdmaSmsTransportMessage::CreateTransportMessage(transMsg);
605 SmsWriteBuffer pduBuffer;
606 if (msg == nullptr || msg->IsEmpty() || !msg->Encode(pduBuffer)) {
607 TELEPHONY_LOGE("encode msg error");
608 return nullptr;
609 }
610 return pduBuffer.GetPduBuffer();
611 }
612
ResendTextDelivery(const std::shared_ptr<SmsSendIndexer> & smsIndexer)613 void CdmaSmsSender::ResendTextDelivery(const std::shared_ptr<SmsSendIndexer> &smsIndexer)
614 {
615 if (smsIndexer == nullptr) {
616 TELEPHONY_LOGE("smsIndexer is nullptr!!");
617 return;
618 }
619 CdmaSmsMessage message;
620 DataCodingScheme codingType = smsIndexer->GetDcs();
621 std::unique_ptr<CdmaTransportMsg> transMsg = nullptr;
622 bool bStatusReport = (smsIndexer->GetDeliveryCallback() == nullptr) ? false : true;
623 transMsg = message.CreateSubmitTransMsg(
624 smsIndexer->GetDestAddr(), smsIndexer->GetSmcaAddr(), smsIndexer->GetText(), bStatusReport, codingType);
625 if (transMsg == nullptr) {
626 SendResultCallBack(smsIndexer->GetSendCallback(), ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
627 TELEPHONY_LOGE("CreateSubmitTransMsg nullptr fail.");
628 return;
629 }
630 /* 1. Set Reply sequence number. */
631 uint8_t msgRef8bit = smsIndexer->GetMsgRefId();
632 transMsg->data.p2p.replySeq = msgRef8bit;
633 /* 2. Set msg ID. */
634 transMsg->data.p2p.telesvcMsg.data.submit.msgId.msgId = smsIndexer->GetMsgId();
635 chrono::system_clock::duration timePoint = chrono::system_clock::now().time_since_epoch();
636 long timeStamp = chrono::duration_cast<chrono::seconds>(timePoint).count();
637 smsIndexer->SetTimeStamp(timeStamp);
638 transMsg->data.p2p.telesvcMsg.data.submit.userData.encodeType = SmsEncodingType::OCTET;
639 (void)memset_s(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data,
640 sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data), 0x00,
641 sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data));
642 if (smsIndexer->GetText().length() > sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data)) {
643 TELEPHONY_LOGE("ResendTextDelivery data length invalid.");
644 return;
645 }
646 if (memcpy_s(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data,
647 sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data), smsIndexer->GetText().data(),
648 smsIndexer->GetText().length()) != EOK) {
649 SendResultCallBack(smsIndexer->GetSendCallback(), ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
650 return;
651 }
652 SetConcact(smsIndexer, transMsg);
653 /* encode msg data */
654 std::unique_ptr<std::vector<uint8_t>> pdu = EncodeMsg(*transMsg.get());
655 if (pdu == nullptr) {
656 SendResultCallBack(smsIndexer->GetSendCallback(), ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
657 return;
658 }
659 smsIndexer->SetEncodePdu(*pdu);
660 smsIndexer->SetNetWorkType(NET_TYPE_CDMA);
661 smsIndexer->SetTimeStamp(timeStamp);
662 SendSmsToRil(smsIndexer);
663 }
664
ResendDataDelivery(const std::shared_ptr<SmsSendIndexer> & smsIndexer)665 void CdmaSmsSender::ResendDataDelivery(const std::shared_ptr<SmsSendIndexer> &smsIndexer)
666 {
667 if (smsIndexer == nullptr) {
668 TELEPHONY_LOGI("ResendDataDelivery::smsIndexer is nullptr error.");
669 return;
670 }
671
672 CdmaSmsMessage message;
673 std::unique_ptr<CdmaTransportMsg> transMsg = nullptr;
674 bool bStatusReport = (smsIndexer->GetDeliveryCallback() == nullptr) ? false : true;
675 transMsg = message.CreateSubmitTransMsg(smsIndexer->GetDestAddr(), smsIndexer->GetSmcaAddr(),
676 smsIndexer->GetDestPort(), smsIndexer->GetData().data(), smsIndexer->GetData().size(), bStatusReport);
677 if (transMsg == nullptr) {
678 SendResultCallBack(smsIndexer->GetSendCallback(), ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
679 TELEPHONY_LOGE("CreateSubmitTransMsg nullptr fail.");
680 return;
681 }
682 /* Set Reply sequence number. */
683 uint8_t msgRef8bit = smsIndexer->GetMsgRefId();
684 transMsg->data.p2p.replySeq = msgRef8bit;
685 /* Set msg ID. */
686 transMsg->data.p2p.telesvcMsg.data.submit.msgId.msgId = smsIndexer->GetMsgId();
687 /* while user data header isn't exist, headerInd must be set false. */
688 transMsg->data.p2p.telesvcMsg.data.submit.msgId.headerInd = true;
689
690 chrono::system_clock::duration timePoint = chrono::system_clock::now().time_since_epoch();
691 long timeStamp = chrono::duration_cast<chrono::seconds>(timePoint).count();
692 transMsg->data.p2p.telesvcMsg.data.submit.userData.encodeType = SmsEncodingType::OCTET;
693 if (smsIndexer->GetData().size() > sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data)) {
694 TELEPHONY_LOGE("ResendDataDelivery data length invalid.");
695 return;
696 }
697 if (memcpy_s(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data,
698 sizeof(transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.data), smsIndexer->GetData().data(),
699 smsIndexer->GetData().size()) != EOK) {
700 SendResultCallBack(smsIndexer->GetSendCallback(), ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
701 return;
702 }
703
704 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.length = static_cast<int>(smsIndexer->GetData().size());
705 /* encode msg data */
706 std::unique_ptr<std::vector<uint8_t>> pdu = EncodeMsg(*transMsg.get());
707 if (pdu == nullptr) {
708 SendResultCallBack(smsIndexer->GetSendCallback(), ISendShortMessageCallback::SEND_SMS_FAILURE_UNKNOWN);
709 return;
710 }
711 smsIndexer->SetEncodePdu(*pdu);
712 smsIndexer->SetNetWorkType(NET_TYPE_CDMA);
713 smsIndexer->SetTimeStamp(timeStamp);
714 SendSmsToRil(smsIndexer);
715 }
716
SetConcact(const std::shared_ptr<SmsSendIndexer> & smsIndexer,const std::unique_ptr<CdmaTransportMsg> & transMsg)717 void CdmaSmsSender::SetConcact(
718 const std::shared_ptr<SmsSendIndexer> &smsIndexer, const std::unique_ptr<CdmaTransportMsg> &transMsg)
719 {
720 if (smsIndexer->GetIsConcat()) {
721 SmsConcat smsConcat = smsIndexer->GetSmsConcat();
722 transMsg->data.p2p.teleserviceId = static_cast<uint16_t>(SmsTransTelsvcId::WEMT);
723 transMsg->data.p2p.telesvcMsg.data.submit.msgId.headerInd = true;
724 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.headerCnt = 1;
725 if (smsConcat.is8Bits) {
726 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udhType = UDH_CONCAT_8BIT;
727 } else {
728 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udhType = UDH_CONCAT_16BIT;
729 }
730 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udh.concat8bit.msgRef = smsConcat.msgRef;
731 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udh.concat8bit.totalSeg =
732 smsConcat.totalSeg;
733 transMsg->data.p2p.telesvcMsg.data.submit.userData.userData.header[0].udh.concat8bit.seqNum = smsConcat.seqNum;
734 }
735 }
736 } // namespace Telephony
737 } // namespace OHOS
738