• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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