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 "media_notification_utils.h"
17
18 #include <thread>
19 #include <securec.h>
20 #include "media_log.h"
21 #include "parcel.h"
22 #include "media_change_info.h"
23 #include "medialibrary_errno.h"
24
25 namespace OHOS::Media {
26 using namespace Notification;
27 const size_t MAX_PARCEL_SIZE = 200 * 1024 * 0.95;
28 const uint64_t INTERVAL_TIME_MS = 10;
29
30 struct MarshallingPtrVisitor {
31 std::shared_ptr<Parcel> &parcel;
32 bool isSystem;
operator ()OHOS::Media::MarshallingPtrVisitor33 bool operator()(const PhotoAssetChangeData &data) const
34 {
35 return data.Marshalling(*parcel, isSystem);
36 }
operator ()OHOS::Media::MarshallingPtrVisitor37 bool operator()(const AlbumChangeData &data) const
38 {
39 return data.Marshalling(*parcel, isSystem);
40 }
41 };
42
UnmarshalInMultiMode(Parcel & parcel)43 std::shared_ptr<MediaChangeInfo> NotificationUtils::UnmarshalInMultiMode(Parcel &parcel)
44 {
45 MediaChangeInfo* info = new (std::nothrow)MediaChangeInfo();
46 if ((info != nullptr) && (!info->ReadFromParcelInMultiMode(parcel))) {
47 delete info;
48 info = nullptr;
49 }
50 return std::shared_ptr<MediaChangeInfo>(info);
51 }
52
Marshalling(const std::shared_ptr<MediaChangeInfo> & mediaChangeInfo,std::vector<std::shared_ptr<Parcel>> & parcels)53 bool NotificationUtils::Marshalling(const std::shared_ptr<MediaChangeInfo> &mediaChangeInfo,
54 std::vector<std::shared_ptr<Parcel>> &parcels)
55 {
56 size_t index = 0;
57 do {
58 std::shared_ptr<Parcel> parcel = std::make_shared<Parcel>();
59 bool validFlag = true;
60 // 在每个包的每一个ChangeData前增加一个标志位,该标志位为false表示为parcel的最后一帧ChangeData。不在压缩和读取ChangeData
61 parcel->WriteBool(mediaChangeInfo->isForRecheck);
62 parcel->WriteUint16(static_cast<uint16_t>(mediaChangeInfo->notifyUri));
63 parcel->WriteUint16(static_cast<uint16_t>(mediaChangeInfo->notifyType));
64 parcel->WriteBool(mediaChangeInfo->isSystem);
65
66 for (size_t i = index; i < mediaChangeInfo->changeInfos.size(); i++) {
67 size_t currentDataSize = parcel->GetDataSize();
68 if (currentDataSize > MAX_PARCEL_SIZE) { // 待补充,动态内存大小难以确定
69 validFlag = false;
70 parcel->WriteBool(validFlag);
71 MEDIA_WARN_LOG("assetChangeData or lbumChangeData size exceeds the maximum limit.");
72 break;
73 } else {
74 validFlag = true;
75 ++index;
76 parcel->WriteBool(validFlag);
77 }
78
79 if (std::holds_alternative<PhotoAssetChangeData>(mediaChangeInfo->changeInfos[i])) {
80 parcel->WriteBool(true);
81 } else if (std::holds_alternative<AlbumChangeData>(mediaChangeInfo->changeInfos[i])) {
82 parcel->WriteBool(false);
83 } else {
84 MEDIA_ERR_LOG("fail to marshalling.");
85 return false;
86 }
87 std::visit(MarshallingPtrVisitor{parcel, mediaChangeInfo->isSystem}, mediaChangeInfo->changeInfos[i]);
88 }
89 parcel->WriteBool(false);
90 parcels.push_back(parcel);
91 } while (index < mediaChangeInfo->changeInfos.size());
92 return true;
93 }
94
WriteToChangeInfo(const std::shared_ptr<MediaChangeInfo> & mediaChangeInfo,std::vector<std::shared_ptr<AAFwk::ChangeInfo>> & changeInfos)95 bool NotificationUtils::WriteToChangeInfo(const std::shared_ptr<MediaChangeInfo> &mediaChangeInfo,
96 std::vector<std::shared_ptr<AAFwk::ChangeInfo>> &changeInfos)
97 {
98 std::vector<std::shared_ptr<Parcel>> parcels;
99 bool ret = Marshalling(mediaChangeInfo, parcels);
100 if (!ret) {
101 MEDIA_INFO_LOG("fail to marshlling");
102 return false;
103 }
104 for (auto &item : parcels) {
105 uintptr_t buf = item->GetData();
106 if (item->GetDataSize() == 0) {
107 MEDIA_ERR_LOG("fail to marshalling sercerParcel");
108 return false;
109 }
110 auto *uBuf = new (std::nothrow) uint8_t[item->GetDataSize()];
111 if (uBuf == nullptr) {
112 MEDIA_ERR_LOG("parcel->GetDataSize is null");
113 return false;
114 }
115 int ret = memcpy_s(uBuf, item->GetDataSize(), reinterpret_cast<uint8_t *>(buf), item->GetDataSize());
116 if (ret != 0) {
117 MEDIA_ERR_LOG("Parcel data copy failed, err = %{public}d", ret);
118 if (uBuf != nullptr) {
119 delete[] uBuf;
120 uBuf = nullptr;
121 }
122 return false;
123 }
124 std::shared_ptr<AAFwk::ChangeInfo> serverChangeInfo = std::make_shared<AAFwk::ChangeInfo>();
125 serverChangeInfo->data_ = uBuf;
126 serverChangeInfo->size_ = item->GetDataSize();
127 MEDIA_INFO_LOG("serverChangeInfo->size_ is: %{public}d", (int)item->GetDataSize());
128 changeInfos.push_back(serverChangeInfo);
129 }
130 return true;
131 }
132
SendNotification(const sptr<AAFwk::IDataAbilityObserver> & dataObserver,const std::shared_ptr<MediaChangeInfo> & mediaChangeInfo)133 int32_t NotificationUtils::SendNotification(const sptr<AAFwk::IDataAbilityObserver> &dataObserver,
134 const std::shared_ptr<MediaChangeInfo> &mediaChangeInfo)
135 {
136 if (dataObserver == nullptr || mediaChangeInfo == nullptr) {
137 MEDIA_ERR_LOG("dataObserver or mediaChangeInfo is nullptr");
138 return E_ERR;
139 }
140 std::shared_ptr<NotificationUtils> utilsHandle = std::make_shared<NotificationUtils>();
141 std::vector<std::shared_ptr<AAFwk::ChangeInfo>> changeInfos;
142 bool ret = utilsHandle->WriteToChangeInfo(mediaChangeInfo, changeInfos);
143 if (!ret || changeInfos.size() == 0) {
144 MEDIA_ERR_LOG("fail to write changeInfo");
145 return E_ERR;
146 }
147
148 for (auto &changeInfo : changeInfos) {
149 MEDIA_INFO_LOG("start send notification at an interval of 10 milliseconds");
150 dataObserver->OnChangeExt(*changeInfo);
151 if (changeInfo->data_ != nullptr) {
152 delete[] static_cast<uint8_t*>(changeInfo->data_);
153 changeInfo->data_ = nullptr;
154 }
155 std::this_thread::sleep_for(std::chrono::milliseconds(INTERVAL_TIME_MS));
156 }
157 return true;
158 }
159 } // OHOS::Media