1 /*
2 * Copyright (C) 2022-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 "device/dev_profile.h"
17 #include <thread>
18
19 #include "device/device_profile_proxy.h"
20 #include "device/dm_adapter.h"
21 #include "ffrt/ffrt_utils.h"
22 #include "pasteboard_error.h"
23 #include "pasteboard_event_ue.h"
24 #include "pasteboard_hilog.h"
25 namespace OHOS {
26 namespace MiscServices {
27 constexpr const char *UE_SWITCH_OPERATION = "PASTEBOARD_SWITCH_OPERATION";
28
GetInstance()29 DevProfile &DevProfile::GetInstance()
30 {
31 static DevProfile instance;
32 return instance;
33 }
34
OnProfileUpdate(const std::string & udid,bool status)35 void DevProfile::OnProfileUpdate(const std::string &udid, bool status)
36 {
37 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "udid=%{public}.5s, status=%{public}d", udid.c_str(), status);
38 DevProfile::GetInstance().UpdateEnabledStatus(udid, status);
39 DevProfile::GetInstance().Notify(status);
40 }
41
PostDelayReleaseProxy()42 void DevProfile::PostDelayReleaseProxy()
43 {
44 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "post delay task start");
45 constexpr uint32_t DELAY_TIME = 60 * 1000; // 60s
46 static FFRTTimer ffrtTimer("release_dp_proxy");
47
48 FFRTTask task = [this]() {
49 std::thread thread([=]() {
50 std::lock_guard lock(proxyMutex_);
51 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "execute delay task");
52 if (proxy_ == nullptr) {
53 return;
54 }
55
56 if (subscribeUdidList_.empty()) {
57 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "deinit dp proxy");
58 proxy_ = nullptr;
59 }
60 });
61 thread.detach();
62 };
63
64 ffrtTimer.SetTimer("release_dp_proxy", task, DELAY_TIME);
65 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "post delay task end");
66 }
67
PutDeviceStatus(bool status)68 void DevProfile::PutDeviceStatus(bool status)
69 {
70 std::string networkId = DMAdapter::GetInstance().GetLocalNetworkId();
71 std::string udid = DMAdapter::GetInstance().GetUdidByNetworkId(networkId);
72 PASTEBOARD_CHECK_AND_RETURN_LOGE(!udid.empty(), PASTEBOARD_MODULE_SERVICE,
73 "get udid failed, netId=%{public}.5s", networkId.c_str());
74
75 UpdateEnabledStatus(udid, status);
76 UE_SWITCH(UE_SWITCH_OPERATION, UeReporter::UE_OPERATION_TYPE, status ?
77 UeReporter::SwitchStatus::SWITCH_OPEN : UeReporter::SwitchStatus::SWITCH_CLOSE);
78
79 std::lock_guard lock(proxyMutex_);
80 PostDelayReleaseProxy();
81 if (proxy_ == nullptr) {
82 proxy_ = std::make_shared<DeviceProfileProxy>();
83 }
84 auto adapter = proxy_->GetAdapter();
85 PASTEBOARD_CHECK_AND_RETURN_LOGE(adapter != nullptr, PASTEBOARD_MODULE_SERVICE, "adapter is null");
86 int32_t ret = adapter->PutDeviceStatus(udid, status);
87 PASTEBOARD_CHECK_AND_RETURN_LOGE(ret == static_cast<int32_t>(PasteboardError::E_OK), PASTEBOARD_MODULE_SERVICE,
88 "put dp status failed, ret=%{public}d", ret);
89
90 Notify(status);
91 }
92
GetDeviceStatus(const std::string & networkId,bool & status)93 int32_t DevProfile::GetDeviceStatus(const std::string &networkId, bool &status)
94 {
95 std::string udid = DMAdapter::GetInstance().GetUdidByNetworkId(networkId);
96 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(!udid.empty(),
97 static_cast<int32_t>(PasteboardError::GET_LOCAL_DEVICE_ID_ERROR), PASTEBOARD_MODULE_SERVICE,
98 "get udid failed, netId=%{public}.5s", networkId.c_str());
99
100 bool cachedStatus = enabledStatusCache_.ComputeIfPresent(udid, [&status](const auto &key, auto &value) {
101 status = value;
102 return true;
103 });
104 if (cachedStatus) {
105 return static_cast<int32_t>(PasteboardError::E_OK);
106 }
107
108 std::lock_guard lock(proxyMutex_);
109 PostDelayReleaseProxy();
110 if (proxy_ == nullptr) {
111 proxy_ = std::make_shared<DeviceProfileProxy>();
112 }
113 auto adapter = proxy_->GetAdapter();
114 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(adapter != nullptr, static_cast<int32_t>(PasteboardError::DLOPEN_FAILED),
115 PASTEBOARD_MODULE_SERVICE, "adapter is null");
116 int32_t ret = adapter->GetDeviceStatus(udid, status);
117 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(ret == static_cast<int32_t>(PasteboardError::E_OK), ret,
118 PASTEBOARD_MODULE_SERVICE, "get dp status failed, udid=%{public}.5s, ret=%{public}d", udid.c_str(), ret);
119
120 UpdateEnabledStatus(udid, status);
121 return static_cast<int32_t>(PasteboardError::E_OK);
122 }
123
GetDeviceVersion(const std::string & networkId,uint32_t & versionId)124 bool DevProfile::GetDeviceVersion(const std::string &networkId, uint32_t &versionId)
125 {
126 std::string udid = DMAdapter::GetInstance().GetUdidByNetworkId(networkId);
127 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(!udid.empty(), false,
128 PASTEBOARD_MODULE_SERVICE, "get udid failed, netId=%{public}.5s", networkId.c_str());
129
130 std::lock_guard lock(proxyMutex_);
131 PostDelayReleaseProxy();
132 if (proxy_ == nullptr) {
133 proxy_ = std::make_shared<DeviceProfileProxy>();
134 }
135 auto adapter = proxy_->GetAdapter();
136 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(adapter != nullptr, false, PASTEBOARD_MODULE_SERVICE, "adapter is null");
137 bool ret = adapter->GetDeviceVersion(udid, versionId);
138 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(ret, false,
139 PASTEBOARD_MODULE_SERVICE, "get dp version failed, udid=%{public}.5s", udid.c_str());
140
141 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "netid=%{public}.5s, udid=%{public}.5s, version=%{public}u",
142 networkId.c_str(), udid.c_str(), versionId);
143 return true;
144 }
145
SubscribeProfileEvent(const std::string & networkId)146 void DevProfile::SubscribeProfileEvent(const std::string &networkId)
147 {
148 std::string udid = DMAdapter::GetInstance().GetUdidByNetworkId(networkId);
149 PASTEBOARD_CHECK_AND_RETURN_LOGE(!udid.empty(), PASTEBOARD_MODULE_SERVICE,
150 "get udid failed, netId=%{public}.5s", networkId.c_str());
151
152 std::lock_guard lock(proxyMutex_);
153 PostDelayReleaseProxy();
154 if (proxy_ == nullptr) {
155 proxy_ = std::make_shared<DeviceProfileProxy>();
156 }
157 auto adapter = proxy_->GetAdapter();
158 PASTEBOARD_CHECK_AND_RETURN_LOGE(adapter != nullptr, PASTEBOARD_MODULE_SERVICE, "adapter is null");
159
160 int32_t ret = adapter->RegisterUpdateCallback(&DevProfile::OnProfileUpdate);
161 PASTEBOARD_CHECK_AND_RETURN_LOGE(ret == static_cast<int32_t>(PasteboardError::E_OK), PASTEBOARD_MODULE_SERVICE,
162 "register dp update callback failed, ret=%{public}d", ret);
163
164 ret = adapter->SubscribeProfileEvent(udid);
165 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "udid=%{public}.5s, ret=%{public}d", udid.c_str(), ret);
166
167 subscribeUdidList_.emplace(udid);
168 }
169
UnSubscribeProfileEvent(const std::string & networkId)170 void DevProfile::UnSubscribeProfileEvent(const std::string &networkId)
171 {
172 std::string udid = DMAdapter::GetInstance().GetUdidByNetworkId(networkId);
173 PASTEBOARD_CHECK_AND_RETURN_LOGE(!udid.empty(), PASTEBOARD_MODULE_SERVICE,
174 "get udid failed, netId=%{public}.5s", networkId.c_str());
175
176 std::lock_guard lock(proxyMutex_);
177 PostDelayReleaseProxy();
178 if (proxy_ == nullptr) {
179 proxy_ = std::make_shared<DeviceProfileProxy>();
180 }
181 auto adapter = proxy_->GetAdapter();
182 PASTEBOARD_CHECK_AND_RETURN_LOGE(adapter != nullptr, PASTEBOARD_MODULE_SERVICE, "adapter is null");
183
184 int32_t ret = adapter->UnSubscribeProfileEvent(udid);
185 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "udid=%{public}.5s, ret=%{public}d", udid.c_str(), ret);
186
187 subscribeUdidList_.erase(udid);
188 }
189
UnSubscribeAllProfileEvents()190 void DevProfile::UnSubscribeAllProfileEvents()
191 {
192 std::lock_guard lock(proxyMutex_);
193 PASTEBOARD_CHECK_AND_RETURN_LOGD(!subscribeUdidList_.empty(), PASTEBOARD_MODULE_SERVICE, "udid list empty");
194
195 PostDelayReleaseProxy();
196 if (proxy_ == nullptr) {
197 proxy_ = std::make_shared<DeviceProfileProxy>();
198 }
199 auto adapter = proxy_->GetAdapter();
200 PASTEBOARD_CHECK_AND_RETURN_LOGE(adapter != nullptr, PASTEBOARD_MODULE_SERVICE, "adapter is null");
201
202 int32_t ret = static_cast<int32_t>(PasteboardError::E_OK);
203 for (const std::string &udid : subscribeUdidList_) {
204 ret = adapter->UnSubscribeProfileEvent(udid);
205 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "udid=%{public}.5s, ret=%{public}d", udid.c_str(), ret);
206 }
207
208 subscribeUdidList_.clear();
209 }
210
SendSubscribeInfos()211 void DevProfile::SendSubscribeInfos()
212 {
213 std::lock_guard lock(proxyMutex_);
214 PASTEBOARD_CHECK_AND_RETURN_LOGD(!subscribeUdidList_.empty(), PASTEBOARD_MODULE_SERVICE, "udid list empty");
215
216 PostDelayReleaseProxy();
217 if (proxy_ == nullptr) {
218 proxy_ = std::make_shared<DeviceProfileProxy>();
219 }
220 auto adapter = proxy_->GetAdapter();
221 PASTEBOARD_CHECK_AND_RETURN_LOGE(adapter != nullptr, PASTEBOARD_MODULE_SERVICE, "adapter is null");
222
223 adapter->SendSubscribeInfos();
224 }
225
ClearDeviceProfileService()226 void DevProfile::ClearDeviceProfileService()
227 {
228 std::lock_guard lock(proxyMutex_);
229 PASTEBOARD_CHECK_AND_RETURN_LOGD(proxy_ != nullptr, PASTEBOARD_MODULE_SERVICE, "not need clear");
230
231 enabledStatusCache_.Clear();
232 PostDelayReleaseProxy();
233 auto adapter = proxy_->GetAdapter();
234 PASTEBOARD_CHECK_AND_RETURN_LOGE(adapter != nullptr, PASTEBOARD_MODULE_SERVICE, "adapter is null");
235
236 adapter->ClearDeviceProfileService();
237 }
238
Watch(Observer observer)239 void DevProfile::Watch(Observer observer)
240 {
241 observer_ = std::move(observer);
242 }
243
Notify(bool isEnable)244 void DevProfile::Notify(bool isEnable)
245 {
246 if (observer_ != nullptr) {
247 observer_(isEnable);
248 }
249 }
250
UpdateEnabledStatus(const std::string & udid,bool status)251 void DevProfile::UpdateEnabledStatus(const std::string &udid, bool status)
252 {
253 enabledStatusCache_.Compute(udid, [&status](const auto &key, auto &value) {
254 value = status;
255 return true;
256 });
257 }
258
EraseEnabledStatus(const std::string & udid)259 void DevProfile::EraseEnabledStatus(const std::string &udid)
260 {
261 enabledStatusCache_.Erase(udid);
262 }
263 } // namespace MiscServices
264 } // namespace OHOS
265