diff options
author | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-13 01:45:44 +0900 |
---|---|---|
committer | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-13 01:45:44 +0900 |
commit | e3038c9c3c7a5c7843d872f2899ffa10abc03cb4 (patch) | |
tree | fd2d8b09ca59f58e8737588c77315595ce65e7eb /src | |
parent | 5611ff5660d14d0ea707447e84ee4c0626b71104 (diff) | |
download | application-e3038c9c3c7a5c7843d872f2899ffa10abc03cb4.tar.gz application-e3038c9c3c7a5c7843d872f2899ffa10abc03cb4.tar.bz2 application-e3038c9c3c7a5c7843d872f2899ffa10abc03cb4.zip |
Tizen 2.1 base
Diffstat (limited to 'src')
-rwxr-xr-x | src/alarm.c | 586 | ||||
-rwxr-xr-x | src/app_device.c | 83 | ||||
-rwxr-xr-x | src/app_error.c | 72 | ||||
-rwxr-xr-x | src/app_finalizer.c | 108 | ||||
-rwxr-xr-x | src/app_main.c | 401 | ||||
-rwxr-xr-x | src/app_package.c | 188 | ||||
-rwxr-xr-x | src/app_resource.c | 250 | ||||
-rwxr-xr-x | src/i18n.c | 29 | ||||
-rwxr-xr-x | src/preference.c | 758 | ||||
-rwxr-xr-x | src/service.c | 1285 | ||||
-rwxr-xr-x | src/storage.c | 397 | ||||
-rwxr-xr-x | src/storage_internal.c | 79 | ||||
-rwxr-xr-x | src/storage_sdcard.c | 125 | ||||
-rwxr-xr-x | src/storage_usbhost.c | 125 | ||||
-rwxr-xr-x | src/ui_notification.c | 1179 |
15 files changed, 5665 insertions, 0 deletions
diff --git a/src/alarm.c b/src/alarm.c new file mode 100755 index 0000000..5b787af --- /dev/null +++ b/src/alarm.c @@ -0,0 +1,586 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> + +#include <aul.h> +#include <alarm.h> +#include <dlog.h> + +#include <app_private.h> +#include <app_alarm.h> +#include <app_service_private.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION_ALARM" + +typedef struct { + alarm_registered_alarm_cb cb; + void* user_data; + bool* foreach_break; +} alarm_foreach_item_cb_context; + +static void alarm_get_interval(alarm_entry_t *alarm_info, int day_week, int *repeat_interval) +{ + time_t due_time = 0; + time_t current_time = 0; + struct tm duetime_tm; + int wday; + int interval = 0; + + time(¤t_time); + localtime_r(¤t_time, &duetime_tm); + wday = duetime_tm.tm_wday; + + due_time = mktime(&duetime_tm); + wday = duetime_tm.tm_wday; + + if (due_time > current_time && day_week == 0) + return; + + if (!(day_week & 1 << wday)) { + int day = wday + 1; + int next_week = 0; + interval = 1; + /*this week */ + + if (day == 7) { + day = 0; + next_week = 1; + } + + while (!(day_week & 1 << day) + && interval < 8) { + day += 1; + interval += 1; + + if (day == 7) { + day = 0; + next_week = 1; + } + + } + *repeat_interval = interval; + } +} + +static int alarm_registered_alarm_cb_broker(int alarm_id, void *user_data) +{ + alarm_foreach_item_cb_context* foreach_cb_context = NULL; + + if (user_data == NULL) + { + return 0; + } + + foreach_cb_context = (alarm_foreach_item_cb_context*)user_data; + + if (foreach_cb_context != NULL && *(foreach_cb_context->foreach_break) == false) + { + if (foreach_cb_context->cb(alarm_id, foreach_cb_context->user_data) == false) + { + *(foreach_cb_context->foreach_break) = true; + } + } + + return 0; +} + +static int convert_error_code_to_alarm(const char* function, alarm_error_t alarm_error) +{ + switch(alarm_error) + { + case ERR_ALARM_INVALID_PARAM: + case ERR_ALARM_INVALID_REPEAT: + LOGE("[%s] INVALID_PARAMETER(0x%08x)", function, ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + break; + + case ERR_ALARM_INVALID_ID: + LOGE("[%s] INVALID_PARAMETER(0x%08x)", function, ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + break; + + case ERR_ALARM_INVALID_TIME: + LOGE("[%s] INVALID_TIME(0x%08x)", function, ALARM_ERROR_INVALID_TIME); + return ALARM_ERROR_INVALID_TIME; + break; + + case ERR_ALARM_INVALID_DATE: + LOGE("[%s] INVALID_DATE(0x%08x)", function, ALARM_ERROR_INVALID_DATE); + return ALARM_ERROR_INVALID_DATE; + break; + + case ERR_ALARM_NO_SERVICE_NAME: + LOGE("[%s] INVALID_PARAMETER(0x%08x)", function, ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + break; + + case ERR_ALARM_SYSTEM_FAIL: + LOGE("[%s] CONNECTION_FAIL(0x%08x)", function, ALARM_ERROR_CONNECTION_FAIL); + return ALARM_ERROR_CONNECTION_FAIL; + break; + + case ALARMMGR_RESULT_SUCCESS: + return ALARM_ERROR_NONE; + break; + + default: + return ALARM_ERROR_INVALID_PARAMETER; + } + +} + +static int _remove_alarm_cb(alarm_id_t alarm_id, void* user_param) +{ + return alarmmgr_remove_alarm(alarm_id); +} + +int alarm_get_scheduled_date(int alarm_id, struct tm* date) +{ + alarm_error_t result; + alarm_entry_t *entry = NULL; + alarm_date_t adate; + alarm_repeat_mode_t repeat=0; + int week_day=0; + int repeat_interval=0; + + if (date == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + } + + entry = alarmmgr_create_alarm(); + + result = alarmmgr_get_info(alarm_id, entry); + if (result != ALARMMGR_RESULT_SUCCESS) + { + if (entry != NULL) { + alarmmgr_free_alarm(entry); + } + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + result = alarmmgr_get_time(entry, &adate); + if (result != ALARMMGR_RESULT_SUCCESS) + { + if (entry != NULL) + { + alarmmgr_free_alarm(entry); + } + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + result = alarmmgr_get_repeat_mode(entry, &repeat, &week_day); + + if (result != ALARMMGR_RESULT_SUCCESS) + { + if (entry != NULL) + { + alarmmgr_free_alarm(entry); + } + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + if ( repeat == ALARM_REPEAT_MODE_WEEKLY) + alarm_get_interval(entry, week_day, &repeat_interval); + else + repeat_interval=0; + + alarm_get_current_time(date); + + date->tm_year = adate.year - 1900; + date->tm_mon = adate.month - 1; + date->tm_mday = adate.day + repeat_interval; + date->tm_hour = adate.hour; + date->tm_min = adate.min; + date->tm_sec = adate.sec; + + mktime(date); + + result = alarmmgr_free_alarm(entry); + if (result != ALARMMGR_RESULT_SUCCESS) + { + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + return ALARM_ERROR_NONE; + +} + +int alarm_get_scheduled_period(int alarm_id, int* period) +{ + alarm_error_t result; + alarm_entry_t *entry = NULL; + alarm_repeat_mode_t mode; + int value; + + if (period == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + } + + entry = alarmmgr_create_alarm(); + + result = alarmmgr_get_info(alarm_id, entry); + if (result != ALARMMGR_RESULT_SUCCESS) + { + if (entry != NULL) + { + alarmmgr_free_alarm(entry); + } + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + result = alarmmgr_get_repeat_mode(entry, &mode, &value); + if (result != ALARMMGR_RESULT_SUCCESS) + { + if (entry != NULL) + { + alarmmgr_free_alarm(entry); + } + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + result = alarmmgr_free_alarm(entry); + if(result != ALARMMGR_RESULT_SUCCESS) + { + if (entry != NULL) + { + alarmmgr_free_alarm(entry); + } + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + (*period) = value; + + return ALARM_ERROR_NONE; + +} + +int alarm_schedule_after_delay(service_h service, int delay, int period, int *alarm_id) +{ + bundle *bundle_data; + int result = 0; + + if (service == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + } + + if (service_to_bundle(service, &bundle_data) != SERVICE_ERROR_NONE) + { + LOGE("INVALID_PARAMETER(0x%08x)", ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + } + + result = alarmmgr_add_alarm_appsvc(ALARM_TYPE_DEFAULT, delay, period, bundle_data, alarm_id); + + return convert_error_code_to_alarm(__FUNCTION__, result); +} + +int alarm_schedule_at_date(service_h service, struct tm *date, int period_in_second, int *alarm_id) +{ + alarm_date_t internal_time; + alarm_entry_t* alarm_info; + bundle *bundle_data; + int result; + + if (service == NULL || date == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + } + + if (service_to_bundle(service, &bundle_data) != SERVICE_ERROR_NONE) + { + LOGE("INVALID_PARAMETER(0x%08x)", ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + } + + alarm_info = alarmmgr_create_alarm(); + + internal_time.year = date->tm_year + 1900; + internal_time.month = date->tm_mon +1; + internal_time.day = date->tm_mday; + + internal_time.hour = date->tm_hour; + internal_time.min = date->tm_min; + internal_time.sec = date->tm_sec; + + result = alarmmgr_set_time(alarm_info,internal_time); + + if (result < 0) + { + alarmmgr_free_alarm(alarm_info); + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + + if (period_in_second > 0) + { + result = alarmmgr_set_repeat_mode(alarm_info, ALARM_REPEAT_MODE_REPEAT, period_in_second); + } + else + { + result = alarmmgr_set_repeat_mode(alarm_info, ALARM_REPEAT_MODE_ONCE, period_in_second); + } + + if (result < 0) + { + alarmmgr_free_alarm(alarm_info); + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + result = alarmmgr_set_type(alarm_info, ALARM_TYPE_DEFAULT); + + if (result < 0) + { + alarmmgr_free_alarm(alarm_info); + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + result = alarmmgr_add_alarm_appsvc_with_localtime(alarm_info, bundle_data, alarm_id); + + if (result < 0) + { + alarmmgr_free_alarm(alarm_info); + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + alarmmgr_free_alarm(alarm_info); + return ALARM_ERROR_NONE; +} + +int alarm_cancel(int alarm_id) +{ + int result; + + result = alarmmgr_remove_alarm(alarm_id); + + return convert_error_code_to_alarm(__FUNCTION__, result); +} + +int alarm_cancel_all() +{ + int result; + + result = alarmmgr_enum_alarm_ids( _remove_alarm_cb, NULL); + + return convert_error_code_to_alarm(__FUNCTION__, result); +} + +int alarm_foreach_registered_alarm(alarm_registered_alarm_cb callback, void* user_data) +{ + int result; + bool foreach_break = false; + + if (callback == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + } + + //alarm_registered_alarm_cb_broker + alarm_foreach_item_cb_context foreach_cb_context = { + .cb = callback, + .user_data = user_data, + .foreach_break = &foreach_break + }; + + result = alarmmgr_enum_alarm_ids(alarm_registered_alarm_cb_broker, &foreach_cb_context); + + return convert_error_code_to_alarm(__FUNCTION__, result); +} + +int alarm_get_current_time(struct tm* date) +{ + time_t now; + + if (date == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + } + + time(&now); + localtime_r(&now, date); + return ALARM_ERROR_NONE; +} + + +int alarm_schedule_with_recurrence_week_flag(service_h service, struct tm *date, int week_flag,int *alarm_id) +{ + alarm_date_t internal_time; + alarm_entry_t* alarm_info; + bundle *bundle_data; + int result; + + if (service == NULL || date == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + } + + if (service_to_bundle(service, &bundle_data) != SERVICE_ERROR_NONE) + { + LOGE("INVALID_PARAMETER(0x%08x)", ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + } + + alarm_info = alarmmgr_create_alarm(); + + internal_time.year = date->tm_year + 1900; + internal_time.month = date->tm_mon +1; + internal_time.day = date->tm_mday; + + internal_time.hour = date->tm_hour; + internal_time.min = date->tm_min; + internal_time.sec = date->tm_sec; + + result = alarmmgr_set_time(alarm_info,internal_time); + + if (result < 0) + { + alarmmgr_free_alarm(alarm_info); + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + if (week_flag > 0) + { + result = alarmmgr_set_repeat_mode(alarm_info, ALARM_REPEAT_MODE_WEEKLY, week_flag); + } + + if (result < 0) + { + alarmmgr_free_alarm(alarm_info); + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + result = alarmmgr_set_type(alarm_info, ALARM_TYPE_DEFAULT); + + if (result < 0) + { + alarmmgr_free_alarm(alarm_info); + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + result = alarmmgr_add_alarm_appsvc_with_localtime(alarm_info, bundle_data, alarm_id); + + alarmmgr_free_alarm(alarm_info); + return convert_error_code_to_alarm(__FUNCTION__, result); +} + +int alarm_get_scheduled_recurrence_week_flag(int alarm_id, int *week_flag) +{ + alarm_error_t result; + alarm_entry_t *entry = NULL; + alarm_repeat_mode_t mode; + int value; + + if(week_flag == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", ALARM_ERROR_INVALID_PARAMETER); + return ALARM_ERROR_INVALID_PARAMETER; + } + + entry = alarmmgr_create_alarm(); + + result = alarmmgr_get_info(alarm_id, entry); + if(result != ALARMMGR_RESULT_SUCCESS) + { + if (entry != NULL) + { + alarmmgr_free_alarm(entry); + } + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + result = alarmmgr_get_repeat_mode(entry, &mode, &value); + + if(mode != ALARM_REPEAT_MODE_WEEKLY) + { + if (entry != NULL) + { + alarmmgr_free_alarm(entry); + } + return ALARM_ERROR_INVALID_PARAMETER; + } + + if(result != ALARMMGR_RESULT_SUCCESS) + { + if (entry != NULL) + { + alarmmgr_free_alarm(entry); + } + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + result = alarmmgr_free_alarm(entry); + if(result != ALARMMGR_RESULT_SUCCESS) + { + if (entry != NULL) + { + alarmmgr_free_alarm(entry); + } + return convert_error_code_to_alarm(__FUNCTION__, result); + } + + (*week_flag) = value; + + return ALARM_ERROR_NONE; +} + +int alarm_get_service(int alarm_id, service_h *service) +{ + bundle *b = NULL; + int error_code = 0; + + b = alarmmgr_get_alarm_appsvc_info(alarm_id, &error_code); + + if(error_code != ALARMMGR_RESULT_SUCCESS) + { + return convert_error_code_to_alarm(__FUNCTION__, error_code); + } + + if(b == NULL) + { + return ALARM_ERROR_INVALID_PARAMETER; + } + + error_code = service_create_request(b, service); + + if(error_code != SERVICE_ERROR_NONE) + { + return ALARM_ERROR_OUT_OF_MEMORY; + } + + bundle_free(b); + + return ALARM_ERROR_NONE; + +} diff --git a/src/app_device.c b/src/app_device.c new file mode 100755 index 0000000..8b6215d --- /dev/null +++ b/src/app_device.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <bundle.h> +#include <appcore-common.h> +#include <aul.h> +#include <dlog.h> +#include <vconf.h> + +#include <app_private.h> +#include <app_service_private.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION" + +app_device_orientation_e app_convert_appcore_rm(enum appcore_rm rm) +{ + app_device_orientation_e dev_orientation; + + switch (rm) + { + case APPCORE_RM_PORTRAIT_NORMAL: + dev_orientation = APP_DEVICE_ORIENTATION_0; + break; + + case APPCORE_RM_PORTRAIT_REVERSE: + dev_orientation = APP_DEVICE_ORIENTATION_180; + break; + + case APPCORE_RM_LANDSCAPE_NORMAL: + dev_orientation = APP_DEVICE_ORIENTATION_270; + break; + + case APPCORE_RM_LANDSCAPE_REVERSE: + dev_orientation = APP_DEVICE_ORIENTATION_90; + break; + + default: + dev_orientation = APP_DEVICE_ORIENTATION_0; + break; + } + + return dev_orientation; +} + +app_device_orientation_e app_get_device_orientation(void) +{ + enum appcore_rm rm; + app_device_orientation_e dev_orientation = APP_DEVICE_ORIENTATION_0; + + if (appcore_get_rotation_state(&rm) == 0) + { + dev_orientation = app_convert_appcore_rm(rm); + } + + return dev_orientation; +} + diff --git a/src/app_error.c b/src/app_error.c new file mode 100755 index 0000000..b3c8c0c --- /dev/null +++ b/src/app_error.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libintl.h> + +#include <dlog.h> + +#include <app_private.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION" + +static const char* app_error_to_string(app_error_e error) +{ + switch (error) + { + case APP_ERROR_NONE: + return "NONE"; + + case APP_ERROR_INVALID_PARAMETER: + return "INVALID_PARAMETER"; + + case APP_ERROR_OUT_OF_MEMORY: + return "OUT_OF_MEMORY"; + + case APP_ERROR_INVALID_CONTEXT: + return "INVALID_CONTEXT"; + + case APP_ERROR_NO_SUCH_FILE: + return "NO_SUCH_FILE"; + + case APP_ERROR_ALREADY_RUNNING: + return "ALREADY_RUNNING"; + + default : + return "UNKNOWN"; + } +} + +int app_error(app_error_e error, const char* function, const char *description) +{ + if (description) + { + LOGE("[%s] %s(0x%08x) : %s", function, app_error_to_string(error), error, description); + } + else + { + LOGE("[%s] %s(0x%08x)", function, app_error_to_string(error), error); + } + + return error; +} diff --git a/src/app_finalizer.c b/src/app_finalizer.c new file mode 100755 index 0000000..ae0b41c --- /dev/null +++ b/src/app_finalizer.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libintl.h> + +#include <app_private.h> + +typedef struct _app_finalizer_s_ { + app_finalizer_cb callback; + void *data; + struct _app_finalizer_s_ *next; +} app_finalizer_s; + +typedef app_finalizer_s *app_finalizer_h; + +static app_finalizer_s finalizer_head = { + .callback = NULL, + .data = NULL, + .next = NULL +}; + +int app_finalizer_add(app_finalizer_cb callback, void *data) +{ + app_finalizer_h finalizer_tail = &finalizer_head; + app_finalizer_h finalizer_new; + + finalizer_new = malloc(sizeof(app_finalizer_s)); + + if (finalizer_new == NULL) + { + return app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + } + + finalizer_new->callback = callback; + finalizer_new->data = data; + finalizer_new->next = NULL; + + while (finalizer_tail->next) + { + finalizer_tail = finalizer_tail->next; + } + + finalizer_tail->next = finalizer_new; + + return APP_ERROR_NONE; +} + +int app_finalizer_remove(app_finalizer_cb callback) +{ + app_finalizer_h finalizer_node = &finalizer_head; + + while (finalizer_node->next) + { + if (finalizer_node->next->callback == callback) + { + app_finalizer_h removed_node = finalizer_node->next; + finalizer_node->next = removed_node->next; + free(removed_node); + return APP_ERROR_NONE; + } + + finalizer_node = finalizer_node->next; + } + + return APP_ERROR_INVALID_PARAMETER; +} + +void app_finalizer_execute(void) +{ + app_finalizer_h finalizer_node = &finalizer_head; + app_finalizer_h finalizer_executed; + app_finalizer_cb finalizer_cb = NULL; + + if(finalizer_node) + finalizer_node = finalizer_node->next; + + while (finalizer_node) + { + finalizer_cb = finalizer_node->callback; + + finalizer_cb(finalizer_node->data); + + finalizer_executed = finalizer_node; + + finalizer_node = finalizer_node->next; + + free(finalizer_executed); + } + + finalizer_head.next = NULL; +} + diff --git a/src/app_main.c b/src/app_main.c new file mode 100755 index 0000000..81f4f5e --- /dev/null +++ b/src/app_main.c @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <bundle.h> +#include <appcore-common.h> +#include <appcore-efl.h> +#include <aul.h> +#include <dlog.h> + +#include <Elementary.h> + +#include <app_private.h> +#include <app_service_private.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION" + +typedef enum { + APP_STATE_NOT_RUNNING, // The application has been launched or was running but was terminated + APP_STATE_CREATING, // The application is initializing the resources on app_create_cb callback + APP_STATE_RUNNING, // The application is running in the foreground and background +} app_state_e; + +typedef struct { + char *package; + char *app_name; + app_state_e state; + app_event_callback_s *callback; + void *data; +} app_context_s; + +typedef app_context_s *app_context_h; + +static int app_appcore_create(void *data); +static int app_appcore_pause(void *data); +static int app_appcore_resume(void *data); +static int app_appcore_terminate(void *data); +static int app_appcore_reset(bundle *appcore_bundle, void *data); + +static int app_appcore_low_memory(void *data); +static int app_appcore_low_battery(void *data); +static int app_appcore_rotation_event(enum appcore_rm rm, void *data); +static int app_appcore_lang_changed(void *data); +static int app_appcore_region_changed(void *data); + +static void app_set_appcore_event_cb(app_context_h app_context); +static void app_unset_appcore_event_cb(void); + + +int app_efl_main(int *argc, char ***argv, app_event_callback_s *callback, void *user_data) +{ + app_context_s app_context = { + .package = NULL, + .app_name = NULL, + .state = APP_STATE_NOT_RUNNING, + .callback = callback, + .data = user_data + }; + + struct appcore_ops appcore_context = { + .data = &app_context, + .create = app_appcore_create, + .terminate = app_appcore_terminate, + .pause = app_appcore_pause, + .resume = app_appcore_resume, + .reset = app_appcore_reset, + }; + + if (argc == NULL || argv == NULL || callback == NULL) + { + return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (callback->create == NULL) + { + return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "app_create_cb() callback must be registered"); + } + + if (app_context.state != APP_STATE_NOT_RUNNING) + { + return app_error(APP_ERROR_ALREADY_RUNNING, __FUNCTION__, NULL); + } + + if (app_get_id(&(app_context.package)) != APP_ERROR_NONE) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package"); + } + + if (app_get_package_app_name(app_context.package, &(app_context.app_name)) != APP_ERROR_NONE) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package's app name"); + } + + app_context.state = APP_STATE_CREATING; + + appcore_efl_main(app_context.app_name, argc, argv, &appcore_context); + + free(app_context.package); + free(app_context.app_name); + + return APP_ERROR_NONE; +} + + +void app_efl_exit(void) +{ + elm_exit(); +} + + +int app_appcore_create(void *data) +{ + app_context_h app_context = data; + app_create_cb create_cb; + char locale_dir[TIZEN_PATH_MAX] = {0, }; + + if (app_context == NULL) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + app_set_appcore_event_cb(app_context); + + snprintf(locale_dir, TIZEN_PATH_MAX, PATH_FMT_LOCALE_DIR, app_context->package); + if (access(locale_dir, R_OK) != 0) { + snprintf(locale_dir, TIZEN_PATH_MAX, PATH_FMT_RO_LOCALE_DIR, app_context->package); + } + appcore_set_i18n(app_context->app_name, locale_dir); + + create_cb = app_context->callback->create; + + if (create_cb == NULL || create_cb(app_context->data) == false) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "app_create_cb() returns false"); + } + + app_context->state = APP_STATE_RUNNING; + + return APP_ERROR_NONE; +} + +int app_appcore_terminate(void *data) +{ + app_context_h app_context = data; + app_terminate_cb terminate_cb; + + if (app_context == NULL) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + terminate_cb = app_context->callback->terminate; + + if (terminate_cb != NULL) + { + terminate_cb(app_context->data); + } + + app_unset_appcore_event_cb(); + + app_finalizer_execute(); + + return APP_ERROR_NONE; +} + +int app_appcore_pause(void *data) +{ + app_context_h app_context = data; + app_pause_cb pause_cb; + + if (app_context == NULL) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + pause_cb = app_context->callback->pause; + + if (pause_cb != NULL) + { + pause_cb(app_context->data); + } + + return APP_ERROR_NONE; +} + +int app_appcore_resume(void *data) +{ + app_context_h app_context = data; + app_resume_cb resume_cb; + + if (app_context == NULL) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + resume_cb = app_context->callback->resume; + + if (resume_cb != NULL) + { + resume_cb(app_context->data); + } + + return APP_ERROR_NONE; +} + + +int app_appcore_reset(bundle *appcore_bundle, void *data) +{ + app_context_h app_context = data; + app_service_cb service_cb; + service_h service; + + if (app_context == NULL) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + if (service_create_event(appcore_bundle, &service) != APP_ERROR_NONE) + { + return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create a service handle from the bundle"); + } + + service_cb = app_context->callback->service; + + if (service_cb != NULL) + { + service_cb(service, app_context->data); + } + + service_destroy(service); + + return APP_ERROR_NONE; +} + + +int app_appcore_low_memory(void *data) +{ + app_context_h app_context = data; + app_low_memory_cb low_memory_cb; + + if (app_context == NULL) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + low_memory_cb = app_context->callback->low_memory; + + if (low_memory_cb != NULL) + { + low_memory_cb(app_context->data); + } + + return APP_ERROR_NONE; +} + +int app_appcore_low_battery(void *data) +{ + app_context_h app_context = data; + app_low_battery_cb low_battery_cb; + + if (app_context == NULL) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + low_battery_cb = app_context->callback->low_battery; + + if (low_battery_cb != NULL) + { + low_battery_cb(app_context->data); + } + + return APP_ERROR_NONE; +} + +int app_appcore_rotation_event(enum appcore_rm rm, void *data) +{ + app_context_h app_context = data; + app_device_orientation_cb device_orientation_cb; + + if (app_context == NULL) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + device_orientation_cb = app_context->callback->device_orientation; + + if (device_orientation_cb != NULL) + { + app_device_orientation_e dev_orientation; + + dev_orientation = app_convert_appcore_rm(rm); + + device_orientation_cb(dev_orientation, app_context->data); + } + + return APP_ERROR_NONE; +} + +int app_appcore_lang_changed(void *data) +{ + app_context_h app_context = data; + app_language_changed_cb lang_changed_cb; + + if (app_context == NULL) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + lang_changed_cb = app_context->callback->language_changed; + + if (lang_changed_cb != NULL) + { + lang_changed_cb(app_context->data); + } + + return APP_ERROR_NONE; +} + +int app_appcore_region_changed(void *data) +{ + app_context_h app_context = data; + app_region_format_changed_cb region_changed_cb; + + if (app_context == NULL) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + region_changed_cb = app_context->callback->region_format_changed; + + if (region_changed_cb != NULL) + { + region_changed_cb(app_context->data); + } + + return APP_ERROR_NONE; +} + + +void app_set_appcore_event_cb(app_context_h app_context) +{ + if (app_context->callback->low_memory != NULL) + { + appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, app_appcore_low_memory, app_context); + } + + if (app_context->callback->low_battery != NULL) + { + appcore_set_event_callback(APPCORE_EVENT_LOW_BATTERY, app_appcore_low_battery, app_context); + } + + if (app_context->callback->device_orientation != NULL) + { + appcore_set_rotation_cb(app_appcore_rotation_event, app_context); + } + + if (app_context->callback->language_changed != NULL) + { + appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, app_appcore_lang_changed, app_context); + } + + if (app_context->callback->region_format_changed != NULL) + { + appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, app_appcore_region_changed, app_context); + } +} + +void app_unset_appcore_event_cb(void) +{ + appcore_set_event_callback(APPCORE_EVENT_LOW_MEMORY, NULL, NULL); + appcore_set_event_callback(APPCORE_EVENT_LOW_BATTERY, NULL, NULL); + appcore_unset_rotation_cb(); + appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE, NULL, NULL); + appcore_set_event_callback(APPCORE_EVENT_REGION_CHANGE, NULL, NULL); +} diff --git a/src/app_package.c b/src/app_package.c new file mode 100755 index 0000000..56893a1 --- /dev/null +++ b/src/app_package.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <bundle.h> +#include <appcore-common.h> +#include <aul.h> +#include <ail.h> +#include <dlog.h> + +#include <app_private.h> +#include <app_service_private.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION" + +int app_get_package_app_name(const char *appid, char **name) +{ + char *name_token = NULL; + + if (appid == NULL) + { + return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + // com.vendor.name -> name + name_token = strrchr(appid, '.'); + + if (name_token == NULL) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL); + } + + name_token++; + + *name = strdup(name_token); + + if (*name == NULL) + { + return app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + } + + return APP_ERROR_NONE; +} + +int app_get_package(char **package) +{ + return app_get_id(package); +} + +int app_get_id(char **id) +{ + static char id_buf[TIZEN_PATH_MAX] = {0, }; + int ret = -1; + + if (id == NULL) + { + return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (id_buf[0] == '\0') + { + ret = aul_app_get_appid_bypid(getpid(), id_buf, sizeof(id_buf)); + if (ret < 0) { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the application ID"); + } + } + + if (id_buf[0] == '\0') + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the application ID"); + } + + *id = strdup(id_buf); + + if (*id == NULL) + { + return app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + } + + return APP_ERROR_NONE; +} + +static int app_get_appinfo(const char *package, const char *property, char **value) +{ + ail_appinfo_h appinfo; + char *appinfo_value; + char *appinfo_value_dup; + + if (ail_get_appinfo(package, &appinfo) != 0) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get app-info"); + } + + if (ail_appinfo_get_str(appinfo, property, &appinfo_value) != 0) + { + ail_destroy_appinfo(appinfo); + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get app-property"); + } + + appinfo_value_dup = strdup(appinfo_value); + + ail_destroy_appinfo(appinfo); + + if (appinfo_value_dup == NULL) + { + return app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + } + + *value = appinfo_value_dup; + + return APP_ERROR_NONE; +} + +int app_get_name(char **name) +{ + char *package = NULL; + int retval; + + if(name == NULL) + { + return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (app_get_id(&package) != 0) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package"); + } + + retval = app_get_appinfo(package, AIL_PROP_NAME_STR, name); + + if (package != NULL) + { + free(package); + } + + return retval; +} + +int app_get_version(char **version) +{ + char *package; + int retval; + + if(version == NULL) + { + return app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (app_get_id(&package) != 0) + { + return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package"); + } + + retval = app_get_appinfo(package, AIL_PROP_VERSION_STR, version); + + if (package != NULL) + { + free(package); + } + + return retval; +} + diff --git a/src/app_resource.c b/src/app_resource.c new file mode 100755 index 0000000..a3c2da5 --- /dev/null +++ b/src/app_resource.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <bundle.h> +#include <appcore-common.h> +#include <appcore-efl.h> +#include <aul.h> +#include <dlog.h> +#include <ail.h> + +#include <app_private.h> +#include <app_service_private.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION" + +static const char *INSTALLED_PATH = "/opt/usr/apps"; +static const char *RO_INSTALLED_PATH = "/usr/apps"; +static const char *RES_DIRECTORY_NAME = "res"; +static const char *DATA_DIRECTORY_NAME = "data"; + +static char * app_get_root_directory(char *buffer, int size) +{ + char *appid = NULL; + char root_directory[TIZEN_PATH_MAX] = {0, }; + char bin_directory[TIZEN_PATH_MAX] = {0, }; + ail_appinfo_h ail_app_info; + char *pkgid; + + if (app_get_id(&appid) != APP_ERROR_NONE) + { + app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the appid"); + return NULL; + } + + if (ail_get_appinfo(appid, &ail_app_info) != AIL_ERROR_OK) + { + app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the appinfo"); + free(appid); + return NULL; + } + + if (ail_appinfo_get_str(ail_app_info, AIL_PROP_X_SLP_PKGID_STR, &pkgid) != AIL_ERROR_OK) + { + app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the pkgid"); + free(appid); + ail_destroy_appinfo(ail_app_info); + return NULL; + } + + if(pkgid) + { + free(appid); + appid = strdup(pkgid); + } + + ail_destroy_appinfo(ail_app_info); + + snprintf(root_directory, sizeof(root_directory), "%s/%s", INSTALLED_PATH, appid); + snprintf(bin_directory, sizeof(bin_directory), "%s/bin", root_directory); + + if (access(bin_directory, R_OK) != 0) { + snprintf(root_directory, sizeof(root_directory), "%s/%s", RO_INSTALLED_PATH, appid); + } + + free(appid); + + if (size < strlen(root_directory)+1) + { + app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "the buffer is not big enough"); + return NULL; + } + + snprintf(buffer, size, "%s", root_directory); + + return buffer; +} + +static char* app_get_resource_directory(char *buffer, int size) +{ + char root_directory[TIZEN_PATH_MAX] = {0, }; + char resource_directory[TIZEN_PATH_MAX] = {0, }; + + if (app_get_root_directory(root_directory, sizeof(root_directory)) == NULL) + { + app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the root directory of the application"); + return NULL; + } + + snprintf(resource_directory, sizeof(resource_directory), "%s/%s", root_directory, RES_DIRECTORY_NAME); + + if (size < strlen(resource_directory) +1) + { + app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "the buffer is not big enough"); + return NULL; + } + + snprintf(buffer, size, "%s", resource_directory); + + return buffer; +} + +char* app_get_data_directory(char *buffer, int size) +{ + static char data_directory[TIZEN_PATH_MAX] = {0, }; + static int data_directory_length = 0; + ail_appinfo_h ail_app_info; + char *pkgid; + + if (data_directory[0] == '\0') + { + char *root_directory = NULL; + char *appid = NULL; + + root_directory = calloc(1, TIZEN_PATH_MAX); + + if (root_directory == NULL) + { + app_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + return NULL; + } + + if (app_get_id(&appid) != APP_ERROR_NONE) + { + app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package"); + free(root_directory); + return NULL; + } + + if (ail_get_appinfo(appid, &ail_app_info) != AIL_ERROR_OK) + { + app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package"); + free(root_directory); + free(appid); + return NULL; + } + + if (ail_appinfo_get_str(ail_app_info, AIL_PROP_X_SLP_PKGID_STR, &pkgid) != AIL_ERROR_OK) + { + app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the package"); + free(root_directory); + free(appid); + ail_destroy_appinfo(ail_app_info); + return NULL; + } + + if(pkgid) + { + free(appid); + appid = strdup(pkgid); + } + + ail_destroy_appinfo(ail_app_info); + + snprintf(root_directory, TIZEN_PATH_MAX, "%s/%s", INSTALLED_PATH, appid); + + free(appid); + + snprintf(data_directory, sizeof(data_directory), "%s/%s", root_directory, DATA_DIRECTORY_NAME); + + data_directory_length = strlen(data_directory); + + free(root_directory); + } + + if (size < data_directory_length+1) + { + app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "the buffer is not big enough"); + return NULL; + } + + snprintf(buffer, size, "%s", data_directory); + + return buffer; +} + +char* app_get_resource(const char *resource, char *buffer, int size) +{ + static char resource_directory[TIZEN_PATH_MAX] = {0, }; + static int resource_directory_length = 0; + + int resource_path_length = 0; + + if (resource == NULL) + { + app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + return NULL; + } + + if (buffer == NULL || size <= 0) + { + app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + return NULL; + } + + if (resource_directory[0] == '\0') + { + if (app_get_resource_directory(resource_directory, sizeof(resource_directory)) == NULL) + { + app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "failed to get the path to the resource directory"); + return NULL; + } + + resource_directory_length = strlen(resource_directory); + } + + resource_path_length = resource_directory_length + strlen("/") + strlen(resource); + + if (size < resource_path_length+1) + { + app_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "the buffer is not big enough"); + return NULL; + } + + snprintf(buffer, size, "%s/%s", resource_directory, resource); + + return buffer; +} + + +void app_set_reclaiming_system_cache_on_pause(bool enable) +{ + appcore_set_system_resource_reclaiming(enable); +} + diff --git a/src/i18n.c b/src/i18n.c new file mode 100755 index 0000000..a1ca9e3 --- /dev/null +++ b/src/i18n.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libintl.h> + +#include <app_i18n.h> + +char* i18n_get_text(const char *message) +{ + return gettext(message); +} + diff --git a/src/preference.c b/src/preference.c new file mode 100755 index 0000000..ad85562 --- /dev/null +++ b/src/preference.c @@ -0,0 +1,758 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sqlite3.h> + +#include <app_private.h> + +#include <app_preference.h> +#include <app_preference_private.h> + +#include <dlog.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION_PREFERENCE" +#define DBG_MODE (1) + +static sqlite3 *pref_db = NULL; +static bool is_update_hook_registered = false; +static pref_changed_cb_node_t *head = NULL; + +static void _finish(void *data) +{ + if (pref_db != NULL) + { + sqlite3_close(pref_db); + pref_db = NULL; + } +} + +static int _initialize(void) +{ + char data_path[TIZEN_PATH_MAX] = {0, }; + char db_path[TIZEN_PATH_MAX] = {0, }; + int ret; + char *errmsg; + + if (app_get_data_directory(data_path, sizeof(data_path)) == NULL) + { + LOGE("IO_ERROR(0x%08x) : fail to get data directory", PREFERENCE_ERROR_IO_ERROR); + return PREFERENCE_ERROR_IO_ERROR; + } + snprintf(db_path, sizeof(db_path), "%s/%s", data_path, PREF_DB_NAME); + + ret = sqlite3_open(db_path, &pref_db); + if (ret != SQLITE_OK) + { + LOGE("IO_ERROR(0x%08x) : fail to open db(%s)", PREFERENCE_ERROR_IO_ERROR, sqlite3_errmsg(pref_db)); + pref_db = NULL; + return PREFERENCE_ERROR_IO_ERROR; + } + + ret = sqlite3_exec(pref_db, "CREATE TABLE IF NOT EXISTS pref ( pref_key TEXT PRIMARY KEY, pref_type TEXT, pref_data TEXT)", + NULL, NULL, &errmsg); + if (ret != SQLITE_OK) + { + LOGE("IO_ERROR(0x%08x) : fail to create db table(%s)", PREFERENCE_ERROR_IO_ERROR, errmsg); + sqlite3_free(errmsg); + sqlite3_close(pref_db); + pref_db = NULL; + return PREFERENCE_ERROR_IO_ERROR; + } + + app_finalizer_add(_finish, NULL); + + return PREFERENCE_ERROR_NONE; +} + +//static int _write_data(const char *key, preference_type_e type, const char *data) +static int _write_data(const char *key, const char *type, const char *data) +{ + int ret; + char *buf; + char *errmsg; + bool exist = false; + + if (key == NULL || key[0] == '\0' || data == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER); + return PREFERENCE_ERROR_INVALID_PARAMETER; + } + + /* insert data or update data if data already exist */ + ret = preference_is_existing(key, &exist); + if (ret != PREFERENCE_ERROR_NONE) + { + return ret; + } + + // to use sqlite3_update_hook, we have to use INSERT/UPDATE operation instead of REPLACE operation + if (exist) + { + buf = sqlite3_mprintf("UPDATE %s SET %s='%s', %s='%s' WHERE %s='%s';", + PREF_TBL_NAME, PREF_F_TYPE_NAME, type, PREF_F_DATA_NAME, data, PREF_F_KEY_NAME, key); + } + else + { + buf = sqlite3_mprintf("INSERT INTO %s (%s, %s, %s) values ('%q', '%q', '%q');", + PREF_TBL_NAME, PREF_F_KEY_NAME, PREF_F_TYPE_NAME, PREF_F_DATA_NAME, key, type, data); + } + + if (buf == NULL) + { + LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR); + return PREFERENCE_ERROR_IO_ERROR; + } + + ret = sqlite3_exec(pref_db, buf, NULL, NULL, &errmsg); + sqlite3_free(buf); + if (ret != SQLITE_OK) + { + LOGE("IO_ERROR(0x%08x): fail to write data(%s)", PREFERENCE_ERROR_IO_ERROR, errmsg); + sqlite3_free(errmsg); + return PREFERENCE_ERROR_IO_ERROR; + } + + return PREFERENCE_ERROR_NONE; +} + +//static int _read_data(const char *key, preference_type_e *type, char *data) +static int _read_data(const char *key, char *type, char *data) +{ + int ret; + char *buf; + char **result; + int rows; + int columns; + char *errmsg; + + if (key == NULL || key[0] == '\0' || data == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER); + return PREFERENCE_ERROR_INVALID_PARAMETER; + } + + if (pref_db == NULL) + { + if (_initialize() != PREFERENCE_ERROR_NONE) + { + LOGE("IO_ERROR(0x%08x) : fail to initialize db", PREFERENCE_ERROR_IO_ERROR); + return PREFERENCE_ERROR_IO_ERROR; + } + } + + buf = sqlite3_mprintf("SELECT %s, %s, %s FROM %s WHERE %s='%q';", + PREF_F_KEY_NAME, PREF_F_TYPE_NAME, PREF_F_DATA_NAME, PREF_TBL_NAME, PREF_F_KEY_NAME, key); + + if (buf == NULL) + { + LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR); + return PREFERENCE_ERROR_IO_ERROR; + } + + ret = sqlite3_get_table(pref_db, buf, &result, &rows, &columns, &errmsg); + sqlite3_free(buf); + if (ret != SQLITE_OK) + { + LOGE("IO_ERROR(0x%08x) : fail to read data (%s)", PREFERENCE_ERROR_IO_ERROR, errmsg); + sqlite3_free(errmsg); + return PREFERENCE_ERROR_IO_ERROR; + } + + if (rows == 0) + { + LOGE("NO_KEY(0x%08x) : fail to find given key(%s)", PREFERENCE_ERROR_NO_KEY, key); + sqlite3_free_table(result); + return PREFERENCE_ERROR_NO_KEY; + } + + snprintf(type, 2, "%s", result[4]); // get type value + snprintf(data, BUF_LEN, "%s", result[5]); // get data value + + sqlite3_free_table(result); + + return PREFERENCE_ERROR_NONE; +} + + +int preference_set_int(const char *key, int value) +{ + char type[2]; + char data[BUF_LEN]; + snprintf(type, 2, "%d", PREFERENCE_TYPE_INT); + snprintf(data, BUF_LEN, "%d", value); + return _write_data(key, type, data); +} + +int preference_get_int(const char *key, int *value) +{ + char type[2]; + char data[BUF_LEN]; + int ret; + + ret = _read_data(key, type, data); + if (ret == PREFERENCE_ERROR_NONE) + { + if (atoi(type) == PREFERENCE_TYPE_INT) + { + *value = atoi(data); + } + else + { + LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type)); + return PREFERENCE_ERROR_INVALID_PARAMETER; + } + } + + return ret; +} + +int preference_set_double(const char *key, double value) +{ + char type[2]; + char data[BUF_LEN]; + snprintf(type, 2, "%d", PREFERENCE_TYPE_DOUBLE); + snprintf(data, BUF_LEN, "%f", value); + return _write_data(key, type, data); +} + +int preference_get_double(const char *key, double *value) +{ + char type[2]; + char data[BUF_LEN]; + + int ret; + + ret = _read_data(key, type, data); + if (ret == PREFERENCE_ERROR_NONE) + { + if (atoi(type) == PREFERENCE_TYPE_DOUBLE) + { + *value = atof(data); + } + else + { + LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type)); + return PREFERENCE_ERROR_INVALID_PARAMETER; + } + } + + return ret; +} + +int preference_set_string(const char *key, const char *value) +{ + char type[2]; + + snprintf(type, 2, "%d", PREFERENCE_TYPE_STRING); + if (strlen(value) > (BUF_LEN-1)) + { + LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type)); + return PREFERENCE_ERROR_INVALID_PARAMETER; + } + return _write_data(key, type, value); +} + +int preference_get_string(const char *key, char **value) +{ + char type[2]; + char data[BUF_LEN]; + + int ret; + + if (value == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER); + return PREFERENCE_ERROR_INVALID_PARAMETER; + } + + ret = _read_data(key, type, data); + if (ret == PREFERENCE_ERROR_NONE) + { + if (atoi(type) == PREFERENCE_TYPE_STRING) + { + *value = strdup(data); + if (value == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", PREFERENCE_ERROR_OUT_OF_MEMORY); + return PREFERENCE_ERROR_OUT_OF_MEMORY; + } + } + else + { + LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type)); + return PREFERENCE_ERROR_INVALID_PARAMETER; + } + } + + return ret; +} + +int preference_set_boolean(const char *key, bool value) +{ + char type[2]; + char data[BUF_LEN]; + snprintf(type, 2, "%d", PREFERENCE_TYPE_BOOLEAN); + snprintf(data, BUF_LEN, "%d", value); + return _write_data(key, type, data); +} + +int preference_get_boolean(const char *key, bool *value) +{ + char type[2]; + char data[BUF_LEN]; + + int ret; + + ret = _read_data(key, type, data); + if (ret == PREFERENCE_ERROR_NONE) + { + if (atoi(type) == PREFERENCE_TYPE_BOOLEAN) + { + *value = (bool)atoi(data); + } + else + { + LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type)); + return PREFERENCE_ERROR_INVALID_PARAMETER; + } + } + + return ret; +} + + +// TODO: below operation is too heavy, let's find the light way to check. +int preference_is_existing(const char *key, bool *exist) +{ + int ret; + char *buf; + char **result; + int rows; + int columns; + char *errmsg; + + if (key == NULL || key[0] == '\0' || exist == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER); + return PREFERENCE_ERROR_INVALID_PARAMETER; + } + + if (pref_db == NULL) + { + if (_initialize() != PREFERENCE_ERROR_NONE) + { + LOGE("IO_ERROR(0x%08x) : fail to initialize db", PREFERENCE_ERROR_IO_ERROR); + return PREFERENCE_ERROR_IO_ERROR; + } + } + + /* check data is exist */ + buf = sqlite3_mprintf("SELECT %s FROM %s WHERE %s='%q';", PREF_F_KEY_NAME, PREF_TBL_NAME, PREF_F_KEY_NAME, key); + + if (buf == NULL) + { + LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR); + return PREFERENCE_ERROR_IO_ERROR; + } + + ret = sqlite3_get_table(pref_db, buf, &result, &rows, &columns, &errmsg); + sqlite3_free(buf); + if (ret != SQLITE_OK) + { + LOGE("IO_ERROR(0x%08x) : fail to read data(%s)", PREFERENCE_ERROR_IO_ERROR, errmsg); + sqlite3_free(errmsg); + return PREFERENCE_ERROR_IO_ERROR; + } + + if (rows > 0) + { + *exist = true; + } + else + { + *exist = false; + } + + sqlite3_free_table(result); + return PREFERENCE_ERROR_NONE; +} + +static pref_changed_cb_node_t* _find_node(const char *key) +{ + pref_changed_cb_node_t *tmp_node; + + if (key == NULL || key[0] == '\0' ) + { + return NULL; + } + + tmp_node = head; + + while (tmp_node) + { + if (strcmp(tmp_node->key, key) == 0) + { + break; + } + tmp_node = tmp_node->next; + } + + return tmp_node; +} + + +static int _add_node(const char *key, preference_changed_cb cb, void *user_data) +{ + pref_changed_cb_node_t *tmp_node; + + if (key == NULL || key[0] == '\0' || cb == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER); + return PREFERENCE_ERROR_INVALID_PARAMETER; + } + + tmp_node = _find_node(key); + + if (tmp_node != NULL) + { + tmp_node->cb = cb; + tmp_node->user_data = user_data; + } + else + { + tmp_node = (pref_changed_cb_node_t*)malloc(sizeof(pref_changed_cb_node_t)); + if (tmp_node == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", PREFERENCE_ERROR_OUT_OF_MEMORY); + return PREFERENCE_ERROR_OUT_OF_MEMORY; + } + + tmp_node->key = strdup(key); + if (tmp_node->key == NULL) + { + free(tmp_node); + LOGE("OUT_OF_MEMORY(0x%08x)", PREFERENCE_ERROR_OUT_OF_MEMORY); + return PREFERENCE_ERROR_OUT_OF_MEMORY; + } + tmp_node->cb = cb; + tmp_node->user_data = user_data; + tmp_node->prev = NULL; + tmp_node->next = head; + head = tmp_node; + } + + return PREFERENCE_ERROR_NONE; +} + +static int _remove_node(const char *key) +{ + pref_changed_cb_node_t *tmp_node; + + if (key == NULL || key[0] == '\0' ) + { + LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER); + return PREFERENCE_ERROR_INVALID_PARAMETER; + } + + tmp_node = _find_node(key); + + if (tmp_node == NULL) + { + return PREFERENCE_ERROR_NONE; + } + + if (tmp_node->prev != NULL) + { + tmp_node->prev->next = tmp_node->next; + } + else + { + head = tmp_node->next; + } + + if (tmp_node->next != NULL) + { + tmp_node->next->prev = tmp_node->prev; + } + + if (tmp_node->key) + { + free(tmp_node->key); + } + + free(tmp_node); + + return PREFERENCE_ERROR_NONE; +} + + +static void _remove_all_node(void) +{ + pref_changed_cb_node_t *tmp_node; + + while (head) + { + tmp_node = head; + head = tmp_node->next; + + if (tmp_node->key) + { + free(tmp_node->key); + } + + free(tmp_node); + } +} + + +static void _update_cb(void *data, int action, char const *db_name, char const *table_name, sqlite_int64 rowid) +{ + int ret; + char *buf; + char **result; + int rows; + int columns; + char *errmsg; + pref_changed_cb_node_t *tmp_node; + + // skip INSERT/DELETE event + if (action != SQLITE_UPDATE) + { + return; + } + + if (strcmp(table_name, PREF_TBL_NAME) != 0) + { + LOGI("given table name (%s) is not same", table_name); + return; + } + + buf = sqlite3_mprintf("SELECT %s FROM %s WHERE rowid='%lld';", PREF_F_KEY_NAME, PREF_TBL_NAME, rowid); + if (buf == NULL) + { + return; + } + ret = sqlite3_get_table(pref_db, buf, &result, &rows, &columns, &errmsg); + sqlite3_free(buf); + if (ret != SQLITE_OK) + { + LOGI("fail to read data(%s)", errmsg); + sqlite3_free(errmsg); + return; + } + + if (rows == 0) + { + sqlite3_free_table(result); + return; + } + + tmp_node = _find_node(result[1]); + + if (tmp_node != NULL && tmp_node->cb != NULL) + { + tmp_node->cb(result[1], tmp_node->user_data); + } + + sqlite3_free_table(result); +} + + +int preference_remove(const char *key) +{ + int ret; + char *buf; + char *errmsg; + bool exist; + + ret = preference_is_existing(key, &exist); + if (ret != PREFERENCE_ERROR_NONE) + { + return ret; + } + + if (!exist) + { + return PREFERENCE_ERROR_NONE; + } + + /* insert data or update data if data already exist */ + buf = sqlite3_mprintf("DELETE FROM %s WHERE %s = '%s';", + PREF_TBL_NAME, PREF_F_KEY_NAME, key); + + if (buf == NULL) + { + LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR); + return PREFERENCE_ERROR_IO_ERROR; + } + + ret = sqlite3_exec(pref_db, buf, NULL, NULL, &errmsg); + sqlite3_free(buf); + if (ret != SQLITE_OK) + { + LOGE("IO_ERROR(0x%08x) : fail to delete data (%s)", PREFERENCE_ERROR_IO_ERROR, errmsg); + sqlite3_free(errmsg); + return PREFERENCE_ERROR_IO_ERROR; + } + + // if exist, remove changed cb + _remove_node(key); + + return PREFERENCE_ERROR_NONE; +} + + +int preference_remove_all(void) +{ + int ret; + char *buf; + char *errmsg; + + if (pref_db == NULL) + { + if (_initialize() != PREFERENCE_ERROR_NONE) + { + LOGE("IO_ERROR(0x%08x) : fail to initialize db", PREFERENCE_ERROR_IO_ERROR); + return PREFERENCE_ERROR_IO_ERROR; + } + } + + /* insert data or update data if data already exist */ + buf = sqlite3_mprintf("DELETE FROM %s;", PREF_TBL_NAME); + if (buf == NULL) + { + LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR); + return PREFERENCE_ERROR_IO_ERROR; + } + + ret = sqlite3_exec(pref_db, buf, NULL, NULL, &errmsg); + sqlite3_free(buf); + if (ret != SQLITE_OK) + { + LOGE("IO_ERROR(0x%08x) : fail to delete data (%s)", PREFERENCE_ERROR_IO_ERROR, errmsg); + sqlite3_free(errmsg); + return PREFERENCE_ERROR_IO_ERROR; + } + + // if exist, remove changed cb + _remove_all_node(); + + return PREFERENCE_ERROR_NONE; +} + + +int preference_set_changed_cb(const char *key, preference_changed_cb callback, void *user_data) +{ + int ret; + bool exist; + + ret = preference_is_existing(key, &exist); + if (ret != PREFERENCE_ERROR_NONE) + { + return ret; + } + + if (!exist) + { + LOGE("NO_KEY(0x%08x) : fail to find given key(%s)", PREFERENCE_ERROR_NO_KEY, key); + return PREFERENCE_ERROR_NO_KEY; + } + + if (!is_update_hook_registered) + { + sqlite3_update_hook(pref_db, _update_cb, NULL); + is_update_hook_registered = true; + } + + return _add_node(key, callback, user_data); +} + +int preference_unset_changed_cb(const char *key) +{ + if (pref_db == NULL) + { + if (_initialize() != PREFERENCE_ERROR_NONE) + { + return PREFERENCE_ERROR_IO_ERROR; + } + } + + return _remove_node(key); +} + +int preference_foreach_item(preference_item_cb callback, void *user_data) +{ + int ret; + char *buf; + char **result; + int rows; + int columns; + char *errmsg; + int i; + + if (pref_db == NULL) + { + if (_initialize() != PREFERENCE_ERROR_NONE) + { + LOGE("IO_ERROR(0x%08x) : fail to initialize db", PREFERENCE_ERROR_IO_ERROR); + return PREFERENCE_ERROR_IO_ERROR; + } + } + + if (callback == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER); + return PREFERENCE_ERROR_INVALID_PARAMETER; + } + + buf = sqlite3_mprintf("SELECT %s FROM %s;", PREF_F_KEY_NAME, PREF_TBL_NAME); + if (buf == NULL) + { + LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR); + return PREFERENCE_ERROR_IO_ERROR; + } + + ret = sqlite3_get_table(pref_db, buf, &result, &rows, &columns, &errmsg); + sqlite3_free(buf); + if (ret != SQLITE_OK) + { + LOGE("IO_ERROR(0x%08x) : fail to read data (%s)", PREFERENCE_ERROR_IO_ERROR, errmsg); + sqlite3_free(errmsg); + return PREFERENCE_ERROR_IO_ERROR; + } + + for (i = 1; i <= rows; i++) + { + if (callback(result[i], user_data) != true) + { + break; + } + } + + sqlite3_free_table(result); + + return PREFERENCE_ERROR_NONE; +} + diff --git a/src/service.c b/src/service.c new file mode 100755 index 0000000..73196b1 --- /dev/null +++ b/src/service.c @@ -0,0 +1,1285 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <bundle.h> +#include <aul.h> +#include <appsvc.h> +#include <dlog.h> + +#include <app_service.h> +#include <app_service_private.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION_SERVICE" + +#ifndef TIZEN_PATH_MAX +#define TIZEN_PATH_MAX 1024 +#endif + +#define BUNDLE_KEY_PREFIX_AUL "__AUL_" +#define BUNDLE_KEY_PREFIX_SERVICE "__APP_SVC_" + +#define BUNDLE_KEY_OPERATION "__APP_SVC_OP_TYPE__" +#define BUNDLE_KEY_URI "__APP_SVC_URI__" +#define BUNDLE_KEY_MIME "__APP_SVC_MIME_TYPE__" +#define BUNDLE_KEY_DATA "__APP_SVC_DATA__" +#define BUNDLE_KEY_PACKAGE "__APP_SVC_PKG_NAME__" +#define BUNDLE_KEY_WINDOW "__APP_SVC_K_WIN_ID__" + + +typedef enum { + SERVICE_TYPE_REQUEST, + SERVICE_TYPE_EVENT, + SERVICE_TYPE_REPLY, +} service_type_e; + +struct service_s { + int id; + service_type_e type; + bundle *data; +}; + +typedef struct service_request_context_s { + service_h service; + service_reply_cb reply_cb; + void *user_data; +} *service_request_context_h; + +extern int appsvc_allow_transient_app(bundle *b, unsigned int id); + +static int service_create_reply(bundle *data, struct service_s **service); + +static const char* service_error_to_string(service_error_e error) +{ + switch (error) + { + case SERVICE_ERROR_NONE: + return "NONE"; + + case SERVICE_ERROR_INVALID_PARAMETER: + return "INVALID_PARAMETER"; + + case SERVICE_ERROR_OUT_OF_MEMORY: + return "OUT_OF_MEMORY"; + + case SERVICE_ERROR_APP_NOT_FOUND: + return "APP_NOT_FOUND"; + + case SERVICE_ERROR_KEY_NOT_FOUND: + return "KEY_NOT_FOUND"; + + case SERVICE_ERROR_KEY_REJECTED: + return "KEY_REJECTED"; + + case SERVICE_ERROR_INVALID_DATA_TYPE: + return "INVALID_DATA_TYPE"; + + case SERVICE_ERROR_LAUNCH_REJECTED: + return "LAUNCH_REJECTED"; + + default : + return "UNKNOWN"; + } +} + +int service_error(service_error_e error, const char* function, const char *description) +{ + if (description) + { + LOGE("[%s] %s(0x%08x) : %s", function, service_error_to_string(error), error, description); + } + else + { + LOGE("[%s] %s(0x%08x)", function, service_error_to_string(error), error); + } + + return error; +} + +static int service_validate_extra_data(const char *data) +{ + if (data == NULL || data[0] == '\0') + { + return SERVICE_ERROR_INVALID_PARAMETER; + } + + return SERVICE_ERROR_NONE; +} + +static int service_valiate_service(service_h service) +{ + if (service == NULL || service->data == NULL) + { + return SERVICE_ERROR_INVALID_PARAMETER; + } + + return SERVICE_ERROR_NONE; +} + +static int service_new_id() +{ + static int sid = 0; + return sid++; +} + +int service_validate_internal_key(const char *key) +{ + if (strncmp(BUNDLE_KEY_PREFIX_AUL, key, strlen(BUNDLE_KEY_PREFIX_AUL)) == 0) + { + return -1; + } + + if (strncmp(BUNDLE_KEY_PREFIX_SERVICE, key, strlen(BUNDLE_KEY_PREFIX_SERVICE)) == 0) + { + return -1; + } + + return 0; +} + +static void service_request_result_broker(bundle *appsvc_bundle, int appsvc_request_code, appsvc_result_val appsvc_result, void *appsvc_data) +{ + service_request_context_h request_context; + service_h request; + service_h reply = NULL; + service_result_e result; + void *user_data; + service_reply_cb reply_cb; + + if (appsvc_data == NULL) + { + service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid service reply"); + return; + } + + if (service_create_reply(appsvc_bundle, &reply) != 0) + { + service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create service reply"); + return; + } + + request_context = appsvc_data; + request = request_context->service; + + switch (appsvc_result) + { + case APPSVC_RES_OK: + result = SERVICE_RESULT_SUCCEEDED; + break; + + case APPSVC_RES_NOT_OK: + result = SERVICE_RESULT_FAILED; + break; + + case APPSVC_RES_CANCEL: + result = SERVICE_RESULT_CANCELED; + break; + + default: + result = SERVICE_RESULT_CANCELED; + break; + } + + user_data = request_context->user_data; + reply_cb = request_context->reply_cb; + + if (reply_cb != NULL) + { + reply_cb(request, reply, result, user_data); + } + else + { + service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid callback "); + } + + service_destroy(reply); + + if (request_context->service != NULL) + { + service_destroy(request_context->service); + } + + free(request_context); +} + + +int service_create(service_h *service) +{ + return service_create_request(NULL, service); +} + +int service_create_request(bundle *data, service_h *service) +{ + struct service_s *service_request; + + if (service == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + service_request = malloc(sizeof(struct service_s)); + + if (service_request == NULL) + { + return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a service handle"); + } + + service_request->type = SERVICE_TYPE_REQUEST; + + if (data != NULL) + { + service_request->data = bundle_dup(data); + } + else + { + service_request->data = bundle_create(); + } + + if (service_request->data == NULL) + { + free(service_request); + return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a bundle"); + } + + service_request->id = service_new_id(); + + *service = service_request; + + return SERVICE_ERROR_NONE; +} + +int service_create_event(bundle *data, struct service_s **service) +{ + struct service_s *service_event; + + const char *operation; + + if (data == NULL || service == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + service_event = malloc(sizeof(struct service_s)); + + if (service_event == NULL) + { + return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a service handle"); + } + + service_event->type = SERVICE_TYPE_EVENT; + service_event->data = bundle_dup(data); + service_event->id = service_new_id(); + + operation = appsvc_get_operation(service_event->data); + + if (operation == NULL) + { + appsvc_set_operation(service_event->data, SERVICE_OPERATION_DEFAULT); + } + + *service = service_event; + + return SERVICE_ERROR_NONE; +} + +static int service_create_reply(bundle *data, struct service_s **service) +{ + struct service_s *service_reply; + + if (data == NULL || service == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + service_reply = malloc(sizeof(struct service_s)); + + if (service_reply == NULL) + { + return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a service handle"); + } + + service_reply->type = SERVICE_TYPE_REPLY; + service_reply->data = bundle_dup(data); + service_reply->id = service_new_id(); + + *service = service_reply; + + return SERVICE_ERROR_NONE; +} + +int service_destroy(service_h service) +{ + if (service_valiate_service(service)) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + bundle_free(service->data); + service->data = NULL; + free(service); + + return SERVICE_ERROR_NONE; +} + +int service_to_bundle(service_h service, bundle **data) +{ + if (service_valiate_service(service) || data == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + *data = service->data; + + return SERVICE_ERROR_NONE; +} + +int service_set_operation(service_h service, const char *operation) +{ + if (service_valiate_service(service)) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (operation != NULL) + { + if (appsvc_set_operation(service->data, operation) != 0) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid operation"); + } + } + else + { + bundle_del(service->data, BUNDLE_KEY_OPERATION); + } + + return SERVICE_ERROR_NONE; +} + +int service_get_operation(service_h service, char **operation) +{ + const char *operation_value; + + if (service_valiate_service(service) || operation == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + operation_value = appsvc_get_operation(service->data); + + if (operation_value != NULL) + { + *operation = strdup(operation_value); + } + else + { + *operation = NULL; + } + + return SERVICE_ERROR_NONE; +} + + +int service_set_uri(service_h service, const char *uri) +{ + if (service_valiate_service(service)) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (uri != NULL) + { + if (appsvc_set_uri(service->data, uri) != 0) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid URI"); + } + } + else + { + bundle_del(service->data, BUNDLE_KEY_URI); + } + + return SERVICE_ERROR_NONE; +} + + +int service_get_uri(service_h service, char **uri) +{ + const char *uri_value; + + if (service_valiate_service(service) || uri == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + uri_value = appsvc_get_uri(service->data); + + if (uri_value != NULL) + { + *uri = strdup(uri_value); + } + else + { + *uri = NULL; + } + + return SERVICE_ERROR_NONE; +} + + +int service_set_mime(service_h service, const char *mime) +{ + if (service_valiate_service(service)) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (mime != NULL) + { + if (appsvc_set_mime(service->data, mime) != 0) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid MIME type"); + } + } + else + { + bundle_del(service->data, BUNDLE_KEY_MIME); + } + + return SERVICE_ERROR_NONE; +} + + +int service_get_mime(service_h service, char **mime) +{ + const char *mime_value; + + if (service_valiate_service(service) || mime == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + mime_value = appsvc_get_mime(service->data); + + if (mime_value != NULL) + { + *mime = strdup(mime_value); + } + else + { + *mime = NULL; + } + + return SERVICE_ERROR_NONE; +} + + +int service_set_category(service_h service, const char *category) +{ + if (service_valiate_service(service)) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (category != NULL) + { + if (appsvc_set_category(service->data, category) != 0) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid MIME type"); + } + } + else + { + bundle_del(service->data, BUNDLE_KEY_MIME); + } + + return SERVICE_ERROR_NONE; +} + + +int service_get_category(service_h service, char **category) +{ + const char *category_value; + + if (service_valiate_service(service) || category == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + category_value = appsvc_get_category(service->data); + + if (category_value != NULL) + { + *category = strdup(category_value); + } + else + { + *category = NULL; + } + + return SERVICE_ERROR_NONE; +} + + +int service_set_package(service_h service, const char *package) +{ + // TODO: this function must be deprecated + return service_set_app_id(service, package); +} + +int service_get_package(service_h service, char **package) +{ + // TODO: this function must be deprecated + return service_get_app_id(service, package); +} + + +int service_set_app_id(service_h service, const char *app_id) +{ + if (service_valiate_service(service)) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (app_id != NULL) + { + if (appsvc_set_appid(service->data, app_id) != 0) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid application ID"); + } + } + else + { + bundle_del(service->data, BUNDLE_KEY_PACKAGE); + } + + return SERVICE_ERROR_NONE; +} + + +int service_get_app_id(service_h service, char **app_id) +{ + const char *app_id_value; + + if (service_valiate_service(service) || app_id == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + app_id_value = appsvc_get_appid(service->data); + + if (app_id_value != NULL) + { + *app_id = strdup(app_id_value); + } + else + { + *app_id = NULL; + } + + return SERVICE_ERROR_NONE; +} + +int service_set_window(service_h service, unsigned int id) +{ + if (service_valiate_service(service)) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (id > 0) + { + if (appsvc_allow_transient_app(service->data, id) != 0) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid id"); + } + } + else + { + bundle_del(service->data, BUNDLE_KEY_WINDOW); + } + + return SERVICE_ERROR_NONE; +} + +int service_get_window(service_h service, unsigned int *id) +{ + const char *window_id; + + if (service_valiate_service(service) || id == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + window_id = bundle_get_val(service->data, BUNDLE_KEY_WINDOW); + + if (window_id != NULL) + { + *id = atoi(window_id); + } + else + { + *id = 0; + } + + return SERVICE_ERROR_NONE; +} + +int service_clone(service_h *clone, service_h service) +{ + service_h service_clone; + + if (service_valiate_service(service) || clone == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + service_clone = malloc(sizeof(struct service_s)); + + if (service_clone == NULL) + { + return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, "failed to create a service handle"); + } + + service_clone->id = service_new_id(); + service_clone->type = service->type; + service_clone->data = bundle_dup(service->data); + + *clone = service_clone; + + return SERVICE_ERROR_NONE; +} + + +int service_send_launch_request(service_h service, service_reply_cb callback, void *user_data) +{ + const char *operation; + const char *appid; + + bool implicit_default_operation = false; + int launch_pid; + + service_request_context_h request_context = NULL; + + if (service_valiate_service(service)) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + operation = appsvc_get_operation(service->data); + + if (operation == NULL) + { + implicit_default_operation = true; + operation = SERVICE_OPERATION_DEFAULT; + } + + appid = appsvc_get_appid(service->data); + + // operation : default + if (!strcmp(operation, SERVICE_OPERATION_DEFAULT)) + { + if (appid == NULL) + { + return service_error(SERVICE_ERROR_APP_NOT_FOUND, __FUNCTION__, "package must be specified if the operation is default value"); + } + } + + if (callback != NULL) + { + service_h request_clone = NULL; + + request_context = calloc(1, sizeof(struct service_request_context_s)); + + if (request_context == NULL) + { + return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + } + + request_context->reply_cb = callback; + + if (service_clone(&request_clone, service) != SERVICE_ERROR_NONE) + { + free(request_context); + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to clone the service request handle"); + } + + request_context->service = request_clone; + request_context->user_data = user_data; + } + + if (implicit_default_operation == true) + { + appsvc_set_operation(service->data, SERVICE_OPERATION_DEFAULT); + } + + launch_pid = appsvc_run_service(service->data, service->id, callback ? service_request_result_broker : NULL, request_context); + + if (implicit_default_operation == true) + { + bundle_del(service->data, BUNDLE_KEY_OPERATION); + } + + if (launch_pid < 0) + { + if (launch_pid == APPSVC_RET_ENOMATCH) + { + return service_error(SERVICE_ERROR_APP_NOT_FOUND, __FUNCTION__, NULL); + } + else + { + return service_error(SERVICE_ERROR_LAUNCH_REJECTED, __FUNCTION__, NULL); + } + } + + return SERVICE_ERROR_NONE; +} + +static bool service_copy_reply_data_cb(service_h service, const char *key, void *user_data) +{ + bundle *reply_data = user_data; + char *value = NULL; + char **value_array = NULL; + int value_array_length = 0; + int value_array_index = 0; + + if (reply_data == NULL) + { + service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + return false; + } + + if (appsvc_data_is_array(service->data, key)) + { + service_get_extra_data_array(service, key, &value_array, &value_array_length); + appsvc_add_data_array(reply_data, key, (const char**)value_array, value_array_length); + + for (value_array_index=0; value_array_index < value_array_length; value_array_index++) + { + free(value_array[value_array_index]); + } + + free(value_array); + } + else + { + service_get_extra_data(service, key, &value); + appsvc_add_data(reply_data, key, value); + free(value); + } + + return true; +} + +int service_reply_to_launch_request(service_h reply, service_h request, service_result_e result) +{ + bundle *reply_data; + int appsvc_result; + + if (service_valiate_service(reply) || service_valiate_service(request)) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (appsvc_create_result_bundle(request->data, &reply_data) != 0) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to create a result bundle"); + } + + service_foreach_extra_data(reply, service_copy_reply_data_cb, reply_data); + + switch (result) + { + case SERVICE_RESULT_SUCCEEDED: + appsvc_result = APPSVC_RES_OK; + break; + + case SERVICE_RESULT_FAILED: + appsvc_result = APPSVC_RES_NOT_OK; + break; + + case SERVICE_RESULT_CANCELED: + appsvc_result = APPSVC_RES_CANCEL; + break; + + default: + appsvc_result = APPSVC_RES_CANCEL; + break; + } + + appsvc_send_result(reply_data, appsvc_result); + + return SERVICE_ERROR_NONE; +} + + +int service_add_extra_data(service_h service, const char *key, const char *value) +{ + if (service_valiate_service(service) || service_validate_extra_data(key) || service_validate_extra_data(value)) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (service_validate_internal_key(key)) + { + return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use"); + } + + if (appsvc_get_data(service->data, key) != NULL) + { + // overwrite any existing value + bundle_del(service->data, key); + } + + if (appsvc_add_data(service->data, key, value) != 0) + { + return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "failed to add data to the appsvc handle"); + } + + return SERVICE_ERROR_NONE; +} + + +int service_add_extra_data_array(service_h service, const char *key, const char* value[], int length) +{ + if (service_valiate_service(service) || service_validate_extra_data(key)) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (value == NULL || length <= 0) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid array"); + } + + if (service_validate_internal_key(key)) + { + return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use"); + } + + if (appsvc_get_data_array(service->data, key, NULL) != NULL) + { + // overwrite any existing value + bundle_del(service->data,key); + } + + if (appsvc_add_data_array(service->data, key, value, length) != 0) + { + return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "failed to add array data to the appsvc handle"); + } + + return SERVICE_ERROR_NONE; +} + + +int service_remove_extra_data(service_h service, const char *key) +{ + if (service_valiate_service(service) || service_validate_extra_data(key)) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (service_validate_internal_key(key)) + { + return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use"); + } + + if (bundle_del(service->data, key)) + { + return service_error(SERVICE_ERROR_KEY_NOT_FOUND, __FUNCTION__, NULL); + } + + return SERVICE_ERROR_NONE; +} + + +int service_get_extra_data(service_h service, const char *key, char **value) +{ + const char *data_value; + + if (service_valiate_service(service) || service_validate_extra_data(key) || value == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + + if (service_validate_internal_key(key)) + { + return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use"); + } + + data_value = appsvc_get_data(service->data, key); + + if (data_value == NULL) + { + if (errno == ENOTSUP) + { + return service_error(SERVICE_ERROR_INVALID_DATA_TYPE, __FUNCTION__, NULL); + } + else + { + return service_error(SERVICE_ERROR_KEY_NOT_FOUND, __FUNCTION__, NULL); + } + } + + *value = strdup(data_value); + + return SERVICE_ERROR_NONE; +} + + +int service_get_extra_data_array(service_h service, const char *key, char ***value, int *length) +{ + const char **array_data; + int array_data_length; + char **array_data_clone; + int i; + + if (service_valiate_service(service) || service_validate_extra_data(key)) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (value == NULL || length == 0) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (service_validate_internal_key(key)) + { + return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use"); + } + + array_data = appsvc_get_data_array(service->data, key, &array_data_length); + + if (array_data == NULL) + { + if (errno == ENOTSUP) + { + return service_error(SERVICE_ERROR_INVALID_DATA_TYPE, __FUNCTION__, NULL); + } + else + { + return service_error(SERVICE_ERROR_KEY_NOT_FOUND, __FUNCTION__, NULL); + } + } + + array_data_clone = calloc(array_data_length, sizeof(char*)); + + if (array_data_clone == NULL) + { + return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + } + + for (i=0; i<array_data_length; i++) + { + if (array_data[i] != NULL) + { + array_data_clone[i] = strdup(array_data[i]); + } + } + + *value = array_data_clone; + *length = array_data_length; + + return SERVICE_ERROR_NONE; +} + + +int service_is_extra_data_array(service_h service, const char *key, bool *array) +{ + if (service_valiate_service(service) || service_validate_extra_data(key) || array == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (service_validate_internal_key(key)) + { + return service_error(SERVICE_ERROR_KEY_REJECTED, __FUNCTION__, "the given key is reserved as internal use"); +
} + + if (!appsvc_data_is_array(service->data, key)) + { + *array = false; + } + else + { + *array = true; + } + + return SERVICE_ERROR_NONE; +} + + +typedef struct { + service_h service; + service_extra_data_cb callback; + void* user_data; + bool foreach_break; +} foreach_context_extra_data_t; + +static void service_cb_broker_bundle_iterator(const char *key, const int type, const bundle_keyval_t *kv, void *user_data) +{ + foreach_context_extra_data_t* foreach_context = NULL; + service_extra_data_cb extra_data_cb; + + if (key == NULL || !(type == BUNDLE_TYPE_STR || type == BUNDLE_TYPE_STR_ARRAY)) + { + return; + } + + foreach_context = (foreach_context_extra_data_t*)user_data; + + if (foreach_context->foreach_break == true) + { + return; + } + + if (service_validate_internal_key(key)) + { + return; + } + + extra_data_cb = foreach_context->callback; + + if (extra_data_cb != NULL) + { + bool stop_foreach = false; + + stop_foreach = !extra_data_cb(foreach_context->service, key, foreach_context->user_data); + + foreach_context->foreach_break = stop_foreach; + } + +} + + +int service_foreach_extra_data(service_h service, service_extra_data_cb callback, void *user_data) +{ + foreach_context_extra_data_t foreach_context = { + .service = service, + .callback = callback, + .user_data = user_data, + .foreach_break = false + }; + + if (service_valiate_service(service) || callback == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + bundle_foreach(service->data, service_cb_broker_bundle_iterator, &foreach_context); + + return SERVICE_ERROR_NONE; +} + +typedef struct { + service_h service; + service_app_matched_cb callback; + void* user_data; + bool foreach_break; +} foreach_context_launchable_app_t; + +int service_cb_broker_foreach_app_matched(const char *package, void *data) +{ + foreach_context_launchable_app_t *foreach_context; + service_app_matched_cb app_matched_cb; + + if (package == NULL || data == NULL) + { + service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + return -1; + } + + foreach_context = (foreach_context_launchable_app_t*)data; + + if (foreach_context->foreach_break == true) + { + return -1; + } + + app_matched_cb = foreach_context->callback; + + if (app_matched_cb != NULL) + { + bool stop_foreach = false; + + stop_foreach = !app_matched_cb(foreach_context->service, package, foreach_context->user_data); + + foreach_context->foreach_break = stop_foreach; + } + + return 0; +} + +int service_foreach_app_matched(service_h service, service_app_matched_cb callback, void *user_data) +{ + foreach_context_launchable_app_t foreach_context = { + .service = service, + .callback = callback, + .user_data = user_data, + .foreach_break = false + }; + + if (service_valiate_service(service) || callback == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + appsvc_get_list(service->data, service_cb_broker_foreach_app_matched, &foreach_context); + + return SERVICE_ERROR_NONE; +} + + +int service_get_caller(service_h service, char **package) +{ + const char *bundle_value; + pid_t caller_pid; + char package_buf[TIZEN_PATH_MAX] = {0, }; + char *package_dup; + + if (service_valiate_service(service) || package == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (service->type != SERVICE_TYPE_EVENT) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid service handle type"); + } + + bundle_value = bundle_get_val(service->data, AUL_K_ORG_CALLER_PID); + + if (bundle_value == NULL) + { + bundle_value = bundle_get_val(service->data, AUL_K_CALLER_PID); + } + + if (bundle_value == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to retrieve the pid of the caller"); + } + + caller_pid = atoi(bundle_value); + + if (caller_pid <= 0) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid pid of the caller"); + } + + if (aul_app_get_appid_bypid(caller_pid, package_buf, sizeof(package_buf)) != AUL_R_OK) + { + return service_error(SERVICE_ERROR_APP_NOT_FOUND, __FUNCTION__, "failed to get the package name of the caller"); + } + + package_dup = strdup(package_buf); + + if (package_dup == NULL) + { + return service_error(SERVICE_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); + } + + *package = package_dup; + + return SERVICE_ERROR_NONE; +} + + +int service_is_reply_requested(service_h service, bool *requested) +{ + const char *bundle_value; + + if (service_valiate_service(service) || requested == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + if (service->type != SERVICE_TYPE_EVENT) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid service handle type"); + } + + bundle_value = bundle_get_val(service->data, AUL_K_WAIT_RESULT); + + if (bundle_value != NULL) + { + *requested = true; + } + else + { + *requested = false; + } + + return SERVICE_ERROR_NONE; +} + +int service_import_from_bundle(service_h service, bundle *data) +{ + bundle *data_dup = NULL; + + if (service_valiate_service(service) || data == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + data_dup = bundle_dup(data); + + if (data_dup == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to duplicate the bundle"); + } + + if (service->data != NULL) + { + bundle_free(service->data); + } + + service->data = data_dup; + + return SERVICE_ERROR_NONE; +} + +int service_export_as_bundle(service_h service, bundle **data) +{ + bundle *data_dup = NULL; + + if (service_valiate_service(service) || data == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); + } + + data_dup = bundle_dup(service->data); + + if (data_dup == NULL) + { + return service_error(SERVICE_ERROR_INVALID_PARAMETER, __FUNCTION__, "failed to duplicate the bundle"); + } + + *data = data_dup; + + return SERVICE_ERROR_NONE; +} + diff --git a/src/storage.c b/src/storage.c new file mode 100755 index 0000000..a6f9202 --- /dev/null +++ b/src/storage.c @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/vfs.h> + +#include <aul.h> +#include <dlog.h> +#include <vconf.h> + +#include <app_storage.h> +#include <app_storage_private.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION_STORAGE" + +static int storage_initialize(); +static int storage_register_device(storage_device_h device); +static int storage_get_storage(int id, storage_info_h* storage_info); + +extern storage_device_h storage_internal_device(); +extern storage_device_h storage_sdcard_device(); +extern storage_device_h storage_usbhost_device(); + + +#define STORAGE_MAX 3 +static struct storage_info_s storage_info_table[STORAGE_MAX]; +static int storage_num = 0; + +static int storage_register_device(storage_device_h device) +{ + if (device == NULL) + { + return -1; + } + + if (storage_num >= STORAGE_MAX) + { + LOGE("failed to register device : not enough device table"); + return -1; + } + + storage_info_table[storage_num].id = storage_num; + storage_info_table[storage_num].device = device; + storage_info_table[storage_num].state = device->get_state(); + storage_info_table[storage_num].state_cb = NULL; + storage_info_table[storage_num].state_cb_data = NULL; + + storage_num++; + + return 0; +} + +static int storage_initialize() +{ + storage_device_h dev_internal; + storage_device_h dev_sdcard; + storage_device_h dev_usbhost; + + dev_internal = storage_internal_device(); + storage_register_device(dev_internal); + + dev_sdcard = storage_sdcard_device(); + storage_register_device( dev_sdcard); + + dev_usbhost = storage_usbhost_device(); + storage_register_device(dev_usbhost); + + return 0; +} + + +static int storage_get_storage(int id, storage_info_h* storage_info) +{ + if (storage_num < 1) + { + if (storage_initialize() != 0) + { + return STORAGE_ERROR_NOT_SUPPORTED; + } + } + + if (id <0 || id >= storage_num) + { + return STORAGE_ERROR_NOT_SUPPORTED; + } + + *storage_info = &(storage_info_table[id]); + + return STORAGE_ERROR_NONE; +} + + +int storage_foreach_device_supported(storage_device_supported_cb callback, void *user_data) +{ + int storage_id = 0; + storage_info_h storage_info = NULL; + bool foreach_next = false; + + if (callback == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid callback", STORAGE_ERROR_INVALID_PARAMETER); + return STORAGE_ERROR_INVALID_PARAMETER; + } + + while (true) + { + if (storage_get_storage(storage_id, &storage_info) != 0) + { + break; + } + + storage_id++; + + foreach_next = callback(storage_info->id, storage_info->device->type, storage_info->state, storage_info->device->path, user_data); + + if (foreach_next == false) + { + break; + } + } + + return STORAGE_ERROR_NONE; +} + + +int storage_get_root_directory(int storage, char **path) +{ + storage_info_h storage_info; + + if (path == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid output param", STORAGE_ERROR_INVALID_PARAMETER); + return STORAGE_ERROR_INVALID_PARAMETER; + } + + if (storage_get_storage(storage, &storage_info) != 0) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + *path = strdup(storage_info->device->path); + + return STORAGE_ERROR_NONE; +} + + +int storage_get_type(int storage, storage_type_e *type) +{ + storage_info_h storage_info; + + if (type == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid output param", STORAGE_ERROR_INVALID_PARAMETER); + return STORAGE_ERROR_INVALID_PARAMETER; + } + + if (storage_get_storage(storage, &storage_info) != 0) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + *type = storage_info->device->type; + + return STORAGE_ERROR_NONE; +} + + +int storage_get_state(int storage, storage_state_e *state) +{ + storage_info_h storage_info; + storage_dev_get_state get_state; + + if (state == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid output param", STORAGE_ERROR_INVALID_PARAMETER); + return STORAGE_ERROR_INVALID_PARAMETER; + } + + if (storage_get_storage(storage, &storage_info) != 0) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + get_state = storage_info->device->get_state; + + if (get_state == NULL) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + storage_info->state = get_state(); + + *state = storage_info->state; + + return STORAGE_ERROR_NONE; +} + + +void storage_dispatch_state_event(storage_state_e state, void* data) +{ + storage_info_h storage_info; + storage_state_changed_cb state_cb; + + storage_info = data; + + if (storage_info == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid storage information", STORAGE_ERROR_INVALID_PARAMETER); + return; + } + + storage_info->state = state; + state_cb = storage_info->state_cb; + + if (state_cb != NULL) + { + state_cb(storage_info->id, state, storage_info->state_cb_data); + } +} + + +int storage_set_state_changed_cb(int storage, storage_state_changed_cb callback, void *user_data) +{ + storage_info_h storage_info; + storage_dev_set_state_cb set_state_cb; + + if (callback == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid callback", STORAGE_ERROR_INVALID_PARAMETER); + return STORAGE_ERROR_INVALID_PARAMETER; + } + + if (storage_get_storage(storage, &storage_info) != 0) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + storage_info->state_cb = callback; + storage_info->state_cb_data = user_data; + + set_state_cb = storage_info->device->set_state_cb; + + if (set_state_cb == NULL) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + if (set_state_cb(storage_info) != 0) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + return STORAGE_ERROR_NONE; +} + + +int storage_unset_state_changed_cb(int storage) +{ + storage_info_h storage_info; + storage_dev_unset_state_cb unset_state_cb; + + if (storage_get_storage(storage, &storage_info) != 0) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + storage_info->state_cb = NULL; + unset_state_cb = storage_info->device->unset_state_cb; + + if (unset_state_cb != NULL) + { + unset_state_cb(); + } + + return STORAGE_ERROR_NONE; +} + + +int storage_get_total_space(int storage, unsigned long long *bytes) +{ + storage_info_h storage_info; + storage_dev_get_space get_space; + + if (bytes == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid output param", STORAGE_ERROR_INVALID_PARAMETER); + return STORAGE_ERROR_INVALID_PARAMETER; + } + + if (storage_get_storage(storage, &storage_info) != 0) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + get_space = storage_info->device->get_space; + + if (get_space == NULL) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + if (get_space(bytes, NULL) != 0) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + return STORAGE_ERROR_NONE; +} + +int storage_get_available_space(int storage, unsigned long long *bytes) +{ + storage_info_h storage_info; + storage_dev_get_space get_space; + + if (bytes == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid output param", STORAGE_ERROR_INVALID_PARAMETER); + return STORAGE_ERROR_INVALID_PARAMETER; + } + + if (storage_get_storage(storage, &storage_info) != 0) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + get_space = storage_info->device->get_space; + + if (get_space == NULL) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + if (get_space(NULL, bytes) != 0) + { + LOGE("NOT_SUPPORTED(0x%08x) : storage(%d)", STORAGE_ERROR_NOT_SUPPORTED, storage); + return STORAGE_ERROR_NOT_SUPPORTED; + } + + return STORAGE_ERROR_NONE; +} + +int storage_statfs(const char *directory, unsigned long long *total, unsigned long long *available) +{ + struct statfs fs; + + if (statfs(directory, &fs) < 0) + { + LOGE("statfs returns error(%d) directory(%s)\n", errno, directory); + return -1; + } + + if (total != NULL) + { + *total = fs.f_bsize * fs.f_blocks; + } + + if (available != NULL) + { + *available = fs.f_bsize * fs.f_bavail; + } + + return 0; +} + diff --git a/src/storage_internal.c b/src/storage_internal.c new file mode 100755 index 0000000..c9e0b6d --- /dev/null +++ b/src/storage_internal.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/vfs.h> + +#include <aul.h> +#include <dlog.h> +#include <vconf.h> + +#include <app_storage.h> +#include <app_storage_private.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION_STORAGE" + +#define INTERNAL_MEMORY_PATH "/opt/media" + +static int storage_internal_get_state() +{ + return STORAGE_STATE_MOUNTED; +} + +static int storage_internal_set_state_cb(void *data) +{ + return 0; +} + +static void storage_internal_unset_state_cb() +{ + // empty function +} + +int storage_internal_get_space(unsigned long long *total, unsigned long long *available) +{ + return storage_statfs(INTERNAL_MEMORY_PATH, total, available); +} + +storage_device_h storage_internal_device() +{ + storage_device_h device; + + device = calloc(1, sizeof(struct storage_device_s)); + + if (device == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", STORAGE_ERROR_OUT_OF_MEMORY); + return NULL; + } + + device->type = STORAGE_TYPE_INTERNAL; + device->path = INTERNAL_MEMORY_PATH; + device->get_state = storage_internal_get_state; + device->set_state_cb = storage_internal_set_state_cb; + device->unset_state_cb = storage_internal_unset_state_cb; + device->get_space = storage_internal_get_space; + + return device; +} + diff --git a/src/storage_sdcard.c b/src/storage_sdcard.c new file mode 100755 index 0000000..9dd9cb0 --- /dev/null +++ b/src/storage_sdcard.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/vfs.h> + +#include <aul.h> +#include <dlog.h> +#include <vconf.h> + +#include <app_storage.h> +#include <app_storage_private.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION_STORAGE" + +#define SDCARD_PATH "/opt/storage/sdcard" + +static int storage_sdcard_get_state() +{ + int sdcard_state = 0; + + vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &sdcard_state); + + switch (sdcard_state) + { + case VCONFKEY_SYSMAN_MMC_REMOVED: + return STORAGE_STATE_REMOVED; + + case VCONFKEY_SYSMAN_MMC_MOUNTED: + return STORAGE_STATE_MOUNTED; + + case VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED: + return STORAGE_STATE_UNMOUNTABLE; + + default: + return STORAGE_STATE_REMOVED; + } +} + +static void storage_sdcard_state_cb_broker(keynode_t* key, void* data) +{ + storage_state_e state; + state = storage_sdcard_get_state(); + + storage_dispatch_state_event(state, data); +} + +static int storage_sdcard_set_state_cb(void *data) +{ + vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_STATUS, storage_sdcard_state_cb_broker, data); + return 0; +} + +static void storage_sdcard_unset_state_cb() +{ + vconf_ignore_key_changed(VCONFKEY_SYSMAN_MMC_STATUS, storage_sdcard_state_cb_broker); +} + +static int storage_sdcard_get_space(unsigned long long *total, unsigned long long *available) +{ + storage_state_e state; + state = storage_sdcard_get_state(); + + if (state < STORAGE_STATE_MOUNTED) + { + if (total != NULL) + { + *total = 0; + } + + if (available != NULL) + { + *available = 0; + } + + return 0; + } + else + { + return storage_statfs(SDCARD_PATH, total, available); + } +} + +storage_device_h storage_sdcard_device() +{ + storage_device_h device; + + device = calloc(1, sizeof(struct storage_device_s)); + + if (device == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", STORAGE_ERROR_OUT_OF_MEMORY); + return NULL; + } + + device->type = STORAGE_TYPE_EXTERNAL; + device->path = SDCARD_PATH; + device->get_state = storage_sdcard_get_state; + device->set_state_cb = storage_sdcard_set_state_cb; + device->unset_state_cb = storage_sdcard_unset_state_cb; + device->get_space = storage_sdcard_get_space; + + return device; +} + diff --git a/src/storage_usbhost.c b/src/storage_usbhost.c new file mode 100755 index 0000000..aba65c0 --- /dev/null +++ b/src/storage_usbhost.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/vfs.h> + +#include <aul.h> +#include <dlog.h> +#include <vconf.h> + +#include <app_storage.h> +#include <app_storage_private.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION_STORAGE" + +#define USBHOST_PATH "/opt/storage/usb" + +static int storage_usbhost_get_state() +{ + int usbhost_state = 0; + + vconf_get_int(VCONFKEY_SYSMAN_USB_HOST_STATUS, &usbhost_state); + + switch (usbhost_state) + { + case VCONFKEY_SYSMAN_USB_HOST_DISCONNECTED: + return STORAGE_STATE_REMOVED; + + case VCONFKEY_SYSMAN_USB_HOST_CONNECTED: + return STORAGE_STATE_MOUNTED; + + default: + return STORAGE_STATE_REMOVED; + } +} + +static void storage_usbhost_state_cb_broker(keynode_t* key, void* data) +{ + storage_state_e state; + + state = storage_usbhost_get_state(); + + storage_dispatch_state_event(state, data); +} + +static int storage_usbhost_set_state_cb(void *data) +{ + vconf_notify_key_changed(VCONFKEY_SYSMAN_USB_HOST_STATUS, storage_usbhost_state_cb_broker, data); + return 0; +} + +static void storage_usbhost_unset_state_cb() +{ + vconf_ignore_key_changed(VCONFKEY_SYSMAN_USB_HOST_STATUS, storage_usbhost_state_cb_broker); +} + + +static int storage_usbhost_get_space(unsigned long long *total, unsigned long long *available) +{ + storage_state_e state; + state = storage_usbhost_get_state(); + + if (state < STORAGE_STATE_MOUNTED) + { + if (total != NULL) + { + *total = 0; + } + + if (available != NULL) + { + *available = 0; + } + + return 0; + } + else + { + return storage_statfs(USBHOST_PATH, total, available); + } +} + + +storage_device_h storage_usbhost_device() +{ + storage_device_h device; + + device = calloc(1, sizeof(struct storage_device_s)); + + if (device == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", STORAGE_ERROR_OUT_OF_MEMORY); + return NULL; + } + + device->type = STORAGE_TYPE_EXTERNAL; + device->path = USBHOST_PATH; + device->get_state = storage_usbhost_get_state; + device->set_state_cb = storage_usbhost_set_state_cb; + device->unset_state_cb = storage_usbhost_unset_state_cb; + device->get_space = storage_usbhost_get_space; + + return device; +} + diff --git a/src/ui_notification.c b/src/ui_notification.c new file mode 100755 index 0000000..1610d02 --- /dev/null +++ b/src/ui_notification.c @@ -0,0 +1,1179 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> + +#include <dlog.h> +#include <notification.h> + +#include <app.h> +#include <app_service_private.h> + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "CAPI_APPFW_APPLICATION_UI_NOTIFICATION" + +struct ui_notification_s { + notification_h raw_handle; + bool ongoing; + bool posted; + bool removed; + char *icon; + struct tm *time; + char *title; + char *content; + service_h service; + char *sound; + bool vibration; +}; + +static int ui_notification_error_handler(int error, const char *func, const char *on_error) +{ + int retcode; + char *error_msg; + + switch (error) + { + case NOTIFICATION_ERROR_NONE: + retcode = UI_NOTIFICATION_ERROR_NONE; + break; + + case NOTIFICATION_ERROR_INVALID_DATA: + retcode = UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + error_msg = "INVALID_PARAMETER"; + break; + + case NOTIFICATION_ERROR_NO_MEMORY: + retcode = UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + error_msg = "OUT_OF_MEMORY"; + break; + + case NOTIFICATION_ERROR_FROM_DB: + retcode = UI_NOTIFICATION_ERROR_DB_FAILED; + error_msg = "DB_FAILED"; + break; + + case NOTIFICATION_ERROR_ALREADY_EXIST_ID: + case NOTIFICATION_ERROR_NOT_EXIST_ID: + retcode = UI_NOTIFICATION_ERROR_INVALID_STATE; + error_msg = "INVALID_STATE"; + break; + + default: + retcode = UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + error_msg = "INVALID_PARAMETER"; + } + + if (retcode != UI_NOTIFICATION_ERROR_NONE) + { + LOGE("[%s] %s(0x%08x) : %s", func, error_msg, retcode, on_error); + } + + return retcode; +} + + +int ui_notification_create(bool ongoing, ui_notification_h *notification) +{ + ui_notification_h notification_out; + + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid output param", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + notification_out = (ui_notification_h)calloc(1, sizeof(struct ui_notification_s)); + + if (notification_out == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + + notification_out->raw_handle = NULL; + notification_out->ongoing = ongoing; + notification_out->posted = false; + notification_out->removed = false; + notification_out->icon = NULL; + notification_out->time = NULL; + notification_out->title = NULL; + notification_out->content = NULL; + notification_out->service = NULL; + notification_out->sound = NULL; + notification_out->vibration = false; + + *notification = notification_out; + + return UI_NOTIFICATION_ERROR_NONE; +} + +static int ui_notification_construct(bool ongoing, notification_h raw_handle, ui_notification_h *notification) +{ + int retcode; + ui_notification_h notification_out; + char *icon; + time_t time; + char *title; + char *content; + bundle *service_data; + const char *sound = NULL; + notification_sound_type_e sound_type; + notification_vibration_type_e vib_type; + + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid output param", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + notification_out = (ui_notification_h)calloc(1, sizeof(struct ui_notification_s)); + + if (notification_out == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + + retcode = ui_notification_error_handler(notification_clone(raw_handle, &(notification_out->raw_handle)),\ + __FUNCTION__, "failed to clone the notification handle"); + + if (retcode != NOTIFICATION_ERROR_NONE) + { + free(notification_out); + return retcode; + } + + notification_out->ongoing = ongoing; + + notification_out->posted = true; + + notification_out->removed = false; + + if (!notification_get_image(raw_handle, NOTIFICATION_IMAGE_TYPE_ICON, &icon) && icon) + { + notification_out->icon = strdup(icon); + } + + if (!notification_get_time(raw_handle, &time)) + { + notification_out->time = malloc(sizeof(struct tm)); + + if (notification_out->time == NULL) + { + ui_notification_destroy(notification_out); + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + + localtime_r(&time, notification_out->time); + } + + if (!notification_get_text(raw_handle, NOTIFICATION_TEXT_TYPE_TITLE, &title) && title) + { + notification_out->title = strdup(title); + } + + if (!notification_get_text(raw_handle, NOTIFICATION_TEXT_TYPE_CONTENT, &content) && content) + { + notification_out->content = strdup(content); + } + + if (!notification_get_sound(raw_handle, &sound_type, &sound) && sound) + { + notification_out->sound = strdup(sound); + } + + if (!notification_get_vibration(raw_handle, &vib_type, NULL)) + { + if (vib_type == NOTIFICATION_VIBRATION_TYPE_DEFAULT) + { + notification_out->vibration = true; + } + } + + if (!notification_get_execute_option(raw_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, &service_data)) + { + service_h service; + + if (!service_create_request(service_data, &service)) + { + notification_out->service = service; + } + } + + *notification = notification_out; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_destroy(ui_notification_h notification) +{ + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid handle", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->raw_handle) + notification_free(notification->raw_handle); + + if (notification->icon) + free(notification->icon); + + if (notification->time) + free(notification->time); + + if (notification->title) + free(notification->title); + + if (notification->content) + free(notification->content); + + if (notification->sound) + free(notification->sound); + + if (notification->service) + service_destroy(notification->service); + + free(notification); + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_get_id(ui_notification_h notification, int *id) +{ + notification_h raw_handle = NULL; + + if (notification == NULL || id == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + if (notification->raw_handle == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + raw_handle = notification->raw_handle; + if (notification_get_id(raw_handle, NULL, id) != NOTIFICATION_ERROR_NONE) { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_clone(ui_notification_h *clone, ui_notification_h notification) +{ + ui_notification_h notification_out; + int retcode; + + if (clone == NULL || notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + notification_out = (ui_notification_h)calloc(1, sizeof(struct ui_notification_s)); + + if (notification_out == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + + if (notification->raw_handle != NULL) + { + retcode = notification_clone(notification->raw_handle, &(notification_out->raw_handle)); + + if (retcode) + { + free(notification_out); + return ui_notification_error_handler(retcode, __FUNCTION__, "failed to clone the handle"); + } + } + + notification_out->ongoing = notification->ongoing; + + notification_out->posted = notification->posted; + + notification_out->removed = notification->removed; + + if (notification->icon) + { + notification_out->icon = strdup(notification->icon); + } + + if (notification->time) + { + notification_out->time = malloc(sizeof(struct tm)); + if (notification_out->time != NULL) + { + memcpy(notification_out->time, notification->time, sizeof(struct tm)); + } + } + + if (notification->title) + { + notification_out->title = strdup(notification->title); + } + + if (notification->content) + { + notification_out->content = strdup(notification->content); + } + + if (notification->sound) + { + notification_out->sound = strdup(notification->sound); + } + + notification_out->vibration = notification->vibration; + + if (notification->service) + { + service_clone(&(notification_out->service), notification->service); + } + + *clone = notification_out; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_is_ongoing(ui_notification_h notification, bool *ongoing) +{ + if (notification == NULL || ongoing == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + *ongoing = notification->ongoing; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_set_icon(ui_notification_h notification, const char *path) +{ + char *path_dup = NULL; + + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (path != NULL) + { + path_dup = strdup(path); + + if (path_dup == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + } + + if (notification->icon != NULL) + { + free(notification->icon); + } + + notification->icon = path_dup; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_get_icon(ui_notification_h notification, char **path) +{ + char *path_dup = NULL; + + if (notification == NULL || path == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->icon != NULL) + { + path_dup = strdup(notification->icon); + + if (path_dup == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + } + + *path = path_dup; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_set_time(ui_notification_h notification, struct tm *time) +{ + struct tm *time_dup = NULL; + + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (time != NULL) + { + time_dup = malloc(sizeof(struct tm)); + + if (time_dup == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + + memcpy(time_dup, time, sizeof(struct tm)); + } + + if (notification->time != NULL) + { + free(notification->time); + } + + notification->time = time_dup; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_get_time(ui_notification_h notification, struct tm **time) +{ + struct tm *time_dup = NULL; + + if (notification == NULL || time == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->time != NULL) + { + time_dup = malloc(sizeof(struct tm)); + + if (time_dup == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + + memcpy(time_dup, notification->time, sizeof(struct tm)); + } + + *time = time_dup; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_set_title(ui_notification_h notification, const char *title) +{ + char *title_dup = NULL; + + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (title != NULL) + { + title_dup = strdup(title); + + if (title_dup == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + } + + if (notification->title != NULL) + { + free(notification->title); + } + + notification->title = title_dup; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_get_title(ui_notification_h notification, char **title) +{ + char *title_dup = NULL; + + if (notification == NULL || title == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->title != NULL) + { + title_dup = strdup(notification->title); + + if (title_dup == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + } + + *title = title_dup; + + return UI_NOTIFICATION_ERROR_NONE; +} + + +int ui_notification_set_content(ui_notification_h notification, const char *content) +{ + char *content_dup = NULL; + + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (content != NULL) + { + content_dup = strdup(content); + + if (content_dup == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + } + + if (notification->content != NULL) + { + free(notification->content); + } + + notification->content = content_dup; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_get_content(ui_notification_h notification, char **content) +{ + char *content_dup = NULL; + + if (notification == NULL || content == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->content != NULL) + { + content_dup = strdup(notification->content); + + if (content_dup == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + } + + *content = content_dup; + + return UI_NOTIFICATION_ERROR_NONE; +} + + +int ui_notification_set_service(ui_notification_h notification, service_h service) +{ + int retcode; + service_h service_dup = NULL; + + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (service != NULL) + { + retcode = service_clone(&service_dup, service); + + if (retcode != SERVICE_ERROR_NONE) + { + if (retcode == SERVICE_ERROR_OUT_OF_MEMORY) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + else + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid service handle", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + } + } + + if (notification->service != NULL) + { + service_destroy(notification->service); + } + + notification->service = service_dup; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_get_service(ui_notification_h notification, service_h *service) +{ + int retcode; + service_h service_dup = NULL; + + if (notification == NULL || service == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->service != NULL) + { + retcode = service_clone(&service_dup, notification->service); + + if (retcode != SERVICE_ERROR_NONE) + { + if (retcode == SERVICE_ERROR_OUT_OF_MEMORY) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + else + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid service handle", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + } + } + + *service = service_dup; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_set_sound(ui_notification_h notification, const char *path) +{ + char *path_dup = NULL; + + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (path != NULL) + { + path_dup = strdup(path); + + if (path_dup == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + } + + if (notification->sound != NULL) + { + free(notification->sound); + } + + notification->sound = path_dup; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_get_sound(ui_notification_h notification, char **path) +{ + char *path_dup = NULL; + + if (notification == NULL || path == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->sound != NULL) + { + path_dup = strdup(notification->sound); + + if (path_dup == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + *path = NULL; + + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + } + + *path = path_dup; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_set_vibration(ui_notification_h notification, bool value) +{ + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + notification->vibration = value; + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_get_vibration(ui_notification_h notification, bool *value) +{ + if (notification == NULL || value == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + *value = notification->vibration; + + return UI_NOTIFICATION_ERROR_NONE; +} + +static int ui_notification_build_attributes(ui_notification_h notification) +{ + bundle *service_data; + + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid handle", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->icon != NULL) + { + struct stat st; + + if (stat(notification->icon, &st) < 0) + { + LOGE("NO_SUCH_FILE(0x%08x) : invalid icon", UI_NOTIFICATION_ERROR_NO_SUCH_FILE); + return UI_NOTIFICATION_ERROR_NO_SUCH_FILE; + } + + notification_set_image(notification->raw_handle, NOTIFICATION_IMAGE_TYPE_ICON, notification->icon); + } + + if (notification->time != NULL) + { + notification_set_time(notification->raw_handle, mktime(notification->time)); + } + + if (notification->title != NULL) + { + notification_set_text(notification->raw_handle, NOTIFICATION_TEXT_TYPE_TITLE, notification->title, NULL, NOTIFICATION_VARIABLE_TYPE_NONE); + } + + if (notification->content != NULL) + { + notification_set_text(notification->raw_handle, NOTIFICATION_TEXT_TYPE_CONTENT, notification->content, NULL, NOTIFICATION_VARIABLE_TYPE_NONE); + } + + if (notification->service != NULL && service_to_bundle(notification->service, &service_data) == SERVICE_ERROR_NONE) + { + notification_set_property(notification->raw_handle, 0); + notification_set_execute_option(notification->raw_handle, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, service_data); + } + else + { + notification_set_property(notification->raw_handle, NOTIFICATION_PROP_DISABLE_APP_LAUNCH); + } + + if (notification->sound != NULL) + { + struct stat st; + + if (stat(notification->sound, &st) < 0) + { + LOGE("NO_SUCH_FILE(0x%08x) : invalid sound file", UI_NOTIFICATION_ERROR_NO_SUCH_FILE); + return UI_NOTIFICATION_ERROR_NO_SUCH_FILE; + } + notification_set_sound(notification->raw_handle, NOTIFICATION_SOUND_TYPE_USER_DATA, notification->sound); + } + + if (notification->vibration) + { + notification_set_vibration(notification->raw_handle, NOTIFICATION_VIBRATION_TYPE_DEFAULT, NULL); + } + + return UI_NOTIFICATION_ERROR_NONE; +} + +int ui_notification_post(ui_notification_h notification) +{ + int retcode; + + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->posted == true) + { + LOGE("INVALID_STATE(0x%08x) : the notification was already posted", UI_NOTIFICATION_ERROR_INVALID_STATE); + return UI_NOTIFICATION_ERROR_INVALID_STATE; + } + + if (notification->ongoing == true) + { + notification->raw_handle = notification_new(NOTIFICATION_TYPE_ONGOING, NOTIFICATION_GROUP_ID_DEFAULT, NOTIFICATION_PRIV_ID_NONE); + } + else + { + notification->raw_handle = notification_new(NOTIFICATION_TYPE_NOTI, NOTIFICATION_GROUP_ID_DEFAULT, NOTIFICATION_PRIV_ID_NONE); + } + + if (notification->raw_handle == NULL) + { + LOGE("OUT_OF_MEMORY(0x%08x)", UI_NOTIFICATION_ERROR_OUT_OF_MEMORY); + return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY; + } + + retcode = ui_notification_build_attributes(notification); + + if (retcode != UI_NOTIFICATION_ERROR_NONE) + { + return retcode; + } + + retcode = ui_notification_error_handler(notification_insert(notification->raw_handle, NULL), __FUNCTION__, "failed to post a notification"); + + if (retcode == UI_NOTIFICATION_ERROR_NONE) + { + notification->posted = true; + } + + return retcode; +} + +int ui_notification_update(ui_notification_h notification) +{ + int retcode; + + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->posted == false) + { + LOGE("INVALID_STATE(0x%08x) : the notification was not posted", UI_NOTIFICATION_ERROR_INVALID_STATE); + return UI_NOTIFICATION_ERROR_INVALID_STATE; + } + + if (notification->removed == true) + { + LOGE("INVALID_STATE(0x%08x) : the notification was canceled or cleared", UI_NOTIFICATION_ERROR_INVALID_STATE); + return UI_NOTIFICATION_ERROR_INVALID_STATE; + } + + retcode = ui_notification_build_attributes(notification); + + if (retcode != UI_NOTIFICATION_ERROR_NONE) + { + return retcode; + } + + retcode = ui_notification_error_handler(notification_update(notification->raw_handle), __FUNCTION__, "failed to post a notification"); + + if (retcode == UI_NOTIFICATION_ERROR_INVALID_STATE) + { + notification->removed = true; + } + + return retcode; +} + +int ui_notification_update_progress(ui_notification_h notification, ui_notification_progress_type_e type, double value) +{ + int retcode; + + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->raw_handle == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid handle", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->posted == false) + { + LOGE("INVALID_STATE(0x%08x) : the notification was not posted", UI_NOTIFICATION_ERROR_INVALID_STATE); + return UI_NOTIFICATION_ERROR_INVALID_STATE; + } + + if (notification->removed == true) + { + LOGE("INVALID_STATE(0x%08x) : the notification was canceled or cleared", UI_NOTIFICATION_ERROR_INVALID_STATE); + return UI_NOTIFICATION_ERROR_INVALID_STATE; + } + + if (value < 0) + { + LOGE("INVALID_PARAMETER(0x%08x) : the value must be greater than or equal to zero.", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + switch (type) + { + case UI_NOTIFICATION_PROGRESS_TYPE_SIZE: + retcode = ui_notification_error_handler( + notification_update_size(notification->raw_handle, NOTIFICATION_PRIV_ID_NONE, value), + __FUNCTION__, "failed to update the progress"); + break; + + case UI_NOTIFICATION_PROGRESS_TYPE_PERCENTAGE: + retcode = ui_notification_error_handler( + notification_update_progress(notification->raw_handle, NOTIFICATION_PRIV_ID_NONE, value), + __FUNCTION__, "failed to update the progress"); + break; + + default: + LOGE("INVALID_PARAMETER(0x%08x) : invalid progress type", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (retcode == UI_NOTIFICATION_ERROR_INVALID_STATE) + { + notification->removed = true; + } + + return retcode; +} + +int ui_notification_cancel(ui_notification_h notification) +{ + int retcode; + + if (notification == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->raw_handle == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x) : invalid handle", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification->posted == false) + { + LOGE("INVALID_STATE(0x%08x) : the notification was not posted", UI_NOTIFICATION_ERROR_INVALID_STATE); + return UI_NOTIFICATION_ERROR_INVALID_STATE; + } + + if (notification->removed == true) + { + LOGE("INVALID_STATE(0x%08x) : the notification was canceled or cleared", UI_NOTIFICATION_ERROR_INVALID_STATE); + return UI_NOTIFICATION_ERROR_INVALID_STATE; + } + + retcode = ui_notification_error_handler(notification_delete(notification->raw_handle), __FUNCTION__, "failed to cancel the notification"); + + if (retcode == UI_NOTIFICATION_ERROR_NONE) + { + notification->removed = true; + } + + return retcode; +} + +void ui_notification_cancel_all(void) +{ + notification_delete_all_by_type(NULL, NOTIFICATION_TYPE_NONE); +} + +void ui_notification_cancel_all_by_type(bool ongoing) +{ + notification_type_e type = NOTIFICATION_TYPE_NONE; + + if (ongoing) + type = NOTIFICATION_TYPE_ONGOING; + else + type = NOTIFICATION_TYPE_NOTI; + + notification_delete_all_by_type(NULL, type); +} + +void ui_notification_cancel_all_by_package(const char *package, bool ongoing) +{ + notification_type_e type = NOTIFICATION_TYPE_NONE; + + if (ongoing) + type = NOTIFICATION_TYPE_ONGOING; + else + type = NOTIFICATION_TYPE_NOTI; + + notification_delete_all_by_type(package, type); +} + +int ui_notification_cancel_all_by_app_id(const char *app_id, bool ongoing) +{ + notification_type_e type = NOTIFICATION_TYPE_NONE; + + if (app_id == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (ongoing) + type = NOTIFICATION_TYPE_ONGOING; + else + type = NOTIFICATION_TYPE_NOTI; + + notification_delete_all_by_type(app_id, type); + + return UI_NOTIFICATION_ERROR_NONE; +} + +static bool ui_notification_package_equal(notification_h handle) +{ + char *package = NULL; + char *handle_package = NULL; + char cmdline[512] = {0,}; + char buf[64] = {0,}; + + if (notification_get_pkgname(handle, &handle_package)) + { + return false; + } + + if (app_get_package(&package)) + { + int ret = 0; + int fd = -1; + int pid = getpid(); + + snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); + + fd = open(buf, O_RDONLY); + if (fd < 0) { + return false; + } + + ret = read(fd, cmdline, sizeof(cmdline) - 1); + if (ret <= 0) { + close(fd); + return false; + } + + cmdline[ret] = 0; + close(fd); + + if (strlen(cmdline) == strlen(handle_package)) + { + if (!strncmp(cmdline, handle_package, strlen(cmdline))) + { + return true; + } + } + } + else + { + if (strlen(package) == strlen(handle_package)) + { + if (!strncmp(package, handle_package, strlen(package))) + { + return true; + } + } + } + + return false; +} + +int ui_notification_foreach_notification_posted(bool ongoing, ui_notification_cb callback, void *user_data) +{ + notification_list_h raw_handle_list; + notification_h raw_handle; + notification_type_e notification_type = ongoing ? NOTIFICATION_TYPE_ONGOING : NOTIFICATION_TYPE_NOTI; + ui_notification_h notification = NULL; + bool iterate_next = true; + + if (callback == NULL) + { + LOGE("INVALID_PARAMETER(0x%08x)", UI_NOTIFICATION_ERROR_INVALID_PARAMETER); + return UI_NOTIFICATION_ERROR_INVALID_PARAMETER; + } + + if (notification_get_grouping_list(notification_type, -1, &raw_handle_list)) + { + LOGE("DB_FAILED(0x%08x) : failed to get a notification list", UI_NOTIFICATION_ERROR_DB_FAILED); + return UI_NOTIFICATION_ERROR_DB_FAILED; + } + + while (raw_handle_list != NULL) + { + raw_handle = notification_list_get_data(raw_handle_list); + + if (raw_handle != NULL && ui_notification_package_equal(raw_handle)) + { + if (!ui_notification_construct(ongoing, raw_handle, ¬ification)) + { + iterate_next = callback(notification, user_data); + + ui_notification_destroy(notification); + + if (iterate_next == false) + { + break; + } + } + } + + raw_handle_list = notification_list_get_next(raw_handle_list); + } + + notification_free_list(raw_handle_list); + + return UI_NOTIFICATION_ERROR_NONE; +} + |