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>(&MediaLibraryDevice::TryToGetTargetDevMLInfos,
212 this, mldevInfo.deviceUdid, mldevInfo.networkId);
213 getTargetMLInfoTask->detach();
214 }
215
OnDeviceOnline(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)216 void MediaLibraryDevice::OnDeviceOnline(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
217 {
218 MEDIA_INFO_LOG("dev online network id %{private}s", deviceInfo.networkId);
219 }
220
OnDeviceOffline(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)221 void MediaLibraryDevice::OnDeviceOffline(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
222 {
223 MEDIA_INFO_LOG("OnDeviceOffline networkId = %{private}s", deviceInfo.networkId);
224
225 if (deviceHandler_ == nullptr) {
226 MEDIA_ERR_LOG("OnDeviceOffline mediaLibraryDeviceHandler null");
227 return;
228 }
229 auto nodeOffline = [this, deviceInfo]() {
230 lock_guard<mutex> autoLock(devMtx_);
231 std::string networkId = deviceInfo.networkId;
232 auto info = deviceInfoMap_.find(networkId);
233 if (info == deviceInfoMap_.end()) {
234 MEDIA_ERR_LOG("OnDeviceOffline can not find networkId:%{private}s", networkId.c_str());
235 return;
236 }
237
238 MediaLibraryDeviceOperations::UpdateDeviceInfo(rdbStore_, info->second, bundleName_);
239 deviceInfoMap_.erase(networkId);
240
241 // 设备变更通知
242 NotifyDeviceChange();
243 };
244 if (!deviceHandler_->PostTask(nodeOffline)) {
245 MEDIA_ERR_LOG("OnDeviceOffline handler postTask failed");
246 }
247 }
248
OnDeviceChanged(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)249 void MediaLibraryDevice::OnDeviceChanged(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
250 {
251 MEDIA_INFO_LOG("MediaLibraryDevice OnDeviceChanged called networkId = %{private}s", deviceInfo.networkId);
252 }
253
OnDeviceReady(const OHOS::DistributedHardware::DmDeviceInfo & deviceInfo)254 void MediaLibraryDevice::OnDeviceReady(const OHOS::DistributedHardware::DmDeviceInfo &deviceInfo)
255 {
256 MEDIA_INFO_LOG("OnDeviceReady network id %{private}s", deviceInfo.networkId);
257 if (deviceHandler_ == nullptr) {
258 MEDIA_ERR_LOG("mediaLibraryDeviceHandler null");
259 return;
260 }
261
262 auto nodeOnline = [this, deviceInfo]() {
263 DevOnlineProcess(deviceInfo);
264 NotifyDeviceChange();
265 };
266 if (!deviceHandler_->PostTask(nodeOnline)) {
267 MEDIA_ERR_LOG("handler postTask failed");
268 }
269 }
270
ClearAllDevices()271 void MediaLibraryDevice::ClearAllDevices()
272 {
273 lock_guard<mutex> autoLock(devMtx_);
274 deviceInfoMap_.clear();
275 excludeMap_.clear();
276 }
277
NotifyDeviceChange()278 void MediaLibraryDevice::NotifyDeviceChange()
279 {
280 auto contextUri = make_unique<Uri>(MEDIALIBRARY_DEVICE_URI);
281 MediaLibraryDataManager::GetInstance()->NotifyChange(*contextUri);
282 }
283
NotifyRemoteFileChange()284 void MediaLibraryDevice::NotifyRemoteFileChange()
285 {
286 auto contextUri = make_unique<Uri>(MEDIALIBRARY_REMOTEFILE_URI);
287 MediaLibraryDataManager::GetInstance()->NotifyChange(*contextUri);
288 }
289
IsHasDevice(const string & deviceUdid)290 bool MediaLibraryDevice::IsHasDevice(const string &deviceUdid)
291 {
292 for (auto &[_, info] : deviceInfoMap_) {
293 if (!deviceUdid.compare(info.deviceUdid)) {
294 return true;
295 }
296 }
297 return false;
298 }
299
InitDeviceRdbStore(const shared_ptr<NativeRdb::RdbStore> & rdbStore)300 bool MediaLibraryDevice::InitDeviceRdbStore(const shared_ptr<NativeRdb::RdbStore> &rdbStore)
301 {
302 rdbStore_ = rdbStore;
303
304 if (!QueryDeviceTable()) {
305 MEDIA_ERR_LOG("MediaLibraryDevice InitDeviceRdbStore QueryDeviceTable fail!");
306 return false;
307 }
308 // 获取同一网络中的所有设备Id
309 std::vector<OHOS::DistributedHardware::DmDeviceInfo> deviceList;
310 GetAllNetworkId(deviceList);
311 MEDIA_INFO_LOG("MediaLibraryDevice InitDeviceRdbStore deviceList size = %{public}d", (int) deviceList.size());
312 for (auto& deviceInfo : deviceList) {
313 DevOnlineProcess(deviceInfo);
314 }
315
316 std::vector<OHOS::Media::MediaLibraryDeviceInfo> deviceDataBaseList;
317 MediaLibraryDeviceOperations::GetAllDeviceData(rdbStore, deviceDataBaseList);
318 for (auto deviceInfo : deviceDataBaseList) {
319 if (!IsHasDevice(deviceInfo.deviceUdid)) {
320 MediaLibraryDeviceOperations::UpdateDeviceInfo(rdbStore_, deviceInfo, bundleName_);
321 }
322 }
323 MEDIA_INFO_LOG("deviceInfoMap size = %{public}d, deviceDataBaseList size = %{public}d",
324 (int) deviceInfoMap_.size(), (int) deviceDataBaseList.size());
325 return true;
326 }
327
InitDeviceKvStore(const shared_ptr<DistributedKv::SingleKvStore> & kvStore)328 bool MediaLibraryDevice::InitDeviceKvStore(const shared_ptr<DistributedKv::SingleKvStore> &kvStore)
329 {
330 kvStore_ = kvStore;
331 return kvStore_ != nullptr;
332 }
333
UpdateDeviceSyncStatus(const std::string & networkId,const string & tableName,int32_t syncStatus)334 bool MediaLibraryDevice::UpdateDeviceSyncStatus(const std::string &networkId,
335 const string &tableName, int32_t syncStatus)
336 {
337 std::string udid;
338 {
339 lock_guard<mutex> autoLock(devMtx_);
340 auto iter = deviceInfoMap_.find(networkId);
341 if (iter == deviceInfoMap_.end()) {
342 MEDIA_ERR_LOG("UpdateDeviceSyncStatus can not find networkId:%{private}s", networkId.c_str());
343 return false;
344 }
345 udid = iter->second.deviceUdid;
346 }
347 return MediaLibraryDeviceOperations::UpdateSyncStatus(rdbStore_, udid, tableName, syncStatus);
348 }
349
GetDeviceSyncStatus(const std::string & networkId,const std::string & tableName,int32_t & syncStatus)350 bool MediaLibraryDevice::GetDeviceSyncStatus(const std::string &networkId, const std::string &tableName,
351 int32_t &syncStatus)
352 {
353 std::string udid;
354 {
355 lock_guard<mutex> autoLock(devMtx_);
356 auto info = deviceInfoMap_.find(networkId);
357 if (info == deviceInfoMap_.end()) {
358 MEDIA_ERR_LOG("GetDeviceSyncStatus can not find networkId:%{private}s", networkId.c_str());
359 return false;
360 }
361 udid = info->second.deviceUdid;
362 }
363 return MediaLibraryDeviceOperations::GetSyncStatusById(rdbStore_, udid, tableName, syncStatus);
364 }
365
GetUdidByNetworkId(std::string & networkId)366 std::string MediaLibraryDevice::GetUdidByNetworkId(std::string &networkId)
367 {
368 auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
369 if (networkId.empty()) {
370 OHOS::DistributedHardware::DmDeviceInfo deviceInfo;
371 auto ret = deviceManager.GetLocalDeviceInfo(bundleName_, deviceInfo);
372 if (ret != ERR_OK) {
373 MEDIA_ERR_LOG("get local device info failed, ret %{public}d", ret);
374 return "";
375 }
376 networkId = deviceInfo.networkId;
377 }
378
379 std::string deviceUdid;
380 auto ret = deviceManager.GetUdidByNetworkId(bundleName_, networkId, deviceUdid);
381 if (ret != 0) {
382 MEDIA_INFO_LOG("GetDeviceUdid error networkId = %{private}s, ret %{public}d", networkId.c_str(), ret);
383 return std::string();
384 }
385 return deviceUdid;
386 }
387
GetMediaLibraryDeviceInfo(const DistributedHardware::DmDeviceInfo & dmInfo,MediaLibraryDeviceInfo & mlInfo)388 void MediaLibraryDevice::GetMediaLibraryDeviceInfo(const DistributedHardware::DmDeviceInfo &dmInfo,
389 MediaLibraryDeviceInfo& mlInfo)
390 {
391 mlInfo.networkId = dmInfo.networkId;
392 mlInfo.deviceName = dmInfo.deviceName;
393 mlInfo.deviceTypeId = dmInfo.deviceTypeId;
394 mlInfo.deviceUdid = GetUdidByNetworkId(mlInfo.networkId);
395 }
396
GetNetworkIdBySelfId(const std::string & selfId)397 string MediaLibraryDevice::GetNetworkIdBySelfId(const std::string &selfId)
398 {
399 for (auto &[_, info] : deviceInfoMap_) {
400 if (!selfId.compare(info.selfId)) {
401 return info.selfId;
402 }
403 }
404 MEDIA_ERR_LOG("GetNetworkIdBySelfId can not find selfId:%{private}s", selfId.c_str());
405 return "";
406 }
407
QueryDeviceTable()408 bool MediaLibraryDevice::QueryDeviceTable()
409 {
410 if (rdbStore_ == nullptr) {
411 return false;
412 }
413 excludeMap_.clear();
414 return MediaLibraryDeviceOperations::QueryDeviceTable(rdbStore_, excludeMap_);
415 }
416
OnRemoteDied()417 void MediaLibraryDevice::OnRemoteDied()
418 {
419 MEDIA_INFO_LOG("dm instance died");
420 UnRegisterFromDM();
421 RegisterToDM();
422 }
423
RegisterToDM()424 void MediaLibraryDevice::RegisterToDM()
425 {
426 auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
427 int errCode = deviceManager.InitDeviceManager(bundleName_, shared_from_this());
428 if (errCode != 0) {
429 MEDIA_ERR_LOG("RegisterToDm InitDeviceManager failed %{public}d", errCode);
430 }
431
432 std::string extra = "";
433 errCode = deviceManager.RegisterDevStateCallback(bundleName_, extra, shared_from_this());
434 if (errCode != 0) {
435 MEDIA_ERR_LOG("RegisterDevStateCallback failed errCode %{public}d", errCode);
436 }
437 MEDIA_INFO_LOG("RegisterToDM success!");
438 }
439
UnRegisterFromDM()440 void MediaLibraryDevice::UnRegisterFromDM()
441 {
442 auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
443 int errCode = deviceManager.UnRegisterDevStateCallback(bundleName_);
444 if (errCode != 0) {
445 MEDIA_ERR_LOG("UnRegisterDevStateCallback failed errCode %{public}d", errCode);
446 }
447 errCode = deviceManager.UnInitDeviceManager(bundleName_);
448 if (errCode != 0) {
449 MEDIA_ERR_LOG("UnInitDeviceManager failed errCode %{public}d", errCode);
450 }
451 MEDIA_INFO_LOG("UnRegisterFromDM success");
452 }
453
GetDeviceInfoMap(unordered_map<string,MediaLibraryDeviceInfo> & outDeviceMap)454 void MediaLibraryDevice::GetDeviceInfoMap(unordered_map<string, MediaLibraryDeviceInfo> &outDeviceMap)
455 {
456 outDeviceMap = deviceInfoMap_;
457 }
458
QueryAgingDeviceInfos(vector<MediaLibraryDeviceInfo> & outDeviceInfos)459 bool MediaLibraryDevice::QueryAgingDeviceInfos(vector<MediaLibraryDeviceInfo> &outDeviceInfos)
460 {
461 return MediaLibraryDeviceOperations::GetAgingDeviceData(rdbStore_, outDeviceInfos);
462 }
463
QueryAllDeviceUdid(vector<string> & deviceUdids)464 bool MediaLibraryDevice::QueryAllDeviceUdid(vector<string> &deviceUdids)
465 {
466 return MediaLibraryDeviceOperations::GetAllDeviceUdid(rdbStore_, deviceUdids);
467 }
468
DeleteDeviceInfo(const string & udid)469 bool MediaLibraryDevice::DeleteDeviceInfo(const string &udid)
470 {
471 return MediaLibraryDeviceOperations::DeleteDeviceInfo(rdbStore_, udid);
472 }
473
IsHasActiveDevice()474 bool MediaLibraryDevice::IsHasActiveDevice()
475 {
476 lock_guard<mutex> autoLock(devMtx_);
477 int deviceNumber = deviceInfoMap_.size();
478 if (deviceNumber > MIN_ACTIVE_DEVICE_NUMBER) {
479 MEDIA_DEBUG_LOG("device number = %{public}d", deviceNumber);
480 return true;
481 } else {
482 return false;
483 }
484 }
485
486 } // namespace Media
487 } // namespace OHOS