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