a898f3b35772acf014be4a4f4f4c982628c931e2
[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)
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 }
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)
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   ret = app_control_get_extra_data(app_control, kAlarmKeyType, &alarm_type);
574   if (APP_CONTROL_ERROR_NONE != ret) {
575     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.",
576                               ("Getting data failed: %d (%s)", ret, get_error_message(ret)));
577   }
578
579   obj.insert(std::make_pair("id", picojson::value(std::to_string(id))));
580
581   if (!strcmp(alarm_type, kAlarmTypeValueAbsolute)) {
582     struct tm date;
583     memset(&date, 0, sizeof(tm));
584
585     ret = app_control_get_extra_data(app_control, kAlarmAbsoluteDateKey, &date_string);
586
587     if (APP_CONTROL_ERROR_NONE != ret) {
588       return LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Failed to get data.",
589                                 ("Failed to get data: %d (%s)", ret, get_error_message(ret)));
590     }
591
592     sscanf(date_string, "%5d %5d %5d %5d %5d %5d %5d", &date.tm_year, &date.tm_mon, &date.tm_mday,
593            &date.tm_hour, &date.tm_min, &date.tm_sec, &date.tm_isdst);
594     mktime(&date);
595
596     obj.insert(std::make_pair("year", picojson::value(std::to_string(date.tm_year + 1900))));
597     obj.insert(std::make_pair("month", picojson::value(std::to_string(date.tm_mon))));
598     obj.insert(std::make_pair("day", picojson::value(std::to_string(date.tm_mday))));
599     obj.insert(std::make_pair("hour", picojson::value(std::to_string(date.tm_hour))));
600     obj.insert(std::make_pair("min", picojson::value(std::to_string(date.tm_min))));
601     obj.insert(std::make_pair("sec", picojson::value(std::to_string(date.tm_sec))));
602
603     int interval = 0;
604
605     ret = app_control_get_extra_data(app_control, kAlarmAbsoluteRecurrenceTypeKey, &alarm_type);
606     if (APP_CONTROL_ERROR_NONE != ret) {
607       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.",
608                                 ("Getting data failed: %d (%s)", ret, get_error_message(ret)));
609     }
610
611     if (!strcmp(alarm_type, kAlarmAbsoluteReccurrenceTypeInterval)) {
612       ret = alarm_get_scheduled_period(id, &interval);
613       if (ALARM_ERROR_NONE != ret) {
614         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.",
615                                   ("Unknown error occurred: %d (%s)", ret, get_error_message(ret)));
616       }
617
618       obj.insert(std::make_pair("second", picojson::value(std::to_string(interval))));
619     } else if (!strcmp(alarm_type, kAlarmAbsoluteReccurrenceTypeByDayValue)) {
620       int byDayValue = 0;
621
622       ret = alarm_get_scheduled_recurrence_week_flag(id, &byDayValue);
623       if (ALARM_ERROR_NONE != ret) {
624         return LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Failed to get data.",
625                                   ("Failed to get data: %d (%s)", ret, get_error_message(ret)));
626       }
627
628       picojson::array& array =
629           obj.insert(std::make_pair("second", picojson::value(picojson::array())))
630               .first->second.get<picojson::array>();
631
632       using namespace util;
633       if (byDayValue & ALARM_WEEK_FLAG_SUNDAY) array.push_back(picojson::value(kSundayShort));
634       if (byDayValue & ALARM_WEEK_FLAG_MONDAY) array.push_back(picojson::value(kMondayShort));
635       if (byDayValue & ALARM_WEEK_FLAG_TUESDAY) array.push_back(picojson::value(kTuesdayShort));
636       if (byDayValue & ALARM_WEEK_FLAG_WEDNESDAY) array.push_back(picojson::value(kWednesdayShort));
637       if (byDayValue & ALARM_WEEK_FLAG_THURSDAY) array.push_back(picojson::value(kThuesdayShort));
638       if (byDayValue & ALARM_WEEK_FLAG_FRIDAY) array.push_back(picojson::value(kFridayShort));
639       if (byDayValue & ALARM_WEEK_FLAG_SATURDAY) array.push_back(picojson::value(kSaturdayShort));
640     }
641
642     obj.insert(std::make_pair("type", picojson::value(kAlarmAbsolute)));
643
644   } else if (!strcmp(alarm_type, kAlarmTypeValueRelative)) {
645     int interval = 0;
646
647     ret = alarm_get_scheduled_period(id, &interval);
648     if (ALARM_ERROR_NONE != ret) {
649       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.",
650                                 ("Unknown error occurred: %d (%s)", ret, get_error_message(ret)));
651     }
652
653     int ret_app = app_control_get_extra_data(app_control, kAlarmRelativeDelayKey, &delay_string);
654     if (APP_CONTROL_ERROR_NONE != ret_app) {
655       return LogAndCreateResult(
656           ErrorCode::NOT_FOUND_ERR, "Failed to get data.",
657           ("Failed to get data: %d (%s)", ret_app, get_error_message(ret_app)));
658     }
659
660     obj.insert(std::make_pair("type", picojson::value(kAlarmRelative)));
661     obj.insert(std::make_pair("delay", picojson::value(delay_string)));
662     if (interval != 0) {
663       // according to documentation interval will not be lower than 600,
664       // thus 0 from native means period wasn't set by user
665       obj.insert(std::make_pair("period", picojson::value(std::to_string(interval))));
666     }
667   } else {
668     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
669   }
670
671   return PlatformResult(ErrorCode::NO_ERROR);
672 }
673
674 void AlarmManager::Get(const picojson::value& args, picojson::object& out) {
675   ScopeLogger();
676
677   int id = 0;
678
679   if (args.contains("id") && args.get("id").is<double>()) {
680     id = static_cast<int>(args.get("id").get<double>());
681   }
682
683   picojson::value result = picojson::value(picojson::object());
684   picojson::object& result_obj = result.get<picojson::object>();
685
686   PlatformResult platform_result = GetAlarm(id, result_obj);
687
688   if (!platform_result) {
689     LogAndReportError(platform_result, &out);
690   } else {
691     ReportSuccess(result, out);
692   }
693 }
694
695 #if defined(TIZEN_MOBILE) || defined(TIZEN_WEARABLE)
696 void AlarmManager::GetAlarmNotification(const picojson::value& args, picojson::object& out) {
697   using namespace extension::notification;
698   ScopeLogger();
699
700   int alarm_id = 0;
701   int ret = ALARM_ERROR_NONE;
702   notification_h notification_handle = nullptr;
703   PlatformResult platform_result = PlatformResult(ErrorCode::NO_ERROR);
704
705   SCOPE_EXIT {
706     notification_free(notification_handle);
707   };
708
709   if (args.contains("id") && args.get("id").is<double>()) {
710     alarm_id = static_cast<int>(args.get("id").get<double>());
711   }
712
713   ret = alarm_get_notification(alarm_id, &notification_handle);
714
715   if (ALARM_ERROR_NONE != ret) {
716     if (ALARM_ERROR_INVALID_PARAMETER == ret) {
717       platform_result =
718           PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alarm with given ID was not found.");
719     } else {
720       platform_result = PlatformResult(ErrorCode::ABORT_ERR, "Failed to get notification.");
721     }
722     LogAndReportError(platform_result, &out);
723   }
724
725   app_control_h app_control = nullptr;
726   platform_result = CommonNotification::GetAppControl(notification_handle, &app_control);
727
728   if (!platform_result) {
729     LogAndReportError(platform_result, &out);
730   }
731
732   picojson::value result = picojson::value(picojson::object());
733   picojson::object& result_obj = result.get<picojson::object>();
734
735   platform_result = UserNotification::ToJson(-1, notification_handle, app_control, &result_obj);
736
737   if (ALARM_ERROR_NONE != ret) {
738     LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Failed ToJson()."), &out);
739   }
740
741   ReportSuccess(result, out);
742 }
743 #endif
744 static bool AlarmIterateCB(int alarm_id, void* user_data) {
745   ScopeLogger();
746
747   std::vector<int>* alarm_ids = reinterpret_cast<std::vector<int>*>(user_data);
748
749   alarm_ids->push_back(alarm_id);
750   return true;
751 }
752 #include <stdio.h>
753
754 void AlarmManager::GetAll(const picojson::value& args, picojson::object& out) {
755   ScopeLogger();
756   std::vector<int> alarm_ids;
757   int ret = alarm_foreach_registered_alarm(AlarmIterateCB, &alarm_ids);
758
759   if (ALARM_ERROR_NONE != ret) {
760     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Platform unknown error."), &out,
761                       ("Platform unknown error: %d (%s)", ret, get_error_message(ret)));
762     return;
763   }
764
765   picojson::value result_array = picojson::value(picojson::array());
766   picojson::array& array_obj = result_array.get<picojson::array>();
767
768   for (size_t i = 0; i < alarm_ids.size(); i++) {
769     picojson::value result = picojson::value(picojson::object());
770     picojson::object& obj = result.get<picojson::object>();
771
772     PlatformResult platform_result = GetAlarm(alarm_ids.at(i), obj);
773     if (!platform_result) {
774       LogAndReportError(platform_result, &out, ("Failed GetAlarm()"));
775       return;
776     }
777     array_obj.push_back(result);
778   }
779
780   ReportSuccess(result_array, out);
781 }
782
783 void AlarmManager::GetRemainingSeconds(const picojson::value& args, picojson::object& out) {
784   ScopeLogger();
785
786   struct tm date;
787   struct tm current;
788   time_t current_time;
789   time_t next_time;
790
791   int id = 0;
792
793   if (args.contains("id") && args.get("id").is<double>()) {
794     id = static_cast<int>(args.get("id").get<double>());
795   }
796
797   picojson::value result = picojson::value(picojson::object());
798   picojson::object& result_obj = result.get<picojson::object>();
799
800   int ret = alarm_get_scheduled_date(id, &date);
801   if (ALARM_ERROR_NONE != ret) {
802     LoggerI("alarm_get_scheduled_date error: %d (%s)", ret, get_error_message(ret));
803     if (ALARM_ERROR_INVALID_PARAMETER == ret || ALARM_ERROR_CONNECTION_FAIL == ret) {
804       result_obj.insert(std::make_pair("seconds", picojson::value()));
805       ReportSuccess(result, out);
806       return;
807     } else {
808       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Platform unknown error."), &out);
809       return;
810     }
811   }
812
813   alarm_get_current_time(&current);
814   next_time = mktime(&date);
815   current_time = mktime(&current);
816
817   long seconds = next_time - current_time;
818
819   result_obj.insert(std::make_pair("seconds", picojson::value(std::to_string(seconds))));
820   ReportSuccess(result, out);
821 }
822
823 void AlarmManager::GetNextScheduledDate(const picojson::value& args, picojson::object& out) {
824   ScopeLogger();
825   int id = 0;
826
827   if (args.contains("id") && args.get("id").is<double>()) {
828     id = static_cast<int>(args.get("id").get<double>());
829   }
830
831   struct tm date;
832   int ret = alarm_get_scheduled_date(id, &date);
833
834   picojson::value result = picojson::value(picojson::object());
835   picojson::object& result_obj = result.get<picojson::object>();
836
837   if (ALARM_ERROR_NONE != ret) {
838     result_obj.insert(std::make_pair("year", picojson::value()));
839     ReportSuccess(result, out);
840     return;
841   }
842
843   struct tm curr_date;
844   ret = alarm_get_current_time(&curr_date);
845   if (ALARM_ERROR_NONE != ret || mktime(&date) < mktime(&curr_date)) {
846     result_obj.insert(std::make_pair("year", picojson::value()));
847     ReportSuccess(result, out);
848     return;
849   }
850
851   // tm struct contains years since 1900
852   // there is added 1900 to tm_year to return proper date
853   result_obj.insert(std::make_pair("year", picojson::value(std::to_string(date.tm_year + 1900))));
854   result_obj.insert(std::make_pair("month", picojson::value(std::to_string(date.tm_mon))));
855   result_obj.insert(std::make_pair("day", picojson::value(std::to_string(date.tm_mday))));
856   result_obj.insert(std::make_pair("hour", picojson::value(std::to_string(date.tm_hour))));
857   result_obj.insert(std::make_pair("min", picojson::value(std::to_string(date.tm_min))));
858   result_obj.insert(std::make_pair("sec", picojson::value(std::to_string(date.tm_sec))));
859
860   ReportSuccess(result, out);
861 }
862
863 }  // namespace alarm
864 }  // namespace extension