1 /*
2 * Copyright (C) 2021 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 MLOG_TAG "Distributed"
16
17 #include "medialibrary_device.h"
18 #include "device_permission_verification.h"
19 #include "device_auth.h"
20 #include "media_log.h"
21 #include "medialibrary_data_manager.h"
22 #include "medialibrary_sync_table.h"
23 #include "medialibrary_tracer.h"
24
25 namespace OHOS {
26 namespace Media {
27 using namespace std;
28 using namespace OHOS::AppExecFwk;
29 std::shared_ptr<MediaLibraryDevice> MediaLibraryDevice::mlDMInstance_ = nullptr;
30
31 constexpr int TRIM_LENGTH = 4;
MediaLibraryDevice()32 MediaLibraryDevice::MediaLibraryDevice()
33 {
34 MEDIA_DEBUG_LOG("MediaLibraryDevice::constructor");
35 }
36
~MediaLibraryDevice()37 MediaLibraryDevice::~MediaLibraryDevice()
38 {
39 MEDIA_DEBUG_LOG("MediaLibraryDevice::deconstructor");
40 }
41
Start()42 void MediaLibraryDevice::Start()
43 {
44 MEDIA_DEBUG_LOG("MediaLibraryDevice::start");
45 bundleName_ = BUNDLE_NAME;
46 RegisterToDM();
47 if (deviceHandler_ == nullptr) {
48 auto runner = AppExecFwk::EventRunner::Create("MediaLibraryDevice");
49 deviceHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
50 }
51 devsInfoInter_ = make_shared<DevicesInfoInteract>();
52 if (devsInfoInter_ != nullptr) {
53 devsInfoInter_->Init();
54 std::string local = "";
55 localUdid_ = GetUdidByNetworkId(local);
56 devsInfoInter_->PutMLDeviceInfos(localUdid_);
57 isStart = true;
58 } else {
59 MEDIA_ERR_LOG("init devsInfoInter failed");
60 }
61 }
62
Stop()63 void MediaLibraryDevice::Stop()
64 {
65 MEDIA_DEBUG_LOG("Stop enter");
66 UnRegisterFromDM();
67 ClearAllDevices();
68 isStart = false;
69 devsInfoInter_ = nullptr;
70 kvSyncDoneCv_.notify_all();
71 }
72
GetInstance()73 std::shared_ptr<MediaLibraryDevice> MediaLibraryDevice::GetInstance()
74 {
75 static std::once_flag onceFlag;
76 std::call_once(onceFlag, []() mutable {
77 mlDMInstance_ = std::shared_ptr<MediaLibraryDevice>(new(std::nothrow) MediaLibraryDevice());
78 if (mlDMInstance_ != nullptr) {
79 mlDMInstance_ ->Start();
80 }
81 });
82 return mlDMInstance_;
83 }
84
GetAllDeviceId(std::vector<OHOS::DistributedHardware::DmDeviceInfo> & deviceList)85 void MediaLibraryDevice::GetAllDeviceId(
86 std::vector<OHOS::DistributedHardware::DmDeviceInfo> &deviceList)
87 {
88 std::string extra = "";
89 auto &deviceManager = OHOS::DistributedHardware::DeviceManager::GetInstance();
90 int32_t ret = deviceManager.GetTrustedDeviceList(bundleName_, extra, deviceList);
91 if (ret != 0) {
92 MEDIA_ERR_LOG("get trusted device list failed, ret %{public}d", ret);
93 }
94 }
OnSyncCompleted(const std::string & devId,const DistributedKv::Status status)95 void MediaLibraryDevice::OnSyncCompleted(const std::string &devId, const DistributedKv::Status status)
96 {
97 MEDIA_INFO_LOG("OnSyncCompleted dev id %{private}s, status %{public}d", devId.c_str(), status);
98 std::unique_lock<std::mutex> lock(cvMtx_);
99 kvSyncDoneCv_.notify_one();
100 }
101
TryToGetTargetDevMLInfos(const std::string & udid,const std::string & networkId)102 void MediaLibraryDevice::TryToGetTargetDevMLInfos(const std::string &udid, const std::string &networkId)
103 {
104 static constexpr int SLEEP_WAITOUT = 500;
105 if (devsInfoInter_ == nullptr) {
106 MEDIA_ERR_LOG("devsInfoInter_ is nullptr");
107 return;
108 }
109 std::string version;
110 bool ret = devsInfoInter_->GetMLDeviceInfos(udid, version);
111 if (!ret) {
112 MEDIA_INFO_LOG("get ml infos failed, so try to sync pull first, wait...");
113 devsInfoInter_->SyncMLDeviceInfos(udid, networkId);
114 {
115 std::unique_lock<std::mutex> lock(cvMtx_);
116 if (kvSyncDoneCv_.wait_for(lock, std::chrono::milliseconds(SLEEP_WAITOUT)) == std::cv_status::timeout) {
117 MEDIA_DEBUG_LOG("get ml infos sync timeout");
118 }
119 if (!isStart) {
120 MEDIA_ERR_LOG("MediaLibraryDevice is stopped, this thread will exit");
121 return;
122 }
123 }
124 MEDIA_DEBUG_LOG("get ml infos sync done, wakeup, try to get again");
125 ret = devsInfoInter_->GetMLDeviceInfos(udid, version);
126 if (!ret) {
127 MEDIA_ERR_LOG("get ml infos failed again, maybe target dev have never init");
128 return;
129 }
130 }
131 lock_guard<std::mutex> lock(devMtx_);
132 deviceInfoMap_[networkId].versionId = version;
133 MEDIA_INFO_LOG("get dev %{private}s ml infos, version %{private}s",
134 networkId.substr(0, TRIM_LENGTH).c_str(), version.c_str());
135 }
136
OnGetDevSecLevel(const std::string & udid,const int32_t devLevel)137 void MediaLibraryDevice::OnGetDevSecLevel(const std::string &udid, const int32_t devLevel)
138 {
139 MEDIA_INFO_LOG("get dev %{public}s sec level %{public}d", udid.substr(0, TRIM_LENGTH).c_str(), devLevel);
140 if (udid == localUdid_) {
141 localDevLev_ = devLevel;
142 localSecLevelGot_.store(true);
143 localSecLevelDoneCv_.notify_all();
144 MEDIA_INFO_LOG("get local dev sec level %{public}d, notify all wait pids", devLevel);
145 return;
146 }
147 {
148 std::unique_lock<std::mutex> cvlock(gotSecLevelMtx_);
149 localSecLevelDoneCv_.wait(cvlock, [this] () { return localSecLevelGot_.load(); });
150 MEDIA_INFO_LOG("wakeup, get other dev sec level %{public}d", devLevel);
151 }
152
153 if (localDevLev_ < devLevel || devLevel <= 0) {
154 MEDIA_ERR_LOG("local dev's sec lev %{public}d is lower than dev %{private}s %{public}d, or level invalid!",
155 localDevLev_, udid.substr(0, TRIM_LENGTH).c_str(), devLevel);
156 return;
157 }
158
159 MediaLibraryDeviceInfo mldevInfo;
160 bool findTargetDev {false};
161 {
162 lock_guard<mutex> lock(devMtx_);
163 for (auto &[_, mlinfo] : deviceInfoMap_) {
164 if (mlinfo.deviceUdid == udid) {
165 mldevInfo = mlinfo;
166 findTargetDev = true;
167 break;
168 }
169 }
170 }
171 if (!findTargetDev) {
172 MEDIA_ERR_LOG("not find this dev %{private}s in device map table", udid.substr(0, TRIM_LENGTH).c_str());
173 return;
174 }
175
176 if (!MediaLibraryDeviceOperations::InsertDeviceInfo(rdbStore_, mldevInfo, bundleName_)) {
177 MEDIA_ERR_LOG("OnDeviceOnline InsertDeviceInfo failed!");
178 return;
179 }
180
181 lock_guard<mutex> lock(devMtx_);
182 mldevInfo.devSecLevel = devLevel;
183 deviceInfoMap_[mldevInfo.networkId] = mldevInfo;
184 }
185
DevOnlineProcess(const DistributedHardware::DmDeviceInfo & devInfo)186 void MediaLibraryDevice::DevOnlineProcess(const DistributedHardware::DmDeviceInfo &devInfo)
187 {
188 if (!localSecLevelGot_.load()) {
189 DevicePermissionVerification::ReqDestDevSecLevel(localUdid_);
190 }
191 MediaLibraryDeviceInfo mldevInfo;
192 GetMediaLibraryDeviceInfo(devInfo, mldevInfo);
193 {
194 lock_guard<mutex> autoLock(devMtx_);
195 deviceInfoMap_[devInfo.networkId] = mldevInfo;
196 }
197
198 if (!DevicePermissionVerification::CheckPermission(mldevInfo.deviceUdid)) {
199 MEDIA_ERR_LOG("this dev has permission denied!");
200 return;
201 }
202
203 std::vector<std::string> devices = { mldevInfo.networkId };
204 MediaLibrarySyncTable::SyncPullAllTableByDeviceId(rdbStore_, bundleName_, devices);
205
206 auto getTargetMLInfoTask = std::make_unique<std::thread>(&MediaLibraryDevice::TryToGetTargetDevMLInfos,
207 this, mldevInfo.deviceUdid, mldevInfo.networkId);
208 getTargetMLInfoTask->detach();
209 }
210
OnDeviceOnline(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)211 void MediaLibraryDevice::OnDeviceOnline(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
212 {
213 MEDIA_INFO_LOG("dev online network id %{private}s", deviceInfo.networkId);
214 }
215
OnDeviceOffline(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)216 void MediaLibraryDevice::OnDeviceOffline(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
217 {
218 MEDIA_INFO_LOG("OnDeviceOffline networkId = %{private}s", deviceInfo.networkId);
219
220 if (deviceHandler_ == nullptr) {
221 MEDIA_ERR_LOG("OnDeviceOffline mediaLibraryDeviceHandler null");
222 return;
223 }
224 auto nodeOffline = [this, deviceInfo]() {
225 lock_guard<mutex> autoLock(devMtx_);
226 std::string networkId = deviceInfo.networkId;
227 auto info = deviceInfoMap_.find(networkId);
228 if (info == deviceInfoMap_.end()) {
229 MEDIA_ERR_LOG("OnDeviceOffline can not find networkId:%{private}s", networkId.c_str());
230 return;
231 }
232
233 MediaLibraryDeviceOperations::UpdateDeviceInfo(rdbStore_, info->second, bundleName_);
234 deviceInfoMap_.erase(networkId);
235
236 // 设备变更通知
237 NotifyDeviceChange();
238 };
239 if (!deviceHandler_->PostTask(nodeOffline)) {
240 MEDIA_ERR_LOG("OnDeviceOffline handler postTask failed");
241 }
242 }
243
OnDeviceChanged(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)244 void MediaLibraryDevice::OnDeviceChanged(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
245 {
246 MEDIA_INFO_LOG("MediaLibraryDevice OnDeviceChanged called networkId = %{private}s", deviceInfo.networkId);
247 }
248
OnDeviceReady(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)249 void MediaLibraryDevice::OnDeviceReady(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
250 {
251 MEDIA_INFO_LOG("OnDeviceReady network id %{private}s", deviceInfo.networkId);
252 if (deviceHandler_ == nullptr) {
253 MEDIA_ERR_LOG("mediaLibraryDeviceHandler null");
254 return;
255 }
256
257 auto nodeOnline = [this, deviceInfo]() {
258 DevOnlineProcess(deviceInfo);
259 NotifyDeviceChange();
260 };
261 if (!deviceHandler_->PostTask(nodeOnline)) {
262 MEDIA_ERR_LOG("handler postTask failed");
263 }
264 }
265
ClearAllDevices()266 void MediaLibraryDevice::ClearAllDevices()
267 {
268 lock_guard<mutex> autoLock(devMtx_);
269 deviceInfoMap_.clear();
270 excludeMap_.clear();
271 }
272
NotifyDeviceChange()273 void MediaLibraryDevice::NotifyDeviceChange()
274 {
275 auto contextUri = make_unique<Uri>(MEDIALIBRARY_DEVICE_URI);
276 MediaLibraryDataManager::GetInstance()->NotifyChange(*contextUri);
277 }
278
NotifyRemoteFileChange()279 void MediaLibraryDevice::NotifyRemoteFileChange()
280 {
281 auto contextUri = make_unique<Uri>(MEDIALIBRARY_REMOTEFILE_URI);
282 MediaLibraryDataManager::GetInstance()->NotifyChange(*contextUri);
283 }
284
IsHasDevice(const string & deviceUdid)285 bool MediaLibraryDevice::IsHasDevice(const string &deviceUdid)
286 {
287 for (auto &[_, info] : deviceInfoMap_) {
288 if (!deviceUdid.compare(info.deviceUdid)) {
289 return true;
290 }
291 }
292 return false;
293 }
294
InitDeviceRdbStore(const shared_ptr<NativeRdb::RdbStore> & rdbStore)295 bool MediaLibraryDevice::InitDeviceRdbStore(const shared_ptr<NativeRdb::RdbStore> &rdbStore)
296 {
297 rdbStore_ = rdbStore;
298
299 if (!QueryDeviceTable()) {
300 MEDIA_ERR_LOG("MediaLibraryDevice InitDeviceRdbStore QueryDeviceTable fail!");
301 return false;
302 }
303 // 获取同一网络中的所有设备Id
304 std::vector<OHOS::DistributedHardware::DmDeviceInfo> deviceList;
305 GetAllDeviceId(deviceList);
306 MEDIA_ERR_LOG("MediaLibraryDevice InitDeviceRdbStore deviceList size = %{public}d", (int) deviceList.size());
307 for (auto& deviceInfo : deviceList) {
308 DevOnlineProcess(deviceInfo);
309 }
310
311 std::vector<OHOS::Media::MediaLibraryDeviceInfo> deviceDataBaseList;
312 MediaLibraryDeviceOperations::GetAllDeviceData(rdbStore, deviceDataBaseList);
313 for (auto deviceInfo : deviceDataBaseList) {
314 if (!IsHasDevice(deviceInfo.deviceUdid)) {
315 MediaLibraryDeviceOperations::UpdateDeviceInfo(rdbStore_, deviceInfo, bundleName_);
316 }
317 }
318 MEDIA_INFO_LOG("deviceInfoMap size = %{public}d, deviceDataBaseList size = %{public}d",
319 (int) deviceInfoMap_.size(), (int) deviceDataBaseList.size());
320 return true;
321 }
322
UpdateDeviceSyncStatus(const std::string & networkId,int32_t syncStatus)323 bool MediaLibraryDevice::UpdateDeviceSyncStatus(const std::string &networkId, int32_t syncStatus)
324 {
325 std::string udid;
326 {
327 lock_guard<mutex> autoLock(devMtx_);
328 auto iter = deviceInfoMap_.find(networkId);
329 if (iter == deviceInfoMap_.end()) {
330 MEDIA_ERR_LOG("UpdateDeviceSyncStatus can not find networkId:%{private}s", networkId.c_str());
331 return false;
332 }
333 udid = iter->second.deviceUdid;
334 }
335 return MediaLibraryDeviceOperations::UpdateSyncStatus(rdbStore_, udid, syncStatus);
336 }
337
GetDevicieSyncStatus(const std::string & networkId,int32_t & syncStatus)338 bool MediaLibraryDevice::GetDevicieSyncStatus(const std::string &networkId, int32_t &syncStatus)
339 {
340 std::string udid;
341 {
342 lock_guard<mutex> autoLock(devMtx_);
343 auto info = deviceInfoMap_.find(networkId);
344 if (info == deviceInfoMap_.end()) {
345 MEDIA_ERR_LOG("GetDevicieSyncStatus can not find networkId:%{private}s", networkId.c_str());
346 return false;
347 }
348 udid = info->second.deviceUdid;
349 }
350 return MediaLibraryDeviceOperations::GetSyncStatusById(rdbStore_, udid, syncStatus);
351 }
352
GetUdidByNetworkId(std::string & networkId)353 std::string MediaLibraryDevice::GetUdidByNetworkId(std::string &networkId)
354 {
355 auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
356 if (networkId.empty()) {
357 OHOS::DistributedHardware::DmDeviceInfo deviceInfo;
358 auto ret = deviceManager.GetLocalDeviceInfo(bundleName_, deviceInfo);
359 if (ret != ERR_OK) {
360 MEDIA_ERR_LOG("get local device info failed, ret %{public}d", ret);
361 return "";
362 }
363 networkId = deviceInfo.networkId;
364 }
365
366 std::string deviceUdid;
367 auto ret = deviceManager.GetUdidByNetworkId(bundleName_, networkId, deviceUdid);
368 if (ret != 0) {
369 MEDIA_INFO_LOG("GetDeviceUdid error networkId = %{private}s, ret %{public}d", networkId.c_str(), ret);
370 return std::string();
371 }
372 return deviceUdid;
373 }
374
GetMediaLibraryDeviceInfo(const DistributedHardware::DmDeviceInfo & dmInfo,MediaLibraryDeviceInfo & mlInfo)375 void MediaLibraryDevice::GetMediaLibraryDeviceInfo(const DistributedHardware::DmDeviceInfo &dmInfo,
376 MediaLibraryDeviceInfo& mlInfo)
377 {
378 mlInfo.networkId = dmInfo.networkId;
379 mlInfo.deviceName = dmInfo.deviceName;
380 mlInfo.deviceTypeId = dmInfo.deviceTypeId;
381 mlInfo.deviceUdid = GetUdidByNetworkId(mlInfo.networkId);
382 }
383
GetNetworkIdBySelfId(const std::string & selfId)384 string MediaLibraryDevice::GetNetworkIdBySelfId(const std::string &selfId)
385 {
386 for (auto &[_, info] : deviceInfoMap_) {
387 if (!selfId.compare(info.selfId)) {
388 return info.selfId;
389 }
390 }
391 MEDIA_ERR_LOG("GetNetworkIdBySelfId can not find selfId:%{private}s", selfId.c_str());
392 return "";
393 }
394
QueryDeviceTable()395 bool MediaLibraryDevice::QueryDeviceTable()
396 {
397 if (rdbStore_ == nullptr) {
398 return false;
399 }
400 excludeMap_.clear();
401 return MediaLibraryDeviceOperations::QueryDeviceTable(rdbStore_, excludeMap_);
402 }
403
OnRemoteDied()404 void MediaLibraryDevice::OnRemoteDied()
405 {
406 MEDIA_INFO_LOG("dm instance died");
407 UnRegisterFromDM();
408 RegisterToDM();
409 }
410
RegisterToDM()411 void MediaLibraryDevice::RegisterToDM()
412 {
413 auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
414 int errCode = deviceManager.InitDeviceManager(bundleName_, shared_from_this());
415 if (errCode != 0) {
416 MEDIA_ERR_LOG("RegisterToDm InitDeviceManager failed %{public}d", errCode);
417 }
418
419 std::string extra = "";
420 errCode = deviceManager.RegisterDevStateCallback(bundleName_, extra, shared_from_this());
421 if (errCode != 0) {
422 MEDIA_ERR_LOG("RegisterDevStateCallback failed errCode %{public}d", errCode);
423 }
424 MEDIA_INFO_LOG("RegisterToDM success!");
425 }
426
UnRegisterFromDM()427 void MediaLibraryDevice::UnRegisterFromDM()
428 {
429 auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
430 int errCode = deviceManager.UnRegisterDevStateCallback(bundleName_);
431 if (errCode != 0) {
432 MEDIA_ERR_LOG("UnRegisterDevStateCallback failed errCode %{public}d", errCode);
433 }
434 errCode = deviceManager.UnInitDeviceManager(bundleName_);
435 if (errCode != 0) {
436 MEDIA_ERR_LOG("UnInitDeviceManager failed errCode %{public}d", errCode);
437 }
438 MEDIA_INFO_LOG("UnRegisterFromDM success");
439 }
440
GetDeviceInfoMap(unordered_map<string,MediaLibraryDeviceInfo> & outDeviceMap)441 void MediaLibraryDevice::GetDeviceInfoMap(unordered_map<string, MediaLibraryDeviceInfo> &outDeviceMap)
442 {
443 outDeviceMap = deviceInfoMap_;
444 }
445
QueryAgingDeviceInfos(vector<MediaLibraryDeviceInfo> & outDeviceInfos)446 bool MediaLibraryDevice::QueryAgingDeviceInfos(vector<MediaLibraryDeviceInfo> &outDeviceInfos)
447 {
448 return MediaLibraryDeviceOperations::GetAgingDeviceData(rdbStore_, outDeviceInfos);
449 }
450
QueryAllDeviceUdid(vector<string> & deviceUdids)451 bool MediaLibraryDevice::QueryAllDeviceUdid(vector<string> &deviceUdids)
452 {
453 return MediaLibraryDeviceOperations::GetAllDeviceUdid(rdbStore_, deviceUdids);
454 }
455
DeleteDeviceInfo(const string & udid)456 bool MediaLibraryDevice::DeleteDeviceInfo(const string &udid)
457 {
458 return MediaLibraryDeviceOperations::DeleteDeviceInfo(rdbStore_, udid);
459 }
460 } // namespace Media
461 } // namespace OHOS