1 /*
2 * Copyright (c) 2021-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_action_button.h"
17
18 #include "ans_image_util.h"
19 #include "ans_log_wrapper.h"
20 #include "want_agent_helper.h"
21 #include "want_params_wrapper.h"
22
23 namespace OHOS {
24 namespace Notification {
Create(const std::shared_ptr<Media::PixelMap> & icon,const std::string & title,const std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> & wantAgent,const std::shared_ptr<AAFwk::WantParams> & extras,NotificationConstant::SemanticActionButton semanticActionButton,bool autoCreatedReplies,const std::vector<std::shared_ptr<NotificationUserInput>> & mimeTypeOnlyInputs,const std::shared_ptr<NotificationUserInput> & userInput,bool isContextual)25 std::shared_ptr<NotificationActionButton> NotificationActionButton::Create(const std::shared_ptr<Media::PixelMap> &icon,
26 const std::string &title, const std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> &wantAgent,
27 const std::shared_ptr<AAFwk::WantParams> &extras, NotificationConstant::SemanticActionButton semanticActionButton,
28 bool autoCreatedReplies, const std::vector<std::shared_ptr<NotificationUserInput>> &mimeTypeOnlyInputs,
29 const std::shared_ptr<NotificationUserInput> &userInput, bool isContextual)
30 {
31 if (isContextual && (!icon || !wantAgent)) {
32 ANS_LOGE("icon or wantAgent can not be null when isContextual is true");
33 return {};
34 }
35
36 auto realExtras = extras;
37 if (!realExtras) {
38 realExtras = std::make_shared<AAFwk::WantParams>();
39 if (!realExtras) {
40 ANS_LOGE("create WantParams object failed");
41 return {};
42 }
43 }
44
45 std::shared_ptr<NotificationUserInput> textInput = userInput;
46 std::vector<std::shared_ptr<NotificationUserInput>> onlyInputs = mimeTypeOnlyInputs;
47 if (userInput && (userInput->IsMimeTypeOnly())) {
48 onlyInputs.push_back(userInput);
49 }
50
51 auto pActionButton = new (std::nothrow) NotificationActionButton(icon,
52 title,
53 wantAgent,
54 realExtras,
55 semanticActionButton,
56 autoCreatedReplies,
57 onlyInputs,
58 textInput,
59 isContextual);
60 if (pActionButton == nullptr) {
61 ANS_LOGE("create NotificationActionButton object failed");
62 return {};
63 }
64
65 return std::shared_ptr<NotificationActionButton>(pActionButton);
66 }
67
Create(const std::shared_ptr<NotificationActionButton> & actionButton)68 std::shared_ptr<NotificationActionButton> NotificationActionButton::Create(
69 const std::shared_ptr<NotificationActionButton> &actionButton)
70 {
71 if (!actionButton) {
72 ANS_LOGW("invalid input NotificationActionButton object");
73 return {};
74 }
75
76 return NotificationActionButton::Create(actionButton->GetIcon(),
77 actionButton->GetTitle(),
78 actionButton->GetWantAgent(),
79 actionButton->GetAdditionalData(),
80 actionButton->GetSemanticActionButton(),
81 actionButton->IsAutoCreatedReplies(),
82 actionButton->GetMimeTypeOnlyUserInputs(),
83 actionButton->GetUserInput(),
84 actionButton->IsContextDependent());
85 }
86
NotificationActionButton(const std::shared_ptr<Media::PixelMap> & icon,const std::string & title,const std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> & wantAgent,const std::shared_ptr<AAFwk::WantParams> & extras,NotificationConstant::SemanticActionButton semanticActionButton,bool autoCreatedReplies,const std::vector<std::shared_ptr<NotificationUserInput>> & mimeTypeOnlyInputs,const std::shared_ptr<NotificationUserInput> & userInput,bool isContextual)87 NotificationActionButton::NotificationActionButton(const std::shared_ptr<Media::PixelMap> &icon,
88 const std::string &title, const std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> &wantAgent,
89 const std::shared_ptr<AAFwk::WantParams> &extras, NotificationConstant::SemanticActionButton semanticActionButton,
90 bool autoCreatedReplies, const std::vector<std::shared_ptr<NotificationUserInput>> &mimeTypeOnlyInputs,
91 const std::shared_ptr<NotificationUserInput> &userInput, bool isContextual)
92 : icon_(icon),
93 title_(title),
94 wantAgent_(wantAgent),
95 extras_(extras),
96 semanticActionButton_(semanticActionButton),
97 autoCreatedReplies_(autoCreatedReplies),
98 mimeTypeOnlyUserInputs_(mimeTypeOnlyInputs),
99 userInput_(userInput),
100 isContextual_(isContextual)
101 {}
102
GetIcon() const103 const std::shared_ptr<Media::PixelMap> NotificationActionButton::GetIcon() const
104 {
105 return icon_;
106 }
107
GetTitle() const108 std::string NotificationActionButton::GetTitle() const
109 {
110 return title_;
111 }
112
GetWantAgent() const113 const std::shared_ptr<AbilityRuntime::WantAgent::WantAgent> NotificationActionButton::GetWantAgent() const
114 {
115 return wantAgent_;
116 }
117
AddAdditionalData(AAFwk::WantParams & extras)118 void NotificationActionButton::AddAdditionalData(AAFwk::WantParams &extras)
119 {
120 if (extras_) {
121 *extras_ = extras;
122 }
123 }
124
GetAdditionalData() const125 const std::shared_ptr<AAFwk::WantParams> NotificationActionButton::GetAdditionalData() const
126 {
127 return extras_;
128 }
129
SetSemanticActionButton(NotificationConstant::SemanticActionButton semanticActionButton)130 void NotificationActionButton::SetSemanticActionButton(NotificationConstant::SemanticActionButton semanticActionButton)
131 {
132 semanticActionButton_ = semanticActionButton;
133 }
134
GetSemanticActionButton() const135 NotificationConstant::SemanticActionButton NotificationActionButton::GetSemanticActionButton() const
136 {
137 return semanticActionButton_;
138 }
139
AddMimeTypeOnlyUserInput(const std::shared_ptr<NotificationUserInput> & userInput)140 void NotificationActionButton::AddMimeTypeOnlyUserInput(const std::shared_ptr<NotificationUserInput> &userInput)
141 {
142 if (!userInput) {
143 ANS_LOGE("The userInput is invalid.");
144 return;
145 }
146
147 if (!userInput->IsMimeTypeOnly()) {
148 ANS_LOGE("The userInput is not a particular MIME types.");
149 return;
150 }
151
152 mimeTypeOnlyUserInputs_.emplace_back(userInput);
153 }
154
GetMimeTypeOnlyUserInputs() const155 std::vector<std::shared_ptr<NotificationUserInput>> NotificationActionButton::GetMimeTypeOnlyUserInputs() const
156 {
157 return mimeTypeOnlyUserInputs_;
158 }
159
AddNotificationUserInput(const std::shared_ptr<NotificationUserInput> & userInput)160 void NotificationActionButton::AddNotificationUserInput(const std::shared_ptr<NotificationUserInput> &userInput)
161 {
162 userInput_ = userInput;
163 }
164
GetUserInput() const165 const std::shared_ptr<NotificationUserInput> NotificationActionButton::GetUserInput() const
166 {
167 return userInput_;
168 }
169
SetAutoCreatedReplies(bool autoCreatedReplies)170 void NotificationActionButton::SetAutoCreatedReplies(bool autoCreatedReplies)
171 {
172 autoCreatedReplies_ = autoCreatedReplies;
173 }
174
IsAutoCreatedReplies() const175 bool NotificationActionButton::IsAutoCreatedReplies() const
176 {
177 return autoCreatedReplies_;
178 }
179
SetContextDependent(bool isContextual)180 void NotificationActionButton::SetContextDependent(bool isContextual)
181 {
182 isContextual_ = isContextual;
183 }
184
IsContextDependent() const185 bool NotificationActionButton::IsContextDependent() const
186 {
187 return isContextual_;
188 }
189
Dump()190 std::string NotificationActionButton::Dump()
191 {
192 std::string mimeTypeOnlyUserInputs = "";
193 for (auto &item : mimeTypeOnlyUserInputs_) {
194 if (!item) {
195 mimeTypeOnlyUserInputs += "nullptr, ";
196 continue;
197 }
198 mimeTypeOnlyUserInputs += item->Dump();
199 mimeTypeOnlyUserInputs += ", ";
200 }
201
202 std::string userInput = "";
203 if (userInput_ == nullptr) {
204 userInput += "nullptr, ";
205 } else {
206 userInput += userInput_->Dump();
207 userInput += ", ";
208 }
209
210 return "NotificationActionButton{ "
211 "title = " + title_ +
212 ", semanticActionButton = " + std::to_string(static_cast<int32_t>(semanticActionButton_)) +
213 ", autoCreatedReplies = " + (autoCreatedReplies_ ? "true" : "false") +
214 ", isContextual = " + (isContextual_ ? "true" : "false") +
215 ", mimeTypeOnlyUserInputs = [" + mimeTypeOnlyUserInputs + "]" +
216 ", userInputs = [" + userInput + "]" +
217 " }";
218 }
219
ToJson(nlohmann::json & jsonObject) const220 bool NotificationActionButton::ToJson(nlohmann::json &jsonObject) const
221 {
222 jsonObject["icon"] = AnsImageUtil::PackImage(icon_);
223 jsonObject["title"] = title_;
224 jsonObject["wantAgent"] = wantAgent_ ? AbilityRuntime::WantAgent::WantAgentHelper::ToString(wantAgent_) : "";
225
226 std::string extrasStr;
227 if (extras_) {
228 AAFwk::WantParamWrapper wWrapper(*extras_);
229 extrasStr = wWrapper.ToString();
230 }
231 jsonObject["extras"] = extrasStr;
232
233 return true;
234 }
235
FromJson(const nlohmann::json & jsonObject)236 NotificationActionButton *NotificationActionButton::FromJson(const nlohmann::json &jsonObject)
237 {
238 if (jsonObject.is_null() or !jsonObject.is_object()) {
239 ANS_LOGE("Invalid JSON object");
240 return nullptr;
241 }
242
243 auto pButton = new (std::nothrow) NotificationActionButton();
244 if (pButton == nullptr) {
245 ANS_LOGE("Failed to create actionButton instance");
246 return nullptr;
247 }
248
249 const auto &jsonEnd = jsonObject.cend();
250 if (jsonObject.find("icon") != jsonEnd && jsonObject.at("icon").is_string()) {
251 auto iconStr = jsonObject.at("icon").get<std::string>();
252 pButton->icon_ = AnsImageUtil::UnPackImage(iconStr);
253 }
254
255 if (jsonObject.find("title") != jsonEnd && jsonObject.at("title").is_string()) {
256 pButton->title_ = jsonObject.at("title").get<std::string>();
257 }
258
259 if (jsonObject.find("wantAgent") != jsonEnd && jsonObject.at("wantAgent").is_string()) {
260 auto wantAgentValue = jsonObject.at("wantAgent").get<std::string>();
261 pButton->wantAgent_ = AbilityRuntime::WantAgent::WantAgentHelper::FromString(wantAgentValue);
262 }
263
264 if (jsonObject.find("extras") != jsonEnd && jsonObject.at("extras").is_string()) {
265 auto extrasString = jsonObject.at("extras").get<std::string>();
266 if (!extrasString.empty()) {
267 AAFwk::WantParams params = AAFwk::WantParamWrapper::ParseWantParams(extrasString);
268 pButton->extras_ = std::make_shared<AAFwk::WantParams>(params);
269 }
270 }
271
272 return pButton;
273 }
274
ConvertNotificationActionButton(const int32_t targetUid,const nlohmann::json & jsonObject)275 NotificationActionButton *NotificationActionButton::ConvertNotificationActionButton(
276 const int32_t targetUid, const nlohmann::json &jsonObject)
277 {
278 if (jsonObject.is_null() or !jsonObject.is_object()) {
279 ANS_LOGE("Converter : Invalid JSON object");
280 return nullptr;
281 }
282 auto pButton = new (std::nothrow) NotificationActionButton();
283 if (pButton == nullptr) {
284 ANS_LOGE("Failed to create actionButton instance");
285 return nullptr;
286 }
287
288 const auto &jsonEnd = jsonObject.cend();
289 if (jsonObject.find("icon") != jsonEnd && jsonObject.at("icon").is_string()) {
290 auto iconStr = jsonObject.at("icon").get<std::string>();
291 pButton->icon_ = AnsImageUtil::UnPackImage(iconStr);
292 }
293
294 if (jsonObject.find("title") != jsonEnd && jsonObject.at("title").is_string()) {
295 pButton->title_ = jsonObject.at("title").get<std::string>();
296 }
297
298 if (jsonObject.find("wantAgent") != jsonEnd && jsonObject.at("wantAgent").is_string()) {
299 auto wantAgentValue = jsonObject.at("wantAgent").get<std::string>();
300 pButton->wantAgent_ = AbilityRuntime::WantAgent::WantAgentHelper::FromString(wantAgentValue, targetUid);
301 }
302
303 if (jsonObject.find("extras") != jsonEnd && jsonObject.at("extras").is_string()) {
304 auto extrasString = jsonObject.at("extras").get<std::string>();
305 if (!extrasString.empty()) {
306 AAFwk::WantParams params = AAFwk::WantParamWrapper::ParseWantParams(extrasString);
307 pButton->extras_ = std::make_shared<AAFwk::WantParams>(params);
308 }
309 }
310 return pButton;
311 }
312
Marshalling(Parcel & parcel) const313 bool NotificationActionButton::Marshalling(Parcel &parcel) const
314 {
315 if (!parcel.WriteString(title_)) {
316 ANS_LOGE("Failed to write title");
317 return false;
318 }
319
320 if (!parcel.WriteBool(autoCreatedReplies_)) {
321 ANS_LOGE("Failed to write flag autoCreatedReplies");
322 return false;
323 }
324
325 if (!parcel.WriteBool(isContextual_)) {
326 ANS_LOGE("Failed to write flag isContextual");
327 return false;
328 }
329
330 if (!parcel.WriteInt32(static_cast<int32_t>(semanticActionButton_))) {
331 ANS_LOGE("Failed to write semanticActionButton");
332 return false;
333 }
334
335 bool valid {false};
336
337 valid = icon_ ? true : false;
338 if (!parcel.WriteBool(valid)) {
339 ANS_LOGE("Failed to write the flag which indicate whether icon is null");
340 return false;
341 }
342
343 if (valid) {
344 if (!parcel.WriteParcelable(icon_.get())) {
345 ANS_LOGE("Failed to write icon");
346 return false;
347 }
348 }
349
350 valid = wantAgent_ ? true : false;
351 if (!parcel.WriteBool(valid)) {
352 ANS_LOGE("Failed to write the flag which indicate whether wantAgent is null");
353 return false;
354 }
355
356 if (valid) {
357 if (!parcel.WriteParcelable(wantAgent_.get())) {
358 ANS_LOGE("Write wantAgent failed.");
359 return false;
360 }
361 }
362
363 valid = extras_ ? true : false;
364 if (!parcel.WriteBool(valid)) {
365 ANS_LOGE("Failed to write the flag which indicate whether extras is null");
366 return false;
367 }
368
369 if (valid) {
370 if (!parcel.WriteParcelable(extras_.get())) {
371 ANS_LOGE("Failed to write extras");
372 return false;
373 }
374 }
375
376 valid = userInput_ ? true : false;
377 if (!parcel.WriteBool(valid)) {
378 ANS_LOGE("Failed to write the flag which indicate whether userInput is null");
379 return false;
380 }
381
382 if (valid) {
383 if (!parcel.WriteParcelable(userInput_.get())) {
384 ANS_LOGE("Failed to write userInput");
385 return false;
386 }
387 }
388
389 return true;
390 }
391
Unmarshalling(Parcel & parcel)392 NotificationActionButton *NotificationActionButton::Unmarshalling(Parcel &parcel)
393 {
394 auto pButton = new (std::nothrow) NotificationActionButton();
395 if ((pButton != nullptr) && !pButton->ReadFromParcel(parcel)) {
396 delete pButton;
397 pButton = nullptr;
398 }
399
400 return pButton;
401 }
402
ReadFromParcel(Parcel & parcel)403 bool NotificationActionButton::ReadFromParcel(Parcel &parcel)
404 {
405 if (!parcel.ReadString(title_)) {
406 ANS_LOGE("Failed to read title");
407 return false;
408 }
409
410 autoCreatedReplies_ = parcel.ReadBool();
411
412 isContextual_ = parcel.ReadBool();
413
414 semanticActionButton_ = static_cast<NotificationConstant::SemanticActionButton>(parcel.ReadInt32());
415
416 bool valid {false};
417
418 valid = parcel.ReadBool();
419 if (valid) {
420 icon_ = std::shared_ptr<Media::PixelMap>(parcel.ReadParcelable<Media::PixelMap>());
421 if (!icon_) {
422 ANS_LOGE("Failed to read icon");
423 return false;
424 }
425 }
426
427 valid = parcel.ReadBool();
428 if (valid) {
429 wantAgent_ = std::shared_ptr<AbilityRuntime::WantAgent::WantAgent>(
430 parcel.ReadParcelable<AbilityRuntime::WantAgent::WantAgent>());
431 if (!wantAgent_) {
432 ANS_LOGE("Failed to read want agent");
433 return false;
434 }
435 }
436
437 valid = parcel.ReadBool();
438 if (valid) {
439 extras_ = std::shared_ptr<AAFwk::WantParams>(parcel.ReadParcelable<AAFwk::WantParams>());
440 if (!extras_) {
441 ANS_LOGE("Failed to read extras");
442 return false;
443 }
444 }
445
446 valid = parcel.ReadBool();
447 if (valid) {
448 userInput_ = std::shared_ptr<NotificationUserInput>(parcel.ReadParcelable<NotificationUserInput>());
449 if (!userInput_) {
450 ANS_LOGE("Failed to read userInput");
451 return false;
452 }
453 }
454
455 return true;
456 }
457 } // namespace Notification
458 } // namespace OHOS
459