diff options
Diffstat (limited to 'appcore_ui_app_ambient')
-rw-r--r--[-rwxr-xr-x] | appcore_ui_app_ambient/CMakeLists.txt | 92 | ||||
-rw-r--r--[-rwxr-xr-x] | appcore_ui_app_ambient/appcore-ui-app-ambient.pc.in | 0 | ||||
-rw-r--r-- | appcore_ui_app_ambient/include/ui_app_ambient.h | 4 | ||||
-rw-r--r-- | appcore_ui_app_ambient/src/common_private.hh | 26 | ||||
-rw-r--r-- | appcore_ui_app_ambient/src/log_private.hh | 37 | ||||
-rw-r--r-- | appcore_ui_app_ambient/src/ui_app_ambient.c | 399 | ||||
-rw-r--r-- | appcore_ui_app_ambient/src/ui_app_ambient.cc | 343 |
7 files changed, 443 insertions, 458 deletions
diff --git a/appcore_ui_app_ambient/CMakeLists.txt b/appcore_ui_app_ambient/CMakeLists.txt index cf71e8d..cbd9038 100755..100644 --- a/appcore_ui_app_ambient/CMakeLists.txt +++ b/appcore_ui_app_ambient/CMakeLists.txt @@ -1,57 +1,35 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(appcore-ui-app-ambient C) - -SET(PREFIX ${CMAKE_INSTALL_PREFIX}) -SET(EXEC_PREFIX "\${prefix}") -SET(LIBDIR "\${prefix}/lib") -SET(INCLUDEDIR "\${prefix}/include") - -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) - -ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") - -################################################################# -# Build appcore-ui-app-ambient Library -# ------------------------------ -SET(fw_name "appcore-ui-app-ambient") - -SET(MAJORVER 0) -SET(FULLVER 0.0.1) -SET(PC_NAME ${fw_name}) - - -SET(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/ui_app_ambient.c) - -INCLUDE(FindPkgConfig) -pkg_check_modules(${fw_name} REQUIRED - aul - alarm-service - bundle - capi-appfw-app-common - dlog - ) - -FOREACH(flag ${${fw_name}_CFLAGS}) - SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag} -Werror") -ENDFOREACH(flag) - -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC ") -SET(CMAKE_C_FLAGS_DEBUG "-O0 -g -Wall -Werror") - -ADD_LIBRARY(${fw_name} SHARED ${SOURCES}) -SET_TARGET_PROPERTIES(${fw_name} PROPERTIES SOVERSION ${MAJORVER}) -SET_TARGET_PROPERTIES(${fw_name} PROPERTIES VERSION ${FULLVER}) - -TARGET_LINK_LIBRARIES(${fw_name} ${${fw_name}_LDFLAGS} "-ldl -Wl,--as-needed") - -SET(PC_LDFLAGS -l${fw_name}) - -CONFIGURE_FILE(${fw_name}.pc.in ${fw_name}.pc @ONLY) - -INSTALL(TARGETS ${fw_name} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${fw_name}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) - -INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ DESTINATION include/${fw_name}/ - FILES_MATCHING - PATTERN "*.h" - )
\ No newline at end of file +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src + APPCORE_UI_APP_AMBIENT_SRCS) + +ADD_LIBRARY(${TARGET_APPCORE_UI_APP_AMBIENT} SHARED + ${APPCORE_UI_APP_AMBIENT_SRCS}) +SET_TARGET_PROPERTIES(${TARGET_APPCORE_UI_APP_AMBIENT} + PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${TARGET_APPCORE_UI_APP_AMBIENT} + PROPERTIES VERSION ${FULLVER}) + +TARGET_INCLUDE_DIRECTORIES(${TARGET_APPCORE_UI_APP_AMBIENT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include) + +APPLY_PKG_CONFIG(${TARGET_APPCORE_UI_APP_AMBIENT} PUBLIC + ALARM_SERVICE_DEPS + AUL_DEPS + BUNDLE_DEPS + CAPI_APPFW_APP_COMMON_DEPS + DLOG_DEPS +) + +SET(PC_LDFLAGS "-l${TARGET_APPCORE_UI_APP_AMBIENT}") +CONFIGURE_FILE(${TARGET_APPCORE_UI_APP_AMBIENT}.pc.in + ${TARGET_APPCORE_UI_APP_AMBIENT}.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${TARGET_APPCORE_UI_APP_AMBIENT}.pc + DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +INSTALL(TARGETS ${TARGET_APPCORE_UI_APP_AMBIENT} + DESTINATION ${LIB_INSTALL_DIR} + COMPONENT RuntimeLibraries) +INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ + DESTINATION include/appcore-ui-app-ambient/ + FILES_MATCHING + PATTERN "*.h") diff --git a/appcore_ui_app_ambient/appcore-ui-app-ambient.pc.in b/appcore_ui_app_ambient/appcore-ui-app-ambient.pc.in index ecad832..ecad832 100755..100644 --- a/appcore_ui_app_ambient/appcore-ui-app-ambient.pc.in +++ b/appcore_ui_app_ambient/appcore-ui-app-ambient.pc.in diff --git a/appcore_ui_app_ambient/include/ui_app_ambient.h b/appcore_ui_app_ambient/include/ui_app_ambient.h index 70f44a9..0496a4f 100644 --- a/appcore_ui_app_ambient/include/ui_app_ambient.h +++ b/appcore_ui_app_ambient/include/ui_app_ambient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -137,4 +137,4 @@ int ui_app_ambient_notify_event(ui_app_ambient_event_e event, bundle *extra); } #endif -#endif /* __UI_APP_AMBIENT__ */
\ No newline at end of file +#endif /* __UI_APP_AMBIENT__ */ diff --git a/appcore_ui_app_ambient/src/common_private.hh b/appcore_ui_app_ambient/src/common_private.hh new file mode 100644 index 0000000..eaf9a66 --- /dev/null +++ b/appcore_ui_app_ambient/src/common_private.hh @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021 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. + */ + +#ifndef COMMON_PRIVATE_HH_ +#define COMMON_PRIVATE_HH_ + +#undef EXPORT +#define EXPORT __attribute__ ((visibility("default"))) + +#undef API +#define API extern "C" EXPORT + +#endif // COMMON_PRIVATE_HH_ diff --git a/appcore_ui_app_ambient/src/log_private.hh b/appcore_ui_app_ambient/src/log_private.hh new file mode 100644 index 0000000..82ef370 --- /dev/null +++ b/appcore_ui_app_ambient/src/log_private.hh @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 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. + */ + +#ifndef LOG_PRIVATE_HH_ +#define LOG_PRIVATE_HH_ + +#include <dlog.h> + +#undef LOG_TAG +#define LOG_TAG "UI_APP_AMBIENT" + +#undef _E +#define _E LOGE + +#undef _W +#define _W LOGW + +#undef _I +#define _I LOGI + +#undef _D +#define _D LOGD + +#endif // LOG_PRIVATE_HH_ diff --git a/appcore_ui_app_ambient/src/ui_app_ambient.c b/appcore_ui_app_ambient/src/ui_app_ambient.c deleted file mode 100644 index 2046d7c..0000000 --- a/appcore_ui_app_ambient/src/ui_app_ambient.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. - * - * 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 <sys/types.h> -#include <unistd.h> -#include <stdlib.h> - -#include <dlog.h> -#include <aul.h> -#include <aul_app_com.h> -#include <app_common_internal.h> -#include <alarm.h> - -#include "ui_app_ambient.h" - -#ifdef LOG_TAG -#undef LOG_TAG -#endif - -#define LOG_TAG "CAPI_UI_APP_AMBIENT" - -#define APPID_BUFFER_MAX 512 - -#define SECOND 1 -#define ONE_MINUTE_IN_SEC 60 - -#define MILLION 1000000 /* for calculating micro seconds */ - -typedef struct -{ - int alarm_id; - int period_type; - ui_app_ambient_update_frame_cb frame_updated; - ui_app_ambient_changed_cb ambient_changed; - void *user_data; -} ambient_lifecycle_s; - -static ambient_lifecycle_s ambient_lifecycle = { - .alarm_id = 0, - .period_type = UI_APP_AMBIENT_UPDATE_NONE, - .frame_updated = NULL, - .ambient_changed = NULL, - .user_data = NULL -}; - -static struct ambient_tick_type_info { - int interval; - int minute_base; - int hour_base; -} ambient_tick_type_infos[] = { - {0, 0, 0}, - {ONE_MINUTE_IN_SEC, 1, 0}, - {ONE_MINUTE_IN_SEC * 5, 5, 0}, - {ONE_MINUTE_IN_SEC * 15, 15, 0}, - {ONE_MINUTE_IN_SEC * 30, 30, 0} -}; - -static aul_app_com_connection_h __conn; -static bool __initialized = false; -static bool __is_ambient_mode = false; - -static void __alarm_init(void) -{ - int r = 0; - int pid = getpid(); - char appid[APPID_BUFFER_MAX] = {0,}; - - r = aul_app_get_appid_bypid(pid, appid, APPID_BUFFER_MAX); - if (r != AUL_R_OK) { - LOGE("fail to get the appid from the pid : %d", pid); - return; - } - - r = alarmmgr_init(appid); - if (r != ALARMMGR_RESULT_SUCCESS) { - LOGE("fail to alarmmgr_init : error_code : %d", r); - } -} - -static int __alarm_cb(alarm_id_t id, void *data) -{ - LOGD("Ambient Tick callback"); - - if (id == ambient_lifecycle.alarm_id) - ambient_lifecycle.frame_updated(data); - - return 0; -} - -static alarm_entry_t* __get_ambient_tick_alarm(ui_app_ambient_update_period_e period) -{ - struct timespec current_time; - struct tm cur_tm; - struct tm next_tm; - int offset = 0; - int remain_min; - int minute_base; - int ret; - time_t next; - alarm_entry_t *alarm_info = NULL; - alarm_date_t date = {0}; - - alarm_info = alarmmgr_create_alarm(); - if (!alarm_info) - return NULL; - - clock_gettime(CLOCK_REALTIME, ¤t_time); - - tzset(); - localtime_r(¤t_time.tv_sec, &cur_tm); - - switch(period) { - case UI_APP_AMBIENT_UPDATE_MINUTE: - offset = ONE_MINUTE_IN_SEC - cur_tm.tm_sec; - break; - case UI_APP_AMBIENT_UPDATE_FIVE_MINUTES: - case UI_APP_AMBIENT_UPDATE_FIFTEEN_MINUTES: - case UI_APP_AMBIENT_UPDATE_THIRTY_MINUTES: - /* To make a gap minutes */ - minute_base = ambient_tick_type_infos[period].minute_base; - remain_min = minute_base - 1 - (cur_tm.tm_min % minute_base); - offset = (remain_min * ONE_MINUTE_IN_SEC) + - (ONE_MINUTE_IN_SEC - cur_tm.tm_sec); - break; - default: - break; - } - - next = current_time.tv_sec + offset; - localtime_r(&next, &next_tm); - - date.year = next_tm.tm_year + 1900; - date.month = next_tm.tm_mon + 1; - date.day = next_tm.tm_mday; - date.hour = next_tm.tm_hour; - date.min = next_tm.tm_min; - date.sec = next_tm.tm_sec; - - alarmmgr_set_type(alarm_info, ALARM_TYPE_VOLATILE); - - ret = alarmmgr_set_time(alarm_info, date); - if (ret != ALARMMGR_RESULT_SUCCESS) { - LOGE("Failed to alarmmgr_set_time : %d", ret); - alarmmgr_free_alarm(alarm_info); - return NULL; - } - - ret = alarmmgr_set_repeat_mode(alarm_info, ALARM_REPEAT_MODE_REPEAT, - ambient_tick_type_infos[period].interval); - if (ret != ALARMMGR_RESULT_SUCCESS) { - LOGE("Failed to alarmmgr_set_time : %d", ret); - alarmmgr_free_alarm(alarm_info); - return NULL; - } - - LOGD("Next alarm tick [%d:%d:%d]", date.hour, date.min, date.sec); - return alarm_info; -} - -static int __set_ambient_tick_cb() -{ - int r; - alarm_entry_t *alarm_info = NULL; - - if (ambient_lifecycle.period_type == UI_APP_AMBIENT_UPDATE_NONE && - ambient_lifecycle.alarm_id == 0) { - LOGI("DEFAULT period is set [FIFTEEN_MINUTES]"); - ambient_lifecycle.period_type = UI_APP_AMBIENT_UPDATE_FIFTEEN_MINUTES; - } - - alarm_info = __get_ambient_tick_alarm(ambient_lifecycle.period_type); - if (!alarm_info) - return -1; - - __alarm_init(); - - r = alarmmgr_add_alarm_withcb_with_localtime(alarm_info, __alarm_cb, - ambient_lifecycle.user_data, &ambient_lifecycle.alarm_id); - if (r < 0) - LOGE("fail to alarmmgr_add_alarm : error_code : %d", r); - - ambient_lifecycle.frame_updated(ambient_lifecycle.user_data); - - alarmmgr_free_alarm(alarm_info); - return r; -} - -int __on_change_signal(const char *endpoint, aul_app_com_result_e e, - bundle *envelope, void *user_data) -{ - LOGE("__on_change_signal"); - - bundle *b = NULL; - char *extra; - char *mode; - ui_app_ambient_state_e state; - - bundle_get_str(envelope, "__AMBIENT_MODE__", &mode); - bundle_get_str(envelope, "__AMBIENT_EXTRA__", &extra); - b = bundle_decode((bundle_raw *)extra, strlen(extra)); - - state = (ui_app_ambient_state_e)atoi(mode); - - if (ambient_lifecycle.ambient_changed) - ambient_lifecycle.ambient_changed(state, b, user_data); - - if (state == UI_APP_AMBIENT_STATE_ENTER && !__is_ambient_mode) { - int ret = __set_ambient_tick_cb(); - if (ret != 0) - LOGE("Failed to set ambient tick cb : %d", ret); - else - __is_ambient_mode = true; - } else if (state == UI_APP_AMBIENT_STATE_LEAVE && __is_ambient_mode) { - if (ambient_lifecycle.alarm_id) { - alarmmgr_remove_alarm(ambient_lifecycle.alarm_id); - ambient_lifecycle.alarm_id = 0; - } - - __is_ambient_mode = false; - } - - if (b) - bundle_free(b); - - return 0; -} - -static int __set_ambient_changed_cb() -{ - int r; - - if (__conn) { - LOGD("Already set ambient changed cb"); - return 0; - } - - LOGD("Set ambient changed cb"); - - r = aul_app_com_create("ui.ambientchange", NULL, __on_change_signal, - ambient_lifecycle.user_data, &__conn); - if (r != AUL_R_OK) { - LOGE("Failed to listen 'ui.ambientchange' signal"); - } - - return r; -} - -int ui_app_ambient_set_lifecycle(ui_app_ambient_lifecycle_callback_s *lifecycle, - void *user_data) -{ - int ret = -1; - - if (!lifecycle) { - LOGE("Invalid parameter"); - return ret; - } - - if (__initialized) { - LOGW("Lifecycle is already set"); - return 0; - } - - ambient_lifecycle.frame_updated = lifecycle->frame_updated; - ambient_lifecycle.ambient_changed = lifecycle->ambient_changed; - ambient_lifecycle.user_data = user_data; - - ret = __set_ambient_changed_cb(); - if (ret != 0) { - LOGE("Failed to set ambient changed cb : %d", ret); - ui_app_ambient_unset_lifecycle(); - return ret; - } - - __initialized = true; - return 0; -} - -void ui_app_ambient_unset_lifecycle() -{ - if (__conn) { - if (aul_app_com_leave(__conn) < 0) - LOGE("failed to leave app com disable"); - - __conn = NULL; - } - - if (ambient_lifecycle.alarm_id) { - alarmmgr_remove_alarm(ambient_lifecycle.alarm_id); - ambient_lifecycle.alarm_id = 0; - } - - if (ambient_lifecycle.ambient_changed) - ambient_lifecycle.ambient_changed = NULL; - - if (ambient_lifecycle.frame_updated) - ambient_lifecycle.frame_updated = NULL; - - if (ambient_lifecycle.user_data) - ambient_lifecycle.user_data = NULL; - - __initialized = false; -} - -int ui_app_ambient_set_update_period(ui_app_ambient_update_period_e period) -{ - int ret = 0; - LOGD("set update period : %d", period); - ambient_lifecycle.period_type = period; - - if (__is_ambient_mode) { - if (ambient_lifecycle.alarm_id) { - alarmmgr_remove_alarm(ambient_lifecycle.alarm_id); - ambient_lifecycle.alarm_id = 0; - } - - if (ambient_lifecycle.period_type != UI_APP_AMBIENT_UPDATE_NONE) - ret = __set_ambient_tick_cb(); - } - - return ret; -} - -int ui_app_ambient_get_update_period(ui_app_ambient_update_period_e *period) -{ - if (!period) { - LOGE("Invalid parameter"); - return -1; - } - - *period = ambient_lifecycle.period_type; - return 0; -} - -int ui_app_ambient_notify_event(ui_app_ambient_event_e event, bundle *extra) -{ - char buf[32]; - char appid_buf[APPID_BUFFER_MAX] = {0, }; - int ret; - bundle *envelope; - - if (extra == NULL) { - LOGE("extra data is null"); - envelope = bundle_create(); - } else { - envelope = bundle_dup(extra); - } - - if (envelope == NULL) { - LOGE("out of memory"); - return -1; - } - - snprintf(buf, sizeof(buf), "%d", event); - ret = bundle_add_str(envelope, "__APP_AMBIENT_EVENT__", buf); - if (ret != BUNDLE_ERROR_NONE) { - LOGE("bundle_add_str returns false"); - bundle_free(envelope); - return -1; - } - - if (aul_app_get_appid_bypid( - getpid(), appid_buf, sizeof(appid_buf)) != AUL_R_OK) { - LOGE("Failed to get appid (%d)", getpid()); - bundle_free(envelope); - return -1; - } - - ret = bundle_add_str(envelope, "__APP_AMBIENT_SENDER__", appid_buf); - if (ret != BUNDLE_ERROR_NONE) { - LOGE("bundle_add_str returns false"); - bundle_free(envelope); - return -1; - } - - ret = aul_app_com_send("aod.ambientevent", envelope); - if (ret != AUL_R_OK) { - LOGE("Failed aul_app_com_send"); - bundle_free(envelope); - return -1; - } - LOGI("Send AOD Event(%d) done", event); - - bundle_free(envelope); - return 0; -}
\ No newline at end of file diff --git a/appcore_ui_app_ambient/src/ui_app_ambient.cc b/appcore_ui_app_ambient/src/ui_app_ambient.cc new file mode 100644 index 0000000..2f13c24 --- /dev/null +++ b/appcore_ui_app_ambient/src/ui_app_ambient.cc @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd. + * + * 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 <alarm.h> +#include <app_common_internal.h> +#include <aul.h> +#include <aul_app_com.h> +#include <bundle_cpp.h> +#include <bundle_internal.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> + +#include <memory> +#include <string> + +#include "common_private.hh" +#include "log_private.hh" +#include "ui_app_ambient.h" + +namespace { + +constexpr const int SECOND = 1; +constexpr const int ONE_MINUTE_IN_SEC = 60; +constexpr const int MILLION = 1000000; // for calculating micro seconds + +struct AmbientTickTypeInfo { + int interval_; + int minute_base_; + int hour_base_; +}; + +AmbientTickTypeInfo ambient_tick_type_infos[] = { + { 0, 0 , 0}, + { ONE_MINUTE_IN_SEC, 1, 0 }, + { ONE_MINUTE_IN_SEC * 5, 5, 0 }, + { ONE_MINUTE_IN_SEC * 15, 15, 0 }, + { ONE_MINUTE_IN_SEC * 30, 30, 0 } +}; + +class UIAppAmbient { + public: + ~UIAppAmbient() {} + + int SetLifecycleCallback(ui_app_ambient_lifecycle_callback_s* callback, + void* user_data) { + if (initialized_) + return 0; + + callback_ = *callback; + user_data_ = user_data; + + int ret = aul_app_com_create("ui.ambientchange", nullptr, OnAppComCb, this, + &conn_); + if (ret != AUL_R_OK) { + _E("aul_app_com_create() is failed. error(%d)", ret); + return ret; + } + + initialized_ = true; + return 0; + } + + void UnsetLifecycleCallback() { + if (conn_) { + aul_app_com_leave(conn_); + conn_ = nullptr; + } + + if (alarm_id_) { + alarmmgr_remove_alarm(alarm_id_); + alarm_id_ = 0; + } + + callback_.ambient_changed = nullptr; + callback_.frame_updated = nullptr; + user_data_ = nullptr; + initialized_ = false; + } + + int SetUpdatePeriod(int period_type) { + period_type_ = period_type; + if (IsAmbientMode()) { + if (alarm_id_) { + alarmmgr_remove_alarm(alarm_id_); + alarm_id_ = 0; + } + + if (period_type != UI_APP_AMBIENT_UPDATE_NONE) + return SetAmbientTick(); + } + + return 0; + } + + int GetUpdatePeriod() { + return period_type_; + } + + int SendAmbientEvent(ui_app_ambient_event_e event, bundle* extra) { + int ret = SetAppId(); + if (ret != 0) + return ret; + + tizen_base::Bundle envelope(extra ? extra : bundle_create(), false, true); + envelope.Add("__APP_AMBIENT_EVENT__", std::to_string(event).c_str()); + envelope.Add("__APP_AMBIENT_SENDER__", app_id_.c_str()); + ret = aul_app_com_send("aod.ambientevent", envelope.GetHandle()); + if (ret != AUL_R_OK) { + _E("aul_app_com_send() is failed. error(%d)", ret); + return -1; + } + + _I("Send AOD Event(%d) done", event); + return 0; + } + + private: + static int OnAppComCb(const char* endpoint, aul_app_com_result_e result, + bundle* envelope, void* user_data) { + _E("OnAppComMessageReceived"); + const char* mode = bundle_get_val(envelope, "__AMBIENT_MODE__"); + if (mode == nullptr) + return -1; + + ui_app_ambient_state_e state = static_cast<ui_app_ambient_state_e>( + std::stoi(mode)); + + const char* extra = bundle_get_val(envelope, "__AMBIENT_EXTRA__"); + if (extra == nullptr) + return -1; + + tizen_base::Bundle b(extra); + + auto* handle = static_cast<UIAppAmbient*>(user_data); + auto callback = handle->callback_; + if (callback.ambient_changed) + callback.ambient_changed(state, b.GetHandle(), handle->user_data_); + + if (state == UI_APP_AMBIENT_STATE_ENTER && !handle->IsAmbientMode()) { + int ret = handle->SetAmbientTick(); + if (ret != 0) + _E("Failed to set alarm"); + } else if (state == UI_APP_AMBIENT_STATE_LEAVE && handle->IsAmbientMode()) { + handle->UnsetAmbientTick(); + } + + return 0; + } + + static int AlarmCb(alarm_id_t id, void* user_data) { + _D("OnAmbientTick"); + auto* handle = static_cast<UIAppAmbient*>(user_data); + if (handle->alarm_id_ == id) { + auto callback = handle->callback_; + callback.frame_updated(handle->user_data_); + } + + return 0; + } + + int SetAppId() { + if (app_id_.empty()) { + char appid[256] = { 0, }; + int ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid)); + if (ret != AUL_R_OK) { + _E("aul_app_get_appid_bypid() is failed. error(%d)", ret); + return ret; + } + + app_id_ = std::string(appid); + } + return 0; + } + + alarm_entry_t* GetAmbientTickAlarm(int period_type) { + alarm_entry_t* alarm_info = alarmmgr_create_alarm(); + if (alarm_info == nullptr) + return nullptr; + + std::unique_ptr<alarm_entry_t, decltype(alarmmgr_free_alarm)*> ptr( + alarm_info, alarmmgr_free_alarm); + + struct timespec current_time; + clock_gettime(CLOCK_REALTIME, ¤t_time); + tzset(); + struct tm current_tm; + localtime_r(¤t_time.tv_sec, ¤t_tm); + + int offset = 0; + if (period_type == UI_APP_AMBIENT_UPDATE_FIVE_MINUTES || + period_type == UI_APP_AMBIENT_UPDATE_FIFTEEN_MINUTES || + period_type == UI_APP_AMBIENT_UPDATE_THIRTY_MINUTES) { + int minute_base = ambient_tick_type_infos[period_type].minute_base_; + int remain_min = minute_base - 1 - (current_tm.tm_min % minute_base); + offset = (remain_min * ONE_MINUTE_IN_SEC) + + (ONE_MINUTE_IN_SEC - current_tm.tm_sec); + } else if (period_type == UI_APP_AMBIENT_UPDATE_MINUTE) { + offset = ONE_MINUTE_IN_SEC - current_tm.tm_sec; + } + + struct tm next_tm; + time_t next = current_time.tv_sec + offset; + localtime_r(&next, &next_tm); + + alarm_date_t date = { 0, }; + date.year = next_tm.tm_year + 1900; + date.month = next_tm.tm_mon + 1; + date.day = next_tm.tm_mday; + date.hour = next_tm.tm_hour; + date.min = next_tm.tm_min; + date.sec = next_tm.tm_sec; + + alarmmgr_set_type(alarm_info, ALARM_TYPE_VOLATILE); + + int ret = alarmmgr_set_time(alarm_info, date); + if (ret != ALARMMGR_RESULT_SUCCESS) { + _E("alarmmgr_set_time() is failed. error(%d)", ret); + return nullptr; + } + + ret = alarmmgr_set_repeat_mode(alarm_info, ALARM_REPEAT_MODE_REPEAT, + ambient_tick_type_infos[period_type].interval_); + if (ret != ALARMMGR_RESULT_SUCCESS) { + _E("alarmmgr_set_repeat_mode() is failed. error(%d)", ret); + return nullptr; + } + + LOGD("Next alarm tick [%d:%d:%d]", date.hour, date.min, date.sec); + return ptr.release(); + } + + int SetAmbientTick() { + if (period_type_ == UI_APP_AMBIENT_UPDATE_NONE && alarm_id_ == 0) { + _I("Default period is set [FIFTEEN_MINUTES]"); + period_type_ = UI_APP_AMBIENT_UPDATE_FIFTEEN_MINUTES; + } + + int ret = SetAppId(); + if (ret != 0) + return ret; + + ret = alarmmgr_init(app_id_.c_str()); + if (ret != ALARMMGR_RESULT_SUCCESS) + _E("alarmmgr_init() is failed. error(%d)", ret); + + alarm_entry_t* alarm_info = GetAmbientTickAlarm(period_type_); + if (alarm_info == nullptr) + return -1; + + ret = alarmmgr_add_alarm_withcb_with_localtime(alarm_info, AlarmCb, + this, &alarm_id_); + if (ret < 0) { + _E("alarmmgr_add_alarm_withcb_with_localtime() is failed. error(%d)", + ret); + } + + callback_.frame_updated(user_data_); + alarmmgr_free_alarm(alarm_info); + ambient_mode_ = true; + return 0; + } + + void UnsetAmbientTick() { + if (alarm_id_) { + alarmmgr_remove_alarm(alarm_id_); + alarm_id_ = 0; + } + + ambient_mode_ = false; + } + + bool IsAmbientMode() { + return ambient_mode_; + } + + private: + bool initialized_ = false; + std::string app_id_; + aul_app_com_connection_h conn_ = nullptr; + ui_app_ambient_lifecycle_callback_s callback_ = { 0, }; + void* user_data_ = nullptr; + bool ambient_mode_ = false; + int period_type_ = UI_APP_AMBIENT_UPDATE_NONE; + int alarm_id_ = 0; +}; + +UIAppAmbient context; + +} // namespace + +API int ui_app_ambient_set_lifecycle( + ui_app_ambient_lifecycle_callback_s* lifecycle, void* user_data) { + if (lifecycle == nullptr || + lifecycle->ambient_changed == nullptr || + lifecycle->frame_updated == nullptr) { + _E("Invalid parameter"); + return -1; + } + + return context.SetLifecycleCallback(lifecycle, user_data); +} + +API void ui_app_ambient_unset_lifecycle(void) { + context.UnsetLifecycleCallback(); +} + +API int ui_app_ambient_set_update_period( + ui_app_ambient_update_period_e period) { + _D("Period: %d", period); + return context.SetUpdatePeriod(period); +} + +API int ui_app_ambient_get_update_period( + ui_app_ambient_update_period_e* period) { + if (period == nullptr) { + _E("Invalid parameter"); + return -1; + } + + *period = static_cast<ui_app_ambient_update_period_e>( + context.GetUpdatePeriod()); + return 0; +} + +API int ui_app_ambient_notify_event(ui_app_ambient_event_e event, + bundle* extra) { + return context.SendAmbientEvent(event, extra); +} |