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