• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_bundle_service.h"
17 
18 #include "bundle_icon_box.h"
19 #include "analytics_util.h"
20 #include "ans_image_util.h"
21 #include "distributed_client.h"
22 #include "distributed_data_define.h"
23 #include "notification_helper.h"
24 #include "bundle_resource_helper.h"
25 #include "distributed_device_service.h"
26 #include "distributed_preference.h"
27 #include "distributed_subscribe_service.h"
28 #include "distributed_send_adapter.h"
29 
30 namespace OHOS {
31 namespace Notification {
32 
GetInstance()33 DistributedBundleService& DistributedBundleService::GetInstance()
34 {
35     static DistributedBundleService distributedBundleService;
36     return distributedBundleService;
37 }
38 
39 #ifdef DISTRIBUTED_FEATURE_MASTER
HandleBundleIconSync(const std::shared_ptr<TlvBox> & boxMessage)40 void DistributedBundleService::HandleBundleIconSync(const std::shared_ptr<TlvBox>& boxMessage)
41 {
42     int32_t type = 0;
43     BundleIconBox iconBox = BundleIconBox(boxMessage);
44     if (!iconBox.GetIconSyncType(type)) {
45         ANS_LOGI("Dans handle bundle icon sync failed.");
46         return;
47     }
48 
49     ANS_LOGI("Dans handle bundl icon type %{public}d.", type);
50     if (type == IconSyncType::REPORT_SAVED_ICON) {
51         std::string deviceId;
52         if (!iconBox.GetLocalDeviceId(deviceId)) {
53             ANS_LOGI("Dans get deviceId failed.");
54             return;
55         }
56 
57         DistributedDeviceInfo device;
58         if (!DistributedDeviceService::GetInstance().GetDeviceInfo(deviceId, device)) {
59             return;
60         }
61         std::set<std::string> bundleSet;
62         std::vector<std::string> bundleList;
63         iconBox.GetBundleList(bundleList);
64         for (auto bundle : bundleList) {
65             ANS_LOGI("Dans handle receive %{public}s.", bundle.c_str());
66             bundleSet.insert(bundle);
67         }
68         bundleIconCache_[device.deviceId_] = bundleSet;
69         GenerateBundleIconSync(device);
70     }
71 }
72 
RequestBundlesIcon(const DistributedDeviceInfo peerDevice,bool isForce)73 void DistributedBundleService::RequestBundlesIcon(const DistributedDeviceInfo peerDevice, bool isForce)
74 {
75     if (!DistributedDeviceService::GetInstance().IsSyncIcons(peerDevice.deviceId_, isForce)) {
76         return;
77     }
78 
79     auto localDevice = DistributedDeviceService::GetInstance().GetLocalDevice();
80     std::shared_ptr<BundleIconBox> iconBox = std::make_shared<BundleIconBox>();
81     iconBox->SetIconSyncType(IconSyncType::REQUEST_BUNDLE_ICON);
82     iconBox->SetLocalDeviceId(localDevice.deviceId_);
83     if (!iconBox->Serialize()) {
84         ANS_LOGW("Dans RequestBundlesIcon serialize failed.");
85         return;
86     }
87 
88     std::shared_ptr<PackageInfo> packageInfo = std::make_shared<PackageInfo>(iconBox, peerDevice,
89         TransDataType::DATA_TYPE_MESSAGE, MODIFY_ERROR_EVENT_CODE);
90     DistributedSendAdapter::GetInstance().SendPackage(packageInfo);
91     DistributedDeviceService::GetInstance().SetDeviceSyncData(peerDevice.deviceId_,
92         DistributedDeviceService::SYNC_BUNDLE_ICONS, true);
93 }
94 
GenerateBundleIconSync(const DistributedDeviceInfo & device)95 void DistributedBundleService::GenerateBundleIconSync(const DistributedDeviceInfo& device)
96 {
97     std::vector<NotificationBundleOption> bundleOption;
98     if (NotificationHelper::GetAllLiveViewEnabledBundles(bundleOption) != 0) {
99         ANS_LOGW("Dans get all live view enable bundle failed.");
100         return;
101     }
102 
103     std::vector<NotificationBundleOption> enableBundleOption;
104     if (NotificationHelper::GetAllDistribuedEnabledBundles("liteWearable", enableBundleOption) != 0) {
105         ANS_LOGW("Dans get all live view enable bundle failed.");
106     }
107 
108     std::set<std::string> enabledBundles;
109     for (auto item : enableBundleOption) {
110         enabledBundles.insert(item.GetBundleName());
111     }
112     std::set<std::string> cachedIcons;
113     std::vector<std::string> unCachedBundleList;
114     if (bundleIconCache_.find(device.deviceId_) != bundleIconCache_.end()) {
115         cachedIcons = bundleIconCache_[device.deviceId_];
116     }
117     for (auto item : bundleOption) {
118         if (enabledBundles.find(item.GetBundleName()) != enabledBundles.end() ||
119             cachedIcons.find(item.GetBundleName()) != cachedIcons.end()) {
120             continue;
121         }
122         unCachedBundleList.push_back(item.GetBundleName());
123     }
124 
125     ANS_LOGI("Dans Generate bundle %{public}zu %{public}zu %{public}zu.", bundleOption.size(),
126         enableBundleOption.size(), unCachedBundleList.size());
127     std::vector<std::string> sendIcon;
128     std::unordered_map<std::string, std::string> icons;
129     for (auto bundle : unCachedBundleList) {
130         std::string icon;
131         if (!GetBundleResourceInfo(bundle, icon)) {
132             continue;
133         }
134         sendIcon.push_back(bundle);
135         icons.insert(std::make_pair(bundle, icon));
136         if (icons.size() == BundleIconBox::MAX_ICON_NUM) {
137             if (UpdateBundlesIcon(icons, device) == ERR_OK) {
138                 cachedIcons.insert(sendIcon.begin(), sendIcon.end());
139             }
140             icons.clear();
141             sendIcon.clear();
142         }
143     }
144     if (!icons.empty() && UpdateBundlesIcon(icons, device) == ERR_OK) {
145         cachedIcons.insert(sendIcon.begin(), sendIcon.end());
146     }
147     bundleIconCache_[device.deviceId_] = cachedIcons;
148 }
149 
HandleBundleRemoved(const std::string & bundleName)150 void DistributedBundleService::HandleBundleRemoved(const std::string& bundleName)
151 {
152     auto localDevice = DistributedDeviceService::GetInstance().GetLocalDevice();
153     auto peerDevices = DistributedDeviceService::GetInstance().GetDeviceList();
154     for (auto& device : peerDevices) {
155         auto iter = bundleIconCache_.find(device.first);
156         if (iter == bundleIconCache_.end() ||
157             iter->second.find(bundleName) == iter->second.end()) {
158             continue;
159         }
160         iter->second.erase(bundleName);
161         if (device.second.deviceType_ == DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE) {
162             continue;
163         }
164 
165         std::shared_ptr<BundleIconBox> iconBox = std::make_shared<BundleIconBox>();
166         iconBox->SetIconSyncType(IconSyncType::REMOVE_BUNDLE_ICON);
167         iconBox->SetBundleList({bundleName});
168         iconBox->SetLocalDeviceId(localDevice.deviceId_);
169         if (!iconBox->Serialize()) {
170             ANS_LOGW("Dans HandleBundleRemove serialize failed.");
171             continue;
172         }
173 
174         auto packageInfo = std::make_shared<PackageInfo>(iconBox, device.second,
175             TransDataType::DATA_TYPE_MESSAGE, MODIFY_ERROR_EVENT_CODE);
176         DistributedSendAdapter::GetInstance().SendPackage(packageInfo);
177         ANS_LOGI("Dans ReportBundleIconList %{public}s %{public}d.",
178             StringAnonymous(device.second.deviceId_).c_str(), device.second.deviceType_);
179     }
180 }
181 
HandleBundleChanged(const std::string & bundleName,bool updatedExit)182 void DistributedBundleService::HandleBundleChanged(const std::string& bundleName, bool updatedExit)
183 {
184     std::vector<DistributedDeviceInfo> updateDeviceList;
185     GetNeedUpdateDevice(updatedExit, bundleName, updateDeviceList);
186     if (updateDeviceList.empty()) {
187         ANS_LOGI("No need update %{public}s.", bundleName.c_str());
188         return;
189     }
190     std::string icon;
191     if (!GetBundleResourceInfo(bundleName, icon)) {
192         return;
193     }
194     std::unordered_map<std::string, std::string> icons;
195     icons.insert(std::make_pair(bundleName, icon));
196     for (auto& device : updateDeviceList) {
197         UpdateBundlesIcon(icons, device);
198     }
199 }
200 
UpdateBundlesIcon(const std::unordered_map<std::string,std::string> & icons,const DistributedDeviceInfo peerDevice)201 int32_t DistributedBundleService::UpdateBundlesIcon(const std::unordered_map<std::string, std::string>& icons,
202     const DistributedDeviceInfo peerDevice)
203 {
204     std::shared_ptr<BundleIconBox> iconBox = std::make_shared<BundleIconBox>();
205     iconBox->SetIconSyncType(IconSyncType::UPDATE_BUNDLE_ICON);
206     iconBox->SetBundlesIcon(icons);
207     if (!iconBox->Serialize()) {
208         ANS_LOGW("Dans UpdateBundlesIcon serialize failed.");
209         return -1;
210     }
211 
212     std::shared_ptr<PackageInfo> packageInfo = std::make_shared<PackageInfo>(iconBox, peerDevice,
213         TransDataType::DATA_TYPE_BYTES, MODIFY_ERROR_EVENT_CODE);
214     DistributedSendAdapter::GetInstance().SendPackage(packageInfo);
215     ANS_LOGI("Dans UpdateBundlesIcon %{public}s %{public}d.",
216         StringAnonymous(peerDevice.deviceId_).c_str(), peerDevice.deviceType_);
217     return ERR_OK;
218 }
219 
GetBundleResourceInfo(const std::string bundleName,std::string & icon)220 bool DistributedBundleService::GetBundleResourceInfo(const std::string bundleName, std::string& icon)
221 {
222     AppExecFwk::BundleResourceInfo resourceInfo;
223     if (DelayedSingleton<BundleResourceHelper>::GetInstance()->GetBundleInfo(bundleName, resourceInfo) != 0) {
224         ANS_LOGW("Dans get bundle icon failed %{public}s.", bundleName.c_str());
225         return false;
226     }
227     std::shared_ptr<Media::PixelMap> iconPixelmap = AnsImageUtil::CreatePixelMapByString(resourceInfo.icon);
228     if (!AnsImageUtil::ImageScale(iconPixelmap, DEFAULT_ICON_WITHE, DEFAULT_ICON_HEIGHT)) {
229         return false;
230     }
231     icon = AnsImageUtil::PackImage(iconPixelmap);
232     ANS_LOGI("Dans get bundle icon bundle %{public}s %{public}zu.", bundleName.c_str(), resourceInfo.icon.size());
233     return true;
234 }
235 
GetNeedUpdateDevice(bool updatedExit,const std::string & bundleName,std::vector<DistributedDeviceInfo> & updateDeviceList)236 void DistributedBundleService::GetNeedUpdateDevice(bool updatedExit, const std::string& bundleName,
237     std::vector<DistributedDeviceInfo>& updateDeviceList)
238 {
239     auto peerDevices = DistributedDeviceService::GetInstance().GetDeviceList();
240     for (auto& device : peerDevices) {
241         if (device.second.deviceType_ == DistributedHardware::DmDeviceType::DEVICE_TYPE_PHONE) {
242             continue;
243         }
244         auto iter = bundleIconCache_.find(device.first);
245         if (updatedExit) {
246             if (iter == bundleIconCache_.end() ||
247                 iter->second.find(bundleName) == iter->second.end()) {
248                 continue;
249             }
250             updateDeviceList.push_back(device.second);
251         } else {
252             if (iter != bundleIconCache_.end() &&
253                 iter->second.find(bundleName) != iter->second.end()) {
254                 continue;
255             }
256             if (iter == bundleIconCache_.end()) {
257                 std::set<std::string> cachedIcons = { bundleName };
258                 bundleIconCache_.insert(std::make_pair(device.first, cachedIcons));
259             } else {
260                 iter->second.insert(bundleName);
261             }
262             updateDeviceList.push_back(device.second);
263         }
264     }
265 }
266 
SetDeviceBundleList(const std::shared_ptr<TlvBox> & boxMessage)267 void DistributedBundleService::SetDeviceBundleList(const std::shared_ptr<TlvBox>& boxMessage)
268 {
269     int32_t operatorType = 0;
270     std::string deviceId;
271     BundleIconBox iconBox = BundleIconBox(boxMessage);
272     if (!iconBox.GetLocalDeviceId(deviceId)) {
273         ANS_LOGW("Dans bundle get deviceid failed.");
274         return;
275     }
276 
277     DistributedDeviceInfo device;
278     if (!DistributedDeviceService::GetInstance().GetDeviceInfo(deviceId, device)) {
279         ANS_LOGW("Dans bundle get device info failed %{public}s.", StringAnonymous(deviceId).c_str());
280         return;
281     }
282 
283     if (!iconBox.GetIconSyncType(operatorType)) {
284         ANS_LOGI("Dans handle bundle icon sync failed.");
285         return;
286     }
287 
288     std::vector<std::string> labelList;
289     std::vector<std::string> bundleList;
290     if (!iconBox.GetBundlesInfo(bundleList, labelList)) {
291         ANS_LOGI("Dans handle bundle list failed.");
292         return;
293     }
294 
295     std::string deviceType = DistributedDeviceService::DeviceTypeToTypeString(device.deviceType_);
296     if (deviceType.empty()) {
297         ANS_LOGW("Dans handle bundle invalid %{public}s %{public}u.", StringAnonymous(deviceId).c_str(),
298             device.deviceType_);
299         return;
300     }
301     auto ret = NotificationHelper::SetTargetDeviceBundleList(deviceType, device.udid_, operatorType,
302         bundleList, labelList);
303     ANS_LOGI("SetDeviceBundleList %{public}s %{public}s %{public}d %{public}zu %{public}d", deviceType.c_str(),
304         StringAnonymous(deviceId).c_str(), operatorType, bundleList.size(), ret);
305 }
306 #else
HandleBundleIconSync(const std::shared_ptr<TlvBox> & boxMessage)307 void DistributedBundleService::HandleBundleIconSync(const std::shared_ptr<TlvBox>& boxMessage)
308 {
309     int32_t type = 0;
310     BundleIconBox iconBox = BundleIconBox(boxMessage);
311     if (!iconBox.GetIconSyncType(type)) {
312         ANS_LOGI("Dans handle bundle icon sync failed.");
313         return;
314     }
315 
316     ANS_LOGI("Dans handle bundl icon type %{public}d.", type);
317     if (type == IconSyncType::UPDATE_BUNDLE_ICON) {
318         std::unordered_map<std::string, std::string> bundlesIcon;
319         if (!iconBox.GetBundlesIcon(bundlesIcon)) {
320             ANS_LOGI("Dans handle bundle icon get icon failed.");
321             return;
322         }
323         DistributedPreferences::GetInstance().InsertBatchBundleIcons(bundlesIcon);
324     }
325 
326     if (type == IconSyncType::REQUEST_BUNDLE_ICON) {
327         std::string deviceId;
328         if (!iconBox.GetLocalDeviceId(deviceId)) {
329             ANS_LOGI("Dans get deviceId failed.");
330             return;
331         }
332 
333         DistributedDeviceInfo device;
334         if (!DistributedDeviceService::GetInstance().GetDeviceInfo(deviceId, device)) {
335             return;
336         }
337         ReportBundleIconList(device);
338     }
339 
340     if (type == IconSyncType::REMOVE_BUNDLE_ICON) {
341         std::vector<std::string> bundleList;
342         iconBox.GetBundleList(bundleList);
343         for (auto& bundle : bundleList) {
344             DistributedPreferences::GetInstance().DeleteBundleIcon(bundle);
345         }
346     }
347 }
348 
ReportBundleIconList(const DistributedDeviceInfo peerDevice)349 void DistributedBundleService::ReportBundleIconList(const DistributedDeviceInfo peerDevice)
350 {
351     std::vector<std::string> bundlesName;
352     DistributedPreferences::GetInstance().GetSavedBundlesIcon(bundlesName);
353     std::shared_ptr<BundleIconBox> iconBox = std::make_shared<BundleIconBox>();
354     auto localDevice = DistributedDeviceService::GetInstance().GetLocalDevice();
355     iconBox->SetIconSyncType(IconSyncType::REPORT_SAVED_ICON);
356     iconBox->SetBundleList(bundlesName);
357     iconBox->SetLocalDeviceId(localDevice.deviceId_);
358     if (!iconBox->Serialize()) {
359         ANS_LOGW("Dans ReportBundleIconList serialize failed.");
360         return;
361     }
362 
363     std::shared_ptr<PackageInfo> packageInfo = std::make_shared<PackageInfo>(iconBox, peerDevice,
364         TransDataType::DATA_TYPE_MESSAGE, MODIFY_ERROR_EVENT_CODE);
365     DistributedSendAdapter::GetInstance().SendPackage(packageInfo);
366     ANS_LOGI("Dans ReportBundleIconList %{public}s %{public}d.",
367         StringAnonymous(peerDevice.deviceId_).c_str(), peerDevice.deviceType_);
368 }
369 
SyncInstalledBundles(const DistributedDeviceInfo & peerDevice,bool isForce)370 void DistributedBundleService::SyncInstalledBundles(const DistributedDeviceInfo& peerDevice, bool isForce)
371 {
372     auto localDevice = DistributedDeviceService::GetInstance().GetLocalDevice();
373     if (!DistributedDeviceService::GetInstance().IsSyncInstalledBundle(peerDevice.deviceId_, isForce)) {
374         return;
375     }
376 
377     std::vector<std::pair<std::string, std::string>> bundlesName;
378     int32_t userId = DistributedSubscribeService::GetCurrentActiveUserId();
379     int32_t result = DelayedSingleton<BundleResourceHelper>::GetInstance()->GetAllInstalledBundles(
380         bundlesName, userId);
381     if (result != ERR_OK) {
382         ANS_LOGW("Dans get bundls failed.");
383         return;
384     }
385 
386     std::vector<std::pair<std::string, std::string>> bundles;
387     for (auto& bundle : bundlesName) {
388         bundles.push_back(bundle);
389         if (bundles.size() >= BundleIconBox::MAX_BUNDLE_NUM) {
390             SendInstalledBundles(peerDevice, localDevice.deviceId_, bundles,
391                 BundleListOperationType::ADD_BUNDLES);
392             bundles.clear();
393         }
394     }
395 
396     if (!bundles.empty()) {
397         SendInstalledBundles(peerDevice, localDevice.deviceId_, bundles, BundleListOperationType::ADD_BUNDLES);
398     }
399     DistributedDeviceService::GetInstance().SetDeviceSyncData(peerDevice.deviceId_,
400         DistributedDeviceService::SYNC_INSTALLED_BUNDLE, true);
401 }
402 
SendInstalledBundles(const DistributedDeviceInfo & peerDevice,const std::string & localDeviceId,const std::vector<std::pair<std::string,std::string>> & bundles,int32_t type)403 void DistributedBundleService::SendInstalledBundles(const DistributedDeviceInfo& peerDevice,
404     const std::string& localDeviceId, const std::vector<std::pair<std::string, std::string>> & bundles, int32_t type)
405 {
406     std::shared_ptr<BundleIconBox> iconBox = std::make_shared<BundleIconBox>();
407     iconBox->SetMessageType(INSTALLED_BUNDLE_SYNC);
408     iconBox->SetLocalDeviceId(localDeviceId);
409     iconBox->SetIconSyncType(type);
410     iconBox->SetBundlesInfo(bundles);
411     if (!iconBox->Serialize()) {
412         ANS_LOGW("Dans SendInstalledBundles serialize failed.");
413         return;
414     }
415 
416     std::shared_ptr<PackageInfo> packageInfo = std::make_shared<PackageInfo>(iconBox, peerDevice,
417         TransDataType::DATA_TYPE_MESSAGE, MODIFY_ERROR_EVENT_CODE);
418     DistributedSendAdapter::GetInstance().SendPackage(packageInfo);
419     ANS_LOGI("Dans send bundle %{public}s %{public}d.",
420         StringAnonymous(peerDevice.deviceId_).c_str(), peerDevice.deviceType_);
421 }
422 #endif
423 
424 }
425 }
426