1 /*
2 * Copyright (c) 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 "connect_ads_stub.h"
17 #include <fstream>
18
19 namespace OHOS {
20 namespace Cloud {
21
22 using namespace std::chrono;
23 using OHOS::AAFwk::ExtensionManagerClient;
24 using OHOS::AAFwk::AbilityConnectionStub;
25 using OHOS::AppExecFwk::ElementName;
26 using OHOS::AAFwk::Want;
27 using OHOS::IRemoteObject;
28 using OHOS::sptr;
29
30 // 静态成员初始化
31 std::u16string ConnectAdsStub::OAID_INFO_TOKEN = u"";
32 std::mutex ConnectAdsStub::queueMutex_;
33 std::mutex ConnectAdsStub::setTokenMutex_;
34 std::mutex ConnectAdsStub::setOaidMutex_;
35 std::mutex ConnectAdsStub::stateMutex_;
36 std::mutex ConnectAdsStub::proxyMutex_;
37 std::mutex ConnectAdsManager::connectMutex_;
38 std::int32_t ConnectAdsStub::CODE_OAID = GET_ALLOW_OAID_CODE;
39
40 // ConnectAdsStub 实现
OnAbilityConnectDone(const ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)41 void ConnectAdsStub::OnAbilityConnectDone(const ElementName &element,
42 const sptr<IRemoteObject> &remoteObject, int resultCode)
43 {
44 OAID_HILOGI(OAID_MODULE_SERVICE, "enter OnAbilityConnectDone");
45 SetProxy(remoteObject);
46 SetConnectionState(ConnectionState::CONNECTED);
47 ProcessMessageQueue();
48 }
49
OnAbilityDisconnectDone(const ElementName & element,int resultCode)50 void ConnectAdsStub::OnAbilityDisconnectDone(const ElementName &element, int resultCode)
51 {
52 OAID_HILOGI(OAID_MODULE_SERVICE, "enter OnAbilityDisconnectDone");
53 SetProxy(nullptr);
54 SetConnectionState(ConnectionState::DISCONNECTED);
55 setCodeOaid(GET_ALLOW_OAID_CODE);
56 }
57
GetRemoteObject()58 sptr<IRemoteObject> ConnectAdsStub::GetRemoteObject()
59 {
60 return GetProxy();
61 }
62
GetProxy() const63 sptr<IRemoteObject> ConnectAdsStub::GetProxy() const
64 {
65 std::lock_guard<std::mutex> lock(proxyMutex_);
66 return proxy_;
67 }
68
SetProxy(const sptr<IRemoteObject> & remoteObject)69 void ConnectAdsStub::SetProxy(const sptr<IRemoteObject> &remoteObject)
70 {
71 std::lock_guard<std::mutex> lock(proxyMutex_);
72 proxy_ = remoteObject;
73 }
74
GetConnectionState() const75 ConnectionState ConnectAdsStub::GetConnectionState() const
76 {
77 std::lock_guard<std::mutex> lock(stateMutex_);
78 return connectionState_;
79 }
80
SetConnectionState(ConnectionState state)81 void ConnectAdsStub::SetConnectionState(ConnectionState state)
82 {
83 std::lock_guard<std::mutex> lock(stateMutex_);
84 connectionState_ = state;
85 }
86
AddMessageToQueue(int32_t code)87 void ConnectAdsStub::AddMessageToQueue(int32_t code)
88 {
89 std::lock_guard<std::mutex> lock(queueMutex_);
90 // 使用哈希集合去重
91 if (messageSet_.find(code) == messageSet_.end()) {
92 messageQueue_.push(code);
93 messageSet_.insert(code);
94 OAID_HILOGI(OAID_MODULE_SERVICE, "Add message %{public}d to queue", code);
95 }
96 }
97
ProcessMessageQueue()98 void ConnectAdsStub::ProcessMessageQueue()
99 {
100 std::queue<int32_t> tempQueue;
101 {
102 std::lock_guard<std::mutex> lock(queueMutex_);
103 OAID_HILOGI(OAID_MODULE_SERVICE, "Processing message queue");
104 if (messageQueue_.empty()) {
105 OAID_HILOGI(OAID_MODULE_SERVICE, "Message queue is empty");
106 return;
107 }
108 std::swap(tempQueue, messageQueue_);
109 messageSet_.clear();
110 }
111
112 // 检查连接状态
113 if (GetConnectionState() != ConnectionState::CONNECTED || GetProxy() == nullptr) {
114 OAID_HILOGW(OAID_MODULE_SERVICE, "Cannot process queue - not connected");
115 // 将未处理的消息重新放回队列
116 std::lock_guard<std::mutex> lock(queueMutex_);
117 while (!tempQueue.empty()) {
118 int32_t code = tempQueue.front();
119 if (messageSet_.find(code) == messageSet_.end()) {
120 messageQueue_.push(code);
121 messageSet_.insert(code);
122 }
123 tempQueue.pop();
124 }
125 return;
126 }
127
128 while (!tempQueue.empty()) {
129 int32_t code = tempQueue.front();
130 tempQueue.pop();
131 OAID_HILOGI(OAID_MODULE_SERVICE, "Processing message code=%{public}d", code);
132 SendMessage(code);
133 }
134 }
135
DisconnectIfIdle()136 void ConnectAdsStub::DisconnectIfIdle()
137 {
138 OAID_HILOGI(OAID_MODULE_SERVICE, "Disconnecting idle connection");
139 if (GetProxy() != nullptr && GetConnectionState() == ConnectionState::CONNECTED) {
140 ExtensionManagerClient::GetInstance().DisconnectAbility(this);
141 SetConnectionState(ConnectionState::DISCONNECTED);
142 }
143 }
144
SendMessage(int32_t code)145 void ConnectAdsStub::SendMessage(int32_t code)
146 {
147 OAID_HILOGI(OAID_MODULE_SERVICE, "SendMessage enter");
148 if (GetConnectionState() != ConnectionState::CONNECTED || GetProxy() == nullptr) {
149 OAID_HILOGI(OAID_MODULE_SERVICE, "SendMessage failed - not connected");
150 AddMessageToQueue(code);
151 return;
152 }
153
154 MessageParcel data;
155 MessageParcel reply;
156 MessageOption option(MessageOption::TF_ASYNC);
157 if (OAID_INFO_TOKEN.empty() || !data.WriteInterfaceToken(OAID_INFO_TOKEN)) {
158 OAID_HILOGW(OAID_MODULE_SERVICE, "SendMessage WriteInterfaceToken failed");
159 return;
160 }
161 sptr<ADSCallbackStub> callback = new ADSCallbackStub();
162 if (!data.WriteRemoteObject(callback->AsObject())) {
163 OAID_HILOGW(OAID_MODULE_SERVICE, "Callback write failed.");
164 return;
165 }
166
167 OAID_HILOGI(OAID_MODULE_SERVICE, "SendMessage CODE_OAID = %{public}d", code);
168 GetProxy()->SendRequest(code, data, reply, option);
169 setCodeOaid(GET_ALLOW_OAID_CODE);
170 OAID_HILOGI(OAID_MODULE_SERVICE, "SendMessage finished");
171 }
172
setToken(std::u16string token)173 void ConnectAdsStub::setToken(std::u16string token)
174 {
175 OAID_HILOGI(OAID_MODULE_SERVICE, "setToken enter");
176 std::lock_guard<std::mutex> lock(setTokenMutex_);
177 OAID_INFO_TOKEN = token;
178 }
179
setCodeOaid(std::int32_t code)180 void ConnectAdsStub::setCodeOaid(std::int32_t code)
181 {
182 std::lock_guard<std::mutex> lock(setOaidMutex_);
183 CODE_OAID = code;
184 }
185
186 // ConnectAdsManager 实现
~ConnectAdsManager()187 ConnectAdsManager::~ConnectAdsManager()
188 {
189 DisconnectService();
190 OAID_HILOGI(OAID_MODULE_SERVICE, "destructor ConnectAdsManager");
191 }
192
GetInstance()193 ConnectAdsManager* ConnectAdsManager::GetInstance()
194 {
195 static ConnectAdsManager instance;
196 return &instance;
197 }
198
DisconnectService()199 int32_t ConnectAdsManager::DisconnectService()
200 {
201 std::lock_guard<std::mutex> lock(connectMutex_);
202 if (connectObject_) {
203 connectObject_->DisconnectIfIdle();
204 }
205 return 0;
206 }
207
getWantInfo()208 Want ConnectAdsManager::getWantInfo()
209 {
210 OAID_HILOGI(OAID_MODULE_SERVICE, "enter getWantInfo ");
211 Want connectionWant;
212 char pathBuff[PATH_MAX] = {0};
213 GetOneCfgFile(OAID_TRUSTLIST_EXTENSION_CONFIG_PATH.c_str(), pathBuff, PATH_MAX);
214 char realPath[PATH_MAX] = {0};
215 if (realpath(pathBuff, realPath) == nullptr) {
216 GetOneCfgFile(OAID_TRUSTLIST_CONFIG_PATH.c_str(), pathBuff, PATH_MAX);
217 if (realpath(pathBuff, realPath) == nullptr) {
218 OAID_HILOGE(OAID_MODULE_SERVICE, "Parse realpath fail");
219 return connectionWant;
220 }
221 }
222 std::ifstream inFile(realPath, std::ios::in);
223 if (!inFile.is_open()) {
224 OAID_HILOGE(OAID_MODULE_SERVICE, "Open file error.");
225 return connectionWant;
226 }
227 std::string fileContent((std::istreambuf_iterator<char>{inFile}), std::istreambuf_iterator<char>{});
228 cJSON *root = cJSON_Parse(fileContent.c_str());
229 inFile.close();
230 if (root == nullptr) {
231 OAID_HILOGE(OAID_MODULE_SERVICE, "ParseJsonFromFile is not in JSON format.");
232 return connectionWant;
233 }
234 cJSON *oaidProviderBundleNameConfig = cJSON_GetObjectItem(root, "providerBundleName");
235 if (oaidProviderBundleNameConfig == nullptr || oaidProviderBundleNameConfig->type != cJSON_String) {
236 OAID_HILOGE(OAID_MODULE_SERVICE, "not contain providerBundleName node.");
237 cJSON_Delete(root);
238 return connectionWant;
239 }
240 cJSON *oaidProviderAbilityNameConfig = cJSON_GetObjectItem(root, "providerAbilityName");
241 if (oaidProviderAbilityNameConfig == nullptr || oaidProviderAbilityNameConfig->type != cJSON_String) {
242 OAID_HILOGE(OAID_MODULE_SERVICE, "not contain providerAbilityName node.");
243 cJSON_Delete(root);
244 return connectionWant;
245 }
246 cJSON *oaidProviderTokenNameConfig = cJSON_GetObjectItem(root, "providerTokenName");
247 if (oaidProviderTokenNameConfig == nullptr || oaidProviderTokenNameConfig->type != cJSON_String
248 || oaidProviderTokenNameConfig->valuestring == nullptr) {
249 OAID_HILOGE(OAID_MODULE_SERVICE, "not contain providerTokenName node.");
250 cJSON_Delete(root);
251 return connectionWant;
252 }
253 ConnectAdsStub::setToken(Str8ToStr16(oaidProviderTokenNameConfig->valuestring));
254 connectionWant.SetElementName(oaidProviderBundleNameConfig->valuestring,
255 oaidProviderAbilityNameConfig->valuestring);
256 cJSON_Delete(root);
257 return connectionWant;
258 }
259
checkAllowGetOaid()260 bool ConnectAdsManager::checkAllowGetOaid()
261 {
262 OAID_HILOGI(OAID_MODULE_SERVICE, "checkAllowGetOaid enter ");
263 DistributedKv::Value allowGetOaid;
264 DistributedKv::Value updateTime;
265 OAIDService::GetInstance()->ReadValueFromUnderAgeKvStore(ALLOW_GET_OAID_KEY, allowGetOaid);
266 OAIDService::GetInstance()->ReadValueFromUnderAgeKvStore(LAST_UPDATE_TIME_KEY, updateTime);
267 OAID_HILOGI(OAID_MODULE_SERVICE, "checkAllowGetOaid kvdata allowGetOaid = %{public}s updateTime = %{public}s",
268 allowGetOaid.ToString().c_str(), updateTime.ToString().c_str());
269 if (allowGetOaid == nullptr || updateTime == nullptr) {
270 OAID_HILOGI(OAID_MODULE_SERVICE, "checkAllowGetOaid get kvData failed");
271 ConnectAdsManager::GetInstance()->notifyKit(GET_ALLOW_OAID_CODE);
272 return true;
273 }
274 std::string updateTimeStr = updateTime.ToString();
275 long long updateTimestamp = std::stol(updateTimeStr);
276 long long nowTimestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
277 std::chrono::system_clock::now().time_since_epoch()).count();
278 if (nowTimestamp < updateTimestamp) {
279 OAID_HILOGW(OAID_MODULE_SERVICE, "user time illegal");
280 } else {
281 long long interval = nowTimestamp - updateTimestamp;
282 OAID_HILOGI(OAID_MODULE_SERVICE,
283 "checkAllowGetOaid kvdata nowTimestamp = %{public}lld updateTime = %{public}s interval = %{public}lld, ",
284 nowTimestamp,
285 updateTimeStr.c_str(),
286 interval);
287 if (interval >= EXPIRATION_TIME) {
288 OAID_HILOGI(OAID_MODULE_SERVICE, "checkAllowGetOaid info expiration");
289 ConnectAdsManager::GetInstance()->notifyKit(GET_ALLOW_OAID_CODE);
290 }
291 }
292 if (allowGetOaid.ToString() == "true") {
293 return true;
294 } else {
295 return false;
296 }
297 }
298
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)299 int ADSCallbackStub::OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
300 {
301 OAID_HILOGI(OAID_MODULE_SERVICE, "OnRemoteRequest enter");
302 int32_t respCode = data.ReadInt32();
303 OAID_HILOGI(OAID_MODULE_SERVICE, "OnRemoteRequest respCode = %{public}d", respCode);
304 std::string isAllowGetOaid = Str16ToStr8(data.ReadString16());
305 std::string updateTimeStr = Str16ToStr8(data.ReadString16());
306 OAID_HILOGI(OAID_MODULE_SERVICE, "isAllowGetOaid = %{public}s, updateTimeStr = %{public}s", isAllowGetOaid.c_str(),
307 updateTimeStr.c_str());
308 if (isAllowGetOaid.empty() || updateTimeStr.empty()) {
309 OAID_HILOGI(OAID_MODULE_SERVICE, "OnRemoteRequest return info is empty");
310 ConnectAdsManager::GetInstance()->DisconnectService();
311 return ERR_OK;
312 }
313 DistributedKv::Value value1(isAllowGetOaid);
314 DistributedKv::Value value2(updateTimeStr);
315 bool allowGetOaidResult = OAIDService::GetInstance()->WriteValueToUnderAgeKvStore(ALLOW_GET_OAID_KEY, value1);
316 bool lastUpdateTimeResult = OAIDService::GetInstance()->WriteValueToUnderAgeKvStore(LAST_UPDATE_TIME_KEY, value2);
317 OAID_HILOGI(OAID_MODULE_SERVICE,
318 "OnRemoteRequest Write AllowGetOaid result=%{public}s.OnRemoteRequest Write lastUpdateTime result=%{public}s",
319 allowGetOaidResult == true ? "success" : "failed",
320 lastUpdateTimeResult == true ? "success" : "failed");
321 ConnectAdsManager::GetInstance()->DisconnectService();
322 return ERR_OK;
323 }
324
notifyKit(int32_t code)325 void ConnectAdsManager::notifyKit(int32_t code)
326 {
327 OAID_HILOGI(OAID_MODULE_SERVICE, "enter notifyKit = %{public}d", code);
328 ConnectionState currentState = connectObject_->GetConnectionState();
329 // 待发送的消息放到队列中,连接成功后处理队列消息
330 connectObject_->AddMessageToQueue(code);
331 if (currentState == ConnectionState::CONNECTED) {
332 OAID_HILOGI(OAID_MODULE_SERVICE, "already connected, process message queue");
333 connectObject_->ProcessMessageQueue();
334 return;
335 }
336
337 if (currentState == ConnectionState::DISCONNECTED) {
338 std::lock_guard<std::mutex> lock(connectMutex_);
339 // 再次检查状态,防止竞态条件
340 if (connectObject_->GetConnectionState() == ConnectionState::DISCONNECTED) {
341 OAID_HILOGI(OAID_MODULE_SERVICE, "not connected, start connecting");
342 connectObject_->SetConnectionState(ConnectionState::CONNECTING);
343 Want want = getWantInfo();
344 if (code == NOTIFY_RESET_OAID_CODE) {
345 ConnectAdsStub::setCodeOaid(code);
346 want.SetParam("code_oaid", code);
347 }
348 int32_t resultNumber = ExtensionManagerClient::GetInstance().ConnectServiceExtensionAbility(
349 want, connectObject_, nullptr, DEFAULT_VALUE);
350 if (resultNumber != ERR_OK) {
351 connectObject_->SetConnectionState(ConnectionState::DISCONNECTED);
352 OAID_HILOGI(OAID_MODULE_SERVICE, "failed to ConnectToAds");
353 }
354 }
355 } else {
356 OAID_HILOGI(OAID_MODULE_SERVICE, "connection in progress, message added to queue");
357 }
358 }
359
getConnection()360 sptr<ConnectAdsStub> ConnectAdsManager::getConnection()
361 {
362 return connectObject_;
363 }
364
ConnectAdsManager()365 ConnectAdsManager::ConnectAdsManager()
366 {
367 connectObject_ = sptr<ConnectAdsStub>(new ConnectAdsStub);
368 connectObject_->SetConnectionState(ConnectionState::DISCONNECTED);
369 OAID_HILOGI(OAID_MODULE_SERVICE, "constructor ConnectAdsManager");
370 }
371
372 } // namespace Cloud
373 } // namespace OHOS
374