1 /*
2  * Copyright (C) 2024 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 "spam_call_adapter.h"
17 
18 #include "call_manager_base.h"
19 #include "call_manager_info.h"
20 #include "extension_manager_client.h"
21 #include "ipc_skeleton.h"
22 #include "nlohmann/json.hpp"
23 #include "telephony_log_wrapper.h"
24 #include "cJSON.h"
25 #include <securec.h>
26 #include "time_wait_helper.h"
27 #include "spam_call_connection.h"
28 
29 namespace OHOS {
30 namespace Telephony {
31 constexpr int32_t DEFAULT_USER_ID = -1;
32 constexpr char DETECT_RESULT[] = "detectResult";
33 constexpr char DECISION_REASON[] = "decisionReason";
34 constexpr char MARK_TYPE[] = "markType";
35 constexpr char MARK_COUNT[] = "markCount";
36 constexpr char MARK_SOURCE[] = "markSource";
37 constexpr char MARK_CONTENT[] = "markContent";
38 constexpr char IS_CLOUD[] = "isCloud";
39 constexpr char MARK_DETAILS[] = "markDetails";
40 sptr<SpamCallConnection> connection_ = nullptr;
41 
SpamCallAdapter()42 SpamCallAdapter::SpamCallAdapter()
43 {
44     timeWaitHelper_ = std::make_unique<TimeWaitHelper>(WAIT_TIME_FIVE_SECOND);
45 }
46 
~SpamCallAdapter()47 SpamCallAdapter::~SpamCallAdapter()
48 {
49     TELEPHONY_LOGI("~SpamCallAdapter");
50 }
51 
DetectSpamCall(const std::string &phoneNumber, const int32_t &slotId)52 bool SpamCallAdapter::DetectSpamCall(const std::string &phoneNumber, const int32_t &slotId)
53 {
54     TELEPHONY_LOGI("DetectSpamCall start");
55     phoneNumber_ = phoneNumber;
56     AAFwk::Want want;
57     std::string bundleName = "com.spamshield";
58     std::string abilityName = "SpamShieldServiceExtAbility";
59     want.SetElementName(bundleName, abilityName);
60     bool connectResult = ConnectSpamCallAbility(want, phoneNumber, slotId);
61     if (!connectResult) {
62         TELEPHONY_LOGE("DetectSpamCall failed!");
63         return false;
64     }
65     return true;
66 }
67 
ConnectSpamCallAbility(const AAFwk::Want &want, const std::string &phoneNumber, const int32_t &slotId)68 bool SpamCallAdapter::ConnectSpamCallAbility(const AAFwk::Want &want, const std::string &phoneNumber,
69     const int32_t &slotId)
70 {
71     std::lock_guard<ffrt::mutex> lock(mutex_);
72     TELEPHONY_LOGI("ConnectSpamCallAbility start");
73     connection_ = new (std::nothrow) SpamCallConnection(phoneNumber, slotId,
74         shared_from_this());
75     if (connection_ == nullptr) {
76         TELEPHONY_LOGE("connection_ is nullptr");
77         return false;
78     }
79     std::string identity = IPCSkeleton::ResetCallingIdentity();
80     auto connectResult = AAFwk::ExtensionManagerClient::GetInstance().ConnectServiceExtensionAbility(want,
81         connection_, nullptr, DEFAULT_USER_ID);
82     IPCSkeleton::SetCallingIdentity(identity);
83     if (connectResult != 0) {
84         TELEPHONY_LOGE("ConnectServiceExtensionAbility Failed!");
85         return false;
86     }
87     return true;
88 }
89 
DisconnectSpamCallAbility()90 void SpamCallAdapter::DisconnectSpamCallAbility()
91 {
92     std::lock_guard<ffrt::mutex> lock(mutex_);
93     TELEPHONY_LOGI("DisconnectSpamCallAbility start");
94     if (connection_ == nullptr) {
95         TELEPHONY_LOGE("connection_ is nullptr");
96         return;
97     }
98     auto disconnectResult = AAFwk::ExtensionManagerClient::GetInstance().DisconnectAbility(connection_);
99     connection_.clear();
100     if (disconnectResult != 0) {
101         TELEPHONY_LOGE("DisconnectAbility failed! %d", disconnectResult);
102     }
103 }
104 
JsonGetNumberValue(cJSON *json, const std::string key, int32_t &out)105 bool SpamCallAdapter::JsonGetNumberValue(cJSON *json, const std::string key, int32_t &out)
106 {
107     do {
108         cJSON *cursor = cJSON_GetObjectItem(json, key.c_str());
109         if (!cJSON_IsNumber(cursor)) {
110             TELEPHONY_LOGE("ParseNumberValue failed to get %{public}s", key.c_str());
111             return false;
112         }
113         out = static_cast<int32_t>(cJSON_GetNumberValue(cursor));
114     } while (0);
115     return true;
116 }
117 
JsonGetStringValue(cJSON *json, const std::string key, std::string &out)118 bool SpamCallAdapter::JsonGetStringValue(cJSON *json, const std::string key, std::string &out)
119 {
120     do {
121         out = "";
122         cJSON *cursor = cJSON_GetObjectItem(json, key.c_str());
123         if (!cJSON_IsString(cursor)) {
124             TELEPHONY_LOGE("ParseStringValue failed to get %{public}s", key.c_str());
125             return false;
126         }
127         char *value = cJSON_GetStringValue(cursor);
128         if (value != nullptr) {
129             out = value;
130         }
131     } while (0);
132     return true;
133 }
134 
JsonGetBoolValue(cJSON *json, const std::string key)135 bool SpamCallAdapter::JsonGetBoolValue(cJSON *json, const std::string key)
136 {
137     cJSON *cursor = cJSON_GetObjectItem(json, key.c_str());
138     bool value = cJSON_IsTrue(cursor);
139     TELEPHONY_LOGI("ParseBoolValue %{public}s: %{public}d", key.c_str(), value);
140     return value;
141 }
142 
ParseDetectResult(const std::string &jsonData, bool &isBlock, NumberMarkInfo &info, int32_t &blockReason)143 void SpamCallAdapter::ParseDetectResult(const std::string &jsonData, bool &isBlock,
144     NumberMarkInfo &info, int32_t &blockReason)
145 {
146     if (jsonData.empty()) {
147         return;
148     }
149     const char *data = jsonData.c_str();
150     cJSON *root = cJSON_Parse(data);
151     if (root == nullptr) {
152         TELEPHONY_LOGE("ParseDetectResult failed to parse JSON");
153         return;
154     }
155     cJSON *jsonObj;
156     int32_t numberValue = 0;
157     std::string stringValue = "";
158     if (!JsonGetNumberValue(root, DETECT_RESULT, numberValue)) {
159         cJSON_Delete(root);
160         return;
161     }
162     isBlock = numberValue == 1;
163     TELEPHONY_LOGI("detectResult: %{public}d", isBlock);
164     if (!JsonGetNumberValue(root, DECISION_REASON, numberValue)) {
165         cJSON_Delete(root);
166         return;
167     }
168     blockReason = numberValue;
169     TELEPHONY_LOGI("decisionReason: %{public}d", blockReason);
170     if (JsonGetNumberValue(root, MARK_TYPE, numberValue)) {
171         info.markType = static_cast<MarkType>(numberValue);
172     }
173     TELEPHONY_LOGI("markType: %{public}d", info.markType);
174     if (JsonGetNumberValue(root, MARK_COUNT, numberValue)) {
175         info.markCount = numberValue;
176     }
177     JsonGetStringValue(root, MARK_SOURCE, stringValue);
178     if (strcpy_s(info.markSource, sizeof(info.markSource), stringValue.c_str()) != EOK) {
179         TELEPHONY_LOGE("strcpy_s markSource fail.");
180     }
181     JsonGetStringValue(root, MARK_CONTENT, stringValue);
182     if (strcpy_s(info.markContent, sizeof(info.markContent), stringValue.c_str()) != EOK) {
183         TELEPHONY_LOGE("strcpy_s markContent fail.");
184     }
185     info.isCloud = JsonGetBoolValue(root, IS_CLOUD);
186     JsonGetStringValue(root, MARK_DETAILS, stringValue);
187     if (strcpy_s(info.markDetails, sizeof(info.markDetails), stringValue.c_str()) != EOK) {
188         TELEPHONY_LOGE("strcpy_s markDetails fail.");
189     }
190     TELEPHONY_LOGI("ParseDetectResult end");
191     cJSON_Delete(root);
192 }
193 
GetDetectResult(int32_t &errCode, std::string &result)194 void SpamCallAdapter::GetDetectResult(int32_t &errCode, std::string &result)
195 {
196     errCode = errCode_;
197     result = result_;
198 }
199 
SetDetectResult(int32_t &errCode, std::string &result)200 void SpamCallAdapter::SetDetectResult(int32_t &errCode, std::string &result)
201 {
202     errCode_ = errCode;
203     result_ = result;
204 }
205 
GetParseResult(bool &isBlock, NumberMarkInfo &info, int32_t &blockReason)206 void SpamCallAdapter::GetParseResult(bool &isBlock, NumberMarkInfo &info, int32_t &blockReason)
207 {
208     isBlock = isBlock_;
209     info = info_;
210     blockReason = blockReason_;
211 }
212 
SetParseResult(bool &isBlock, NumberMarkInfo &info, int32_t &blockReason)213 void SpamCallAdapter::SetParseResult(bool &isBlock, NumberMarkInfo &info, int32_t &blockReason)
214 {
215     isBlock_ = isBlock;
216     info_ = info;
217     blockReason_ = blockReason;
218 }
219 
GetDetectPhoneNum()220 std::string SpamCallAdapter::GetDetectPhoneNum()
221 {
222     return phoneNumber_;
223 }
224 
NotifyAll()225 void SpamCallAdapter::NotifyAll()
226 {
227     if (timeWaitHelper_ == nullptr) {
228         TELEPHONY_LOGE("timeWaitHelper_ is null");
229         return;
230     }
231     timeWaitHelper_->NotifyAll();
232 }
233 
WaitForDetectResult()234 bool SpamCallAdapter::WaitForDetectResult()
235 {
236     if (!timeWaitHelper_->WaitForResult()) {
237         DisconnectSpamCallAbility();
238         return false;
239     }
240     DisconnectSpamCallAbility();
241     return true;
242 }
243 } // namespace Telephony
244 } // namespace OHOS
245