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