1 /*
2 * Copyright (c) 2023 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 "notification_local_live_view_button.h"
17
18 #include <cstdint>
19 #include <sstream>
20 #include <string> // for basic_string, operator+, basic_string<>...
21 #include <memory> // for shared_ptr, shared_ptr<>::element_type
22 #include <vector>
23
24 #include "ans_image_util.h"
25 #include "ans_log_wrapper.h"
26 #include "nlohmann/json.hpp" // for json, basic_json<>::object_t, basic_json
27 #include "notification_button_option.h"
28 #include "notification_json_convert.h"
29 #include "parcel.h" // for Parcel
30 #include "pixel_map.h" // for PixelMap
31
32 namespace OHOS {
33 namespace Notification {
34 const uint32_t BUTTON_MAX_SIZE = 3;
35 const uint32_t BUTTON_RESOURCE_SIZE = 3;
36 const uint32_t RESOURCE_BUNDLENAME_INDEX = 0;
37 const uint32_t RESOURCE_MODULENAME_INDEX = 1;
38 const uint32_t RESOURCE_ID_INDEX = 2;
39 using ResourceVectorPtr = std::vector<std::shared_ptr<ResourceManager::Resource>>;
40
GetAllButtonNames() const41 std::vector<std::string> NotificationLocalLiveViewButton::GetAllButtonNames() const
42 {
43 return buttonNames_;
44 }
45
addSingleButtonName(const std::string & buttonName)46 void NotificationLocalLiveViewButton::addSingleButtonName(const std::string &buttonName)
47 {
48 if (buttonNames_.size() >= BUTTON_MAX_SIZE) {
49 ANS_LOGW("already added 3 buttonOption");
50 return;
51 }
52
53 buttonNames_.emplace_back(buttonName);
54 }
55
GetAllButtonIcons() const56 std::vector<std::shared_ptr<Media::PixelMap>> NotificationLocalLiveViewButton::GetAllButtonIcons() const
57 {
58 return buttonIcons_;
59 }
60
addSingleButtonIcon(std::shared_ptr<Media::PixelMap> & icon)61 void NotificationLocalLiveViewButton::addSingleButtonIcon(std::shared_ptr<Media::PixelMap> &icon)
62 {
63 if (buttonIcons_.size() >= BUTTON_MAX_SIZE) {
64 ANS_LOGW("already added 3 buttonIcon");
65 return;
66 }
67
68 buttonIcons_.emplace_back(icon);
69 }
70
GetAllButtonIconResource() const71 ResourceVectorPtr NotificationLocalLiveViewButton::GetAllButtonIconResource() const
72 {
73 return buttonIconsResource_;
74 }
75
addSingleButtonIconResource(std::shared_ptr<ResourceManager::Resource> & iconResource)76 void NotificationLocalLiveViewButton::addSingleButtonIconResource(
77 std::shared_ptr<ResourceManager::Resource> &iconResource)
78 {
79 if (buttonIcons_.size() >= BUTTON_MAX_SIZE) {
80 ANS_LOGW("already added 3 buttonIcon");
81 return;
82 }
83
84 buttonIconsResource_.emplace_back(iconResource);
85 }
86
Dump()87 std::string NotificationLocalLiveViewButton::Dump()
88 {
89 return "";
90 }
91
ToJson(nlohmann::json & jsonObject) const92 bool NotificationLocalLiveViewButton::ToJson(nlohmann::json &jsonObject) const
93 {
94 nlohmann::json buttonsArr = nlohmann::json::array();
95
96 jsonObject["names"] = nlohmann::json(buttonNames_);
97
98 nlohmann::json iconsArr = nlohmann::json::array();
99 for (auto &btn : buttonIcons_) {
100 if (!btn) {
101 continue;
102 }
103 nlohmann::json btnObj = AnsImageUtil::PackImage(btn);
104 iconsArr.emplace_back(btnObj);
105 }
106 jsonObject["icons"] = iconsArr;
107
108 nlohmann::json iconResourceArr = nlohmann::json::array();
109 for (const auto &resource : buttonIconsResource_) {
110 if (!resource) {
111 continue;
112 }
113 nlohmann::json resourceObj;
114 resourceObj["id"] = resource->id;
115 resourceObj["bundleName"] = resource->bundleName;
116 resourceObj["moduleName"] = resource->moduleName;
117 iconResourceArr.emplace_back(resourceObj);
118 }
119 jsonObject["iconResources"] = iconResourceArr;
120
121 return true;
122 }
123
ResourceFromJson(const nlohmann::json & resource,std::shared_ptr<ResourceManager::Resource> & resourceObj)124 bool NotificationLocalLiveViewButton::ResourceFromJson(const nlohmann::json &resource,
125 std::shared_ptr<ResourceManager::Resource>& resourceObj)
126 {
127 const auto &jsonEnd = resource.cend();
128 int resourceCount = BUTTON_RESOURCE_SIZE;
129 if (resource.find("bundleName") != jsonEnd && resource.at("bundleName").is_string()) {
130 resourceCount--;
131 resourceObj->bundleName = resource.at("bundleName").get<std::string>();
132 }
133 if (resource.find("moduleName") != jsonEnd && resource.at("moduleName").is_string()) {
134 resourceCount--;
135 resourceObj->moduleName = resource.at("moduleName").get<std::string>();
136 }
137 if (resource.find("id") != jsonEnd && resource.at("id").is_number_integer()) {
138 resourceCount--;
139 resourceObj->id = resource.at("id").get<int32_t>();
140 }
141 if (resourceCount == 0) {
142 return true;
143 }
144 ANS_LOGE("Resource from json failed.");
145 return false;
146 }
147
FromJson(const nlohmann::json & jsonObject)148 NotificationLocalLiveViewButton *NotificationLocalLiveViewButton::FromJson(const nlohmann::json &jsonObject)
149 {
150 if (jsonObject.is_null() or !jsonObject.is_object()) {
151 ANS_LOGE("Invalid JSON object");
152 return nullptr;
153 }
154
155 NotificationLocalLiveViewButton *button = new (std::nothrow) NotificationLocalLiveViewButton();
156 if (button == nullptr) {
157 ANS_LOGE("Failed to create capsule instance");
158 return nullptr;
159 }
160
161 const auto &jsonEnd = jsonObject.cend();
162
163 if (jsonObject.find("names") != jsonEnd && jsonObject.at("names").is_array()) {
164 button->buttonNames_ = jsonObject.at("names").get<std::vector<std::string>>();
165 }
166
167 if (jsonObject.find("icons") != jsonEnd) {
168 auto iconArr = jsonObject.at("icons");
169 for (auto &iconObj : iconArr) {
170 if (!iconObj.is_string()) {
171 continue;
172 }
173 auto pIcon = AnsImageUtil::UnPackImage(iconObj.get<std::string>());
174 if (pIcon == nullptr) {
175 ANS_LOGE("Failed to parse button icon");
176 delete button;
177 return nullptr;
178 }
179 button->buttonIcons_.emplace_back(pIcon);
180 }
181 }
182
183 if (jsonObject.find("iconResources") != jsonEnd) {
184 auto resourcesArr = jsonObject.at("iconResources");
185 for (auto &resource : resourcesArr) {
186 auto resourceObj = std::make_shared<Global::Resource::ResourceManager::Resource>();
187 if (ResourceFromJson(resource, resourceObj)) {
188 button->buttonIconsResource_.emplace_back(resourceObj);
189 }
190 }
191 }
192
193 return button;
194 }
195
Marshalling(Parcel & parcel) const196 bool NotificationLocalLiveViewButton::Marshalling(Parcel &parcel) const
197 {
198 if (!parcel.WriteStringVector(buttonNames_)) {
199 ANS_LOGE("Failed to write buttonNames");
200 return false;
201 }
202
203 if (!parcel.WriteUint64(buttonIcons_.size())) {
204 ANS_LOGE("Failed to write the size of buttonIcons");
205 return false;
206 }
207
208 for (auto it = buttonIcons_.begin(); it != buttonIcons_.end(); ++it) {
209 if (!parcel.WriteParcelable(it->get())) {
210 ANS_LOGE("Failed to write buttonIcons");
211 return false;
212 }
213 }
214
215 if (!parcel.WriteUint64(buttonIconsResource_.size())) {
216 ANS_LOGE("Failed to write the size of buttonIcons");
217 return false;
218 }
219
220 for (auto it = buttonIconsResource_.begin(); it != buttonIconsResource_.end(); ++it) {
221 std::vector<std::string> iconsResource = {};
222 // Insertion cannot be changed, Marshalling and Unmarshalling need to match
223 iconsResource.push_back((*it)->bundleName);
224 iconsResource.push_back((*it)->moduleName);
225 iconsResource.push_back(std::to_string((*it)->id));
226 if (!parcel.WriteStringVector(iconsResource)) {
227 ANS_LOGE("Failed to write button icon resource");
228 return false;
229 }
230 }
231
232 return true;
233 }
234
ReadFromParcel(Parcel & parcel)235 bool NotificationLocalLiveViewButton::ReadFromParcel(Parcel &parcel)
236 {
237 if (!parcel.ReadStringVector(&buttonNames_)) {
238 ANS_LOGE("Failed to read button names");
239 return false;
240 }
241
242 auto vsize = parcel.ReadUint64();
243 vsize = (vsize < BUTTON_MAX_SIZE) ? vsize : BUTTON_MAX_SIZE;
244 for (uint64_t it = 0; it < vsize; ++it) {
245 auto member = std::shared_ptr<Media::PixelMap>(parcel.ReadParcelable<Media::PixelMap>());
246 if (member == nullptr) {
247 buttonIcons_.clear();
248 ANS_LOGE("Failed to read LocalLiveViewButton");
249 return false;
250 }
251
252 buttonIcons_.emplace_back(member);
253 }
254
255 vsize = parcel.ReadUint64();
256 for (uint64_t it = 0; it < vsize; ++it) {
257 std::vector<std::string> iconsResource = {};
258 if (!parcel.ReadStringVector(&iconsResource)) {
259 ANS_LOGE("Failed to read button names");
260 return false;
261 }
262 if (iconsResource.size() < BUTTON_RESOURCE_SIZE) {
263 ANS_LOGE("Invalid input for button icons resource");
264 return false;
265 }
266 auto resource = std::make_shared<ResourceManager::Resource>();
267 resource->bundleName = iconsResource[RESOURCE_BUNDLENAME_INDEX];
268 resource->moduleName = iconsResource[RESOURCE_MODULENAME_INDEX];
269 std::stringstream sin(iconsResource[RESOURCE_ID_INDEX]);
270 int32_t checknum;
271 if (!(sin >> checknum)) {
272 ANS_LOGE("Invalid input for button icons resource");
273 return false;
274 }
275 resource->id = std::stoi(iconsResource[RESOURCE_ID_INDEX]);
276 buttonIconsResource_.emplace_back(resource);
277 }
278
279 return true;
280 }
281
Unmarshalling(Parcel & parcel)282 NotificationLocalLiveViewButton *NotificationLocalLiveViewButton::Unmarshalling(Parcel &parcel)
283 {
284 NotificationLocalLiveViewButton *button = new (std::nothrow) NotificationLocalLiveViewButton();
285
286 if (button && !button->ReadFromParcel(parcel)) {
287 delete button;
288 button = nullptr;
289 }
290
291 return button;
292 }
293
ClearButtonIcons()294 void NotificationLocalLiveViewButton::ClearButtonIcons()
295 {
296 buttonIcons_.clear();
297 }
298
ClearButtonIconsResource()299 void NotificationLocalLiveViewButton::ClearButtonIconsResource()
300 {
301 buttonIconsResource_.clear();
302 }
303 } // namespace Notification
304 } // namespace OHOS
305