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