Merge "Implementation of new OOM policy" into devel_3.0_main
[platform/framework/native/appfw.git] / src / app / FApp_NotificationManagerImpl.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file                FApp_NotificationManagerImpl.cpp
19  * @brief               This is the placeholder for _NotificationManagerImpl class.
20  */
21
22 #include <unique_ptr.h>
23 #include <appsvc/appsvc.h>
24 #include <bundle.h>
25 #include <notification/notification.h>
26 #include <appfw/app.h>
27 #include <appfw/app_manager.h>
28 #include <appfw/app_ui_notification.h>
29
30 #include <FBaseSysLog.h>
31 #include <FAppNotificationManager.h>
32
33 #include <FBaseInternalTypes.h>
34 #include <FBase_StringConverter.h>
35 #include "FApp_NotificationManagerImpl.h"
36 #include "FApp_AppInfo.h"
37 #include "FIoFile.h"
38 #include "FAppPkg_PackageManagerImpl.h"
39 #include "FApp_Aul.h"
40 #include "FApp_AppArg.h"
41 #include "FAppPkgPackageAppInfo.h"
42 #include "FAppPkg_PackageAppInfoImpl.h"
43
44 using namespace Tizen::Base;
45 using namespace Tizen::App;
46 using namespace Tizen::App::Package;
47 using namespace Tizen::Io;
48
49 extern "C" int service_create_request(bundle *data, service_h *service);
50
51 namespace
52 {
53
54 result
55 ConvertNotificationResult(int error)
56 {
57         switch (error)
58         {
59         case UI_NOTIFICATION_ERROR_NONE:
60                 return E_SUCCESS;
61         case UI_NOTIFICATION_ERROR_INVALID_PARAMETER:
62                 return E_INVALID_ARG;
63         case UI_NOTIFICATION_ERROR_OUT_OF_MEMORY:
64                 return E_OUT_OF_MEMORY;
65         case UI_NOTIFICATION_ERROR_DB_FAILED:
66                 return E_DATABASE;
67         case UI_NOTIFICATION_ERROR_NO_SUCH_FILE:
68                 return E_SYSTEM;
69         case UI_NOTIFICATION_ERROR_INVALID_STATE:
70                 return E_SYSTEM;
71         default:
72                 return E_SYSTEM;
73         }
74 }
75
76 bool
77 IsPosted(ui_notification_h handle)
78 {
79         struct ui_notification_s
80         {
81                 void* raw_handle;
82                 bool ongoing;
83                 bool posted;
84                 bool removed;
85                 char *icon;
86                 struct tm *time;
87                 char *title;
88                 char *content;
89                 service_h service;
90                 char *sound;
91                 bool vibration;
92         };
93
94         if (handle == NULL)
95         {
96                 return false;
97         }
98
99         ui_notification_s* pStruct = reinterpret_cast<ui_notification_s*>(handle);
100
101         return pStruct->posted;
102 }
103
104 }
105
106 namespace Tizen { namespace App
107 {
108
109 _NotificationManagerImpl::_NotificationManagerImpl(void)
110 {
111 }
112
113 _NotificationManagerImpl::~_NotificationManagerImpl(void)
114 {
115 }
116
117 result
118 _NotificationManagerImpl::Construct(void)
119 {
120         return E_SUCCESS;
121 }
122
123 const _NotificationManagerImpl*
124 _NotificationManagerImpl::GetInstance(const NotificationManager& notiMgr)
125 {
126         return notiMgr.__pNotificationManagerImpl;
127 }
128
129 _NotificationManagerImpl*
130 _NotificationManagerImpl::GetInstance(NotificationManager& notiMgr)
131 {
132         return notiMgr.__pNotificationManagerImpl;
133 }
134
135 int
136 _NotificationManagerImpl::GetBadgeNumber(void) const
137 {
138         int count = -1;
139         notification_get_badge(NULL, NOTIFICATION_GROUP_ID_NONE, &count);
140         return count;
141 }
142
143 result
144 _NotificationManagerImpl::OngoingImpl(const String& messageText, const String& launchArguments) const
145 {
146         return NotifyImpl(messageText, -1, launchArguments, true);
147 }
148
149 result
150 _NotificationManagerImpl::OngoingImpl(const AppId& appId, const String& messageText, const String& launchArguments) const
151 {
152
153         return NotifyImpl(appId, messageText, -1, launchArguments, true);
154 }
155
156 result
157 _NotificationManagerImpl::NotifyImpl(const String& messageText, int badgeNumber,
158                                                                          const String& launchArguments,
159                                                                          bool isOngoing) const
160 {
161         result r = E_SUCCESS;
162         int retcode = 0;
163         char* pMsg = null;
164         char* pkgname = NULL;
165         char* pIcon = NULL;
166         bundle* pKb = NULL;
167         service_h svc = NULL;
168         _AppArg arg;
169         String iconPath;
170         ui_notification_h core = NULL;
171         PackageAppInfo* pPackageAppInfo = NULL;
172
173         if (!messageText.IsEmpty())
174         {
175                 SysTryReturnResult(NID_APP,
176                                           messageText.GetLength() <= MAX_NOTIFICATION_MESSAGE_LENGTH, E_INVALID_ARG,
177                                           "MessageText is greater than MAX_NOTIFICATION_MESSAGE_LENGTH.");
178
179                 retcode = ui_notification_create(isOngoing, &core);
180                 SysTryReturnResult(NID_APP, retcode == UI_NOTIFICATION_ERROR_NONE, E_SYSTEM, "Notification creation error : 0x%x.", retcode);
181
182                 pMsg = _StringConverter::CopyToCharArrayN(messageText);
183
184                 int ret = ui_notification_set_content(core, pMsg);
185                 SysTryLog(NID_APP, ret == UI_NOTIFICATION_ERROR_NONE, "Setting notification content failure : %d.", ret);
186
187                 const String& currappId = _AppInfo::GetApplicationId();
188
189                 pPackageAppInfo = _PackageManagerImpl::GetInstance()->GetPackageAppInfoN(currappId);
190                 iconPath = _PackageAppInfoImpl::GetInstance(pPackageAppInfo)->GetAppNotificationIconPath();
191
192                 if (!iconPath.IsEmpty() && File::IsFileExist(iconPath))
193                 {
194                         pIcon = _StringConverter::CopyToCharArrayN(iconPath);
195                         r = ConvertNotificationResult(ui_notification_set_icon(core, pIcon));
196                         SysTryLog(NID_APP, !IsFailed(r), "[%s] Notification set icon failed.", GetErrorMessage(r));
197                 }
198
199                 app_get_package(&pkgname);
200                 SysTryCatch(NID_APP, pkgname != NULL, r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] Cannot acquire package name for current application.");
201
202                 r = arg.Construct(launchArguments);
203                 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
204
205                 pKb = arg.GetBundle();
206                 service_create_request(pKb, &svc);
207
208                 service_set_package(svc, pkgname);
209                 r = ConvertNotificationResult(ui_notification_set_service(core, svc));
210                 SysTryLog(NID_APP, !IsFailed(r), "[%s] Notification set service failed.", GetErrorMessage(r));
211
212                 SysLog(NID_APP, "Sending notification[%ls] for package %s.", messageText.GetPointer(), pkgname);
213
214                 r = ConvertNotificationResult(ui_notification_post(core));
215                 SysTryLog(NID_APP, !IsFailed(r), "[%s] Notification post failure.", GetErrorMessage(r));
216         }
217
218         if (badgeNumber >= 0)
219         {
220                 notification_set_badge(NULL, NOTIFICATION_GROUP_ID_NONE, badgeNumber);
221                 SysLog(NID_APP, "Badge number is set to %d.", badgeNumber);
222         }
223
224 CATCH:
225         delete pPackageAppInfo;
226         delete[] pMsg;
227         delete[] pIcon;
228
229         if (pkgname)
230         {
231                 free(pkgname);
232         }
233         if (core)
234         {
235                 ui_notification_destroy(core);
236         }
237         service_destroy(svc);
238         return r;
239 }
240
241 result
242 _NotificationManagerImpl::NotifyImpl(const AppId& appId, const String& messageText, int badgeNumber,
243                                                                          const String& launchArguments,
244                                                                          bool isOngoing) const
245 {
246         result r = E_SUCCESS;
247         int retcode = 0;
248         String iconPath;
249         char* pMsg = null;
250         char* pIcon = null;
251         char* pDefaultIconPath = NULL;
252         char* pName = NULL;
253         ui_notification_h core = NULL;
254         char buffer[256];
255         bundle* pKb = NULL;
256         service_h svc = NULL;
257         _AppArg arg;
258         PackageAppInfo* pPackageAppInfo = null;
259
260         memset(buffer, 0, 256);
261
262         bool inInstalled = _Aul::IsInstalled(appId);
263         SysTryReturnResult(NID_APP, inInstalled == true, E_APP_NOT_INSTALLED, "The application %ls is not installed", appId.GetPointer());
264
265         if (!isOngoing || !messageText.IsEmpty())
266         {
267                 SysTryReturnResult(NID_APP,
268                                           messageText.GetLength() <= MAX_NOTIFICATION_MESSAGE_LENGTH, E_INVALID_ARG,
269                                           "MessageText is greater than MAX_NOTIFICATION_MESSAGE_LENGTH.");
270
271                 retcode = ui_notification_create(isOngoing, &core);
272                 SysTryReturnResult(NID_APP, retcode == UI_NOTIFICATION_ERROR_NONE, E_SYSTEM, "Notification creation error : 0x%x.", retcode);
273
274                 pMsg = _StringConverter::CopyToCharArrayN(messageText);
275
276                 int ret = ui_notification_set_content(core, pMsg);
277                 SysTryLog(NID_APP, ret == UI_NOTIFICATION_ERROR_NONE, "Setting notification content failure : %d.", ret);
278
279                 snprintf(buffer, 256, "%ls", appId.GetPointer());
280
281                 pPackageAppInfo = _PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId);
282                 iconPath = _PackageAppInfoImpl::GetInstance(pPackageAppInfo)->GetAppNotificationIconPath();
283
284                 if (!iconPath.IsEmpty() && File::IsFileExist(iconPath))
285                 {
286                         pIcon = _StringConverter::CopyToCharArrayN(iconPath);
287                         r = ConvertNotificationResult(ui_notification_set_icon(core, pIcon));
288                         SysTryLog(NID_APP, !IsFailed(r), "[%s] Notification set icon failed.", GetErrorMessage(r));
289                 }
290                 else
291                 {
292                         app_manager_get_app_icon_path(buffer, &pDefaultIconPath);
293                         r = ConvertNotificationResult(ui_notification_set_icon(core, pDefaultIconPath));
294                         SysTryLog(NID_APP, !IsFailed(r), "[%s] Notification Set icon path  failed.", GetErrorMessage(r));
295                 }
296
297                 app_manager_get_app_name(buffer, &pName);
298                 r = ConvertNotificationResult(ui_notification_set_title(core, pName));
299                 SysTryLog(NID_APP, !IsFailed(r), "[%s] Notification set title failed.", GetErrorMessage(r));
300
301                 r = arg.Construct(launchArguments);
302                 SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] Propagating.", GetErrorMessage(r));
303
304                 pKb = arg.GetBundle();
305                 service_create_request(pKb, &svc);
306
307                 service_set_app_id(svc, buffer);
308                 r = ConvertNotificationResult(ui_notification_set_service(core, svc));
309                 SysTryLog(NID_APP, !IsFailed(r), "[%s] Notification set service failed.", GetErrorMessage(r));
310
311                 SysLog(NID_APP, "Sending notification[%ls] for package %s.", messageText.GetPointer(), buffer);
312
313                 r = ConvertNotificationResult(ui_notification_post(core));
314                 SysTryLog(NID_APP, !IsFailed(r), "[%s] Notification post failure.", GetErrorMessage(r));
315         }
316
317         if (badgeNumber >= 0)
318         {
319                 notification_set_badge(buffer, NOTIFICATION_GROUP_ID_NONE, badgeNumber);
320                 SysLog(NID_APP, "Badge number is set to %d.", badgeNumber);
321         }
322
323 CATCH:
324         delete pPackageAppInfo;
325         delete[] pMsg;
326         delete[] pIcon;
327         if (pDefaultIconPath)
328         {
329                 free(pDefaultIconPath);
330         }
331         if (core)
332         {
333                 ui_notification_destroy(core);
334         }
335         if (pName)
336         {
337                 free(pName);
338         }
339         service_destroy(svc);
340         return r;
341 }
342
343
344 result
345 _NotificationManagerImpl::RemoveImpl(const char* pAppId, notification_type_e type)
346 {
347         result r = E_SUCCESS;
348
349         notification_error_e err = notification_delete_all_by_type(pAppId, type);
350         switch (err)
351         {
352         case NOTIFICATION_ERROR_NONE:
353                 r = E_SUCCESS;
354                 break;
355
356         case NOTIFICATION_ERROR_INVALID_DATA:
357                 r = E_INVALID_ARG;
358                 break;
359
360         default:
361                 r = E_SYSTEM;
362                 break;
363         }
364
365         return r;
366 }
367
368
369 result
370 _NotificationManagerImpl::RemoveImpl(const AppId& appId, bool isOngoing)
371 {
372         const bool isValidAppId = _Aul::IsInstalled(appId);
373         SysTryReturnResult(NID_APP, isValidAppId, E_APP_NOT_INSTALLED, "The application %ls is not installed", appId.GetPointer());
374
375         std::unique_ptr<char[]> pAppId(_StringConverter::CopyToCharArrayN(appId));
376         const notification_type_e notiType = (isOngoing) ? NOTIFICATION_TYPE_ONGOING : NOTIFICATION_TYPE_NOTI;
377
378         return RemoveImpl(pAppId.get(), notiType);
379 }
380
381 result
382 _NotificationManagerImpl::Notify(int badgeNumber) const
383 {
384         SysTryReturnResult(NID_APP, badgeNumber >= 0, E_INVALID_ARG, "BadgeNumber is less than 0.");
385
386         if (badgeNumber > MAX_NOTIFICATION_BADGE_NUMBER)
387         {
388                 badgeNumber = MAX_NOTIFICATION_BADGE_NUMBER;
389         }
390
391         String messageText = String(L"");
392         String appMessage = String(L"");
393
394         return NotifyImpl(messageText, badgeNumber, appMessage, false);
395 }
396
397 result
398 _NotificationManagerImpl::Notify(const String& messageText) const
399 {
400         SysTryReturnResult(NID_APP, messageText.GetLength() > 0, E_INVALID_ARG, "MessageText is less than 0.");
401
402         String appMessage = String(L"");
403
404         return NotifyImpl(messageText, -1, appMessage, false);
405 }
406
407 result
408 _NotificationManagerImpl::Notify(const String& messageText, int badgeNumber) const
409 {
410         SysTryReturnResult(NID_APP, badgeNumber >= 0, E_INVALID_ARG, "BadgeNumber is less than 0.");
411         SysTryReturnResult(NID_APP, messageText.GetLength() > 0, E_INVALID_ARG, "MessageText is less than 0.");
412
413         if (badgeNumber > MAX_NOTIFICATION_BADGE_NUMBER)
414         {
415                 badgeNumber = MAX_NOTIFICATION_BADGE_NUMBER;
416         }
417
418         String appMessage = String(L"");
419
420         return NotifyImpl(messageText, badgeNumber, appMessage, false);
421 }
422
423 result
424 _NotificationManagerImpl::Notify(const String& messageText, int badgeNumber, const String& launchArguments) const
425 {
426         SysTryReturnResult(NID_APP, badgeNumber >= 0, E_INVALID_ARG, "BadgeNumber is less than 0.");
427         SysTryReturnResult(NID_APP, messageText.GetLength() > 0, E_INVALID_ARG, "MessageText is less than 0.");
428         SysTryReturnResult(NID_APP,
429                                           launchArguments != null && launchArguments.GetLength() > 0, E_INVALID_ARG,
430                                           "launchArguments is less than 0.");
431
432         SysTryReturnResult(NID_APP,
433                                           launchArguments.GetLength() <= MAX_NOTIFICATION_LAUNCH_ARGUMENTS_LENGTH, E_INVALID_ARG,
434                                           "launchArguments is greater than MAX_NOTIFICATION_LAUNCH_ARGUMENTS_LENGTH.");
435
436         if (badgeNumber > MAX_NOTIFICATION_BADGE_NUMBER)
437         {
438                 badgeNumber = MAX_NOTIFICATION_BADGE_NUMBER;
439         }
440
441         return NotifyImpl(messageText, badgeNumber, launchArguments, false);
442 }
443
444 int
445 _NotificationManagerImpl::GetBadgeNumber(const AppId& appId) const
446 {
447         bool b = _Aul::IsInstalled(appId);
448
449         SysTryReturn(NID_APP, b == true, -1, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] The application %ls is not installed",
450                                 appId.GetPointer());
451
452         char buffer[256];
453         int count = -1;
454
455         memset(buffer, 0, 256);
456
457         snprintf(buffer, 256, "%ls", appId.GetPointer());
458
459         notification_get_badge(buffer, NOTIFICATION_GROUP_ID_NONE, &count);
460
461         return count;
462 }
463
464
465 result
466 _NotificationManagerImpl::NotifyOnBehalf(const AppId& appId, int badgeNumber) const
467 {
468         SysTryReturnResult(NID_APP, badgeNumber >= 0, E_INVALID_ARG, "BadgeNumber is less than 0.");
469
470         String messageText = String(L"");
471         String appMessage = String(L"");
472         return NotifyImpl(appId, messageText, badgeNumber, appMessage);
473 }
474
475 result
476 _NotificationManagerImpl::NotifyOnBehalf(const AppId& appId, const String& messageText) const
477 {
478         SysTryReturnResult(NID_APP, messageText.GetLength() > 0, E_INVALID_ARG, "MessageText is less than 0.");
479
480         return NotifyImpl(appId, messageText, -1, String(L""));
481 }
482
483 result
484 _NotificationManagerImpl::NotifyOnBehalf(const AppId& appId, const String& messageText, int badgeNumber) const
485 {
486         SysTryReturnResult(NID_APP, badgeNumber >= 0, E_INVALID_ARG, "BadgeNumber is less than 0.");
487         SysTryReturnResult(NID_APP, messageText.GetLength() > 0, E_INVALID_ARG, "MessageText is less than 0.");
488
489         return NotifyImpl(appId, messageText, badgeNumber, String(L""));
490 }
491
492 result
493 _NotificationManagerImpl::NotifyOnBehalf(const AppId& appId, const String& messageText, const String& launchArguments) const
494 {
495         SysTryReturnResult(NID_APP, messageText.GetLength() > 0, E_INVALID_ARG, "MessageText is less than 0.");
496         SysTryReturnResult(NID_APP, launchArguments.GetLength() > 0, E_INVALID_ARG, "launchArguments is less than 0.");
497         SysTryReturnResult(NID_APP,
498                                           launchArguments.GetLength() <= MAX_NOTIFICATION_LAUNCH_ARGUMENTS_LENGTH, E_INVALID_ARG,
499                                           "launchArguments is greater than MAX_NOTIFICATION_LAUNCH_ARGUMENTS_LENGTH.");
500
501         return NotifyImpl(appId, messageText, -1, launchArguments);
502 }
503
504 result
505 _NotificationManagerImpl::NotifyOnBehalf(const AppId& appId, const String& messageText, int badgeNumber,
506                                                                                  const String& launchArguments) const
507 {
508         SysTryReturnResult(NID_APP, badgeNumber >= 0, E_INVALID_ARG, "BadgeNumber is less than 0.");
509         SysTryReturnResult(NID_APP, messageText.GetLength() > 0, E_INVALID_ARG, "MessageText is less than 0.");
510         SysTryReturnResult(NID_APP, launchArguments.GetLength() > 0, E_INVALID_ARG, "launchArguments is less than 0.");
511         SysTryReturnResult(NID_APP,
512                                           launchArguments.GetLength() <= MAX_NOTIFICATION_LAUNCH_ARGUMENTS_LENGTH, E_INVALID_ARG,
513                                           "launchArguments is greater than MAX_NOTIFICATION_LAUNCH_ARGUMENTS_LENGTH.");
514
515         return NotifyImpl(appId, messageText, badgeNumber, launchArguments);
516 }
517
518 result
519 _NotificationManagerImpl::NotifyOngoingActivity(const String& messageText) const
520 {
521         SysTryReturnResult(NID_APP, messageText.GetLength() > 0, E_INVALID_ARG, "MessageText is less than 0.");
522
523         return OngoingImpl(messageText, String(L""));
524 }
525
526 result
527 _NotificationManagerImpl::NotifyOngoingActivity(const String& messageText, const String& launchArguments) const
528 {
529         SysTryReturnResult(NID_APP, messageText.GetLength() > 0, E_INVALID_ARG, "MessageText is less than 0.");
530         SysTryReturnResult(NID_APP, launchArguments.GetLength() > 0, E_INVALID_ARG, "launchArguments is less than 0.");
531         SysTryReturnResult(NID_APP,
532                                           launchArguments.GetLength() <= MAX_NOTIFICATION_LAUNCH_ARGUMENTS_LENGTH, E_INVALID_ARG,
533                                           "launchArguments is greater than MAX_NOTIFICATION_LAUNCH_ARGUMENTS_LENGTH.");
534
535         return OngoingImpl(messageText, launchArguments);
536 }
537
538 result
539 _NotificationManagerImpl::NotifyOngoingActivityOnBehalf(const AppId& appId, const String& messageText) const
540 {
541         SysTryReturnResult(NID_APP, messageText.GetLength() > 0, E_INVALID_ARG, "MessageText is less than 0.");
542
543         return OngoingImpl(appId, messageText, String(L""));
544 }
545
546 result
547 _NotificationManagerImpl::NotifyOngoingActivityOnBehalf(const AppId& appId, const String& messageText,
548                                                                                                                 const String& launchArguments) const
549 {
550         SysTryReturnResult(NID_APP, messageText.GetLength() > 0, E_INVALID_ARG, "MessageText is less than 0.");
551         SysTryReturnResult(NID_APP, launchArguments.GetLength() > 0, E_INVALID_ARG, "launchArguments is less than 0.");
552         SysTryReturnResult(NID_APP,
553                                           launchArguments.GetLength() <= MAX_NOTIFICATION_LAUNCH_ARGUMENTS_LENGTH, E_INVALID_ARG,
554                                           "launchArguments is greater than MAX_NOTIFICATION_LAUNCH_ARGUMENTS_LENGTH.");
555
556         return OngoingImpl(appId, messageText, launchArguments);
557 }
558
559 result
560 _NotificationManagerImpl::RemoveOngoingActivityNotification(void)
561 {
562         return RemoveImpl(NULL, NOTIFICATION_TYPE_ONGOING);
563 }
564
565 result
566 _NotificationManagerImpl::RemoveOngoingActivityNotificationOnBehalf(const AppId& appId)
567 {
568         return RemoveImpl(appId, true);
569 }
570
571 result
572 _NotificationManagerImpl::RemoveNotification(void)
573 {
574         return RemoveImpl(NULL, NOTIFICATION_TYPE_NOTI);
575 }
576
577 result
578 _NotificationManagerImpl::RemoveNotificationOnBehalf(const AppId& appId)
579 {
580         return RemoveImpl(appId, false);
581 }
582
583 };
584 };    // Tizen::App