Alarm / src /

data.c

  1. /*
  2. * Copyright (c) 2016 Samsung Electronics Co., Ltd
  3. *
  4. * Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
  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 <efl_extension.h>
  18. #include <app_alarm.h>
  19.  
  20. #include "$(appName).h"
  21. #include "data.h"
  22.  
  23. static struct data_info {
  24. int ontime_alarm_id; /* id of the alarm set at date */
  25. int recurring_alarm_id; /* id of the delayed recurring alarm */
  26. int recurring_alarm_count; /* recurring alarm invocations count */
  27. time_t t_ontime_alarm;
  28. data_alarm_scheduled_t scheduled_alarm_callback;
  29. data_alarm_callback_t ontime_alarm_callback;
  30. data_alarm_callback_t recurring_alarm_callback;
  31. } s_info = {
  32. .ontime_alarm_id = -1,
  33. .recurring_alarm_id = -1,
  34. .recurring_alarm_count = -1,
  35. .t_ontime_alarm = 0,
  36. .scheduled_alarm_callback = NULL,
  37. .ontime_alarm_callback = NULL,
  38. .recurring_alarm_callback = NULL,
  39. };
  40.  
  41. #define APP_CONTROL_OPERATION_ALARM_RECURRING "http://tizen.org/appcontrol/operation/my_recurring_alarm"
  42. #define APP_CONTROL_OPERATION_ALARM_ONTIME "http://tizen.org/appcontrol/operation/my_ontime_alarm"
  43. #define RECURRING_ALARMS_TO_BE_INVOKED 5
  44. #define ALARM_DELAY 10
  45. #define ALARMS_INTERVAL ALARM_STANDARD_INTERVAL_FIFTEEN_MINUTES
  46. #define TIME_STRING_FORMAT_BUFFER_SIZE 10
  47.  
  48. static void _initialize_recurring_alarm(void);
  49. static void _initialize_ontime_alarm(void);
  50. static void _data_recurring_alarm_invoked(app_control_h app_control);
  51. static void _data_ontime_alarm_invoked(app_control_h app_control);
  52.  
  53. /**
  54. * @brief Initialization function for data module.
  55. */
  56. void data_initialize(void)
  57. {
  58. time_t t_alarm;
  59.  
  60. /*
  61. * initialization of recurring alarm.
  62. */
  63. _initialize_recurring_alarm();
  64.  
  65. /*
  66. * initialization of on-time alarm.
  67. */
  68. _initialize_ontime_alarm();
  69.  
  70. if (s_info.scheduled_alarm_callback) {
  71. t_alarm = time(NULL) + ALARM_DELAY;
  72. s_info.scheduled_alarm_callback(t_alarm);
  73. }
  74. }
  75.  
  76. /**
  77. * @brief Finalization function for data module.
  78. */
  79. void data_finalize(void)
  80. {
  81. dlog_print(DLOG_DEBUG, LOG_TAG, "data finalize");
  82.  
  83. if (s_info.recurring_alarm_id >= 0)
  84. alarm_cancel(s_info.recurring_alarm_id);
  85.  
  86. if (s_info.ontime_alarm_id >= 0)
  87. alarm_cancel(s_info.ontime_alarm_id);
  88. }
  89.  
  90. static bool _app_control_operation_equals(const char *predefined_operation, const char *app_control_operation)
  91. {
  92. if (!predefined_operation && !app_control_operation)
  93. return true;
  94.  
  95. if (!predefined_operation || !app_control_operation)
  96. return false;
  97.  
  98. /*now we have non null strings*/
  99. if (strlen(predefined_operation) != strlen(app_control_operation))
  100. return false;
  101.  
  102. return !strncmp(predefined_operation, app_control_operation, strlen(app_control_operation));
  103. }
  104.  
  105. /* function is invoked by controller module (main.c)
  106. * to to handle app_controls call-backs from application life cycle loop
  107. */
  108. void data_handle_app_control(app_control_h app_control)
  109. {
  110. char *operation = NULL;
  111. int ret;
  112.  
  113. dlog_print(DLOG_DEBUG, LOG_TAG, "data_handle_app_control");
  114.  
  115. /*
  116. * Get operation name bind to the app_control handle.
  117. * If this function fails, then it is not possible to handle app_control
  118. * call.
  119. */
  120. ret = app_control_get_operation(app_control, &operation);
  121. if (ret != APP_CONTROL_ERROR_NONE) {
  122. dlog_print(DLOG_ERROR, LOG_TAG, "Function app_control_get_operation() failed.");
  123. return;
  124. }
  125. dlog_print(DLOG_DEBUG, LOG_TAG, "operation: %s", operation);
  126. /*
  127. * Based on app_control operation, then proper action is executed.
  128. * In this case, only alarm related operations are supported. Below
  129. * conditional statements verify if operation type match any of customly
  130. * predefined alarm operation.
  131. */
  132. if (_app_control_operation_equals(APP_CONTROL_OPERATION_ALARM_RECURRING, operation))
  133. _data_recurring_alarm_invoked(app_control);
  134. else if (_app_control_operation_equals(APP_CONTROL_OPERATION_ALARM_ONTIME, operation))
  135. _data_ontime_alarm_invoked(app_control);
  136.  
  137. free(operation);
  138. }
  139.  
  140. /**
  141. * Function sets callbacks that are invoked when recurring and ontime alarms are fired
  142. */
  143. void data_set_alarms_callbacks(data_alarm_scheduled_t scheduled_alarm_callback, data_alarm_callback_t ontime_alarm_callback, data_alarm_callback_t recurring_alarm_callback)
  144. {
  145. s_info.ontime_alarm_callback = ontime_alarm_callback;
  146. s_info.recurring_alarm_callback = recurring_alarm_callback;
  147. s_info.scheduled_alarm_callback = scheduled_alarm_callback;
  148. }
  149.  
  150. /*
  151. * Function returns current local time in string format: HH:MM:SS
  152. * Obtained char buffer must be released using free() function.
  153. */
  154. static char* _get_current_time(void)
  155. {
  156. char *time_buff = (char *)calloc(TIME_STRING_FORMAT_BUFFER_SIZE, sizeof(char));
  157. time_t current_time;
  158.  
  159. time(&current_time);
  160. strftime(time_buff, TIME_STRING_FORMAT_BUFFER_SIZE, "%H:%M:%S", localtime(&current_time));
  161.  
  162. return time_buff;
  163. }
  164.  
  165. /*
  166. * Function creates new recurring alarm using alarm_schedule_after_delay()
  167. * function. If the alarm is created successfully, then it will be fired
  168. * with delay of ALARM_DELAY seconds and with interval of ALARMS_INTERVAL
  169. * seconds.
  170. */
  171. static void _initialize_recurring_alarm(void)
  172. {
  173. int ret;
  174. app_control_h app_control;
  175.  
  176. /*
  177. * Creating new app_control handle.
  178. * If this function fails, the alarm will not be scheduled.
  179. */
  180. ret = app_control_create(&app_control);
  181. if (ret != APP_CONTROL_ERROR_NONE) {
  182. dlog_print(DLOG_ERROR, LOG_TAG, "Function app_control_create() failed.");
  183. return;
  184. }
  185.  
  186. /*
  187. * Bind operation to created app_control handle.
  188. * Custom operation name will be used to identify the alarm invocation
  189. * within app_control callback and distinguish alarm types.
  190. * If this function fails, the app_control handle must be released
  191. * and the alarm will not be scheduled.
  192. */
  193. ret = app_control_set_operation(app_control, APP_CONTROL_OPERATION_ALARM_RECURRING);
  194. if (ret != APP_CONTROL_ERROR_NONE) {
  195. dlog_print(DLOG_ERROR, LOG_TAG, "Function app_control_set_operation() failed.");
  196. app_control_destroy(app_control);
  197. return;
  198. }
  199.  
  200. /*
  201. * Bind package name to created app_control handle.
  202. * Based on provided package name, the alarm will be invoked within
  203. * the context of the application referenced by provided package name.
  204. * If this function fails, the app_control handle must be released
  205. * and the alarm will not be scheduled.
  206. */
  207. ret = app_control_set_app_id(app_control, PACKAGE);
  208. if (ret != APP_CONTROL_ERROR_NONE) {
  209. dlog_print(DLOG_ERROR, LOG_TAG, "Function app_control_set_app_id() failed.");
  210. app_control_destroy(app_control);
  211. return;
  212. }
  213.  
  214. /*
  215. * Set the alarm for created app_control handle.
  216. * The alarm will be scheduled with ALARM_DELAY delay and ALARMS_INTERVAL
  217. * period. In result, the first alarm invokation will occur ofter
  218. * ALARM_DELAY seconds. Subsequent alarms invokations will occur
  219. * with ALARMS_INTERVAL seconds. If ALARMS_INTERVAL == 0, then the alarm
  220. * will be invoked only once after ALARM_DELAY seconds.
  221. * If function succeeds, the alarm ID is returned and stored in appdata_s
  222. * structure.
  223. */
  224. ret = alarm_schedule_after_delay(app_control, ALARM_DELAY, ALARMS_INTERVAL, &s_info.recurring_alarm_id);
  225. if (ret != ALARM_ERROR_NONE)
  226. dlog_print(DLOG_ERROR, LOG_TAG, "Function alarm_schedule_after_delay() failed.");
  227.  
  228. /*
  229. * Finally, the app_control handle is released.
  230. */
  231. ret = app_control_destroy(app_control);
  232. if (ret != APP_CONTROL_ERROR_NONE)
  233. dlog_print(DLOG_ERROR, LOG_TAG, "Function app_control_destroy() failed.");
  234. else
  235. dlog_print(DLOG_DEBUG, LOG_TAG, "Set recurring alarm with id: %i", s_info.recurring_alarm_id);
  236. }
  237.  
  238. /*
  239. * Function creates new alarm set on time, using alarm_schedule_at_date()
  240. * function. If the alarm is created successfully, then it will be fired
  241. * at specified date and time.
  242. */
  243. static void _initialize_ontime_alarm(void)
  244. {
  245. int ret;
  246. app_control_h app_control;
  247.  
  248. /*
  249. * Creating new app_control handle.
  250. * If this function fails, the alarm will not be scheduled.
  251. */
  252. ret = app_control_create(&app_control);
  253. if (ret != 0) {
  254. dlog_print(DLOG_ERROR, LOG_TAG, "Function app_control_create() failed.");
  255. return;
  256. }
  257.  
  258. /*
  259. * Bind operation to created app_control handle.
  260. * Custom operation name will be used to identify the alarm invokation
  261. * within app_control callback and distinguish alarm types.
  262. * If this function fails, the app_control handle must be released
  263. * and the alarm will not be scheduled.
  264. */
  265. ret = app_control_set_operation(app_control, APP_CONTROL_OPERATION_ALARM_ONTIME);
  266. if (ret != APP_CONTROL_ERROR_NONE) {
  267. dlog_print(DLOG_ERROR, LOG_TAG, "Function app_control_set_operation() failed.");
  268. app_control_destroy(app_control);
  269. return;
  270. }
  271.  
  272. /*
  273. * Bind package name to created app_control handle.
  274. * Based on provided package name, the alarm will be invoked within
  275. * the context of the application referenced by provided package name.
  276. * If this function fails, the app_control handle must be released
  277. * and the alarm will not be scheduled.
  278. */
  279. ret = app_control_set_app_id(app_control, PACKAGE);
  280. if (ret != APP_CONTROL_ERROR_NONE) {
  281. dlog_print(DLOG_ERROR, LOG_TAG, "Function app_control_set_app_id() failed.");
  282. app_control_destroy(app_control);
  283. return;
  284. }
  285.  
  286. /*
  287. * Compute the time of on-time alarm invocation.
  288. */
  289. s_info.t_ontime_alarm = time(NULL) + ALARM_DELAY;
  290.  
  291. /*
  292. * Set the alarm for created app_control handle.
  293. * The alarm will be scheduled on time t_alarm without recurrency.
  294. * If function succeeds, the alarm ID is returned and stored in appdata_s
  295. * structure.
  296. */
  297. ret = alarm_schedule_once_at_date(app_control, localtime(&s_info.t_ontime_alarm), &s_info.ontime_alarm_id);
  298. if (ret != ALARM_ERROR_NONE)
  299. dlog_print(DLOG_ERROR, LOG_TAG, "Function alarm_schedule_at_date() failed.");
  300.  
  301. /*
  302. * Finally, the app_control handle is released.
  303. */
  304. ret = app_control_destroy(app_control);
  305. if (ret != APP_CONTROL_ERROR_NONE)
  306. dlog_print(DLOG_ERROR, LOG_TAG, "Function app_control_destroy() failed.");
  307. else
  308. dlog_print(DLOG_DEBUG, LOG_TAG, "Set ontime alarm with id: %i", s_info.ontime_alarm_id);
  309. }
  310.  
  311. /*
  312. * Function is called if alarm control arrives and is identified
  313. * as recurring alarm.
  314. */
  315. static void _data_recurring_alarm_invoked(app_control_h app_control)
  316. {
  317. int ret;
  318. char *alarm_data = NULL;
  319. char *time_str = NULL;
  320. time_t t_alarm;
  321.  
  322. dlog_print(DLOG_DEBUG, LOG_TAG, "recurring alarm invoked by appcontrol");
  323.  
  324. if (s_info.scheduled_alarm_callback) {
  325. t_alarm = time(NULL) + ALARMS_INTERVAL;
  326. s_info.scheduled_alarm_callback(t_alarm);
  327. }
  328.  
  329. /*
  330. * Get data attached to the app_control handle by using common alarm data
  331. * identifier APP_CONTROL_DATA_ALARM_ID. The extracted data contains alarm
  332. * identifier stored as char buffer.
  333. * If this function fails, the alarm can not be properly verified.
  334. */
  335. ret = app_control_get_extra_data(app_control, APP_CONTROL_DATA_ALARM_ID, &alarm_data);
  336.  
  337. if (ret != APP_CONTROL_ERROR_NONE) {
  338. dlog_print(DLOG_ERROR, LOG_TAG, "Function app_control_get_extra_data() failed.");
  339. return;
  340. }
  341.  
  342. if (alarm_data == NULL) {
  343. dlog_print(DLOG_ERROR, LOG_TAG, "alarm_data == NULL");
  344. return;
  345. }
  346. /*
  347. * Verify if obtained alarm identifier is equal to the identifier
  348. * of created alarm. If IDs does not match, then the alarm invocation
  349. * belongs to other recurring alarm.
  350. */
  351. if (atoi(alarm_data) != s_info.recurring_alarm_id)
  352. return;
  353.  
  354. /*
  355. * Count number of recurring alarm invocations
  356. */
  357. s_info.recurring_alarm_count++;
  358.  
  359. /*
  360. * Inform controller about firing an alarm.
  361. */
  362. if (s_info.recurring_alarm_callback)
  363. s_info.recurring_alarm_callback();
  364.  
  365. time_str = _get_current_time();
  366. dlog_print(DLOG_INFO, LOG_TAG, "Recurring alarm #%d invoked at %s", s_info.recurring_alarm_count, time_str);
  367. free(time_str);
  368.  
  369. /*
  370. * If number of recurring alarm invocations is less then expected number,
  371. * then the function ends its execution and the alarm will be invoked again.
  372. */
  373. if (s_info.recurring_alarm_count < RECURRING_ALARMS_TO_BE_INVOKED)
  374. return;
  375.  
  376. /*
  377. * If recurring alarm is invoked expected number of times, then it is
  378. * canceled. If this function fails, then the recurring alarm will not
  379. * be stopped.
  380. */
  381. ret = alarm_cancel(s_info.recurring_alarm_id);
  382. if (ret != APP_CONTROL_ERROR_NONE) {
  383. dlog_print(DLOG_ERROR, LOG_TAG, "Function alarm_cancel() failed.");
  384. return;
  385. }
  386.  
  387. dlog_print(DLOG_INFO, LOG_TAG, "Recurring alarm canceled");
  388.  
  389. if (s_info.scheduled_alarm_callback)
  390. s_info.scheduled_alarm_callback(s_info.t_ontime_alarm);
  391. }
  392.  
  393. /*
  394. * Function is called if alarm control arrives and is identified as on-time alarm.
  395. */
  396. static void _data_ontime_alarm_invoked(app_control_h app_control)
  397. {
  398. int ret;
  399. char *alarm_data = NULL;
  400. char *time_str = NULL;
  401.  
  402. dlog_print(DLOG_DEBUG, LOG_TAG, "ontime alarm invoked by appcontrol");
  403.  
  404. if (s_info.scheduled_alarm_callback)
  405. s_info.scheduled_alarm_callback(0);
  406.  
  407. /*
  408. * Get data attached to the app_control handle by using common alarm data
  409. * identifier APP_CONTROL_DATA_ALARM_ID. The extracted data contains alarm
  410. * identifier stored as char buffer.
  411. * If this function fails, the alarm can not be properly verified.
  412. */
  413. ret = app_control_get_extra_data(app_control, APP_CONTROL_DATA_ALARM_ID, &alarm_data);
  414. if (ret != APP_CONTROL_ERROR_NONE) {
  415. dlog_print(DLOG_ERROR, LOG_TAG, "Function app_control_get_extra_data() failed.");
  416. return;
  417. }
  418.  
  419. if (alarm_data == NULL) {
  420. dlog_print(DLOG_ERROR, LOG_TAG, "alarm_data empty");
  421. return;
  422. }
  423.  
  424. /*
  425. * Verify if obtained alarm identifier is equal to the identifier of
  426. * created alarm. If IDs does not match, then the alarm invocation belongs
  427. * to other on-time alarm.
  428. */
  429. if (atoi(alarm_data) != s_info.ontime_alarm_id)
  430. return;
  431.  
  432. /*
  433. * Inform controller about firing an alarm.
  434. */
  435. if (s_info.ontime_alarm_callback)
  436. s_info.ontime_alarm_callback();
  437.  
  438. time_str = _get_current_time();
  439. dlog_print(DLOG_INFO, LOG_TAG, "Ontime alarm invoked at %s", time_str);
  440. free(time_str);
  441.  
  442. /*
  443. * If the alarm is not set as recurring, then it must not call
  444. * alarm_cancel() function. In this case, the on-tim alarm is automatically
  445. * released.
  446. */
  447. }