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 "DeviceManagerAdapter"
16 #include "device_manager_adapter.h"
17 #include <thread>
18 #include "log_print.h"
19 #include "kvstore_utils.h"
20
21 namespace OHOS::DistributedData {
22 using namespace OHOS::DistributedHardware;
23 using namespace OHOS::AppDistributedKv;
24 using KvStoreUtils = OHOS::DistributedKv::KvStoreUtils;
25 constexpr int32_t DM_OK = 0;
26 constexpr const char *PKG_NAME = "ohos.distributeddata.service";
27 class DataMgrDmStateCall final : public DistributedHardware::DeviceStateCallback {
28 public:
DataMgrDmStateCall(DeviceManagerAdapter & dmAdapter)29 explicit DataMgrDmStateCall(DeviceManagerAdapter &dmAdapter) : dmAdapter_(dmAdapter) {}
30 void OnDeviceOnline(const DmDeviceInfo &info) override;
31 void OnDeviceOffline(const DmDeviceInfo &info) override;
32 void OnDeviceChanged(const DmDeviceInfo &info) override;
33 void OnDeviceReady(const DmDeviceInfo &info) override;
34
35 private:
36 DeviceManagerAdapter &dmAdapter_;
37 };
38
OnDeviceOnline(const DmDeviceInfo & info)39 void DataMgrDmStateCall::OnDeviceOnline(const DmDeviceInfo &info)
40 {
41 dmAdapter_.Online(info);
42 }
43
OnDeviceOffline(const DmDeviceInfo & info)44 void DataMgrDmStateCall::OnDeviceOffline(const DmDeviceInfo &info)
45 {
46 dmAdapter_.Offline(info);
47 }
48
OnDeviceChanged(const DmDeviceInfo & info)49 void DataMgrDmStateCall::OnDeviceChanged(const DmDeviceInfo &info)
50 {
51 dmAdapter_.OnChanged(info);
52 }
53
OnDeviceReady(const DmDeviceInfo & info)54 void DataMgrDmStateCall::OnDeviceReady(const DmDeviceInfo &info)
55 {
56 dmAdapter_.OnReady(info);
57 }
58
59 class DataMgrDmInitCall final : public DistributedHardware::DmInitCallback {
60 public:
DataMgrDmInitCall(DeviceManagerAdapter & dmAdapter)61 explicit DataMgrDmInitCall(DeviceManagerAdapter &dmAdapter) : dmAdapter_(dmAdapter) {}
62 void OnRemoteDied() override;
63
64 private:
65 DeviceManagerAdapter &dmAdapter_;
66 };
67
OnRemoteDied()68 void DataMgrDmInitCall::OnRemoteDied()
69 {
70 ZLOGI("device manager died, init again");
71 dmAdapter_.Init();
72 }
73
DeviceManagerAdapter()74 DeviceManagerAdapter::DeviceManagerAdapter()
75 {
76 ZLOGI("construct");
77 threadPool_ = KvStoreThreadPool::GetPool(POOL_SIZE, "DeviceMgr", true);
78 }
79
~DeviceManagerAdapter()80 DeviceManagerAdapter::~DeviceManagerAdapter()
81 {
82 ZLOGI("Destruct");
83 if (threadPool_ != nullptr) {
84 threadPool_->Stop();
85 threadPool_ = nullptr;
86 }
87 }
88
GetInstance()89 DeviceManagerAdapter &DeviceManagerAdapter::GetInstance()
90 {
91 static DeviceManagerAdapter dmAdapter;
92 return dmAdapter;
93 }
94
Init()95 void DeviceManagerAdapter::Init()
96 {
97 ZLOGI("begin");
98 Execute(RegDevCallback());
99 }
100
RegDevCallback()101 std::function<void()> DeviceManagerAdapter::RegDevCallback()
102 {
103 return [this]() {
104 auto &devManager = DeviceManager::GetInstance();
105 auto dmStateCall = std::make_shared<DataMgrDmStateCall>(*this);
106 auto dmInitCall = std::make_shared<DataMgrDmInitCall>(*this);
107 auto resultInit = devManager.InitDeviceManager(PKG_NAME, dmInitCall);
108 auto resultState = devManager.RegisterDevStateCallback(PKG_NAME, "", dmStateCall);
109 if (resultInit == DM_OK && resultState == DM_OK) {
110 return;
111 }
112 constexpr int32_t INTERVAL = 500;
113 auto time = std::chrono::steady_clock::now() + std::chrono::milliseconds(INTERVAL);
114 scheduler_.At(time, RegDevCallback());
115 };
116 }
117
StartWatchDeviceChange(const AppDeviceChangeListener * observer,const PipeInfo & pipeInfo)118 Status DeviceManagerAdapter::StartWatchDeviceChange(const AppDeviceChangeListener *observer,
119 __attribute__((unused)) const PipeInfo &pipeInfo)
120 {
121 if (observer == nullptr) {
122 ZLOGE("observer is nullptr");
123 return Status::INVALID_ARGUMENT;
124 }
125 if (!observers_.Insert(observer, observer)) {
126 ZLOGE("insert observer fail");
127 return Status::ERROR;
128 }
129 return Status::SUCCESS;
130 }
131
StopWatchDeviceChange(const AppDeviceChangeListener * observer,const PipeInfo & pipeInfo)132 Status DeviceManagerAdapter::StopWatchDeviceChange(const AppDeviceChangeListener *observer,
133 __attribute__((unused)) const PipeInfo &pipeInfo)
134 {
135 if (observer == nullptr) {
136 ZLOGE("observer is nullptr");
137 return Status::INVALID_ARGUMENT;
138 }
139 if (!observers_.Erase(observer)) {
140 ZLOGE("erase observer fail");
141 return Status::ERROR;
142 }
143 return Status::SUCCESS;
144 }
145
Online(const DmDeviceInfo & info)146 void DeviceManagerAdapter::Online(const DmDeviceInfo &info)
147 {
148 DeviceInfo dvInfo;
149 if (!GetDeviceInfo(info, dvInfo)) {
150 ZLOGE("get device info fail");
151 return;
152 }
153 ZLOGI("[online] uuid:%{public}s, name:%{public}s, type:%{public}d",
154 KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType);
155 SaveDeviceInfo(dvInfo, DeviceChangeType::DEVICE_ONLINE);
156 auto observers = GetObservers();
157 for (const auto &item : observers) { // notify db
158 if (item == nullptr) {
159 continue;
160 }
161 if (item->GetChangeLevelType() == ChangeLevelType::HIGH) {
162 item->OnDeviceChanged(dvInfo, DeviceChangeType::DEVICE_OFFLINE);
163 item->OnDeviceChanged(dvInfo, DeviceChangeType::DEVICE_ONLINE);
164 }
165 }
166 for (const auto &item : observers) { // sync meta, get device security level
167 if (item == nullptr) {
168 continue;
169 }
170 if (item->GetChangeLevelType() == ChangeLevelType::LOW) {
171 item->OnDeviceChanged(dvInfo, DeviceChangeType::DEVICE_ONLINE);
172 }
173 }
174 auto time = std::chrono::steady_clock::now() + std::chrono::milliseconds(SYNC_TIMEOUT);
175 scheduler_.At(time, [this, dvInfo]() { TimeOut(dvInfo.uuid); });
176 syncTask_.Insert(dvInfo.uuid, dvInfo.uuid);
177 for (const auto &item : observers) { // set compatible identify, sync service meta
178 if (item == nullptr) {
179 continue;
180 }
181 if (item->GetChangeLevelType() == ChangeLevelType::MIN) {
182 item->OnDeviceChanged(dvInfo, DeviceChangeType::DEVICE_ONLINE);
183 }
184 }
185 }
186
TimeOut(const std::string uuid)187 void DeviceManagerAdapter::TimeOut(const std::string uuid)
188 {
189 if (uuid.empty()) {
190 ZLOGE("uuid empty!");
191 return;
192 }
193 if (syncTask_.Contains(uuid)) {
194 ZLOGI("[TimeOutReadyEvent] uuid:%{public}s", KvStoreUtils::ToBeAnonymous(uuid).c_str());
195 std::string event = R"({"extra": {"deviceId":")" + uuid + R"(" } })";
196 DeviceManager::GetInstance().NotifyEvent(PKG_NAME, DmNotifyEvent::DM_NOTIFY_EVENT_ONDEVICEREADY, event);
197 }
198 syncTask_.Erase(uuid);
199 }
200
NotifyReadyEvent(const std::string & uuid)201 void DeviceManagerAdapter::NotifyReadyEvent(const std::string &uuid)
202 {
203 if (uuid.empty() || !syncTask_.Contains(uuid)) {
204 return;
205 }
206
207 syncTask_.Erase(uuid);
208 ZLOGI("[NotifyReadyEvent] uuid:%{public}s", KvStoreUtils::ToBeAnonymous(uuid).c_str());
209 std::string event = R"({"extra": {"deviceId":")" + uuid + R"(" } })";
210 DeviceManager::GetInstance().NotifyEvent(PKG_NAME, DmNotifyEvent::DM_NOTIFY_EVENT_ONDEVICEREADY, event);
211 }
212
GetObservers()213 std::vector<const AppDeviceChangeListener *> DeviceManagerAdapter::GetObservers()
214 {
215 std::vector<const AppDeviceChangeListener *> observers;
216 observers.resize(observers_.Size());
217 observers_.ForEach([&observers](const auto &key, auto &value) {
218 observers.emplace_back(value);
219 return false;
220 });
221 return observers;
222 }
223
Offline(const DmDeviceInfo & info)224 void DeviceManagerAdapter::Offline(const DmDeviceInfo &info)
225 {
226 DeviceInfo dvInfo;
227 if (!GetDeviceInfo(info, dvInfo)) {
228 ZLOGE("get device info fail");
229 return;
230 }
231 syncTask_.Erase(dvInfo.uuid);
232 ZLOGI("[offline] uuid:%{public}s, name:%{public}s, type:%{public}d",
233 KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType);
234 SaveDeviceInfo(dvInfo, DeviceChangeType::DEVICE_OFFLINE);
235 KvStoreTask task([this, dvInfo]() {
236 auto observers = GetObservers();
237 for (const auto &item : observers) {
238 if (item == nullptr) {
239 continue;
240 }
241 item->OnDeviceChanged(dvInfo, DeviceChangeType::DEVICE_OFFLINE);
242 }
243 }, "deviceOffline");
244 Execute(std::move(task));
245 }
246
OnChanged(const DmDeviceInfo & info)247 void DeviceManagerAdapter::OnChanged(const DmDeviceInfo &info)
248 {
249 DeviceInfo dvInfo;
250 if (!GetDeviceInfo(info, dvInfo)) {
251 ZLOGE("get device info fail");
252 return;
253 }
254 ZLOGI("[OnChanged] uuid:%{public}s, name:%{public}s, type:%{public}d",
255 KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType);
256 }
257
OnReady(const DmDeviceInfo & info)258 void DeviceManagerAdapter::OnReady(const DmDeviceInfo &info)
259 {
260 DeviceInfo dvInfo;
261 if (!GetDeviceInfo(info, dvInfo)) {
262 ZLOGE("get device info fail");
263 return;
264 }
265 ZLOGI("[OnReady] uuid:%{public}s, name:%{public}s, type:%{public}d",
266 KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType);
267 KvStoreTask task([this, dvInfo]() {
268 auto observers = GetObservers();
269 for (const auto &item : observers) {
270 if (item == nullptr) {
271 continue;
272 }
273 item->OnDeviceChanged(dvInfo, DeviceChangeType::DEVICE_ONREADY);
274 }
275 }, "deviceReady");
276 Execute(std::move(task));
277 }
278
GetDeviceInfo(const DmDeviceInfo & dmInfo,DeviceInfo & dvInfo)279 bool DeviceManagerAdapter::GetDeviceInfo(const DmDeviceInfo &dmInfo, DeviceInfo &dvInfo)
280 {
281 std::string networkId = std::string(dmInfo.networkId);
282 if (networkId.empty()) {
283 return false;
284 }
285 auto uuid = GetUuidByNetworkId(networkId);
286 auto udid = GetUdidByNetworkId(networkId);
287 if (uuid.empty() || udid.empty()) {
288 return false;
289 }
290 dvInfo = { uuid, udid, networkId, std::string(dmInfo.deviceName), dmInfo.deviceTypeId };
291 return true;
292 }
293
SaveDeviceInfo(const DeviceInfo & dvInfo,const DeviceChangeType & type)294 void DeviceManagerAdapter::SaveDeviceInfo(const DeviceInfo &dvInfo, const DeviceChangeType &type)
295 {
296 switch (type) {
297 case DeviceChangeType::DEVICE_ONLINE: {
298 deviceInfos_.Set(dvInfo.networkId, dvInfo);
299 deviceInfos_.Set(dvInfo.uuid, dvInfo);
300 deviceInfos_.Set(dvInfo.udid, dvInfo);
301 break;
302 }
303 case DeviceChangeType::DEVICE_OFFLINE: {
304 deviceInfos_.Delete(dvInfo.networkId);
305 deviceInfos_.Delete(dvInfo.uuid);
306 deviceInfos_.Delete(dvInfo.udid);
307 break;
308 }
309 default: {
310 ZLOGW("unknown type.");
311 break;
312 }
313 }
314 }
315
GetLocalDevice()316 DeviceInfo DeviceManagerAdapter::GetLocalDevice()
317 {
318 std::lock_guard<decltype(devInfoMutex_)> lock(devInfoMutex_);
319 if (!localInfo_.uuid.empty()) {
320 return localInfo_;
321 }
322
323 DmDeviceInfo info;
324 auto ret = DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, info);
325 if (ret != DM_OK) {
326 ZLOGE("get local device info fail");
327 return {};
328 }
329 auto networkId = std::string(info.networkId);
330 auto uuid = GetUuidByNetworkId(networkId);
331 auto udid = GetUdidByNetworkId(networkId);
332 if (uuid.empty() || udid.empty()) {
333 return {};
334 }
335 ZLOGI("[LocalDevice] uuid:%{public}s, name:%{public}s, type:%{public}d",
336 KvStoreUtils::ToBeAnonymous(uuid).c_str(), info.deviceName, info.deviceTypeId);
337 localInfo_ = { std::move(uuid), std::move(udid), std::move(networkId),
338 std::string(info.deviceName), info.deviceTypeId };
339 return localInfo_;
340 }
341
GetRemoteDevices()342 std::vector<DeviceInfo> DeviceManagerAdapter::GetRemoteDevices()
343 {
344 std::vector<DmDeviceInfo> dmInfos;
345 auto ret = DeviceManager::GetInstance().GetTrustedDeviceList(PKG_NAME, "", dmInfos);
346 if (ret != DM_OK) {
347 ZLOGE("get trusted device:%{public}d", ret);
348 return {};
349 }
350
351 std::vector<DeviceInfo> dvInfos;
352 for (const auto &dmInfo : dmInfos) {
353 auto networkId = std::string(dmInfo.networkId);
354 auto uuid = GetUuidByNetworkId(networkId);
355 auto udid = GetUdidByNetworkId(networkId);
356 DeviceInfo dvInfo = { std::move(uuid), std::move(udid), std::move(networkId),
357 std::string(dmInfo.deviceName), dmInfo.deviceTypeId };
358 dvInfos.emplace_back(std::move(dvInfo));
359 }
360 return dvInfos;
361 }
362
GetDeviceInfo(const std::string & id)363 DeviceInfo DeviceManagerAdapter::GetDeviceInfo(const std::string &id)
364 {
365 return GetDeviceInfoFromCache(id);
366 }
367
GetDeviceInfoFromCache(const std::string & id)368 DeviceInfo DeviceManagerAdapter::GetDeviceInfoFromCache(const std::string &id)
369 {
370 DeviceInfo dvInfo;
371 if (!deviceInfos_.Get(id, dvInfo)) {
372 UpdateDeviceInfo();
373 deviceInfos_.Get(id, dvInfo);
374 }
375 if (dvInfo.uuid.empty()) {
376 ZLOGE("invalid id:%{public}s", KvStoreUtils::ToBeAnonymous(id).c_str());
377 }
378 return dvInfo;
379 }
380
Execute(KvStoreTask && task)381 bool DeviceManagerAdapter::Execute(KvStoreTask &&task)
382 {
383 if (threadPool_ == nullptr) {
384 return false;
385 }
386 threadPool_->AddTask(std::move(task));
387 return true;
388 }
389
UpdateDeviceInfo()390 void DeviceManagerAdapter::UpdateDeviceInfo()
391 {
392 std::vector<DeviceInfo> dvInfos = GetRemoteDevices();
393 if (dvInfos.empty()) {
394 ZLOGW("there is no trusted device!");
395 return;
396 }
397 dvInfos.emplace_back(GetLocalDevice());
398 for (const auto &info : dvInfos) {
399 if (info.networkId.empty() || info.uuid.empty() || info.udid.empty()) {
400 ZLOGE("networkId:%{public}s, uuid:%{public}d, udid:%{public}d",
401 KvStoreUtils::ToBeAnonymous(info.networkId).c_str(), info.uuid.empty(), info.udid.empty());
402 continue;
403 }
404 deviceInfos_.Set(info.networkId, info);
405 deviceInfos_.Set(info.uuid, info);
406 deviceInfos_.Set(info.udid, info);
407 }
408 }
409
GetUuidByNetworkId(const std::string & networkId)410 std::string DeviceManagerAdapter::GetUuidByNetworkId(const std::string &networkId)
411 {
412 if (networkId.empty()) {
413 return "";
414 }
415 DeviceInfo dvInfo;
416 if (deviceInfos_.Get(networkId, dvInfo)) {
417 return dvInfo.uuid;
418 }
419 std::string uuid;
420 auto ret = DeviceManager::GetInstance().GetUuidByNetworkId(PKG_NAME, networkId, uuid);
421 if (ret != DM_OK || uuid.empty()) {
422 ZLOGE("failed, result:%{public}d, networkId:%{public}s", ret, KvStoreUtils::ToBeAnonymous(networkId).c_str());
423 return "";
424 }
425 return uuid;
426 }
427
GetUdidByNetworkId(const std::string & networkId)428 std::string DeviceManagerAdapter::GetUdidByNetworkId(const std::string &networkId)
429 {
430 if (networkId.empty()) {
431 return "";
432 }
433 DeviceInfo dvInfo;
434 if (deviceInfos_.Get(networkId, dvInfo)) {
435 return dvInfo.udid;
436 }
437 std::string udid;
438 auto ret = DeviceManager::GetInstance().GetUdidByNetworkId(PKG_NAME, networkId, udid);
439 if (ret != DM_OK || udid.empty()) {
440 ZLOGE("failed, result:%{public}d, networkId:%{public}s", ret, KvStoreUtils::ToBeAnonymous(networkId).c_str());
441 return "";
442 }
443 return udid;
444 }
445
GetLocalBasicInfo()446 DeviceInfo DeviceManagerAdapter::GetLocalBasicInfo()
447 {
448 return GetLocalDevice();
449 }
450
ToUUID(const std::string & id)451 std::string DeviceManagerAdapter::ToUUID(const std::string &id)
452 {
453 return GetDeviceInfoFromCache(id).uuid;
454 }
455
ToUDID(const std::string & id)456 std::string DeviceManagerAdapter::ToUDID(const std::string &id)
457 {
458 return GetDeviceInfoFromCache(id).udid;
459 }
460
ToUUID(const std::vector<std::string> & devices)461 std::vector<std::string> DeviceManagerAdapter::ToUUID(const std::vector<std::string> &devices)
462 {
463 std::vector<std::string> uuids;
464 for (auto &device : devices) {
465 auto uuid = DeviceManagerAdapter::GetInstance().ToUUID(device);
466 if (uuid.empty()) {
467 continue ;
468 }
469 uuids.push_back(std::move(uuid));
470 }
471 return uuids;
472 }
473
ToUUID(std::vector<DeviceInfo> devices)474 std::vector<std::string> DeviceManagerAdapter::ToUUID(std::vector<DeviceInfo> devices)
475 {
476 std::vector<std::string> uuids;
477 for (auto &device : devices) {
478 if (device.uuid.empty()) {
479 continue ;
480 }
481 uuids.push_back(std::move(device.uuid));
482 }
483 return uuids;
484 }
485
ToNetworkID(const std::string & id)486 std::string DeviceManagerAdapter::ToNetworkID(const std::string &id)
487 {
488 return GetDeviceInfoFromCache(id).networkId;
489 }
490
CalcClientUuid(const std::string & appId,const std::string & uuid)491 std::string DeviceManagerAdapter::CalcClientUuid(const std::string &appId, const std::string &uuid)
492 {
493 if (uuid.empty()) {
494 return "";
495 }
496 std::string encryptedUuid;
497 auto ret = DeviceManager::GetInstance().GenerateEncryptedUuid(PKG_NAME, uuid, appId, encryptedUuid);
498 if (ret != DM_OK) {
499 ZLOGE("failed, result:%{public}d", ret);
500 return "";
501 }
502 return encryptedUuid;
503 }
504 } // namespace OHOS::DistributedData
505