1 /*
2 * Copyright (c) 2021 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
Marshalling(Parcel & parcel) const275 bool NotificationActionButton::Marshalling(Parcel &parcel) const
276 {
277 if (!parcel.WriteString(title_)) {
278 ANS_LOGE("Failed to write title");
279 return false;
280 }
281
282 if (!parcel.WriteBool(autoCreatedReplies_)) {
283 ANS_LOGE("Failed to write flag autoCreatedReplies");
284 return false;
285 }
286
287 if (!parcel.WriteBool(isContextual_)) {
288 ANS_LOGE("Failed to write flag isContextual");
289 return false;
290 }
291
292 if (!parcel.WriteInt32(static_cast<int32_t>(semanticActionButton_))) {
293 ANS_LOGE("Failed to write semanticActionButton");
294 return false;
295 }
296
297 bool valid {false};
298
299 valid = icon_ ? true : false;
300 if (!parcel.WriteBool(valid)) {
301 ANS_LOGE("Failed to write the flag which indicate whether icon is null");
302 return false;
303 }
304
305 if (valid) {
306 if (!parcel.WriteParcelable(icon_.get())) {
307 ANS_LOGE("Failed to write icon");
308 return false;
309 }
310 }
311
312 valid = wantAgent_ ? true : false;
313 if (!parcel.WriteBool(valid)) {
314 ANS_LOGE("Failed to write the flag which indicate whether wantAgent is null");
315 return false;
316 }
317
318 if (valid) {
319 if (!parcel.WriteParcelable(wantAgent_.get())) {
320 ANS_LOGE("Failed to write wantAgent");
321 return false;
322 }
323 }
324
325 valid = extras_ ? true : false;
326 if (!parcel.WriteBool(valid)) {
327 ANS_LOGE("Failed to write the flag which indicate whether extras is null");
328 return false;
329 }
330
331 if (valid) {
332 if (!parcel.WriteParcelable(extras_.get())) {
333 ANS_LOGE("Failed to write extras");
334 return false;
335 }
336 }
337
338 valid = userInput_ ? true : false;
339 if (!parcel.WriteBool(valid)) {
340 ANS_LOGE("Failed to write the flag which indicate whether userInput is null");
341 return false;
342 }
343
344 if (valid) {
345 if (!parcel.WriteParcelable(userInput_.get())) {
346 ANS_LOGE("Failed to write userInput");
347 return false;
348 }
349 }
350
351 return true;
352 }
353
Unmarshalling(Parcel & parcel)354 NotificationActionButton *NotificationActionButton::Unmarshalling(Parcel &parcel)
355 {
356 auto pButton = new (std::nothrow) NotificationActionButton();
357 if ((pButton != nullptr) && !pButton->ReadFromParcel(parcel)) {
358 delete pButton;
359 pButton = nullptr;
360 }
361
362 return pButton;
363 }
364
ReadFromParcel(Parcel & parcel)365 bool NotificationActionButton::ReadFromParcel(Parcel &parcel)
366 {
367 if (!parcel.ReadString(title_)) {
368 ANS_LOGE("Failed to read title");
369 return false;
370 }
371
372 autoCreatedReplies_ = parcel.ReadBool();
373
374 isContextual_ = parcel.ReadBool();
375
376 semanticActionButton_ = static_cast<NotificationConstant::SemanticActionButton>(parcel.ReadInt32());
377
378 bool valid {false};
379
380 valid = parcel.ReadBool();
381 if (valid) {
382 icon_ = std::shared_ptr<Media::PixelMap>(parcel.ReadParcelable<Media::PixelMap>());
383 if (!icon_) {
384 ANS_LOGE("Failed to read icon");
385 return false;
386 }
387 }
388
389 valid = parcel.ReadBool();
390 if (valid) {
391 wantAgent_ = std::shared_ptr<AbilityRuntime::WantAgent::WantAgent>(
392 parcel.ReadParcelable<AbilityRuntime::WantAgent::WantAgent>());
393 if (!wantAgent_) {
394 ANS_LOGE("Failed to read wantAgent");
395 return false;
396 }
397 }
398
399 valid = parcel.ReadBool();
400 if (valid) {
401 extras_ = std::shared_ptr<AAFwk::WantParams>(parcel.ReadParcelable<AAFwk::WantParams>());
402 if (!extras_) {
403 ANS_LOGE("Failed to read extras");
404 return false;
405 }
406 }
407
408 valid = parcel.ReadBool();
409 if (valid) {
410 userInput_ = std::shared_ptr<NotificationUserInput>(parcel.ReadParcelable<NotificationUserInput>());
411 if (!userInput_) {
412 ANS_LOGE("Failed to read userInput");
413 return false;
414 }
415 }
416
417 return true;
418 }
419 } // namespace Notification
420 } // namespace OHOS
421