• 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 "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