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 <unistd.h>
18 #include "device_manager.h"
19 #include "device_manager_callback.h"
20 #include "dm_device_info.h"
21 #include "kvdb_service_client.h"
22 #include "log_print.h"
23 #include "store_util.h"
24 #include "task_executor.h"
25 namespace OHOS::DistributedKv {
26 using namespace OHOS::DistributedHardware;
27 using DevInfo = OHOS::DistributedHardware::DmDeviceInfo;
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 DmDeathCallback : public DmInitCallback {
33 public:
DmDeathCallback(DevManager & devManager)34     explicit DmDeathCallback(DevManager &devManager) : devManager_(devManager){};
35     void OnRemoteDied() override;
36 
37 private:
38     DevManager &devManager_;
39 };
40 
OnRemoteDied()41 void DmDeathCallback::OnRemoteDied()
42 {
43     ZLOGI("dm device manager died, init it again");
44     devManager_.RegisterDevCallback();
45 }
46 
DevManager(const std::string & pkgName)47 DevManager::DevManager(const std::string &pkgName) : PKG_NAME(pkgName + PKG_NAME_EX)
48 {
49     RegisterDevCallback();
50 }
51 
Init()52 int32_t DevManager::Init()
53 {
54     auto &deviceManager = DeviceManager::GetInstance();
55     auto deviceInitCallback = std::make_shared<DmDeathCallback>(*this);
56     return deviceManager.InitDeviceManager(PKG_NAME, deviceInitCallback);
57 }
58 
RegisterDevCallback()59 void DevManager::RegisterDevCallback()
60 {
61     auto check = Retry();
62     check();
63 }
64 
Retry()65 std::function<void()> DevManager::Retry()
66 {
67     return [this]() {
68         int32_t errNo = DM_ERROR;
69         errNo = Init();
70         if (errNo == DM_OK) {
71             return;
72         }
73         constexpr int32_t interval = 100;
74         TaskExecutor::GetInstance().Schedule(std::chrono::milliseconds(interval), Retry());
75     };
76 }
77 
GetInstance()78 DevManager &DevManager::GetInstance()
79 {
80     static DevManager instance(std::to_string(getpid()));
81     return instance;
82 }
83 
ToUUID(const std::string & networkId)84 std::string DevManager::ToUUID(const std::string &networkId)
85 {
86     return GetDevInfoFromBucket(networkId).uuid;
87 }
88 
ToNetworkId(const std::string & uuid)89 std::string DevManager::ToNetworkId(const std::string &uuid)
90 {
91     return GetDevInfoFromBucket(uuid).networkId;
92 }
93 
GetDevInfoFromBucket(const std::string & id)94 DevManager::DetailInfo DevManager::GetDevInfoFromBucket(const std::string &id)
95 {
96     DetailInfo detailInfo;
97     if (!deviceInfos_.Get(id, detailInfo)) {
98         UpdateBucket();
99         deviceInfos_.Get(id, detailInfo);
100     }
101     if (detailInfo.uuid.empty()) {
102         ZLOGE("id:%{public}s", StoreUtil::Anonymous(id).c_str());
103     }
104     return detailInfo;
105 }
106 
UpdateBucket()107 void DevManager::UpdateBucket()
108 {
109     auto detailInfos = GetRemoteDevices();
110     if (detailInfos.empty()) {
111         ZLOGD("no remote device");
112     }
113     detailInfos.emplace_back(GetLocalDevice());
114     for (const auto &detailInfo : detailInfos) {
115         if (detailInfo.uuid.empty() || detailInfo.networkId.empty()) {
116             continue;
117         }
118         deviceInfos_.Set(detailInfo.uuid, detailInfo);
119         deviceInfos_.Set(detailInfo.networkId, detailInfo);
120     }
121 }
122 
GetUnEncryptedUuid()123 std::string DevManager::GetUnEncryptedUuid()
124 {
125     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
126     if (!UnEncryptedLocalInfo_.uuid.empty()) {
127         return UnEncryptedLocalInfo_.uuid;
128     }
129     DevInfo info;
130     auto ret = DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, info);
131     if (ret != DM_OK) {
132         ZLOGE("get local device info fail");
133         return "";
134     }
135     auto networkId = std::string(info.networkId);
136     if (networkId.empty()) {
137         ZLOGE("networkid empty");
138         return "";
139     }
140     std::string uuid;
141     DeviceManager::GetInstance().GetUuidByNetworkId(PKG_NAME, networkId, uuid);
142     if (uuid.empty()) {
143         ZLOGE("get uuid by networkid fail");
144         return "";
145     }
146     UnEncryptedLocalInfo_.uuid = std::move(uuid);
147     ZLOGI("[GetUnEncryptedUuid] uuid:%{public}s, networkId:%{public}s",
148         StoreUtil::Anonymous(UnEncryptedLocalInfo_.uuid).c_str(),
149         StoreUtil::Anonymous(networkId).c_str());
150     return UnEncryptedLocalInfo_.uuid;
151 }
152 
GetLocalDevice()153 const DevManager::DetailInfo &DevManager::GetLocalDevice()
154 {
155     std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
156     if (!localInfo_.uuid.empty()) {
157         return localInfo_;
158     }
159     DevInfo info;
160     auto ret = DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, info);
161     if (ret != DM_OK) {
162         ZLOGE("get local device info fail");
163         return invalidDetail_;
164     }
165     auto networkId = std::string(info.networkId);
166     std::string uuid;
167     DeviceManager::GetInstance().GetEncryptedUuidByNetworkId(PKG_NAME, networkId, uuid);
168     if (uuid.empty() || networkId.empty()) {
169         return invalidDetail_;
170     }
171     localInfo_.networkId = std::move(networkId);
172     localInfo_.uuid = std::move(uuid);
173     ZLOGI("[LocalDevice] uuid:%{public}s, networkId:%{public}s", StoreUtil::Anonymous(localInfo_.uuid).c_str(),
174         StoreUtil::Anonymous(localInfo_.networkId).c_str());
175     return localInfo_;
176 }
177 
GetRemoteDevices()178 std::vector<DevManager::DetailInfo> DevManager::GetRemoteDevices()
179 {
180     std::vector<DevInfo> dmInfos;
181     auto ret = DeviceManager::GetInstance().GetTrustedDeviceList(PKG_NAME, "", dmInfos);
182     if (ret != DM_OK) {
183         ZLOGE("get trusted device:%{public}d", ret);
184         return {};
185     }
186     if (dmInfos.empty()) {
187         ZLOGD("no remote device");
188         return {};
189     }
190     std::vector<DetailInfo> dtInfos;
191     for (auto &device : dmInfos) {
192         DetailInfo dtInfo;
193         auto networkId = std::string(device.networkId);
194         std::string uuid;
195         DeviceManager::GetInstance().GetEncryptedUuidByNetworkId(PKG_NAME, networkId, uuid);
196         dtInfo.networkId = std::move(device.networkId);
197         dtInfo.uuid = std::move(uuid);
198         dtInfos.push_back(dtInfo);
199     }
200     return dtInfos;
201 }
202 } // namespace OHOS::DistributedKv
203