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