1 /*
2 * Copyright (C) 2025 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
16 #include "distributed_device_service.h"
17
18 #include "state_box.h"
19 #include "analytics_util.h"
20 #include "distributed_client.h"
21 #include "distributed_data_define.h"
22 #include "distributed_device_data.h"
23 #include "notification_helper.h"
24 #include "distributed_observer_service.h"
25 #include "distributed_service.h"
26 #include "distributed_send_adapter.h"
27
28 namespace OHOS {
29 namespace Notification {
30
31 static const int32_t MAX_CONNECTED_TYR = 5;
32 static const uint32_t DEFAULT_LOCK_SCREEN_FLAG = 2;
33
GetInstance()34 DistributedDeviceService& DistributedDeviceService::GetInstance()
35 {
36 static DistributedDeviceService distributedDeviceService;
37 return distributedDeviceService;
38 }
39
DeviceTypeToTypeString(uint16_t deviceType)40 std::string DistributedDeviceService::DeviceTypeToTypeString(uint16_t deviceType)
41 {
42 switch (deviceType) {
43 case DistributedHardware::DmDeviceType::DEVICE_TYPE_WATCH: {
44 return DistributedService::WEARABLE_DEVICE_TYPE;
45 }
46 case DistributedHardware::DmDeviceType::DEVICE_TYPE_PAD: {
47 return DistributedService::PAD_DEVICE_TYPE;
48 }
49 case DistributedHardware::DmDeviceType::DEVICE_TYPE_PC: {
50 return DistributedService::PC_DEVICE_TYPE;
51 }
52 case DistributedHardware::DmDeviceType::DEVICE_TYPE_2IN1: {
53 return DistributedService::PC_DEVICE_TYPE;
54 }
55 case DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE: {
56 return DistributedService::PHONE_DEVICE_TYPE;
57 }
58 default:
59 return "";
60 }
61 }
62
DeviceTypeConversion(const std::string & deviceType)63 static std::string DeviceTypeConversion(const std::string& deviceType)
64 {
65 if (deviceType == DistributedService::PAD_DEVICE_TYPE) {
66 return "pad";
67 }
68
69 if (deviceType == DistributedService::PC_DEVICE_TYPE) {
70 return "pc";
71 }
72 return deviceType;
73 }
74
InitLocalDevice(const std::string & deviceId,uint16_t deviceType)75 void DistributedDeviceService::InitLocalDevice(const std::string &deviceId, uint16_t deviceType)
76 {
77 localDevice_.deviceId_ = deviceId;
78 localDevice_.deviceType_ = deviceType;
79 }
80
GetLocalDevice()81 DistributedDeviceInfo DistributedDeviceService::GetLocalDevice()
82 {
83 return localDevice_;
84 }
85
IsLocalPadOrPC()86 bool DistributedDeviceService::IsLocalPadOrPC()
87 {
88 return localDevice_.IsPadOrPc();
89 }
90
IsReportDataByHa()91 bool DistributedDeviceService::IsReportDataByHa()
92 {
93 return localDevice_.deviceType_ != DistributedHardware::DmDeviceType::DEVICE_TYPE_WATCH;
94 }
95
SetSubscribeAllConnect(bool subscribe)96 void DistributedDeviceService::SetSubscribeAllConnect(bool subscribe)
97 {
98 subscribeAllConnect = subscribe;
99 }
100
IsSubscribeAllConnect()101 bool DistributedDeviceService::IsSubscribeAllConnect()
102 {
103 return subscribeAllConnect;
104 }
105
CheckNeedSubscribeAllConnect()106 bool DistributedDeviceService::CheckNeedSubscribeAllConnect()
107 {
108 std::lock_guard<ffrt::mutex> lock(mapLock_);
109 for (auto& device : peerDevice_) {
110 if (device.second.IsPadOrPc()) {
111 return true;
112 }
113 }
114 return false;
115 }
116
IsSyncLiveView(const std::string & deviceId,bool forceSync)117 bool DistributedDeviceService::IsSyncLiveView(const std::string& deviceId, bool forceSync)
118 {
119 std::lock_guard<ffrt::mutex> lock(mapLock_);
120 auto iter = peerDevice_.find(deviceId);
121 if (iter == peerDevice_.end()) {
122 ANS_LOGE("Dans unknown device is data %{public}s.", StringAnonymous(deviceId).c_str());
123 return false;
124 }
125
126 if (iter->second.deviceType_ == DistributedHardware::DmDeviceType::DEVICE_TYPE_PC ||
127 iter->second.deviceType_ == DistributedHardware::DmDeviceType::DEVICE_TYPE_2IN1) {
128 ANS_LOGI("Dans device pc no need sync %{public}s.", StringAnonymous(deviceId).c_str());
129 return false;
130 }
131 if (iter->second.deviceType_ == DistributedHardware::DmDeviceType::DEVICE_TYPE_PAD) {
132 if (!iter->second.deviceUsage || iter->second.peerState_ == DeviceState::STATE_SYNC) {
133 ANS_LOGI("Dans pad sync %{public}d %{public}d.", iter->second.peerState_,
134 iter->second.deviceUsage);
135 return false;
136 }
137 }
138
139 if (!forceSync && iter->second.liveViewSync) {
140 ANS_LOGI("Dans live view sync %{public}d %{public}d.", forceSync, iter->second.liveViewSync);
141 return false;
142 }
143 return true;
144 }
145
IsSyncIcons(const std::string & deviceId,bool forceSync)146 bool DistributedDeviceService::IsSyncIcons(const std::string& deviceId, bool forceSync)
147 {
148 std::lock_guard<ffrt::mutex> lock(mapLock_);
149 auto iter = peerDevice_.find(deviceId);
150 if (iter == peerDevice_.end()) {
151 ANS_LOGE("Dans unknown device is data %{public}s.", StringAnonymous(deviceId).c_str());
152 return false;
153 }
154 if (iter->second.deviceType_ != DistributedHardware::DmDeviceType::DEVICE_TYPE_WATCH) {
155 return false;
156 }
157
158 if (!forceSync && iter->second.iconSync) {
159 ANS_LOGI("Dans icon sync %{public}d %{public}d.", forceSync, iter->second.iconSync);
160 return false;
161 }
162 return true;
163 }
164
IsSyncInstalledBundle(const std::string & deviceId,bool forceSync)165 bool DistributedDeviceService::IsSyncInstalledBundle(const std::string& deviceId, bool forceSync)
166 {
167 std::lock_guard<ffrt::mutex> lock(mapLock_);
168 auto iter = peerDevice_.find(deviceId);
169 if (iter == peerDevice_.end()) {
170 ANS_LOGE("Dans unknown device is data %{public}s.", StringAnonymous(deviceId).c_str());
171 return false;
172 }
173
174 if (iter->second.deviceType_ == DistributedHardware::DmDeviceType::DEVICE_TYPE_WATCH) {
175 return false;
176 }
177
178 if (!forceSync && iter->second.installedBundlesSync) {
179 ANS_LOGI("Dans bundle sync %{public}d %{public}d.", forceSync, iter->second.installedBundlesSync);
180 return false;
181 }
182 return true;
183 }
184
SetDeviceSyncData(const std::string & deviceId,int32_t type,bool syncData)185 void DistributedDeviceService::SetDeviceSyncData(const std::string& deviceId, int32_t type, bool syncData)
186 {
187 std::lock_guard<ffrt::mutex> lock(mapLock_);
188 auto iter = peerDevice_.find(deviceId);
189 if (iter == peerDevice_.end()) {
190 ANS_LOGE("Dans unknown device set data %{public}s.", StringAnonymous(deviceId).c_str());
191 return;
192 }
193 if (type == SYNC_BUNDLE_ICONS) {
194 iter->second.iconSync = syncData;
195 }
196 if (type == SYNC_LIVE_VIEW) {
197 iter->second.liveViewSync = syncData;
198 }
199 if (type == SYNC_INSTALLED_BUNDLE) {
200 iter->second.installedBundlesSync = syncData;
201 }
202 if (type == DEVICE_USAGE) {
203 iter->second.deviceUsage = syncData;
204 }
205 }
206
ResetDeviceInfo(const std::string & deviceId,int32_t peerState)207 void DistributedDeviceService::ResetDeviceInfo(const std::string& deviceId, int32_t peerState)
208 {
209 std::lock_guard<ffrt::mutex> lock(mapLock_);
210 auto deviceIter = peerDevice_.find(deviceId);
211 if (deviceIter == peerDevice_.end()) {
212 ANS_LOGI("Dans unknown device %{public}s.", StringAnonymous(deviceId).c_str());
213 return;
214 }
215 deviceIter->second.connectedTry_ = 0;
216 deviceIter->second.deviceUsage = false;
217 deviceIter->second.liveViewSync = false;
218 deviceIter->second.iconSync = false;
219 deviceIter->second.installedBundlesSync = false;
220 deviceIter->second.peerState_ = peerState;
221 }
222
SetDeviceState(const std::string & deviceId,int32_t state)223 void DistributedDeviceService::SetDeviceState(const std::string& deviceId, int32_t state)
224 {
225 std::lock_guard<ffrt::mutex> lock(mapLock_);
226 auto iter = peerDevice_.find(deviceId);
227 if (iter == peerDevice_.end()) {
228 ANS_LOGE("Dans unknown device set status %{public}s.", StringAnonymous(deviceId).c_str());
229 return;
230 }
231 iter->second.peerState_ = state;
232 }
233
CheckDeviceExist(const std::string & deviceId)234 bool DistributedDeviceService::CheckDeviceExist(const std::string& deviceId)
235 {
236 std::lock_guard<ffrt::mutex> lock(mapLock_);
237 if (peerDevice_.find(deviceId) == peerDevice_.end()) {
238 ANS_LOGI("Dans unknown device %{public}s.", StringAnonymous(deviceId).c_str());
239 return false;
240 }
241 return true;
242 }
243
GetDeviceInfo(const std::string & deviceId,DistributedDeviceInfo & device)244 bool DistributedDeviceService::GetDeviceInfo(const std::string& deviceId, DistributedDeviceInfo& device)
245 {
246 std::lock_guard<ffrt::mutex> lock(mapLock_);
247 auto iter = peerDevice_.find(deviceId);
248 if (iter == peerDevice_.end()) {
249 ANS_LOGI("Dans get deviceId unknonw %{public}s.", StringAnonymous(deviceId).c_str());
250 return false;
251 }
252 device = iter->second;
253 return true;
254 }
255
GetDeviceInfoByUdid(const std::string & udid,DistributedDeviceInfo & device)256 bool DistributedDeviceService::GetDeviceInfoByUdid(const std::string& udid, DistributedDeviceInfo& device)
257 {
258 std::lock_guard<ffrt::mutex> lock(mapLock_);
259 for (auto deviceItem : peerDevice_) {
260 if (udid == deviceItem.second.udid_) {
261 device = deviceItem.second;
262 return true;
263 }
264 }
265 ANS_LOGI("Dans get deviceId unknonw %{public}s.", StringAnonymous(udid).c_str());
266 return false;
267 }
268
CheckDeviceNeedSync(const std::string & deviceId)269 bool DistributedDeviceService::CheckDeviceNeedSync(const std::string& deviceId)
270 {
271 std::lock_guard<ffrt::mutex> lock(mapLock_);
272 auto iter = peerDevice_.find(deviceId);
273 if (iter == peerDevice_.end()) {
274 ANS_LOGE("Dans unknown device connected %{public}s.", StringAnonymous(deviceId).c_str());
275 return false;
276 }
277 if (iter->second.connectedTry_ >= MAX_CONNECTED_TYR || iter->second.peerState_ != DeviceState::STATE_SYNC) {
278 ANS_LOGI("Dans no need try %{public}d %{public}d.", iter->second.connectedTry_,
279 iter->second.peerState_);
280 iter->second.connectedTry_ = 0;
281 return false;
282 }
283 return true;
284 }
285
IncreaseDeviceSyncCount(const std::string & deviceId)286 void DistributedDeviceService::IncreaseDeviceSyncCount(const std::string& deviceId)
287 {
288 std::lock_guard<ffrt::mutex> lock(mapLock_);
289 auto iter = peerDevice_.find(deviceId);
290 if (iter == peerDevice_.end()) {
291 ANS_LOGE("Dans unknown device count %{public}s.", StringAnonymous(deviceId).c_str());
292 return;
293 }
294 iter->second.connectedTry_ = iter->second.connectedTry_ + 1;
295 ANS_LOGI("Dans sync device count %{public}s %{public}d.", StringAnonymous(deviceId).c_str(),
296 iter->second.connectedTry_);
297 }
298
AddDeviceInfo(DistributedDeviceInfo deviceItem)299 void DistributedDeviceService::AddDeviceInfo(DistributedDeviceInfo deviceItem)
300 {
301 std::lock_guard<ffrt::mutex> lock(mapLock_);
302 peerDevice_[deviceItem.deviceId_] = deviceItem;
303 }
304
DeleteDeviceInfo(const std::string & deviceId)305 void DistributedDeviceService::DeleteDeviceInfo(const std::string& deviceId)
306 {
307 std::lock_guard<ffrt::mutex> lock(mapLock_);
308 auto deviceIter = peerDevice_.find(deviceId);
309 if (deviceIter != peerDevice_.end()) {
310 ANS_LOGI("Delete device %{public}s.", StringAnonymous(deviceId).c_str());
311 peerDevice_.erase(deviceId);
312 }
313 }
314
GetDeviceList()315 std::map<std::string, DistributedDeviceInfo>& DistributedDeviceService::GetDeviceList()
316 {
317 std::lock_guard<ffrt::mutex> lock(mapLock_);
318 return peerDevice_;
319 }
320
GetDeviceList(std::map<std::string,DistributedDeviceInfo> & peerDevices)321 void DistributedDeviceService::GetDeviceList(std::map<std::string, DistributedDeviceInfo>& peerDevices)
322 {
323 std::lock_guard<ffrt::mutex> lock(mapLock_);
324 for (auto deviceItem : peerDevice_) {
325 peerDevices[deviceItem.first] = deviceItem.second;
326 }
327 }
328
SyncDeviceMatch(const DistributedDeviceInfo peerDevice,MatchType type)329 void DistributedDeviceService::SyncDeviceMatch(const DistributedDeviceInfo peerDevice, MatchType type)
330 {
331 std::shared_ptr<NotifticationMatchBox> matchBox = std::make_shared<NotifticationMatchBox>();
332 matchBox->SetVersion(CURRENT_VERSION);
333 matchBox->SetMatchType(type);
334 matchBox->SetLocalDeviceId(localDevice_.deviceId_);
335 matchBox->SetLocalDeviceType(localDevice_.deviceType_);
336 if (type == MatchType::MATCH_ACK) {
337 matchBox->SetPeerDeviceId(peerDevice.deviceId_);
338 matchBox->SetPeerDeviceType(peerDevice.deviceType_);
339 }
340 if (!matchBox->Serialize()) {
341 ANS_LOGW("Dans SyncDeviceMatch serialize failed.");
342 return;
343 }
344
345 std::shared_ptr<PackageInfo> packageInfo = std::make_shared<PackageInfo>(matchBox, peerDevice,
346 TransDataType::DATA_TYPE_MESSAGE, MODIFY_ERROR_EVENT_CODE);
347 DistributedSendAdapter::GetInstance().SendPackage(packageInfo);
348 ANS_LOGI("Dans SyncDeviceMatch %{public}s %{public}d.",
349 StringAnonymous(peerDevice.deviceId_).c_str(), peerDevice.deviceType_);
350 }
351
352 #ifdef DISTRIBUTED_FEATURE_MASTER
SetDeviceStatus(const std::shared_ptr<TlvBox> & boxMessage)353 void DistributedDeviceService::SetDeviceStatus(const std::shared_ptr<TlvBox>& boxMessage)
354 {
355 std::string deviceId;
356 NotifticationStateBox stateBox = NotifticationStateBox(boxMessage);
357 if (!stateBox.GetDeviceId(deviceId)) {
358 ANS_LOGW("Dans unbox deviceId and name failed.");
359 return;
360 }
361
362 DistributedDeviceInfo device;
363 if (!GetDeviceInfo(deviceId, device)) {
364 ANS_LOGW("Dans get device failed %{public}s.", StringAnonymous(deviceId).c_str());
365 return;
366 }
367 int32_t status;
368 std::string deviceName = DistributedDeviceService::DeviceTypeToTypeString(device.deviceType_);
369 if (stateBox.GetState(status)) {
370 int32_t result = NotificationHelper::SetTargetDeviceStatus(deviceName, status,
371 DEFAULT_LOCK_SCREEN_FLAG, device.udid_);
372 ANS_LOGI("Dans set state %{public}s %{public}s %{public}d %{public}d.", deviceName.c_str(),
373 StringAnonymous(deviceId).c_str(), status, result);
374 }
375
376 bool liveViewEnable;
377 bool notificationEnable;
378 if (stateBox.GetLiveViewEnable(liveViewEnable) && stateBox.GetNotificationEnable(notificationEnable)) {
379 int32_t result = NotificationHelper::SetTargetDeviceSwitch(deviceName, device.udid_,
380 notificationEnable, liveViewEnable);
381 ANS_LOGI("Dans set enable %{public}s %{public}s %{public}d %{public}d %{public}d.", deviceName.c_str(),
382 StringAnonymous(deviceId).c_str(), liveViewEnable, notificationEnable, result);
383 }
384 }
385 #else
InitCurrentDeviceStatus()386 void DistributedDeviceService::InitCurrentDeviceStatus()
387 {
388 bool notificationEnable = false;
389 bool liveViewEnable = false;
390 std::string localType = DeviceTypeToTypeString(localDevice_.deviceType_);
391 int32_t status = OberverService::GetInstance().IsScreenLocked();
392 auto result = NotificationHelper::IsDistributedEnabledBySlot(NotificationConstant::SlotType::LIVE_VIEW,
393 localType, liveViewEnable);
394 if (result != ERR_OK) {
395 ANS_LOGW("Dans get live view enable failed.");
396 }
397 result = NotificationHelper::IsDistributedEnabled(localType, notificationEnable);
398 if (result != ERR_OK) {
399 ANS_LOGW("Dans get notification enable failed.");
400 }
401 SyncDeviceStatus(STATE_TYPE_BOTH, status, notificationEnable, liveViewEnable);
402 }
403
SyncDeviceStatus(int32_t type,int32_t status,bool notificationEnable,bool liveViewEnable)404 void DistributedDeviceService::SyncDeviceStatus(int32_t type, int32_t status,
405 bool notificationEnable, bool liveViewEnable)
406 {
407 std::shared_ptr<NotifticationStateBox> stateBox = std::make_shared<NotifticationStateBox>();
408 std::string deviceType = DeviceTypeToTypeString(localDevice_.deviceType_);
409 deviceType = DeviceTypeConversion(deviceType);
410 stateBox->SetDeviceType(deviceType);
411 stateBox->SetDeviceId(localDevice_.deviceId_);
412 if (type == STATE_TYPE_LOCKSCREEN || type == STATE_TYPE_BOTH) {
413 stateBox->SetState(status);
414 }
415 if (type == STATE_TYPE_SWITCH || type == STATE_TYPE_BOTH) {
416 stateBox->SetLiveViewEnable(liveViewEnable);
417 stateBox->SetNotificationEnable(notificationEnable);
418 }
419
420 if (!stateBox->Serialize()) {
421 ANS_LOGW("Dans SyncDeviceState serialize failed.");
422 return;
423 }
424 bool isPad = IsLocalPadOrPC();
425 std::lock_guard<ffrt::mutex> lock(mapLock_);
426 for (const auto& peer : peerDevice_) {
427 if (isPad && peer.second.peerState_ != DeviceState::STATE_ONLINE) {
428 ANS_LOGI("DeviceState %{public}d %{public}d %{public}d %{public}d %{public}s.",
429 status, notificationEnable, liveViewEnable, peer.second.deviceType_,
430 StringAnonymous(peer.second.deviceId_).c_str());
431 continue;
432 }
433 std::shared_ptr<PackageInfo> packageInfo = std::make_shared<PackageInfo>(stateBox, peer.second,
434 TransDataType::DATA_TYPE_MESSAGE, MODIFY_ERROR_EVENT_CODE);
435 DistributedSendAdapter::GetInstance().SendPackage(packageInfo);
436 ANS_LOGI("DeviceState %{public}d %{public}d %{public}d %{public}d %{public}lu.",
437 type, status, liveViewEnable, notificationEnable, peerDevice_.size());
438 }
439 }
440 #endif
441 }
442 }
443
444