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