summaryrefslogtreecommitdiff
path: root/appcore_ui_app_ambient
diff options
context:
space:
mode:
Diffstat (limited to 'appcore_ui_app_ambient')
-rw-r--r--[-rwxr-xr-x]appcore_ui_app_ambient/CMakeLists.txt92
-rw-r--r--[-rwxr-xr-x]appcore_ui_app_ambient/appcore-ui-app-ambient.pc.in0
-rw-r--r--appcore_ui_app_ambient/include/ui_app_ambient.h4
-rw-r--r--appcore_ui_app_ambient/src/common_private.hh26
-rw-r--r--appcore_ui_app_ambient/src/log_private.hh37
-rw-r--r--appcore_ui_app_ambient/src/ui_app_ambient.c399
-rw-r--r--appcore_ui_app_ambient/src/ui_app_ambient.cc343
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, &current_time);
-
- tzset();
- localtime_r(&current_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, &current_time);
+ tzset();
+ struct tm current_tm;
+ localtime_r(&current_time.tv_sec, &current_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);
+}