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 #include "device/distributed_module_config.h"
16
17 #include <thread>
18 #include "device/dev_profile.h"
19 #include "pasteboard_error.h"
20 #include "pasteboard_hilog.h"
21
22 namespace OHOS {
23 namespace MiscServices {
24 constexpr uint32_t RETRY_TIMES = 30;
25 constexpr uint32_t RETRY_INTERVAL = 1000; // milliseconds
26 constexpr uint32_t RANDOM_MAX = 500;
27 constexpr uint32_t RANDOM_MIN = 5;
IsOn()28 bool DistributedModuleConfig::IsOn()
29 {
30 if (GetDeviceNum() != 0) {
31 Notify();
32 }
33 return status_;
34 }
35
Watch(const Observer & observer)36 void DistributedModuleConfig::Watch(const Observer &observer)
37 {
38 observer_ = std::move(observer);
39 }
40
Notify()41 void DistributedModuleConfig::Notify()
42 {
43 auto status = GetEnabledStatus();
44 if (status == static_cast<int32_t>(PasteboardError::DP_LOAD_SERVICE_ERROR)) {
45 if (!retrying_.exchange(true)) {
46 GetRetryTask();
47 }
48 return;
49 }
50 bool newStatus = (status == static_cast<int32_t>(PasteboardError::E_OK));
51 if (newStatus != status_) {
52 status_ = newStatus;
53 if (observer_ != nullptr) {
54 observer_(newStatus);
55 }
56 }
57 }
58
GetRetryTask()59 void DistributedModuleConfig::GetRetryTask()
60 {
61 std::thread remover([this]() {
62 retrying_.store(true);
63 uint32_t retry = 0;
64 auto status = static_cast<int32_t>(PasteboardError::REMOTE_TASK_ERROR);
65 while (retry < RETRY_TIMES) {
66 ++retry;
67 status = GetEnabledStatus();
68 if (status == static_cast<int32_t>(PasteboardError::DP_LOAD_SERVICE_ERROR)) {
69 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE,
70 "dp load err, retry:%{public}d, status_:%{public}d"
71 "newStatus:%{public}d",
72 retry, status_, status);
73 std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_INTERVAL));
74 continue;
75 }
76 break;
77 }
78 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE,
79 "Retry end. count:%{public}d, status_:%{public}d"
80 "newStatus:%{public}d",
81 retry, status_, status);
82 bool newStatus = (status == static_cast<int32_t>(PasteboardError::E_OK));
83 if (newStatus != status_) {
84 status_ = newStatus;
85 if (observer_ != nullptr) {
86 observer_(newStatus);
87 }
88 }
89 retrying_.store(false);
90 });
91 remover.detach();
92 }
93
GetDeviceNum()94 size_t DistributedModuleConfig::GetDeviceNum()
95 {
96 auto networkIds = DMAdapter::GetInstance().GetNetworkIds();
97 return networkIds.size();
98 }
99
GetEnabledStatus()100 int32_t DistributedModuleConfig::GetEnabledStatus()
101 {
102 auto localNetworkId = DMAdapter::GetInstance().GetLocalNetworkId();
103 bool localEnable = false;
104 auto status = DevProfile::GetInstance().GetDeviceStatus(localNetworkId, localEnable);
105 if (status != static_cast<int32_t>(PasteboardError::E_OK) || !localEnable) {
106 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_SERVICE, "GetLocalEnable false, ret:%{public}d, switch:%{public}d",
107 status, localEnable);
108 return static_cast<int32_t>(PasteboardError::LOCAL_SWITCH_NOT_TURNED_ON);
109 }
110 auto networkIds = DMAdapter::GetInstance().GetNetworkIds();
111 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_SERVICE, "device online nums: %{public}zu", networkIds.size());
112 for (auto &id : networkIds) {
113 bool remoteEnable = false;
114 auto res = DevProfile::GetInstance().GetDeviceStatus(id, remoteEnable);
115 if (res == static_cast<int32_t>(PasteboardError::E_OK) && remoteEnable) {
116 return static_cast<int32_t>(PasteboardError::E_OK);
117 }
118 }
119 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_SERVICE, "remoteEnabledStatus is false.");
120 return static_cast<int32_t>(PasteboardError::NO_TRUST_DEVICE_ERROR);
121 }
122
GetRemoteDeviceMinVersion()123 uint32_t DistributedModuleConfig::GetRemoteDeviceMinVersion()
124 {
125 auto [minVersion, maxVersion] = GetRemoteDeviceVersion();
126 return minVersion;
127 }
128
GetRemoteDeviceMaxVersion()129 uint32_t DistributedModuleConfig::GetRemoteDeviceMaxVersion()
130 {
131 auto [minVersion, maxVersion] = GetRemoteDeviceVersion();
132 return maxVersion;
133 }
134
GetRemoteDeviceVersion()135 std::pair<uint32_t, uint32_t> DistributedModuleConfig::GetRemoteDeviceVersion()
136 {
137 uint32_t minVersion = UINT_MAX;
138 uint32_t maxVersion = 0;
139
140 const auto &networkIds = DMAdapter::GetInstance().GetNetworkIds();
141 for (const auto &networkId : networkIds) {
142 bool remoteEnable = false;
143 auto res = DevProfile::GetInstance().GetDeviceStatus(networkId, remoteEnable);
144 if (res != static_cast<int32_t>(PasteboardError::E_OK) || !remoteEnable) {
145 continue;
146 }
147
148 uint32_t deviceVersion = 0;
149 if (!DevProfile::GetInstance().GetDeviceVersion(networkId, deviceVersion)) {
150 continue;
151 }
152
153 minVersion = minVersion < deviceVersion ? minVersion : deviceVersion;
154 maxVersion = maxVersion > deviceVersion ? maxVersion : deviceVersion;
155 }
156 return std::make_pair(minVersion, maxVersion);
157 }
158
Online(const std::string & device)159 void DistributedModuleConfig::Online(const std::string &device)
160 {
161 srand(time(nullptr));
162 std::this_thread::sleep_for(std::chrono::milliseconds((int32_t(rand() % (RANDOM_MAX - RANDOM_MIN)))));
163 DevProfile::GetInstance().SubscribeProfileEvent(device);
164 bool remoteEnable = false;
165 DevProfile::GetInstance().GetDeviceStatus(device, remoteEnable);
166 Notify();
167 }
168
Offline(const std::string & device)169 void DistributedModuleConfig::Offline(const std::string &device)
170 {
171 srand(time(nullptr));
172 std::this_thread::sleep_for(std::chrono::milliseconds((int32_t(rand() % (RANDOM_MAX - RANDOM_MIN)))));
173 DevProfile::GetInstance().UnSubscribeProfileEvent(device);
174 std::string udid = DMAdapter::GetInstance().GetUdidByNetworkId(device);
175 DevProfile::GetInstance().EraseEnabledStatus(udid);
176 Notify();
177 }
178
OnReady(const std::string & device)179 void DistributedModuleConfig::OnReady(const std::string &device)
180 {
181 (void)device;
182 }
183
Init()184 void DistributedModuleConfig::Init()
185 {
186 DMAdapter::GetInstance().Register(this);
187 DevProfile::GetInstance().Watch([this](bool isEnable) -> void {
188 Notify();
189 });
190 }
191
DeInit()192 void DistributedModuleConfig::DeInit()
193 {
194 DMAdapter::GetInstance().Unregister(this);
195 }
196
197 } // namespace MiscServices
198 } // namespace OHOS