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