From: Inkyun Kil Date: Mon, 20 Jan 2020 03:47:12 +0000 (+0900) Subject: Adds appcore-ui-app-ambient X-Git-Tag: submit/tizen_5.5/20200306.033842~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1a894d929472f84d54a7bc44d49264b0cbe664fa;p=platform%2Fcore%2Fapi%2Fapplication.git Adds appcore-ui-app-ambient Change-Id: Ic3e61ff958249c50f4a6c3fdbf3a0b94ea7f01b5 Signed-off-by: Inkyun Kil --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 085faf4..9b9e154 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) SET(INC_DIR include) ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(appcore_ui_app_ambient) INSTALL( DIRECTORY ${INC_DIR}/ DESTINATION include/appfw diff --git a/appcore_ui_app_ambient/CMakeLists.txt b/appcore_ui_app_ambient/CMakeLists.txt new file mode 100755 index 0000000..46a79b2 --- /dev/null +++ b/appcore_ui_app_ambient/CMakeLists.txt @@ -0,0 +1,56 @@ +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 + ) + +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 diff --git a/appcore_ui_app_ambient/appcore-ui-app-ambient.pc.in b/appcore_ui_app_ambient/appcore-ui-app-ambient.pc.in new file mode 100755 index 0000000..ecad832 --- /dev/null +++ b/appcore_ui_app_ambient/appcore-ui-app-ambient.pc.in @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=/usr +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDE_INSTALL_DIR@/@PC_NAME@ + +Name: @PC_NAME@ +Description: ui application ambient library +Version: @FULLVER@ +Requires: @PC_REQUIRED@ +Libs: -L${libdir} @PC_LDFLAGS@ +Cflags: -I${includedir} diff --git a/appcore_ui_app_ambient/include/ui_app_ambient.h b/appcore_ui_app_ambient/include/ui_app_ambient.h new file mode 100644 index 0000000..9d3702b --- /dev/null +++ b/appcore_ui_app_ambient/include/ui_app_ambient.h @@ -0,0 +1,132 @@ +/* + * 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. + */ + +#ifndef __UI_APP_AMBIENT__ +#define __UI_APP_AMBIENT__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +/** + * @brief Enumeration for period. + * @remark This function only for internal applications + */ +typedef enum { + UI_APP_AMBIENT_UPDATE_NONE, + UI_APP_AMBIENT_UPDATE_MINUTE, + UI_APP_AMBIENT_UPDATE_FIVE_MINUTES, + UI_APP_AMBIENT_UPDATE_FIFTEEN_MINUTES, + UI_APP_AMBIENT_UPDATE_THIRTY_MINUTES +} ui_app_ambient_update_period_e; + +/** + * @brief Enumeration for event. + * @remark This function only for internal applications + */ +typedef enum { + UI_APP_AMBIENT_EVENT_PREPARE, + UI_APP_AMBIENT_EVENT_READY, + UI_APP_AMBIENT_EVENT_CHANGED, +} ui_app_ambient_event_e; + +/** + * @brief Called with the period set with ui_app_ambient_set_update_period() if the device is in the ambient mode. + * @remark This function only for internal applications + * @param[in] user_data The user data to be passed to the callback functions + * @see ui_app_ambient_set_lifecycle() + * @see ui_app_ambient_set_update_period() + */ +typedef void (*ui_app_ambient_update_frame_cb) (void *user_data); + +/** + * @brief Called when the device enters or exits the ambient mode. + * @remark This function only for internal applications + * @param[in] ambient_mode Whether ambient mode is true or not + * @param[in] data The extra bundle data from ambient viewer + * @param[in] user_data The user data to be passed to the callback functions + * @see ui_app_ambient_set_lifecycle() + */ +typedef void (*ui_app_ambient_changed_cb) (bool ambient_mode, bundle *data, void *user_data); + +/** + * @brief The structure type containing the set of callback functions for application events handle. + * @remark This function only for internal applications + * @see ui_app_ambient_set_lifecycle() + */ +typedef struct { + ui_app_ambient_update_frame_cb frame_updated; + ui_app_ambient_changed_cb ambient_changed; +} ui_app_ambient_lifecycle_callback_s; + +/** + * @brief Sets lifecycle for UI ambient lifecycle. + * @remark This function only for internal applications + * @param[in] lifecycle The set of callback functions to handle application lifecycle events + * @param[in] user_data The user data to be passed to the callback functions + * @return @c 0 on success, + * otherwise a negative error value + * @see ui_app_ambient_unset_lifecycle() + */ +int ui_app_ambient_set_lifecycle(ui_app_ambient_lifecycle_callback_s *lifecycle, void *user_data); + +/** + * @brief Unsets lifecycle for UI ambient lifecycle. + * @remark This function only for internal applications + * @see ui_app_ambient_set_lifecycle() + */ +void ui_app_ambient_unset_lifecycle(void); + +/** + * @brief Sets the period of ui_app_ambient_update_frame_cb() calls. + * @remark This function only for internal applications + * @param[in] period period type + * @return @c 0 on success, + * otherwise a negative error value + * @see ui_app_ambient_get_update_period() + */ +int ui_app_ambient_set_update_period(ui_app_ambient_update_period_e period); + +/** + * @brief Gets the period of ui_app_ambient_update_frame_cb() calls. + * @remark This function only for internal applications + * @param[out] period period type + * @return @c 0 on success, + * otherwise a negative error value + * @see ui_app_ambient_set_update_period() + */ +int ui_app_ambient_get_update_period(ui_app_ambient_update_period_e *period); + +/** + * @brief Sends event with bundle data to the @a receiver. + * @remark This function only for internal applications + * @param[in] receiver application id of receiver + * @param[in] event ambient event type + * @param[in] extra extra bundle data + * @return @c 0 on success, + * otherwise a negative error value + */ +int ui_app_ambient_send_event(const char *receiver, ui_app_ambient_event_e event, bundle *extra); + +#ifdef __cplusplus +} +#endif + +#endif /* __UI_APP_AMBIENT__ */ \ No newline at end of file diff --git a/appcore_ui_app_ambient/src/ui_app_ambient.c b/appcore_ui_app_ambient/src/ui_app_ambient.c new file mode 100644 index 0000000..21a3d84 --- /dev/null +++ b/appcore_ui_app_ambient/src/ui_app_ambient.c @@ -0,0 +1,353 @@ +/* + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include + +#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 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 int __get_ambient_tick_offset(ui_app_ambient_update_period_e period) +{ + struct timespec current_time; + struct tm cur_tm; + int offset = 0; + int remain_min; + int minute_base; + + 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; + } + + return offset; +} + +static int __set_ambient_tick_cb() +{ + int r; + int offset_sec = 0; + + 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; + } + + offset_sec = __get_ambient_tick_offset(ambient_lifecycle.period_type); + LOGD("next time offset: %d[type:%d]", offset_sec, ambient_lifecycle.period_type); + + __alarm_init(); + r = alarmmgr_add_alarm_withcb(ALARM_TYPE_VOLATILE, offset_sec, + ambient_tick_type_infos[ambient_lifecycle.period_type].interval, + __alarm_cb, ambient_lifecycle.user_data, &ambient_lifecycle.alarm_id); + if (r < 0) + LOGE("fail to alarmmgr_add_alarm_withcb : error_code : %d", r); + + ambient_lifecycle.frame_updated(ambient_lifecycle.user_data); + + 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; + + bundle_get_str(envelope, "__AMBIENT_MODE__", &mode); + bundle_get_str(envelope, "__AMBIENT_EXTRA__", &extra); + b = bundle_decode((bundle_raw *)extra, strlen(extra)); + + if (ambient_lifecycle.ambient_changed) + ambient_lifecycle.ambient_changed((bool)atoi(mode), b, user_data); + + 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_tick_cb(); + if (ret != 0) { + LOGE("Failed to set ambient tick cb : %d", ret); + return ret; + } + + 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 (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_send_event(const char *receiver, + ui_app_ambient_event_e event, bundle *extra) +{ + char buf[32]; + char endpoint[APPID_BUFFER_MAX]; + char appid_buf[APPID_BUFFER_MAX] = {0, }; + int ret; + bundle *envelope; + + if (!receiver) { + LOGE("receiver should not be null"); + return -1; + } + + 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; + } + + snprintf(endpoint, sizeof(endpoint), "send_extra_data:%s", receiver); + + ret = aul_app_com_send(endpoint, envelope); + if (ret != AUL_R_OK) { + LOGE("Failed aul_app_com_send"); + bundle_free(envelope); + return -1; + } + + bundle_free(envelope); + return 0; +} \ No newline at end of file diff --git a/packaging/appcore-ui-app-ambient.manifest b/packaging/appcore-ui-app-ambient.manifest new file mode 100755 index 0000000..97e8c31 --- /dev/null +++ b/packaging/appcore-ui-app-ambient.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/capi-appfw-application.spec b/packaging/capi-appfw-application.spec index 4a513bc..2433d4f 100644 --- a/packaging/capi-appfw-application.spec +++ b/packaging/capi-appfw-application.spec @@ -6,12 +6,14 @@ Group: System/API License: Apache-2.0 Source0: %{name}-%{version}.tar.gz Source1001: capi-appfw-application.manifest +Source1002: appcore-ui-app-ambient.manifest BuildRequires: cmake BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(bundle) BuildRequires: pkgconfig(appcore-common) BuildRequires: pkgconfig(appcore-efl) BuildRequires: pkgconfig(aul) +BuildRequires: pkgconfig(alarm-service) BuildRequires: pkgconfig(appsvc) BuildRequires: pkgconfig(elementary) BuildRequires: pkgconfig(capi-base-common) @@ -47,6 +49,7 @@ gcov objects of an application library %prep %setup -q cp %{SOURCE1001} . +cp %{SOURCE1002} . %build %if 0%{?gcov:1} @@ -77,6 +80,28 @@ install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj %post -p /sbin/ldconfig %postun -p /sbin/ldconfig +################################################ +# libappcore-ui-app-ambient +%package -n appcore-ui-app-ambient +Summary: APIs to set lifecycle ui application ambient +Version: 0.0.1 +License: Apache-2.0 +Group: Applications/Core Applications + +%description -n appcore-ui-app-ambient +A set of APIs to set lifecycle ui application ambient + +%package -n appcore-ui-app-ambient-devel +Summary: APIs to set lifecycle ui application ambient +Group: Development/Libraries +Requires: watch-holder + +%description -n appcore-ui-app-ambient-devel +Header & package configuration of appcore-ui-app-ambient + +%post -n appcore-ui-app-ambient -p /sbin/ldconfig +%postun -n appcore-ui-app-ambient -p /sbin/ldconfig + %files %manifest %{name}.manifest %{_libdir}/libcapi-appfw-application.so.* @@ -91,6 +116,16 @@ install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj %{_libdir}/pkgconfig/capi-appfw-application.pc %{_libdir}/libcapi-appfw-application.so +%files -n appcore-ui-app-ambient +%manifest appcore-ui-app-ambient.manifest +%license LICENSE +%{_libdir}/libappcore-ui-app-ambient.so.* + +%files -n appcore-ui-app-ambient-devel +%{_includedir}/appcore-ui-app-ambient/*.h +%{_libdir}/pkgconfig/appcore-ui-app-ambient.pc +%{_libdir}/libappcore-ui-app-ambient.so + %if 0%{?gcov:1} %files gcov %{_datadir}/gcov/obj/*