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