1 /*
2 * Copyright (c) 2022 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 #define LOG_TAG "DevManager"
16 #include "dev_manager.h"
17 #include <thread>
18 #include <unistd.h>
19 #include "device_manager.h"
20 #include "device_manager_callback.h"
21 #include "dm_device_info.h"
22 #include "kvdb_service_client.h"
23 #include "log_print.h"
24 #include "store_util.h"
25 #include "task_executor.h"
26 namespace OHOS::DistributedKv {
27 using namespace OHOS::DistributedHardware;
28 constexpr int32_t DM_OK = 0;
29 constexpr int32_t DM_ERROR = -1;
30 constexpr size_t DevManager::MAX_ID_LEN;
31 constexpr const char *PKG_NAME_EX = "_distributed_data";
32 class DMStateCallback : public DeviceStateCallback {
33 public:
DMStateCallback(DevManager & devManager)34 explicit DMStateCallback(DevManager &devManager) : devManager_(devManager){};
35 void OnDeviceOnline(const DmDeviceInfo &deviceInfo) override;
36 void OnDeviceOffline(const DmDeviceInfo &deviceInfo) override;
37 void OnDeviceChanged(const DmDeviceInfo &deviceInfo) override;
38 void OnDeviceReady(const DmDeviceInfo &deviceInfo) override;
39
40 private:
41 DevManager &devManager_;
42 };
43
OnDeviceOnline(const DmDeviceInfo & deviceInfo)44 void DMStateCallback::OnDeviceOnline(const DmDeviceInfo &deviceInfo)
45 {
46 devManager_.Online(deviceInfo.networkId);
47 }
48
OnDeviceOffline(const DmDeviceInfo & deviceInfo)49 void DMStateCallback::OnDeviceOffline(const DmDeviceInfo &deviceInfo)
50 {
51 devManager_.Offline(deviceInfo.networkId);
52 }
53
OnDeviceChanged(const DmDeviceInfo & deviceInfo)54 void DMStateCallback::OnDeviceChanged(const DmDeviceInfo &deviceInfo)
55 {
56 devManager_.OnChanged(deviceInfo.networkId);
57 }
58
OnDeviceReady(const DmDeviceInfo & deviceInfo)59 void DMStateCallback::OnDeviceReady(const DmDeviceInfo &deviceInfo)
60 {
61 devManager_.OnReady(deviceInfo.networkId);
62 }
63
64 class DmDeathCallback : public DmInitCallback {
65 public:
DmDeathCallback(DevManager & devManager)66 explicit DmDeathCallback(DevManager &devManager) : devManager_(devManager){};
67 void OnRemoteDied() override;
68
69 private:
70 DevManager &devManager_;
71 };
72
OnRemoteDied()73 void DmDeathCallback::OnRemoteDied()
74 {
75 ZLOGI("dm device manager died, init it again");
76 devManager_.RegisterDevCallback();
77 }
78
DevManager(const std::string & pkgName)79 DevManager::DevManager(const std::string &pkgName) : PKG_NAME(pkgName + PKG_NAME_EX)
80 {
81 RegisterDevCallback();
82 }
83
Init()84 int32_t DevManager::Init()
85 {
86 auto &deviceManager = DeviceManager::GetInstance();
87 auto deviceInitCallback = std::make_shared<DmDeathCallback>(*this);
88 auto deviceCallback = std::make_shared<DMStateCallback>(*this);
89 int32_t errNo = deviceManager.InitDeviceManager(PKG_NAME, deviceInitCallback);
90 if (errNo != DM_OK) {
91 return errNo;
92 }
93 errNo = deviceManager.RegisterDevStateCallback(PKG_NAME, "", deviceCallback);
94 return errNo;
95 }
96
RegisterDevCallback()97 void DevManager::RegisterDevCallback()
98 {
99 auto check = Retry();
100 check();
101 }
102
Retry()103 std::function<void()> DevManager::Retry()
104 {
105 return [this]() {
106 int32_t errNo = DM_ERROR;
107 errNo = Init();
108 if (errNo == DM_OK) {
109 return;
110 }
111 constexpr int32_t interval = 100;
112 TaskExecutor::GetInstance().Execute(Retry(), interval);
113 };
114 }
115
GetInstance()116 DevManager &DevManager::GetInstance()
117 {
118 static DevManager instance(std::to_string(getpid()));
119 return instance;
120 }
121
ToUUID(const std::string & networkId)122 std::string DevManager::ToUUID(const std::string &networkId)
123 {
124 return GetDvInfoFromBucket(networkId).uuid;
125 }
126
ToNetworkId(const std::string & uuid)127 std::string DevManager::ToNetworkId(const std::string &uuid)
128 {
129 return GetDvInfoFromBucket(uuid).networkId;
130 }
131
GetDvInfoFromBucket(const std::string & id)132 DevManager::DetailInfo DevManager::GetDvInfoFromBucket(const std::string &id)
133 {
134 DetailInfo dtInfo;
135 if (!deviceInfos_.Get(id, dtInfo)) {
136 UpdateBucket();
137 deviceInfos_.Get(id, dtInfo);
138 }
139 if (dtInfo.uuid.empty()) {
140 ZLOGE("id:%{public}s", StoreUtil::Anonymous(id).c_str());
141 }
142 return dtInfo;
143 }
144
UpdateBucket()145 void DevManager::UpdateBucket()
146 {
147 auto dtInfos = GetRemoteDevices();
148 if (dtInfos.empty()) {
149 ZLOGD("no remote device");
150 }
151 dtInfos.emplace_back(GetLocalDevice());
152 for (const auto &dtInfo : dtInfos) {
153 if (dtInfo.uuid.empty() || dtInfo.networkId.empty()) {
154 continue;
155 }
156 deviceInfos_.Set(dtInfo.uuid, dtInfo);
157 deviceInfos_.Set(dtInfo.networkId, dtInfo);
158 }
159 }
160
GetLocalDevice()161 const DevManager::DetailInfo &DevManager::GetLocalDevice()
162 {
163 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
164 if (!localInfo_.uuid.empty()) {
165 return localInfo_;
166 }
167
168 auto service = KVDBServiceClient::GetInstance();
169 if (service == nullptr) {
170 ZLOGE("service unavailable");
171 return invalidDetail_;
172 }
173 auto device = service->GetLocalDevice();
174 if (device.uuid.empty() || device.networkId.empty()) {
175 return invalidDetail_;
176 }
177 localInfo_.networkId = std::move(device.networkId);
178 localInfo_.uuid = std::move(device.uuid);
179 ZLOGI("[LocalDevice] uuid:%{public}s, networkId:%{public}s",
180 StoreUtil::Anonymous(localInfo_.uuid).c_str(), StoreUtil::Anonymous(localInfo_.networkId).c_str());
181 return localInfo_;
182 }
183
GetRemoteDevices() const184 std::vector<DevManager::DetailInfo> DevManager::GetRemoteDevices() const
185 {
186 auto service = KVDBServiceClient::GetInstance();
187 if (service == nullptr) {
188 ZLOGE("service unavailable");
189 return {};
190 }
191 auto devices = service->GetRemoteDevices();
192 if (devices.empty()) {
193 ZLOGD("no remote device");
194 return {};
195 }
196 std::vector<DetailInfo> dtInfos;
197 for (auto &device : devices) {
198 DetailInfo dtInfo;
199 dtInfo.networkId = std::move(device.networkId);
200 dtInfo.uuid = std::move(device.uuid);
201 dtInfos.push_back(dtInfo);
202 }
203 return dtInfos;
204 }
205
Online(const std::string & networkId)206 void DevManager::Online(const std::string &networkId)
207 {
208 // do nothing
209 ZLOGI("%{public}s observers:%{public}zu", StoreUtil::Anonymous(networkId).c_str(), observers_.Size());
210 }
211
Offline(const std::string & networkId)212 void DevManager::Offline(const std::string &networkId)
213 {
214 DetailInfo deviceInfo;
215 if (deviceInfos_.Get(networkId, deviceInfo)) {
216 deviceInfos_.Delete(networkId);
217 deviceInfos_.Delete(deviceInfo.uuid);
218 }
219 ZLOGI("%{public}s observers:%{public}zu", StoreUtil::Anonymous(networkId).c_str(), observers_.Size());
220 observers_.ForEach([&networkId](const auto &key, auto &value) {
221 value->Offline(networkId);
222 return false;
223 });
224 }
225
OnChanged(const std::string & networkId)226 void DevManager::OnChanged(const std::string &networkId)
227 {
228 // do nothing
229 ZLOGI("%{public}s observers:%{public}zu", StoreUtil::Anonymous(networkId).c_str(), observers_.Size());
230 }
231
OnReady(const std::string & networkId)232 void DevManager::OnReady(const std::string &networkId)
233 {
234 ZLOGI("%{public}s observers:%{public}zu", StoreUtil::Anonymous(networkId).c_str(), observers_.Size());
235 observers_.ForEach([&networkId](const auto &key, auto &value) {
236 value->Online(networkId);
237 return false;
238 });
239 }
240
Register(DevManager::Observer * observer)241 void DevManager::Register(DevManager::Observer *observer)
242 {
243 observers_.Insert(observer, observer);
244 }
245
Unregister(DevManager::Observer * observer)246 void DevManager::Unregister(DevManager::Observer *observer)
247 {
248 observers_.Erase(observer);
249 }
250 } // namespace OHOS::DistributedKv
251