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