[Common] Changed configuration for common profile build
[platform/core/api/webapi-plugins.git] / src / alarm / alarm_manager.cc
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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 #include "alarm_manager.h"
18
19 #include <alarm.h>
20 #include <app.h>
21 #include <app_alarm.h>
22 #include <app_control_internal.h>
23
24 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE) || defined(TIZEN_COMMON)
25 #include <notification_internal.h>
26 #endif
27
28 #include "common/converter.h"
29 #include "common/logger.h"
30 #include "common/scope_exit.h"
31 #include "common/tools.h"
32
33 #include "alarm_instance.h"
34 #include "alarm_utils.h"
35
36 #include "notification/common_notification.h"
37 #include "notification/status_notification.h"
38 #include "notification/user_notification.h"
39
40 using namespace common;
41 using namespace common::tools;
42
43 namespace extension {
44 namespace alarm {
45
46 namespace {
47 const int kDateSize = 22;  //"yyy mm dd hh mm ss dd" e.g 115 11 28 11 25 50 -1
48 const std::string kPrivilegeAlarm = "http://tizen.org/privilege/alarm";
49 const std::string kPrivilegeNotification = "http://tizen.org/privilege/notification";
50
51 const std::string kAlarmRelative = "AlarmRelative";
52 const std::string kAlarmAbsolute = "AlarmAbsolute";
53
54 const char* kAlarmAbsoluteRecurrenceTypeKey = "RECURRENCE";
55 const char* kAlarmAbsoluteReccurrenceTypeInterval = "INTERVAL";
56 const char* kAlarmAbsoluteReccurrenceTypeByDayValue = "BYDAYVALUE";
57 const char* kAlarmAbsoluteRecurrenceTypeNone = "NONE";
58 const char* kAlarmAbsoluteDateKey = "DATE";
59
60 const char* kAlarmKeyType = "TYPE";
61
62 const char* kAlarmTypeValueAbsolute = "ABSOLUTE";
63 const char* kAlarmTypeValueRelative = "RELATIVE";
64
65 const char* kAlarmRelativeDelayKey = "RELATIVE_DELAY";
66 }  // namespace
67
68 AlarmManager::AlarmManager() {
69   ScopeLogger();
70 }
71
72 AlarmManager::~AlarmManager() {
73   ScopeLogger();
74 }
75
76 void AlarmManager::Add(const picojson::value& args, picojson::object& out) {
77   ScopeLogger();
78   CHECK_PRIVILEGE_ACCESS(kPrivilegeAlarm, &out);
79
80   if (!args.contains("alarm")) {
81     LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
82                       &out);
83     return;
84   }
85   const picojson::object& alarm = args.get("alarm").get<picojson::object>();
86
87   std::string alarm_type;
88   if (args.contains("type")) {
89     alarm_type = args.get("type").get<std::string>();
90   }
91
92   std::string app_id;
93   if (args.contains("applicationId")) {
94     app_id = args.get("applicationId").get<std::string>();
95   }
96
97   app_control_h app_control = nullptr;
98   SCOPE_EXIT {
99     app_control_destroy(app_control);
100   };
101
102   if (args.contains("appControl") && args.get("appControl").is<picojson::object>()) {
103     PlatformResult result =
104         util::AppControlToService(args.get("appControl").get<picojson::object>(), &app_control);
105     if (!result) {
106       LogAndReportError(result, &out, ("Failed: util::AppControlToService"));
107       return;
108     }
109   } else {
110     int ret = app_control_create(&app_control);
111
112     if (APP_CONTROL_ERROR_NONE != ret) {
113       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "app_control_create() failed."),
114                         &out,
115                         ("app_control_create() failed: %d (%s)", ret, get_error_message(ret)));
116       return;
117     }
118     ret = app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
119     if (APP_CONTROL_ERROR_NONE != ret) {
120       LogAndReportError(
121           PlatformResult(ErrorCode::UNKNOWN_ERR, "app_control_set_operation() failed."), &out,
122           ("app_control_set_operation() failed: %d (%s)", ret, get_error_message(ret)));
123       return;
124     }
125   }
126
127   app_control_set_app_id(app_control, app_id.c_str());
128
129   int alarm_id = 0;
130   int period = 0;
131
132   // result object
133   picojson::value result = picojson::value(picojson::object());
134   picojson::object& result_obj = result.get<picojson::object>();
135
136   if (kAlarmRelative == alarm_type) {
137     app_control_add_extra_data(app_control, kAlarmKeyType, kAlarmTypeValueRelative);
138
139     const auto it_delay = alarm.find("delay");
140     const auto it_period = alarm.find("period");
141
142     if (alarm.end() == it_delay || alarm.end() == it_period || !it_delay->second.is<double>()) {
143       LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
144                         &out);
145       return;
146     }
147     int delay = static_cast<int>(it_delay->second.get<double>());
148
149     if (it_period->second.is<double>()) {
150       period = static_cast<int>(it_period->second.get<double>());
151     }
152
153     bool isPeriodSet = false;
154     if (args.contains("isPeriodSet")) {
155       isPeriodSet = args.get("isPeriodSet").get<bool>();
156     }
157
158     std::string delay_str = std::to_string(delay);
159     int ret_app =
160         app_control_add_extra_data(app_control, kAlarmRelativeDelayKey, delay_str.c_str());
161     if (APP_CONTROL_ERROR_NONE != ret_app) {
162       LogAndReportError(
163           PlatformResult(ErrorCode::UNKNOWN_ERR, "Fail to add data from app_control."), &out,
164           ("Fail to add data from app_control: %d (%s)", ret_app, get_error_message(ret_app)));
165       return;
166     }
167
168     int ret = ALARM_ERROR_NONE;
169     if (!isPeriodSet) {
170       ret = alarm_schedule_once_after_delay(app_control, delay, &alarm_id);
171     } else {
172       ret = alarm_schedule_after_delay(app_control, delay, period, &alarm_id);
173     }
174     if (ALARM_ERROR_NONE != ret) {
175       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while add alarm to server."),
176                         &out,
177                         ("Error while add alarm to server: %d (%s)", ret, get_error_message(ret)));
178       return;
179     }
180
181     ret = alarm_get_scheduled_period(alarm_id, &period);
182     if (ALARM_ERROR_NONE != ret) {
183       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."), &out,
184                         ("Unknown error occurred: %d (%s)", ret, get_error_message(ret)));
185       return;
186     }
187     if (period != 0) {
188       result_obj.insert(std::make_pair("period", picojson::value(std::to_string(period))));
189     }
190   } else {
191     app_control_add_extra_data(app_control, kAlarmKeyType, kAlarmTypeValueAbsolute);
192
193     const auto it_period = alarm.find("period");
194     const auto it_daysOfTheWeek = alarm.find("daysOfTheWeek");
195
196     long long int seconds = 0;
197     if (args.contains("seconds")) {
198       seconds = atoll(args.get("seconds").get<std::string>().c_str());
199     }
200
201     time_t second = seconds / 1000;
202     struct tm start_date = {0};
203
204     tzset();
205     if (nullptr == localtime_r(&second, &start_date)) {
206       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Invalid date."), &out);
207       return;
208     }
209
210     mktime(&start_date);
211
212     char str_date[kDateSize];
213
214     snprintf(str_date, sizeof(str_date), "%d %d %d %d %d %d %d", start_date.tm_year,
215              start_date.tm_mon, start_date.tm_mday, start_date.tm_hour, start_date.tm_min,
216              start_date.tm_sec, start_date.tm_isdst);
217
218     app_control_add_extra_data(app_control, kAlarmAbsoluteDateKey, str_date);
219
220     int ret = 0;
221     if (alarm.end() != it_period && it_period->second.is<double>()) {
222       app_control_add_extra_data(app_control, kAlarmAbsoluteRecurrenceTypeKey,
223                                  kAlarmAbsoluteReccurrenceTypeInterval);
224       period = static_cast<int>(it_period->second.get<double>());
225       ret = alarm_schedule_at_date(app_control, &start_date, period, &alarm_id);
226       if (ALARM_ERROR_NONE != ret) {
227         LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Adding alarm to server failed."),
228                           &out,
229                           ("Adding alarm to server failed: %d (%s)", ret, get_error_message(ret)));
230         return;
231       }
232
233       ret = alarm_get_scheduled_period(alarm_id, &period);
234       result_obj.insert(std::make_pair("period", picojson::value(std::to_string(period))));
235     } else if (alarm.end() != it_daysOfTheWeek && it_daysOfTheWeek->second.is<picojson::array>() &&
236                !(it_daysOfTheWeek->second.get<picojson::array>()).empty()) {
237       app_control_add_extra_data(app_control, kAlarmAbsoluteRecurrenceTypeKey,
238                                  kAlarmAbsoluteReccurrenceTypeByDayValue);
239       const picojson::array& days_of_the_week = it_daysOfTheWeek->second.get<picojson::array>();
240       int repeat_value = 0;
241       PlatformResult result = util::ArrayDaysToMask(days_of_the_week, &repeat_value);
242       if (!result) {
243         LogAndReportError(PlatformResult(result.error_code(), result.message()), &out);
244         return;
245       }
246       ret = alarm_schedule_with_recurrence_week_flag(app_control, &start_date, repeat_value,
247                                                      &alarm_id);
248     } else {
249       app_control_add_extra_data(app_control, kAlarmAbsoluteRecurrenceTypeKey,
250                                  kAlarmAbsoluteRecurrenceTypeNone);
251       ret = alarm_schedule_at_date(app_control, &start_date, 0, &alarm_id);
252     }
253
254     if (ALARM_ERROR_NONE != ret) {
255       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Adding alarm to server failed."),
256                         &out,
257                         ("Adding alarm to server failed: %d (%s)", ret, get_error_message(ret)));
258       return;
259     }
260   }
261
262   result_obj.insert(std::make_pair("id", picojson::value(std::to_string(alarm_id))));
263   ReportSuccess(result, out);
264 }
265
266 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE) || defined(TIZEN_COMMON)
267 void AlarmManager::AddAlarmNotification(const picojson::value& args, picojson::object& out) {
268   using namespace extension::notification;
269   ScopeLogger();
270   CHECK_PRIVILEGE_ACCESS(kPrivilegeAlarm, &out);
271   CHECK_PRIVILEGE_ACCESS(kPrivilegeNotification, &out);
272
273   if (!args.contains("alarm") || !args.contains("notification")) {
274     LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
275                       &out);
276     return;
277   }
278
279   const picojson::object& alarm = args.get("alarm").get<picojson::object>();
280
281   std::string alarm_type;
282   if (args.contains("type")) {
283     alarm_type = args.get("type").get<std::string>();
284   }
285
286   notification_h notification_handle = nullptr;
287   app_control_h app_control = nullptr;
288
289   SCOPE_EXIT {
290     notification_free(notification_handle);
291     app_control_destroy(app_control);
292   };
293
294   using namespace std::placeholders;
295   GetHandleFromJsonFun impl{};
296   if (args.contains("newImpl") && args.get("newImpl").is<bool>() &&
297       args.get("newImpl").get<bool>()) {
298     LoggerD("New implementation");
299     impl = std::bind(&UserNotification::GetNotiHandleFromJson, _1, _2, _3);
300   } else {
301     LoggerW("Deprecated object used");
302     impl = std::bind(&StatusNotification::GetNotiHandleFromJson, _1, _2, _3);
303   }
304
305   PlatformResult platform_result = impl(args.get("notification"), false, &notification_handle);
306   if (!platform_result) {
307     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, platform_result.message().c_str()),
308                       &out);
309   }
310   platform_result = CommonNotification::GetAppControl(notification_handle, &app_control);
311
312   if (!platform_result) {
313     LogAndReportError(
314         PlatformResult(platform_result.error_code(), platform_result.message().c_str()), &out);
315   }
316
317   int alarm_id = 0;
318   int ret = 0;
319
320   if (kAlarmRelative == alarm_type) {
321     ret = app_control_add_extra_data(app_control, kAlarmKeyType, kAlarmTypeValueRelative);
322     if (ret != APP_CONTROL_ERROR_NONE) {
323       LogAndReportError(
324           PlatformResult(ErrorCode::ABORT_ERR, "Fail to add data from app_control."), &out,
325           ("Fail to add data from app_control: %d (%s)", ret, get_error_message(ret)));
326       return;
327     }
328
329     const auto it_period = alarm.find("period");
330     const auto it_delay = alarm.find("delay");
331
332     if (alarm.end() == it_delay || alarm.end() == it_period || !it_delay->second.is<double>()) {
333       LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
334                         &out);
335       return;
336     }
337
338     int delay = static_cast<int>(it_delay->second.get<double>());
339
340     std::string delay_str = std::to_string(delay);
341     ret = app_control_add_extra_data(app_control, kAlarmRelativeDelayKey, delay_str.c_str());
342     if (APP_CONTROL_ERROR_NONE != ret) {
343       LogAndReportError(
344           PlatformResult(ErrorCode::ABORT_ERR, "Fail to add data from app_control."), &out,
345           ("Fail to add data from app_control: %d (%s)", ret, get_error_message(ret)));
346       return;
347     }
348
349     platform_result = CommonNotification::SetAppControl(notification_handle, app_control);
350
351     if (!platform_result) {
352       LogAndReportError(
353           PlatformResult(platform_result.error_code(), platform_result.message().c_str()), &out);
354     }
355
356     int period = 0;
357     if (it_period->second.is<double>()) {
358       period = static_cast<int>(it_period->second.get<double>());
359     }
360
361     bool isPeriodSet = false;
362     if (args.contains("isPeriodSet")) {
363       isPeriodSet = args.get("isPeriodSet").get<bool>();
364     }
365
366     if (!isPeriodSet) {
367       ret = alarm_schedule_noti_once_after_delay(notification_handle, delay, &alarm_id);
368     } else {
369       ret = alarm_schedule_noti_after_delay(notification_handle, delay, period, &alarm_id);
370     }
371   } else {
372     if (alarm.find("period")->second.is<double>()) {
373       LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR,
374                                        "AlarmAbsolute constructed by deprecated constructor."),
375                         &out);
376       return;
377     }
378
379     ret = app_control_add_extra_data(app_control, kAlarmKeyType, kAlarmTypeValueAbsolute);
380     if (APP_CONTROL_ERROR_NONE != ret) {
381       LogAndReportError(
382           PlatformResult(ErrorCode::ABORT_ERR, "Fail to add data from app_control."), &out,
383           ("Fail to add data from app_control: %d (%s)", ret, get_error_message(ret)));
384       return;
385     }
386
387     const auto it_daysOfTheWeek = alarm.find("daysOfTheWeek");
388     long long int milliseconds = 0;
389
390     if (args.contains("milliseconds")) {
391       milliseconds = strtoll(args.get("milliseconds").get<std::string>().c_str(), nullptr, 10);
392     }
393
394     time_t second = milliseconds / 1000;
395     struct tm start_date = {0};
396
397     tzset();
398     if (nullptr == localtime_r(&second, &start_date)) {
399       LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Invalid date."), &out);
400       return;
401     }
402
403     mktime(&start_date);
404
405     char str_date[kDateSize];
406
407     snprintf(str_date, sizeof(str_date), "%d %d %d %d %d %d %d", start_date.tm_year,
408              start_date.tm_mon, start_date.tm_mday, start_date.tm_hour, start_date.tm_min,
409              start_date.tm_sec, start_date.tm_isdst);
410
411     ret = app_control_add_extra_data(app_control, kAlarmAbsoluteDateKey, str_date);
412     if (APP_CONTROL_ERROR_NONE != ret) {
413       LogAndReportError(
414           PlatformResult(ErrorCode::ABORT_ERR, "Fail to add data from app_control."), &out,
415           ("Fail to add data from app_control: %d (%s)", ret, get_error_message(ret)));
416       return;
417     }
418
419     if (alarm.end() != it_daysOfTheWeek && it_daysOfTheWeek->second.is<picojson::array>() &&
420         !(it_daysOfTheWeek->second.get<picojson::array>()).empty()) {
421       app_control_add_extra_data(app_control, kAlarmAbsoluteRecurrenceTypeKey,
422                                  kAlarmAbsoluteReccurrenceTypeByDayValue);
423
424       const picojson::array& days_of_the_week = it_daysOfTheWeek->second.get<picojson::array>();
425       int repeat_value = 0;
426       util::ArrayDaysToMask(days_of_the_week, &repeat_value);
427
428       platform_result = CommonNotification::SetAppControl(notification_handle, app_control);
429       if (!platform_result) {
430         LogAndReportError(
431             PlatformResult(platform_result.error_code(), platform_result.message().c_str()), &out);
432       }
433
434       ret = alarm_schedule_noti_with_recurrence_week_flag(notification_handle, &start_date,
435                                                           repeat_value, &alarm_id);
436     } else {
437       ret = app_control_add_extra_data(app_control, kAlarmAbsoluteRecurrenceTypeKey,
438                                        kAlarmAbsoluteRecurrenceTypeNone);
439       if (APP_CONTROL_ERROR_NONE != ret) {
440         LogAndReportError(
441             PlatformResult(ErrorCode::ABORT_ERR, "Fail to add data from app_control."), &out,
442             ("Fail to add data from app_control: %d (%s)", ret, get_error_message(ret)));
443         return;
444       }
445
446       platform_result = CommonNotification::SetAppControl(notification_handle, app_control);
447       if (!platform_result) {
448         LogAndReportError(
449             PlatformResult(platform_result.error_code(), platform_result.message().c_str()), &out);
450       }
451
452       ret = alarm_schedule_noti_once_at_date(notification_handle, &start_date, &alarm_id);
453     }
454   }
455
456   if (ALARM_ERROR_NONE != ret) {
457     if (ALARM_ERROR_INVALID_TIME == ret || ALARM_ERROR_INVALID_DATE == ret ||
458         ALARM_ERROR_INVALID_PARAMETER == ret) {
459       platform_result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid data.");
460     } else {
461       platform_result = PlatformResult(ErrorCode::ABORT_ERR, "Error while adding alarm to server.");
462     }
463
464     LogAndReportError(platform_result, &out,
465                       ("Error while add alarm to server: %d (%s)", ret, get_error_message(ret)));
466     return;
467   }
468
469   picojson::value result = picojson::value(picojson::object());
470   picojson::object& result_obj = result.get<picojson::object>();
471
472   if (alarm_type == kAlarmRelative) {
473     int period = 0;
474     ret = alarm_get_scheduled_period(alarm_id, &period);
475     if (ALARM_ERROR_NONE != ret) {
476       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."), &out,
477                         ("Unknown error occurred: %d (%s)", ret, get_error_message(ret)));
478       return;
479     }
480     if (0 != period) {
481       result_obj.insert(std::make_pair("period", picojson::value(std::to_string(period))));
482     }
483   }
484
485   result_obj.insert(std::make_pair("id", picojson::value(std::to_string(alarm_id))));
486   ReportSuccess(result, out);
487 }
488 #endif
489
490 void AlarmManager::Remove(const picojson::value& args, picojson::object& out) {
491   ScopeLogger();
492   CHECK_PRIVILEGE_ACCESS(kPrivilegeAlarm, &out);
493
494   int id = 0;
495
496   if (args.contains("id") && args.get("id").is<double>()) {
497     id = static_cast<int>(args.get("id").get<double>());
498   }
499
500   if (id <= 0) {
501     LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid id."), &out,
502                       ("id is wrong: %d", id));
503     return;
504   }
505
506   int ret = alarm_cancel(id);
507   if (ALARM_ERROR_NONE == ret) {
508     ReportSuccess(out);
509   } else if (ALARM_ERROR_INVALID_PARAMETER == ret) {
510     LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alarm not found."), &out);
511   } else {
512     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Platform unknown error."), &out,
513                       ("Platform unknown error: %d (%s)", ret, get_error_message(ret)));
514   }
515 }
516
517 void AlarmManager::RemoveAll(const picojson::value& args, picojson::object& out) {
518   ScopeLogger();
519   CHECK_PRIVILEGE_ACCESS(kPrivilegeAlarm, &out);
520
521   int ret = alarm_cancel_all();
522   if (ALARM_ERROR_NONE != ret) {
523     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Platform unknown error."), &out,
524                       ("Platform unknown error: %d (%s)", ret, get_error_message(ret)));
525     return;
526   }
527
528   ReportSuccess(out);
529 }
530
531 PlatformResult AlarmManager::GetAlarm(int id, picojson::object& obj) {
532   ScopeLogger();
533
534   if (id <= 0) {
535     return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid id.",
536                               ("id is wrong: %d", id));
537   }
538
539   int ret = ALARM_ERROR_NONE;
540   app_control_h app_control = nullptr;
541   char* alarm_type = nullptr;
542   char* date_string = nullptr;
543   char* delay_string = nullptr;
544   notification_h notification_handle = nullptr;
545
546   SCOPE_EXIT {
547     app_control_destroy(app_control);
548     free(alarm_type);
549     free(date_string);
550     free(delay_string);
551     notification_free(notification_handle);
552   };
553
554   if (ALARM_ERROR_NONE != alarm_get_app_control(id, &app_control)) {
555     // This is a special kind of alarm, which has the notification instead of an app_control handle.
556     // In case of error during app_control gathering, we check if it has notification. If both calls
557     // end with error, then we report NOT_FOUND_ERROR
558     if (ALARM_ERROR_NONE != alarm_get_notification(id, &notification_handle)) {
559       return LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Alarm not found.",
560                                 ("Alarm not found: %d (%s)", ret, get_error_message(ret)));
561     } else {
562       PlatformResult platform_result = extension::notification::CommonNotification::GetAppControl(
563           notification_handle, &app_control);
564       if (!platform_result) {
565         return LogAndCreateResult(
566             platform_result.error_code(), platform_result.message().c_str(),
567             ("Failed to get AppControl: %d (%s)", static_cast<int>(platform_result.error_code()),
568              platform_result.message().c_str()));
569       }
570     }
571   }
572
573   obj.insert(std::make_pair("id", picojson::value(std::to_string(id))));
574
575   ret = app_control_get_extra_data(app_control, kAlarmKeyType, &alarm_type);
576   if (APP_CONTROL_ERROR_NONE != ret) {
577     // This is not always an error.
578     // Sometimes an application adds an alarm without alarm type set in appcontrol's extra data
579     // (possibly, when the alarm is set by a C service app, which doesn't set this value in extra
580     // data). In such cases, we return the alarm as an "Alarm" JS object, having only ID
581     LoggerW("Getting extra data (%s) failed: [%d](%s)", kAlarmKeyType, ret, get_error_message(ret));
582     return PlatformResult(ErrorCode::NO_ERROR);
583   }
584
585   if (!strcmp(alarm_type, kAlarmTypeValueAbsolute)) {
586     struct tm date;
587     memset(&date, 0, sizeof(tm));
588
589     ret = app_control_get_extra_data(app_control, kAlarmAbsoluteDateKey, &date_string);
590
591     if (APP_CONTROL_ERROR_NONE != ret) {
592       return LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Failed to get data.",
593                                 ("Failed to get data: %d (%s)", ret, get_error_message(ret)));
594     }
595
596     sscanf(date_string, "%5d %5d %5d %5d %5d %5d %5d", &date.tm_year, &date.tm_mon, &date.tm_mday,
597            &date.tm_hour, &date.tm_min, &date.tm_sec, &date.tm_isdst);
598     mktime(&date);
599
600     obj.insert(std::make_pair("year", picojson::value(std::to_string(date.tm_year + 1900))));
601     obj.insert(std::make_pair("month", picojson::value(std::to_string(date.tm_mon))));
602     obj.insert(std::make_pair("day", picojson::value(std::to_string(date.tm_mday))));
603     obj.insert(std::make_pair("hour", picojson::value(std::to_string(date.tm_hour))));
604     obj.insert(std::make_pair("min", picojson::value(std::to_string(date.tm_min))));
605     obj.insert(std::make_pair("sec", picojson::value(std::to_string(date.tm_sec))));
606
607     int interval = 0;
608
609     ret = app_control_get_extra_data(app_control, kAlarmAbsoluteRecurrenceTypeKey, &alarm_type);
610     if (APP_CONTROL_ERROR_NONE != ret) {
611       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.",
612                                 ("Getting data failed: %d (%s)", ret, get_error_message(ret)));
613     }
614
615     if (!strcmp(alarm_type, kAlarmAbsoluteReccurrenceTypeInterval)) {
616       ret = alarm_get_scheduled_period(id, &interval);
617       if (ALARM_ERROR_NONE != ret) {
618         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.",
619                                   ("Unknown error occurred: %d (%s)", ret, get_error_message(ret)));
620       }
621
622       obj.insert(std::make_pair("second", picojson::value(std::to_string(interval))));
623     } else if (!strcmp(alarm_type, kAlarmAbsoluteReccurrenceTypeByDayValue)) {
624       int byDayValue = 0;
625
626       ret = alarm_get_scheduled_recurrence_week_flag(id, &byDayValue);
627       if (ALARM_ERROR_NONE != ret) {
628         return LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Failed to get data.",
629                                   ("Failed to get data: %d (%s)", ret, get_error_message(ret)));
630       }
631
632       picojson::array& array =
633           obj.insert(std::make_pair("second", picojson::value(picojson::array())))
634               .first->second.get<picojson::array>();
635
636       using namespace util;
637       if (byDayValue & ALARM_WEEK_FLAG_SUNDAY) array.push_back(picojson::value(kSundayShort));
638       if (byDayValue & ALARM_WEEK_FLAG_MONDAY) array.push_back(picojson::value(kMondayShort));
639       if (byDayValue & ALARM_WEEK_FLAG_TUESDAY) array.push_back(picojson::value(kTuesdayShort));
640       if (byDayValue & ALARM_WEEK_FLAG_WEDNESDAY) array.push_back(picojson::value(kWednesdayShort));
641       if (byDayValue & ALARM_WEEK_FLAG_THURSDAY) array.push_back(picojson::value(kThuesdayShort));
642       if (byDayValue & ALARM_WEEK_FLAG_FRIDAY) array.push_back(picojson::value(kFridayShort));
643       if (byDayValue & ALARM_WEEK_FLAG_SATURDAY) array.push_back(picojson::value(kSaturdayShort));
644     }
645
646     obj.insert(std::make_pair("type", picojson::value(kAlarmAbsolute)));
647
648   } else if (!strcmp(alarm_type, kAlarmTypeValueRelative)) {
649     int interval = 0;
650
651     ret = alarm_get_scheduled_period(id, &interval);
652     if (ALARM_ERROR_NONE != ret) {
653       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.",
654                                 ("Unknown error occurred: %d (%s)", ret, get_error_message(ret)));
655     }
656
657     int ret_app = app_control_get_extra_data(app_control, kAlarmRelativeDelayKey, &delay_string);
658     if (APP_CONTROL_ERROR_NONE != ret_app) {
659       return LogAndCreateResult(
660           ErrorCode::NOT_FOUND_ERR, "Failed to get data.",
661           ("Failed to get data: %d (%s)", ret_app, get_error_message(ret_app)));
662     }
663
664     obj.insert(std::make_pair("type", picojson::value(kAlarmRelative)));
665     obj.insert(std::make_pair("delay", picojson::value(delay_string)));
666     if (interval != 0) {
667       // according to documentation interval will not be lower than 600,
668       // thus 0 from native means period wasn't set by user
669       obj.insert(std::make_pair("period", picojson::value(std::to_string(interval))));
670     }
671   } else {
672     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
673   }
674
675   return PlatformResult(ErrorCode::NO_ERROR);
676 }
677
678 void AlarmManager::Get(const picojson::value& args, picojson::object& out) {
679   ScopeLogger();
680
681   int id = 0;
682
683   if (args.contains("id") && args.get("id").is<double>()) {
684     id = static_cast<int>(args.get("id").get<double>());
685   }
686
687   picojson::value result = picojson::value(picojson::object());
688   picojson::object& result_obj = result.get<picojson::object>();
689
690   PlatformResult platform_result = GetAlarm(id, result_obj);
691
692   if (!platform_result) {
693     LogAndReportError(platform_result, &out);
694   } else {
695     ReportSuccess(result, out);
696   }
697 }
698
699 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE) || defined(TIZEN_COMMON)
700 void AlarmManager::GetAlarmNotification(const picojson::value& args, picojson::object& out) {
701   using namespace extension::notification;
702   ScopeLogger();
703
704   int alarm_id = 0;
705   int ret = ALARM_ERROR_NONE;
706   notification_h notification_handle = nullptr;
707   PlatformResult platform_result = PlatformResult(ErrorCode::NO_ERROR);
708
709   SCOPE_EXIT {
710     notification_free(notification_handle);
711   };
712
713   if (args.contains("id") && args.get("id").is<double>()) {
714     alarm_id = static_cast<int>(args.get("id").get<double>());
715   }
716
717   ret = alarm_get_notification(alarm_id, &notification_handle);
718
719   if (ALARM_ERROR_NONE != ret) {
720     if (ALARM_ERROR_INVALID_PARAMETER == ret) {
721       platform_result =
722           PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alarm with given ID was not found.");
723     } else {
724       platform_result = PlatformResult(ErrorCode::ABORT_ERR, "Failed to get notification.");
725     }
726     LogAndReportError(platform_result, &out);
727   }
728
729   app_control_h app_control = nullptr;
730   platform_result = CommonNotification::GetAppControl(notification_handle, &app_control);
731
732   if (!platform_result) {
733     LogAndReportError(platform_result, &out);
734   }
735
736   picojson::value result = picojson::value(picojson::object());
737   picojson::object& result_obj = result.get<picojson::object>();
738
739   platform_result = UserNotification::ToJson(-1, notification_handle, app_control, &result_obj);
740
741   if (ALARM_ERROR_NONE != ret) {
742     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Failed ToJson()."), &out);
743   }
744
745   ReportSuccess(result, out);
746 }
747 #endif
748 static bool AlarmIterateCB(int alarm_id, void* user_data) {
749   ScopeLogger();
750
751   std::vector<int>* alarm_ids = reinterpret_cast<std::vector<int>*>(user_data);
752
753   alarm_ids->push_back(alarm_id);
754   return true;
755 }
756 #include <stdio.h>
757
758 void AlarmManager::GetAll(const picojson::value& args, picojson::object& out) {
759   ScopeLogger();
760   std::vector<int> alarm_ids;
761   int ret = alarm_foreach_registered_alarm(AlarmIterateCB, &alarm_ids);
762
763   if (ALARM_ERROR_NONE != ret) {
764     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Platform unknown error."), &out,
765                       ("Platform unknown error: %d (%s)", ret, get_error_message(ret)));
766     return;
767   }
768
769   picojson::value result_array = picojson::value(picojson::array());
770   picojson::array& array_obj = result_array.get<picojson::array>();
771
772   for (size_t i = 0; i < alarm_ids.size(); i++) {
773     picojson::value result = picojson::value(picojson::object());
774     picojson::object& obj = result.get<picojson::object>();
775
776     PlatformResult platform_result = GetAlarm(alarm_ids.at(i), obj);
777     if (!platform_result) {
778       LogAndReportError(platform_result, &out, ("Failed GetAlarm()"));
779       return;
780     }
781     array_obj.push_back(result);
782   }
783
784   ReportSuccess(result_array, out);
785 }
786
787 void AlarmManager::GetRemainingSeconds(const picojson::value& args, picojson::object& out) {
788   ScopeLogger();
789
790   struct tm date;
791   struct tm current;
792   time_t current_time;
793   time_t next_time;
794
795   int id = 0;
796
797   if (args.contains("id") && args.get("id").is<double>()) {
798     id = static_cast<int>(args.get("id").get<double>());
799   }
800
801   picojson::value result = picojson::value(picojson::object());
802   picojson::object& result_obj = result.get<picojson::object>();
803
804   int ret = alarm_get_scheduled_date(id, &date);
805   if (ALARM_ERROR_NONE != ret) {
806     LoggerI("alarm_get_scheduled_date error: %d (%s)", ret, get_error_message(ret));
807     if (ALARM_ERROR_INVALID_PARAMETER == ret || ALARM_ERROR_CONNECTION_FAIL == ret) {
808       result_obj.insert(std::make_pair("seconds", picojson::value()));
809       ReportSuccess(result, out);
810       return;
811     } else {
812       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Platform unknown error."), &out);
813       return;
814     }
815   }
816
817   alarm_get_current_time(&current);
818   next_time = mktime(&date);
819   current_time = mktime(&current);
820
821   long seconds = next_time - current_time;
822
823   result_obj.insert(std::make_pair("seconds", picojson::value(std::to_string(seconds))));
824   ReportSuccess(result, out);
825 }
826
827 void AlarmManager::GetNextScheduledDate(const picojson::value& args, picojson::object& out) {
828   ScopeLogger();
829   int id = 0;
830
831   if (args.contains("id") && args.get("id").is<double>()) {
832     id = static_cast<int>(args.get("id").get<double>());
833   }
834
835   struct tm date;
836   int ret = alarm_get_scheduled_date(id, &date);
837
838   picojson::value result = picojson::value(picojson::object());
839   picojson::object& result_obj = result.get<picojson::object>();
840
841   if (ALARM_ERROR_NONE != ret) {
842     result_obj.insert(std::make_pair("year", picojson::value()));
843     ReportSuccess(result, out);
844     return;
845   }
846
847   struct tm curr_date;
848   ret = alarm_get_current_time(&curr_date);
849   if (ALARM_ERROR_NONE != ret || mktime(&date) < mktime(&curr_date)) {
850     result_obj.insert(std::make_pair("year", picojson::value()));
851     ReportSuccess(result, out);
852     return;
853   }
854
855   // tm struct contains years since 1900
856   // there is added 1900 to tm_year to return proper date
857   result_obj.insert(std::make_pair("year", picojson::value(std::to_string(date.tm_year + 1900))));
858   result_obj.insert(std::make_pair("month", picojson::value(std::to_string(date.tm_mon))));
859   result_obj.insert(std::make_pair("day", picojson::value(std::to_string(date.tm_mday))));
860   result_obj.insert(std::make_pair("hour", picojson::value(std::to_string(date.tm_hour))));
861   result_obj.insert(std::make_pair("min", picojson::value(std::to_string(date.tm_min))));
862   result_obj.insert(std::make_pair("sec", picojson::value(std::to_string(date.tm_sec))));
863
864   ReportSuccess(result, out);
865 }
866
867 }  // namespace alarm
868 }  // namespace extension