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