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