• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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