1 /*
2 * Copyright (C) 2024 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 #include "distributed_service.h"
16
17 #include "notification_helper.h"
18 #include "distributed_client.h"
19 #include "state_box.h"
20 #include "in_process_call_wrapper.h"
21 #include "distributed_observer_service.h"
22 #include "distributed_device_data.h"
23 #include "dm_device_info.h"
24 #include "match_box.h"
25 #include "bundle_icon_box.h"
26 #include "distributed_preference.h"
27 #include "bundle_resource_helper.h"
28 #include "notification_sync_box.h"
29
30 namespace OHOS {
31 namespace Notification {
32
TransDeviceTypeIdToName(uint16_t deviceType)33 std::string TransDeviceTypeIdToName(uint16_t deviceType)
34 {
35 switch (deviceType) {
36 case DistributedHardware::DmDeviceType::DEVICE_TYPE_WATCH: {
37 return "wearable";
38 }
39 case DistributedHardware::DmDeviceType::DEVICE_TYPE_PAD: {
40 return "Pad";
41 }
42 case DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE: {
43 return "Phone";
44 }
45 default:
46 return "";
47 }
48 }
49
50 namespace {
51 constexpr uint32_t DEFAULT_LOCK_SCREEN_FLAG = 2;
52 }
53
InitDeviceState(const DistributedDeviceInfo device)54 void DistributedService::InitDeviceState(const DistributedDeviceInfo device)
55 {
56 if (device.deviceType_ == DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE &&
57 localDevice_.deviceType_ != DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE) {
58 int32_t state = OberverService::GetInstance().IsScreenLocked();
59 SyncDeviceState(state);
60 }
61 }
62
HandleDeviceState(const std::shared_ptr<TlvBox> & boxMessage)63 void DistributedService::HandleDeviceState(const std::shared_ptr<TlvBox>& boxMessage)
64 {
65 int32_t state;
66 std::string deviceName;
67 NotifticationStateBox stateBox = NotifticationStateBox(boxMessage);
68 if (!stateBox.GetDeviceType(deviceName) || !stateBox.GetState(state)) {
69 ANS_LOGW("Dans unbox state failed.");
70 return;
71 }
72 uint32_t status = (static_cast<uint32_t>(state) << 1);
73 int32_t result = NotificationHelper::SetTargetDeviceStatus(deviceName, status, DEFAULT_LOCK_SCREEN_FLAG);
74 ANS_LOGI("Dans set state %{public}s %{public}d.", deviceName.c_str(), state);
75 }
76
SyncDeviceState(int32_t state)77 void DistributedService::SyncDeviceState(int32_t state)
78 {
79 if (serviceQueue_ == nullptr) {
80 ANS_LOGE("Check handler is null.");
81 return;
82 }
83 std::function<void()> task = std::bind([&, state]() {
84 NotifticationStateBox stateBox;
85 stateBox.SetState(state);
86 stateBox.SetDeviceType(TransDeviceTypeIdToName(localDevice_.deviceType_));
87 if (!stateBox.Serialize()) {
88 ANS_LOGW("Dans SyncDeviceState serialize failed.");
89 return;
90 }
91 for (const auto& peer : peerDevice_) {
92 DistributedClient::GetInstance().SendMessage(stateBox.GetByteBuffer(),
93 stateBox.GetByteLength(), TransDataType::DATA_TYPE_MESSAGE,
94 peer.second.deviceId_, peer.second.deviceType_);
95 ANS_LOGI("Dans SyncDeviceState %{public}d %{public}d %{public}d %{public}d.",
96 peer.second.deviceType_, localDevice_.deviceType_, state, (int32_t)(peerDevice_.size()));
97 }
98 });
99 serviceQueue_->submit(task);
100 }
101
SyncDeviceMatch(const DistributedDeviceInfo peerDevice,MatchType type)102 int32_t DistributedService::SyncDeviceMatch(const DistributedDeviceInfo peerDevice, MatchType type)
103 {
104 NotifticationMatchBox matchBox;
105 matchBox.SetVersion(CURRENT_VERSION);
106 matchBox.SetMatchType(type);
107 matchBox.SetLocalDeviceId(localDevice_.deviceId_);
108 matchBox.SetLocalDeviceType(localDevice_.deviceType_);
109 if (type == MatchType::MATCH_ACK) {
110 matchBox.SetPeerDeviceId(peerDevice.deviceId_);
111 matchBox.SetPeerDeviceType(peerDevice.deviceType_);
112 }
113 if (!matchBox.Serialize()) {
114 ANS_LOGW("Dans SyncDeviceMatch serialize failed.");
115 return -1;
116 }
117 int32_t result = DistributedClient::GetInstance().SendMessage(matchBox.GetByteBuffer(),
118 matchBox.GetByteLength(), TransDataType::DATA_TYPE_MESSAGE,
119 peerDevice.deviceId_, peerDevice.deviceType_);
120 ANS_LOGI("Dans SyncDeviceMatch %{public}s %{public}d %{public}s %{public}d %{public}d.",
121 StringAnonymous(peerDevice.deviceId_).c_str(), peerDevice.deviceType_,
122 StringAnonymous(localDevice_.deviceId_).c_str(), localDevice_.deviceType_, type);
123 return result;
124 }
125
SyncAllLiveViewNotification(const DistributedDeviceInfo peerDevice,bool isForce)126 void DistributedService::SyncAllLiveViewNotification(const DistributedDeviceInfo peerDevice, bool isForce)
127 {
128 if (localDevice_.deviceType_ != DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE) {
129 return;
130 }
131
132 auto iter = peerDevice_.find(peerDevice.deviceId_);
133 if (iter == peerDevice_.end()) {
134 ANS_LOGI("Dans %{public}s.", StringAnonymous(peerDevice.deviceId_).c_str());
135 return;
136 }
137
138 if (!isForce && iter->second.isSync) {
139 ANS_LOGI("Dans %{public}d %{public}d.", isForce, iter->second.isSync);
140 return;
141 }
142
143 std::vector<sptr<Notification>> notifications;
144 auto result = NotificationHelper::GetAllNotificationsBySlotType(notifications,
145 NotificationConstant::SlotType::LIVE_VIEW);
146 if (result != ERR_OK) {
147 ANS_LOGI("Dans get all active %{public}d.", result);
148 return;
149 }
150
151 std::vector<std::string> notificationList;
152 for (auto& notification : notifications) {
153 if (notification == nullptr || notification->GetNotificationRequestPoint() == nullptr ||
154 !notification->GetNotificationRequestPoint()->IsCommonLiveView()) {
155 ANS_LOGI("Dans no need sync remove notification.");
156 continue;
157 }
158 notificationList.push_back(notification->GetKey());
159 }
160 SyncNotifictionList(peerDevice, notificationList);
161
162 for (auto& notification : notifications) {
163 if (notification == nullptr || notification->GetNotificationRequestPoint() == nullptr ||
164 !notification->GetNotificationRequestPoint()->IsCommonLiveView()) {
165 ANS_LOGI("Dans no need sync notification.");
166 continue;
167 }
168 std::shared_ptr<Notification> sharedNotification = std::make_shared<Notification>(*notification);
169 SendNotifictionRequest(sharedNotification, peerDevice, true);
170 }
171 }
172
SyncNotifictionList(const DistributedDeviceInfo & peerDevice,const std::vector<std::string> & notificationList)173 void DistributedService::SyncNotifictionList(const DistributedDeviceInfo& peerDevice,
174 const std::vector<std::string>& notificationList)
175 {
176 ANS_LOGI("Dans sync notification %{public}d.", (int32_t)(notificationList.size()));
177 NotificationSyncBox notificationSyncBox;
178 notificationSyncBox.SetLocalDeviceId(peerDevice.deviceId_);
179 notificationSyncBox.SetNotificationEmpty(notificationList.empty());
180 if (!notificationList.empty()) {
181 notificationSyncBox.SetNotificationList(notificationList);
182 }
183
184 if (!notificationSyncBox.Serialize()) {
185 ANS_LOGW("Dans SyncNotifictionList serialize failed.");
186 return;
187 }
188 int32_t result = DistributedClient::GetInstance().SendMessage(notificationSyncBox.GetByteBuffer(),
189 notificationSyncBox.GetByteLength(), TransDataType::DATA_TYPE_BYTES,
190 peerDevice.deviceId_, peerDevice.deviceType_);
191 ANS_LOGI("Dans SyncNotifictionList %{public}s %{public}d %{public}s %{public}d.",
192 StringAnonymous(peerDevice.deviceId_).c_str(), peerDevice.deviceType_,
193 StringAnonymous(localDevice_.deviceId_).c_str(), localDevice_.deviceType_);
194 }
195
HandleMatchSync(const std::shared_ptr<TlvBox> & boxMessage)196 void DistributedService::HandleMatchSync(const std::shared_ptr<TlvBox>& boxMessage)
197 {
198 int32_t type = 0;
199 DistributedDeviceInfo peerDevice;
200 NotifticationMatchBox matchBox = NotifticationMatchBox(boxMessage);
201 if (!matchBox.GetLocalDeviceType(type)) {
202 ANS_LOGI("Dans handle match device type failed.");
203 return;
204 } else {
205 peerDevice.deviceType_ = static_cast<uint16_t>(type);
206 }
207 if (!matchBox.GetLocalDeviceId(peerDevice.deviceId_)) {
208 ANS_LOGI("Dans handle match device id failed.");
209 return;
210 }
211 int32_t matchType = 0;
212 if (!matchBox.GetMatchType(matchType)) {
213 ANS_LOGI("Dans handle match sync failed.");
214 return;
215 }
216 ANS_LOGI("Dans handle match device type %{public}d.", matchType);
217 if (matchType == MatchType::MATCH_SYN) {
218 SyncDeviceMatch(peerDevice, MatchType::MATCH_ACK);
219 SyncAllLiveViewNotification(peerDevice, true);
220 } else if (matchType == MatchType::MATCH_ACK) {
221 InitDeviceState(peerDevice);
222 RequestBundlesIcon(peerDevice);
223 ReportBundleIconList(peerDevice);
224 SubscribeNotifictaion(peerDevice);
225 SyncAllLiveViewNotification(peerDevice, false);
226 }
227
228 auto iter = peerDevice_.find(peerDevice.deviceId_);
229 if (iter == peerDevice_.end()) {
230 ANS_LOGI("Dans get deviceId unknonw %{public}s.", peerDevice.deviceId_.c_str());
231 return;
232 }
233 iter->second.isSync = true;
234 }
235
CheckPeerDevice(const BundleIconBox & boxMessage,DistributedDeviceInfo & device)236 bool DistributedService::CheckPeerDevice(const BundleIconBox& boxMessage, DistributedDeviceInfo& device)
237 {
238 std::string deviceId;
239 if (!boxMessage.GetLocalDeviceId(deviceId)) {
240 ANS_LOGI("Dans get deviceId failed.");
241 return false;
242 }
243 auto iter = peerDevice_.find(deviceId);
244 if (iter == peerDevice_.end()) {
245 ANS_LOGI("Dans get deviceId unknonw %{public}s.", StringAnonymous(deviceId).c_str());
246 return false;
247 }
248 device = iter->second;
249 return true;
250 }
251
ReportBundleIconList(const DistributedDeviceInfo peerDevice)252 void DistributedService::ReportBundleIconList(const DistributedDeviceInfo peerDevice)
253 {
254 if (localDevice_.deviceType_ == DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE) {
255 return;
256 }
257 std::vector<std::string> bundlesName;
258 DistributedPreferences::GetInstance().GetSavedBundlesIcon(bundlesName);
259 BundleIconBox iconBox;
260 iconBox.SetIconSyncType(IconSyncType::REPORT_SAVED_ICON);
261 iconBox.SetBundleList(bundlesName);
262 iconBox.SetLocalDeviceId(localDevice_.deviceId_);
263 if (!iconBox.Serialize()) {
264 ANS_LOGW("Dans ReportBundleIconList serialize failed.");
265 return;
266 }
267
268 DistributedClient::GetInstance().SendMessage(iconBox.GetByteBuffer(),
269 iconBox.GetByteLength(), TransDataType::DATA_TYPE_MESSAGE,
270 peerDevice.deviceId_, peerDevice.deviceType_);
271 ANS_LOGI("Dans ReportBundleIconList %{public}s %{public}d %{public}s %{public}d.",
272 StringAnonymous(peerDevice.deviceId_).c_str(), peerDevice.deviceType_,
273 StringAnonymous(localDevice_.deviceId_).c_str(), localDevice_.deviceType_);
274 }
275
RequestBundlesIcon(const DistributedDeviceInfo peerDevice)276 void DistributedService::RequestBundlesIcon(const DistributedDeviceInfo peerDevice)
277 {
278 if (localDevice_.deviceType_ != DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE) {
279 return;
280 }
281 BundleIconBox iconBox;
282 iconBox.SetIconSyncType(IconSyncType::REQUEST_BUNDLE_ICON);
283 iconBox.SetLocalDeviceId(localDevice_.deviceId_);
284 if (!iconBox.Serialize()) {
285 ANS_LOGW("Dans RequestBundlesIcon serialize failed.");
286 return;
287 }
288
289 DistributedClient::GetInstance().SendMessage(iconBox.GetByteBuffer(),
290 iconBox.GetByteLength(), TransDataType::DATA_TYPE_MESSAGE,
291 peerDevice.deviceId_, peerDevice.deviceType_);
292 ANS_LOGI("Dans RequestBundlesIcon %{public}s %{public}d %{public}s %{public}d.",
293 StringAnonymous(peerDevice.deviceId_).c_str(), peerDevice.deviceType_,
294 StringAnonymous(localDevice_.deviceId_).c_str(), localDevice_.deviceType_);
295 }
296
UpdateBundlesIcon(const std::unordered_map<std::string,std::string> & icons,const DistributedDeviceInfo peerDevice)297 void DistributedService::UpdateBundlesIcon(const std::unordered_map<std::string, std::string>& icons,
298 const DistributedDeviceInfo peerDevice)
299 {
300 BundleIconBox iconBox;
301 iconBox.SetIconSyncType(IconSyncType::UPDATE_BUNDLE_ICON);
302 iconBox.SetBundlesIcon(icons);
303 if (!iconBox.Serialize()) {
304 ANS_LOGW("Dans UpdateBundlesIcon serialize failed.");
305 return;
306 }
307
308 DistributedClient::GetInstance().SendMessage(iconBox.GetByteBuffer(),
309 iconBox.GetByteLength(), TransDataType::DATA_TYPE_BYTES,
310 peerDevice.deviceId_, peerDevice.deviceType_);
311 ANS_LOGI("Dans UpdateBundlesIcon %{public}s %{public}d %{public}s %{public}d.",
312 StringAnonymous(peerDevice.deviceId_).c_str(), peerDevice.deviceType_,
313 StringAnonymous(localDevice_.deviceId_).c_str(), localDevice_.deviceType_);
314 }
315
GenerateBundleIconSync(const DistributedDeviceInfo & device)316 void DistributedService::GenerateBundleIconSync(const DistributedDeviceInfo& device)
317 {
318 std::vector<NotificationBundleOption> bundleOption;
319 if (NotificationHelper::GetAllLiveViewEnabledBundles(bundleOption) != 0) {
320 ANS_LOGW("Dans get all live view enable bundle failed.");
321 return;
322 }
323
324 std::vector<NotificationBundleOption> enableBundleOption;
325 if (NotificationHelper::GetAllDistribuedEnabledBundles("liteWearable", enableBundleOption) != 0) {
326 ANS_LOGW("Dans get all live view enable bundle failed.");
327 }
328
329 std::set<std::string> enabledBundles;
330 for (auto item : enableBundleOption) {
331 enabledBundles.insert(item.GetBundleName());
332 }
333 std::set<std::string> cachedIcons;
334 std::vector<std::string> unCachedBundleList;
335 auto itemIter = bundleIconCache_.find(device.deviceId_);
336 if (itemIter != bundleIconCache_.end()) {
337 cachedIcons = itemIter->second;
338 }
339 for (auto item : bundleOption) {
340 if (enabledBundles.find(item.GetBundleName()) != enabledBundles.end()) {
341 continue;
342 }
343 if (cachedIcons.find(item.GetBundleName()) != cachedIcons.end()) {
344 continue;
345 }
346 unCachedBundleList.push_back(item.GetBundleName());
347 cachedIcons.insert(item.GetBundleName());
348 }
349 bundleIconCache_.insert(std::make_pair(device.deviceId_, cachedIcons));
350 ANS_LOGI("Dans Generate bundle %{public}d %{public}d %{public}d.", (int32_t)(bundleOption.size()),
351 (int32_t)(enableBundleOption.size()), (int32_t)(unCachedBundleList.size()));
352 std::unordered_map<std::string, std::string> icons;
353 for (auto bundle : unCachedBundleList) {
354 std::string icon;
355 if (!GetBundleResourceInfo(bundle, icon)) {
356 continue;
357 }
358 icons.insert(std::make_pair(bundle, icon));
359 if (icons.size() == BundleIconBox::MAX_ICON_NUM) {
360 UpdateBundlesIcon(icons, device);
361 icons.clear();
362 }
363 }
364 if (!icons.empty()) {
365 UpdateBundlesIcon(icons, device);
366 }
367 }
368
HandleBundleIconSync(const std::shared_ptr<TlvBox> & boxMessage)369 void DistributedService::HandleBundleIconSync(const std::shared_ptr<TlvBox>& boxMessage)
370 {
371 int32_t type = 0;
372 BundleIconBox iconBox = BundleIconBox(boxMessage);
373 if (!iconBox.GetIconSyncType(type)) {
374 ANS_LOGI("Dans handle bundle icon sync failed.");
375 return;
376 }
377
378 ANS_LOGI("Dans handle bundl icon type %{public}d %{public}d.", type, localDevice_.deviceType_);
379 if (type == IconSyncType::REPORT_SAVED_ICON &&
380 localDevice_.deviceType_ == DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE) {
381 DistributedDeviceInfo device;
382 if (!CheckPeerDevice(iconBox, device)) {
383 return;
384 }
385 std::set<std::string> bundleSet;
386 std::vector<std::string> bundleList;
387 iconBox.GetBundleList(bundleList);
388 for (auto bundle : bundleList) {
389 ANS_LOGI("Dans handle receive %{public}s.", bundle.c_str());
390 bundleSet.insert(bundle);
391 }
392 bundleIconCache_.insert(std::make_pair(device.deviceId_, bundleSet));
393 GenerateBundleIconSync(device);
394 }
395
396 if (type == IconSyncType::UPDATE_BUNDLE_ICON &&
397 localDevice_.deviceType_ != DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE) {
398 std::unordered_map<std::string, std::string> bundlesIcon;
399 if (!iconBox.GetBundlesIcon(bundlesIcon)) {
400 ANS_LOGI("Dans handle bundle icon get icon failed.");
401 return;
402 }
403 DistributedPreferences::GetInstance().InertBatchBundleIcons(bundlesIcon);
404 }
405
406 if (type == IconSyncType::REQUEST_BUNDLE_ICON &&
407 localDevice_.deviceType_ != DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE) {
408 DistributedDeviceInfo device;
409 if (!CheckPeerDevice(iconBox, device)) {
410 return;
411 }
412 ReportBundleIconList(device);
413 }
414
415 if (type == IconSyncType::REMOVE_BUNDLE_ICON &&
416 localDevice_.deviceType_ != DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE) {
417 std::vector<std::string> bundleList;
418 iconBox.GetBundleList(bundleList);
419 for (auto& bundle : bundleList) {
420 DistributedPreferences::GetInstance().DeleteBundleIcon(bundle);
421 }
422 }
423 }
424 }
425 }
426