1/*
2 * Copyright (C) 2021 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 "sms_receive_handler.h"
17#include "gsm_sms_message.h"
18#include "radio_event.h"
19#include "sms_hisysevent.h"
20#include "sms_persist_helper.h"
21#include "telephony_log_wrapper.h"
22#include "iservice_registry.h"
23#include <queue>
24
25namespace OHOS {
26namespace Telephony {
27using namespace std;
28constexpr static uint16_t PDU_POS_OFFSET = 1;
29constexpr static uint8_t SMS_TYPE_GSM = 1;
30constexpr static uint8_t SMS_TYPE_CDMA = 2;
31static const std::string WAP_SEQ_NUMBER_TAG = "0003";
32constexpr static size_t WAP_SEQ_NUMBER_LEN = 10;
33const std::string STR_URI = "datashare:///com.ohos.smsmmsability/sms_mms/sms_subsection";
34const std::string EXT_URI = "datashare:///com.ohos.smsmmsability";
35
36std::queue<std::shared_ptr<SmsBaseMessage>> g_smsBaseMessageQueue;
37uint8_t g_reconnectDataShareCount = 0;
38bool g_alreadySendEvent = false;
39
40SmsReceiveHandler::SmsReceiveHandler(int32_t slotId) : TelEventHandler("SmsReceiveHandler"), slotId_(slotId)
41{
42    smsWapPushHandler_ = std::make_unique<SmsWapPushHandler>(slotId);
43    if (smsWapPushHandler_ == nullptr) {
44        TELEPHONY_LOGE("make sms wapPush Hander error.");
45    }
46    CreateRunningLockInner();
47}
48
49SmsReceiveHandler::~SmsReceiveHandler() {}
50// Function is used to judge if datashare interface is ready
51bool SmsReceiveHandler::IsDataShareReady()
52{
53    auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
54    if (saManager == nullptr) {
55        TELEPHONY_LOGE("Get system ability mgr failed.");
56        return false;
57    }
58    auto remoteObj = saManager->GetSystemAbility(TELEPHONY_SMS_MMS_SYS_ABILITY_ID);
59    if (remoteObj == nullptr) {
60        TELEPHONY_LOGE("Getsystemability service failed.");
61        return false;
62    }
63    std::lock_guard<std::mutex> lock(datashareMutex_);
64    std::pair<int, std::shared_ptr<DataShare::DataShareHelper>> ret =
65        DataShare::DataShareHelper::Create(remoteObj, STR_URI, EXT_URI);
66    TELEPHONY_LOGI("create data_share helper, ret=%{public}d", ret.first);
67    if (ret.first == E_OK) {
68        ret.second->Release();
69        return true;
70    }
71    return false;
72}
73
74void SmsReceiveHandler::HandleMessageQueue()
75{
76    uint8_t queueLength = g_smsBaseMessageQueue.size();
77    // send un-operate message to the remain receive procedure.
78    for (uint8_t i = 0; i < queueLength; i++) {
79        HandleRemainDataShare(g_smsBaseMessageQueue.front());
80        g_smsBaseMessageQueue.pop();
81        TELEPHONY_LOGI("operated a sms and there are %{public}zu sms wait to be operated",
82            g_smsBaseMessageQueue.size());
83    }
84    // give app 20s power lock time to handle receive.
85    this->SendEvent(DELAY_RELEASE_RUNNING_LOCK_EVENT_ID, DELAY_REDUCE_RUNNING_LOCK_SMS_QUEUE_TIMEOUT_MS);
86    g_reconnectDataShareCount = 0;
87    // set the flag of datashare is not ready to false.
88    g_alreadySendEvent = false;
89}
90
91void SmsReceiveHandler::HandleReconnectEvent()
92{
93    if (IsDataShareReady()) {
94        std::lock_guard<std::mutex> lock(queueMutex_);
95        HandleMessageQueue();
96    } else {
97        g_reconnectDataShareCount++;
98        // if retry times over 20(the datashare is not ready in 100s), stop try.
99        if (g_reconnectDataShareCount >= RECONNECT_MAX_COUNT) {
100            TELEPHONY_LOGI("Over the max reconnect count:20 and there are %{public}zu sms have not been operated",
101                g_smsBaseMessageQueue.size());
102            g_reconnectDataShareCount = 0;
103            g_alreadySendEvent = false;
104            ReleaseRunningLock();
105        } else {
106            TELEPHONY_LOGI("Send event %{public}u times", g_reconnectDataShareCount);
107            /*
108             *applylock can only hold power lock 60s, so reapply lock every 5s to ensure have entire 60s to
109             *operate sms when datashare is ready('reduce' to release and 'apply' to rehold)
110             */
111            ReduceRunningLock();
112            ApplyRunningLock();
113            this->SendEvent(RETRY_CONNECT_DATASHARE_EVENT_ID, DELAY_RETRY_CONNECT_DATASHARE_MS);
114        }
115    }
116}
117
118void SmsReceiveHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
119{
120    if (event == nullptr) {
121        TELEPHONY_LOGE("SmsReceiveHandler::ProcessEvent event == nullptr");
122        return;
123    }
124
125    uint32_t eventId = 0;
126    eventId = event->GetInnerEventId();
127    TELEPHONY_LOGI("SmsReceiveHandler::ProcessEvent eventId = %{public}d", eventId);
128    switch (eventId) {
129        case RadioEvent::RADIO_GSM_SMS:
130        case RadioEvent::RADIO_CDMA_SMS: {
131            ApplyRunningLock();
132            std::shared_ptr<SmsBaseMessage> message = nullptr;
133            message = TransformMessageInfo(event->GetSharedObject<SmsMessageInfo>());
134            if (message != nullptr) {
135                TELEPHONY_LOGI("[raw pdu] =%{private}s", StringUtils::StringToHex(message->GetRawPdu()).c_str());
136            }
137            if (!g_alreadySendEvent) {
138                if (IsDataShareReady()) {
139                    HandleReceivedSms(message);
140                    this->SendEvent(DELAY_RELEASE_RUNNING_LOCK_EVENT_ID, DELAY_REDUCE_RUNNING_LOCK_TIMEOUT_MS);
141                } else {
142                    HandleReceivedSmsWithoutDataShare(message);
143                    this->SendEvent(RETRY_CONNECT_DATASHARE_EVENT_ID, DELAY_RETRY_CONNECT_DATASHARE_MS);
144                    g_alreadySendEvent = true;
145                }
146            } else {
147                HandleReceivedSmsWithoutDataShare(message);
148            }
149            break;
150        }
151        case RUNNING_LOCK_TIMEOUT_EVENT_ID:
152            HandleRunningLockTimeoutEvent(event);
153            break;
154        case DELAY_RELEASE_RUNNING_LOCK_EVENT_ID:
155            ReduceRunningLock();
156            break;
157        case RETRY_CONNECT_DATASHARE_EVENT_ID: {
158            HandleReconnectEvent();
159            break;
160        }
161        default:
162            TELEPHONY_LOGE("SmsReceiveHandler::ProcessEvent Unknown eventId %{public}d", eventId);
163            break;
164    }
165}
166
167void SmsReceiveHandler::ApplyRunningLock()
168{
169#ifdef ABILITY_POWER_SUPPORT
170    if (smsRunningLock_ == nullptr) {
171        CreateRunningLockInner();
172    }
173    std::lock_guard<std::mutex> lockGuard(mutexRunningLock_);
174    if (smsRunningLock_ != nullptr) {
175        smsRunningLockCount_++;
176        smsLockSerialNum_++;
177        TELEPHONY_LOGI("ApplyRunningLock, try to lock. count: %{public}d, serial: %{public}d",
178            static_cast<int>(smsRunningLockCount_), static_cast<int>(smsLockSerialNum_));
179        smsRunningLock_->Lock(RUNNING_LOCK_DEFAULT_TIMEOUT_MS); // Automatic release after the 60s.
180        this->SendEvent(RUNNING_LOCK_TIMEOUT_EVENT_ID, smsLockSerialNum_, RUNNING_LOCK_DEFAULT_TIMEOUT_MS);
181    }
182#endif
183}
184
185void SmsReceiveHandler::ReduceRunningLock()
186{
187#ifdef ABILITY_POWER_SUPPORT
188    std::lock_guard<std::mutex> lockRequest(mutexRunningLock_);
189    TELEPHONY_LOGI("ReduceRunningLock, count:%{public}d", static_cast<int>(smsRunningLockCount_));
190    if (smsRunningLock_ != nullptr) {
191        if (smsRunningLockCount_ > 1) {
192            smsRunningLockCount_--;
193        } else {
194            smsRunningLockCount_ = 0;
195            ReleaseRunningLock();
196        }
197    }
198#endif
199}
200
201void SmsReceiveHandler::ReleaseRunningLock()
202{
203#ifdef ABILITY_POWER_SUPPORT
204    if (smsRunningLock_ == nullptr) {
205        TELEPHONY_LOGE("ReleaseRunningLock, smsRunningLock_ is nullptr");
206        return;
207    }
208    TELEPHONY_LOGI("ReleaseRunningLock, try to unlock.");
209    smsRunningLockCount_ = 0;
210    int ret = smsRunningLock_->UnLock();
211    if (ret != PowerMgr::E_GET_POWER_SERVICE_FAILED) {
212        // Call UnLock success, remove event.
213        this->RemoveEvent(RUNNING_LOCK_TIMEOUT_EVENT_ID);
214        return;
215    }
216    TELEPHONY_LOGI("ReleaseRunningLock, no found power service, retry.");
217    this->SendEvent(RUNNING_LOCK_TIMEOUT_EVENT_ID, smsLockSerialNum_, DELAY_RELEASE_RUNNING_LOCK_TIMEOUT_MS);
218#endif
219}
220
221void SmsReceiveHandler::CreateRunningLockInner()
222{
223#ifdef ABILITY_POWER_SUPPORT
224    auto &powerMgrClient = PowerMgr::PowerMgrClient::GetInstance();
225    std::lock_guard<std::mutex> lockGuard(mutexRunningLock_);
226    smsRunningLock_ = powerMgrClient.CreateRunningLock("telSmsRunningLock",
227        PowerMgr::RunningLockType::RUNNINGLOCK_BACKGROUND_PHONE);
228    smsRunningLockCount_ = 0;
229    smsLockSerialNum_ = 0;
230#endif
231}
232
233void SmsReceiveHandler::HandleRunningLockTimeoutEvent(const AppExecFwk::InnerEvent::Pointer &event)
234{
235#ifdef ABILITY_POWER_SUPPORT
236    auto serial = event->GetParam();
237    if (serial == smsLockSerialNum_) {
238        TELEPHONY_LOGE("HandleRunningLockTimeoutEvent, serial:%{public}d, smsLockSerialNum_:%{public}d",
239            static_cast<int>(serial), static_cast<int>(smsLockSerialNum_));
240        ReleaseRunningLock();
241    }
242#endif
243}
244
245void SmsReceiveHandler::HandleReceivedSms(const std::shared_ptr<SmsBaseMessage> smsBaseMessage)
246{
247    if (smsBaseMessage == nullptr) {
248        TELEPHONY_LOGE("smsBaseMessage is nullptr");
249        return;
250    }
251    ReplySmsToSmsc(HandleSmsByType(smsBaseMessage));
252}
253
254void SmsReceiveHandler::HandleReceivedSmsWithoutDataShare(const std::shared_ptr<SmsBaseMessage> smsBaseMessage)
255{
256    if (smsBaseMessage == nullptr) {
257        TELEPHONY_LOGE("smsBaseMessage is nullptr");
258        return;
259    }
260    int32_t result = ReplySmsToSmsc(HandleAck(smsBaseMessage));
261    if (result) {
262        std::lock_guard lock(queueMutex_);
263        g_smsBaseMessageQueue.push(smsBaseMessage);
264        TELEPHONY_LOGI("Received a new message and pushed it in queue");
265    }
266}
267
268void SmsReceiveHandler::CombineMessagePart(const std::shared_ptr<SmsReceiveIndexer> &indexer)
269{
270    std::shared_ptr<vector<string>> pdus = make_shared<vector<string>>();
271    if ((indexer == nullptr) || (pdus == nullptr)) {
272        TELEPHONY_LOGE("indexer or pdus is nullptr");
273        return;
274    }
275    auto reliabilityHandler = std::make_shared<SmsReceiveReliabilityHandler>(slotId_);
276    if ((reliabilityHandler == nullptr)) {
277        TELEPHONY_LOGE("reliabilityHandler is nullptr");
278        return;
279    }
280    if (indexer->IsSingleMsg()) {
281        string pdu = StringUtils::StringToHex(indexer->GetPdu());
282        pdus->push_back(pdu);
283    } else {
284        if (!CombineMultiPageMessage(indexer, pdus, reliabilityHandler)) {
285            TELEPHONY_LOGI("The multi-page text didn't all arrive");
286            return;
287        }
288    }
289
290    if (indexer->GetIsWapPushMsg()) {
291        if (smsWapPushHandler_ != nullptr) {
292            auto rawWapPushUserData = indexer->GetRawWapPushUserData();
293            if (!smsWapPushHandler_->DecodeWapPushPdu(indexer, rawWapPushUserData)) {
294                SmsHiSysEvent::WriteSmsReceiveFaultEvent(slotId_, SmsMmsMessageType::WAP_PUSH,
295                    SmsMmsErrorCode::SMS_ERROR_PDU_DECODE_FAIL, "Wap push decode wap push fail");
296            }
297        }
298        return;
299    }
300    reliabilityHandler->SendBroadcast(indexer, pdus);
301}
302
303bool SmsReceiveHandler::CombineMultiPageMessage(const std::shared_ptr<SmsReceiveIndexer> &indexer,
304    std::shared_ptr<std::vector<std::string>> pdus, std::shared_ptr<SmsReceiveReliabilityHandler> reliabilityHandler)
305{
306    pdus->assign(MAX_SEGMENT_NUM, "");
307    int msgSeg = static_cast<int>(indexer->GetMsgCount());
308    int8_t notNullPart = msgSeg;
309    std::vector<SmsReceiveIndexer> dbIndexers;
310    DataShare::DataSharePredicates predicates;
311    predicates.EqualTo(SmsSubsection::SENDER_NUMBER, indexer->GetOriginatingAddress())
312        ->And()
313        ->EqualTo(SmsSubsection::SMS_SUBSECTION_ID, std::to_string(indexer->GetMsgRefId()))
314        ->And()
315        ->EqualTo(SmsSubsection::SIZE, std::to_string(indexer->GetMsgCount()));
316    DelayedSingleton<SmsPersistHelper>::GetInstance()->Query(predicates, dbIndexers);
317    int8_t count = 0;
318    for (const auto &v : dbIndexers) {
319        ++count;
320        string pdu = StringUtils::StringToHex(v.GetPdu());
321        if ((v.GetMsgSeqId() - PDU_POS_OFFSET >= MAX_SEGMENT_NUM) || (v.GetMsgSeqId() - PDU_POS_OFFSET < 0)) {
322            reliabilityHandler->DeleteMessageFormDb(indexer->GetMsgRefId());
323            return false;
324        }
325        pdus->at(v.GetMsgSeqId() - PDU_POS_OFFSET) = pdu;
326        if (v.GetPdu().size() == 0) {
327            --notNullPart;
328        }
329    }
330    if ((count != msgSeg) || (pdus->empty()) || (notNullPart != msgSeg)) {
331        return false;
332    }
333    UpdateMultiPageMessage(indexer, pdus);
334    return true;
335}
336
337void SmsReceiveHandler::UpdateMultiPageMessage(
338    const std::shared_ptr<SmsReceiveIndexer> &indexer, std::shared_ptr<std::vector<std::string>> pdus)
339{
340    if ((indexer == nullptr) || (pdus == nullptr) || (pdus->empty())) {
341        TELEPHONY_LOGE("indexer or pdus is null");
342        return;
343    }
344    std::string messagBody;
345    std::string userDataRaw;
346    std::string rawWapPushUserData;
347    for (const auto &pdu : *pdus) {
348        if (pdu.empty()) {
349            continue;
350        }
351        std::shared_ptr<SmsBaseMessage> baseMessage = GsmSmsMessage::CreateMessage(pdu);
352        if (baseMessage == nullptr) {
353            continue;
354        }
355        messagBody.append(baseMessage->GetVisibleMessageBody());
356        userDataRaw.append(baseMessage->GetRawUserData());
357        if (!indexer->GetIsWapPushMsg()) {
358            continue;
359        }
360        auto wapDataHex = StringUtils::StringToHex(baseMessage->GetRawWapPushUserData());
361        if (wapDataHex.substr(0, WAP_SEQ_NUMBER_TAG.size()) == WAP_SEQ_NUMBER_TAG) {
362            rawWapPushUserData.append(StringUtils::HexToString(wapDataHex.substr(WAP_SEQ_NUMBER_LEN)));
363        } else {
364            rawWapPushUserData.append(StringUtils::HexToString(wapDataHex));
365        }
366    }
367
368    indexer->SetVisibleMessageBody(messagBody);
369    indexer->SetRawUserData(userDataRaw);
370    if (indexer->GetIsWapPushMsg()) {
371        indexer->SetRawWapPushUserData(rawWapPushUserData);
372    }
373}
374
375bool SmsReceiveHandler::IsRepeatedMessagePart(const shared_ptr<SmsReceiveIndexer> &smsIndexer)
376{
377    if (smsIndexer != nullptr) {
378        std::vector<SmsReceiveIndexer> dbIndexers;
379        DataShare::DataSharePredicates predicates;
380        predicates.EqualTo(SmsSubsection::SENDER_NUMBER, smsIndexer->GetOriginatingAddress())
381            ->And()
382            ->EqualTo(SmsSubsection::SMS_SUBSECTION_ID, std::to_string(smsIndexer->GetMsgRefId()))
383            ->And()
384            ->EqualTo(SmsSubsection::SIZE, std::to_string(smsIndexer->GetMsgCount()));
385        DelayedSingleton<SmsPersistHelper>::GetInstance()->Query(predicates, dbIndexers);
386
387        for (const auto &it : dbIndexers) {
388            if (it.GetMsgSeqId() == smsIndexer->GetMsgSeqId()) {
389                return true;
390            }
391        }
392    }
393    return false;
394}
395
396bool SmsReceiveHandler::AddMsgToDB(const std::shared_ptr<SmsReceiveIndexer> indexer)
397{
398    if (indexer == nullptr) {
399        TELEPHONY_LOGE("indexer is nullptr.");
400        return false;
401    }
402
403    DataShare::DataShareValuesBucket bucket;
404    bucket.Put(SmsSubsection::SLOT_ID, std::to_string(slotId_));
405    bucket.Put(SmsSubsection::RECEIVER_NUMBER, indexer->GetOriginatingAddress());
406    bucket.Put(SmsSubsection::SENDER_NUMBER, indexer->GetOriginatingAddress());
407    bucket.Put(SmsSubsection::START_TIME, std::to_string(indexer->GetTimestamp()));
408    bucket.Put(SmsSubsection::END_TIME, std::to_string(indexer->GetTimestamp()));
409    bucket.Put(SmsSubsection::REW_PUD, StringUtils::StringToHex(indexer->GetPdu()));
410
411    bucket.Put(SmsSubsection::FORMAT, indexer->GetIsCdma() ? SMS_TYPE_CDMA : SMS_TYPE_GSM);
412    bucket.Put(SmsSubsection::DEST_PORT, indexer->GetDestPort());
413    bucket.Put(SmsSubsection::SMS_SUBSECTION_ID, indexer->GetMsgRefId());
414    bucket.Put(SmsSubsection::SIZE, indexer->GetMsgCount());
415    bucket.Put(SmsSubsection::SUBSECTION_INDEX, indexer->GetMsgSeqId());
416    uint16_t dataBaseId = 0;
417    bool ret = DelayedSingleton<SmsPersistHelper>::GetInstance()->Insert(bucket, dataBaseId);
418    indexer->SetDataBaseId(dataBaseId);
419    if (!ret) {
420        SmsHiSysEvent::WriteSmsReceiveFaultEvent(slotId_, SmsMmsMessageType::SMS_SHORT_MESSAGE,
421            SmsMmsErrorCode::SMS_ERROR_ADD_TO_DATABASE_FAIL, "add msg to database error");
422    }
423    return ret;
424}
425} // namespace Telephony
426} // namespace OHOS