1 /*
2 * Copyright (C) 2024-2025 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 #include "common_event_manager.h"
29 #include "common_event_support.h"
30 #include "telephony_permission.h"
31
32 namespace OHOS {
33 namespace Telephony {
34 constexpr int32_t DEFAULT_USER_ID = -1;
35 constexpr int16_t INCOMING_CALL_MISSED_CODE = 0;
36 constexpr char REMINDER_RESULT[] = "reminderResult";
37 constexpr char SLOT_ID[] = "slotId";
38 constexpr char DETECT_RESULT[] = "detectResult";
39 constexpr char DECISION_REASON[] = "decisionReason";
40 constexpr char MARK_TYPE[] = "markType";
41 constexpr char MARK_COUNT[] = "markCount";
42 constexpr char MARK_SOURCE[] = "markSource";
43 constexpr char MARK_CONTENT[] = "markContent";
44 constexpr char IS_CLOUD[] = "isCloud";
45 constexpr char MARK_DETAILS[] = "markDetails";
46 constexpr char DETECT_DETAILS[] = "detectDetails";
47 sptr<SpamCallConnection> connection_ = nullptr;
48
SpamCallAdapter()49 SpamCallAdapter::SpamCallAdapter()
50 {
51 timeWaitHelper_ = std::make_unique<TimeWaitHelper>(WAIT_TIME_FIVE_SECOND);
52 }
53
~SpamCallAdapter()54 SpamCallAdapter::~SpamCallAdapter()
55 {
56 TELEPHONY_LOGW("~SpamCallAdapter");
57 }
58
DetectSpamCall(const std::string & phoneNumber,const int32_t & slotId)59 bool SpamCallAdapter::DetectSpamCall(const std::string &phoneNumber, const int32_t &slotId)
60 {
61 TELEPHONY_LOGW("DetectSpamCall start");
62 phoneNumber_ = phoneNumber;
63 AAFwk::Want want;
64 std::string bundleName = "com.spamshield";
65 std::string abilityName = "SpamShieldServiceExtAbility";
66 want.SetElementName(bundleName, abilityName);
67 bool connectResult = ConnectSpamCallAbility(want, phoneNumber, slotId);
68 if (!connectResult) {
69 TELEPHONY_LOGE("DetectSpamCall failed!");
70 return false;
71 }
72 return true;
73 }
74
ConnectSpamCallAbility(const AAFwk::Want & want,const std::string & phoneNumber,const int32_t & slotId)75 bool SpamCallAdapter::ConnectSpamCallAbility(const AAFwk::Want &want, const std::string &phoneNumber,
76 const int32_t &slotId)
77 {
78 std::lock_guard<ffrt::mutex> lock(mutex_);
79 TELEPHONY_LOGW("ConnectSpamCallAbility start");
80 connection_ = new (std::nothrow) SpamCallConnection(phoneNumber, slotId,
81 shared_from_this());
82 if (connection_ == nullptr) {
83 TELEPHONY_LOGE("connection_ is nullptr");
84 return false;
85 }
86 std::string identity = IPCSkeleton::ResetCallingIdentity();
87 auto connectResult = AAFwk::ExtensionManagerClient::GetInstance().ConnectServiceExtensionAbility(want,
88 connection_, nullptr, DEFAULT_USER_ID);
89 IPCSkeleton::SetCallingIdentity(identity);
90 if (connectResult != 0) {
91 TELEPHONY_LOGE("ConnectServiceExtensionAbility Failed!");
92 return false;
93 }
94 return true;
95 }
96
DisconnectSpamCallAbility()97 void SpamCallAdapter::DisconnectSpamCallAbility()
98 {
99 std::lock_guard<ffrt::mutex> lock(mutex_);
100 TELEPHONY_LOGW("DisconnectSpamCallAbility start");
101 if (connection_ == nullptr) {
102 TELEPHONY_LOGE("connection_ is nullptr");
103 return;
104 }
105 auto disconnectResult = AAFwk::ExtensionManagerClient::GetInstance().DisconnectAbility(connection_);
106 connection_.clear();
107 if (disconnectResult != 0) {
108 TELEPHONY_LOGE("DisconnectAbility failed! %d", disconnectResult);
109 }
110 }
111
JsonGetNumberValue(cJSON * json,const std::string key,int32_t & out)112 bool SpamCallAdapter::JsonGetNumberValue(cJSON *json, const std::string key, int32_t &out)
113 {
114 do {
115 cJSON *cursor = cJSON_GetObjectItem(json, key.c_str());
116 if (!cJSON_IsNumber(cursor)) {
117 TELEPHONY_LOGE("ParseNumberValue failed to get %{public}s", key.c_str());
118 return false;
119 }
120 out = static_cast<int32_t>(cJSON_GetNumberValue(cursor));
121 } while (0);
122 return true;
123 }
124
JsonGetStringValue(cJSON * json,const std::string key,std::string & out)125 bool SpamCallAdapter::JsonGetStringValue(cJSON *json, const std::string key, std::string &out)
126 {
127 do {
128 out = "";
129 cJSON *cursor = cJSON_GetObjectItem(json, key.c_str());
130 if (!cJSON_IsString(cursor)) {
131 TELEPHONY_LOGE("ParseStringValue failed to get %{public}s", key.c_str());
132 return false;
133 }
134 char *value = cJSON_GetStringValue(cursor);
135 if (value != nullptr) {
136 out = value;
137 }
138 } while (0);
139 return true;
140 }
141
JsonGetBoolValue(cJSON * json,const std::string key)142 bool SpamCallAdapter::JsonGetBoolValue(cJSON *json, const std::string key)
143 {
144 cJSON *cursor = cJSON_GetObjectItem(json, key.c_str());
145 bool value = cJSON_IsTrue(cursor);
146 TELEPHONY_LOGW("ParseBoolValue %{public}s: %{public}d", key.c_str(), value);
147 return value;
148 }
149
ParseNeedNotifyResult(const std::string & jsonData)150 void SpamCallAdapter::ParseNeedNotifyResult(const std::string &jsonData)
151 {
152 if (jsonData.empty()) {
153 return;
154 }
155 const char *data = jsonData.c_str();
156 cJSON *root = cJSON_Parse(data);
157 if (root == nullptr) {
158 TELEPHONY_LOGE("ParseNeedNotifyResult failed to parse JSON");
159 return;
160 }
161 int32_t slotId = 0;
162 if (!JsonGetNumberValue(root, SLOT_ID, slotId)) {
163 cJSON_Delete(root);
164 return;
165 }
166 bool result = JsonGetBoolValue(root, REMINDER_RESULT);
167 TELEPHONY_LOGI("result: %{public}d, slotId: %{public}d", result, slotId);
168 if (result) {
169 TELEPHONY_LOGI("send notify to contacts");
170 AAFwk::Want want;
171 want.SetParam("isHarassmentGuidance", true);
172 want.SetParam("slotId", slotId);
173 want.SetAction(EventFwk::CommonEventSupport::COMMON_EVENT_INCOMING_CALL_MISSED);
174 EventFwk::CommonEventData eventData;
175 eventData.SetWant(want);
176 EventFwk::CommonEventPublishInfo publishInfo;
177 std::vector<std::string> callPermissions;
178 callPermissions.emplace_back(Permission::GET_TELEPHONY_STATE);
179 publishInfo.SetSubscriberPermissions(callPermissions);
180 if (!EventFwk::CommonEventManager::PublishCommonEvent(eventData, publishInfo, nullptr)) {
181 TELEPHONY_LOGE("PublishCommonEvent fail.");
182 }
183 }
184 cJSON_Delete(root);
185 }
186
ParseDetectResult(const std::string & jsonData,bool & isBlock,NumberMarkInfo & info,int32_t & blockReason,std::string & detectDetails)187 void SpamCallAdapter::ParseDetectResult(const std::string &jsonData, bool &isBlock,
188 NumberMarkInfo &info, int32_t &blockReason, std::string &detectDetails)
189 {
190 if (jsonData.empty()) {
191 return;
192 }
193 const char *data = jsonData.c_str();
194 cJSON *root = cJSON_Parse(data);
195 if (root == nullptr) {
196 TELEPHONY_LOGE("ParseDetectResult failed to parse JSON");
197 return;
198 }
199 int32_t numberValue = 0;
200 if (!JsonGetNumberValue(root, DETECT_RESULT, numberValue)) {
201 cJSON_Delete(root);
202 return;
203 }
204 isBlock = numberValue == 1;
205 TELEPHONY_LOGI("DetectSpamCall detectResult: %{public}d", isBlock);
206 if (!JsonGetNumberValue(root, DECISION_REASON, numberValue)) {
207 cJSON_Delete(root);
208 return;
209 }
210 blockReason = numberValue;
211 TELEPHONY_LOGI("DetectSpamCall decisionReason: %{public}d", blockReason);
212 ParseMarkResults(info, root, detectDetails, isBlock);
213 cJSON_Delete(root);
214 }
215
ParseMarkResults(NumberMarkInfo & info,cJSON * root,std::string & detectDetails,bool isBlock)216 void SpamCallAdapter::ParseMarkResults(NumberMarkInfo &info, cJSON *root, std::string &detectDetails, bool isBlock)
217 {
218 int32_t numberValue = 0;
219 std::string stringValue = "";
220 if (JsonGetNumberValue(root, MARK_TYPE, numberValue)) {
221 info.markType = static_cast<MarkType>(numberValue);
222 }
223 TELEPHONY_LOGI("DetectSpamCall markType: %{public}d", info.markType);
224 if (!isBlock && (info.markType == MarkType::MARK_TYPE_CRANK || info.markType == MarkType::MARK_TYPE_FRAUD ||
225 info.markType == MarkType::MARK_TYPE_PROMOTE_SALES || info.markType == MarkType::MARK_TYPE_HOUSE_AGENT)) {
226 connection_->RequireCallReminder();
227 }
228 if (JsonGetNumberValue(root, MARK_COUNT, numberValue)) {
229 info.markCount = numberValue;
230 }
231 JsonGetStringValue(root, MARK_SOURCE, stringValue);
232 if (strcpy_s(info.markSource, sizeof(info.markSource), stringValue.c_str()) != EOK) {
233 TELEPHONY_LOGE("strcpy_s markSource fail.");
234 }
235 JsonGetStringValue(root, MARK_CONTENT, stringValue);
236 if (strcpy_s(info.markContent, sizeof(info.markContent), stringValue.c_str()) != EOK) {
237 TELEPHONY_LOGE("strcpy_s markContent fail.");
238 }
239 info.isCloud = JsonGetBoolValue(root, IS_CLOUD);
240 JsonGetStringValue(root, MARK_DETAILS, stringValue);
241 if (strcpy_s(info.markDetails, sizeof(info.markDetails), stringValue.c_str()) != EOK) {
242 TELEPHONY_LOGE("strcpy_s markDetails fail.");
243 }
244 JsonGetStringValue(root, DETECT_DETAILS, detectDetails);
245 TELEPHONY_LOGI("DetectSpamCall detectDetails length: %{public}zu", detectDetails.length());
246 }
247
GetDetectResult(int32_t & errCode,std::string & result)248 void SpamCallAdapter::GetDetectResult(int32_t &errCode, std::string &result)
249 {
250 errCode = errCode_;
251 result = result_;
252 }
253
SetDetectResult(int32_t & errCode,std::string & result)254 void SpamCallAdapter::SetDetectResult(int32_t &errCode, std::string &result)
255 {
256 errCode_ = errCode;
257 result_ = result;
258 }
259
GetParseResult(bool & isBlock,NumberMarkInfo & info,int32_t & blockReason,std::string & detectDetails)260 void SpamCallAdapter::GetParseResult(bool &isBlock, NumberMarkInfo &info,
261 int32_t &blockReason, std::string &detectDetails)
262 {
263 isBlock = isBlock_;
264 info = info_;
265 blockReason = blockReason_;
266 detectDetails = detectDetails_;
267 }
268
SetParseResult(bool & isBlock,NumberMarkInfo & info,int32_t & blockReason,std::string & detectDetails)269 void SpamCallAdapter::SetParseResult(bool &isBlock, NumberMarkInfo &info,
270 int32_t &blockReason, std::string &detectDetails)
271 {
272 isBlock_ = isBlock;
273 info_ = info;
274 blockReason_ = blockReason;
275 detectDetails_ = detectDetails;
276 }
277
GetDetectPhoneNum()278 std::string SpamCallAdapter::GetDetectPhoneNum()
279 {
280 return phoneNumber_;
281 }
282
NotifyAll()283 void SpamCallAdapter::NotifyAll()
284 {
285 if (timeWaitHelper_ == nullptr) {
286 TELEPHONY_LOGE("timeWaitHelper_ is null");
287 return;
288 }
289 timeWaitHelper_->NotifyAll();
290 }
291
WaitForDetectResult()292 bool SpamCallAdapter::WaitForDetectResult()
293 {
294 if (timeWaitHelper_ == nullptr) {
295 TELEPHONY_LOGE("timeWaitHelper_ is null");
296 return false;
297 }
298 if (!timeWaitHelper_->WaitForResult()) {
299 DisconnectSpamCallAbility();
300 return false;
301 }
302 DisconnectSpamCallAbility();
303 return true;
304 }
305 } // namespace Telephony
306 } // namespace OHOS
307