INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED sqlite3 db-util libtzplatform-config bundle aul)
+pkg_check_modules(pkgs REQUIRED sqlite3 db-util libtzplatform-config bundle aul gio-2.0)
FOREACH(flag ${pkgs_CFLAGS})
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/rua_stat.h DESTINATION include/${PROJECT_NAME})
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/rua_stat_internal.h DESTINATION include/${PROJECT_NAME})
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/rua_util.h DESTINATION include/${PROJECT_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/rua_dbus.h DESTINATION include/${PROJECT_NAME})
ADD_SUBDIRECTORY(test)
};
/**
+ * @brief Called when the history is updated.
+ * @param[in] table db table pointer
+ * @param[in] nrows the number of record
+ * @param[in] ncols the number of field
+ * @param[in] user_data The user data passed from rua_register_update_cb()
+ */
+typedef void (*rua_history_update_cb) (
+ char **table,
+ int nrows,
+ int ncols,
+ void *user_data);
+
+/**
* @brief Add history
* @param[in] pkg_name package name to delete history
* @return 0 on success, otherwise a nagative error value
const char *instance_id);
/**
+ * @brief Registers a callback function to be invoked when the history is updated
+ * @param[in] callback The callback function to be registered
+ * @param[in] user_data The user data passed to rua_register_update_cb()
+ * @param[out] callback_id Added callback id
+ * @return 0 on success, otherwise a nagative error value
+ * @retval 0 if on successful
+ * @retval -1 if it is already registered or on failed
+ */
+API int rua_register_update_cb(rua_history_update_cb callback,
+ void *user_data, int *callback_id);
+API int rua_register_update_cb_for_uid(rua_history_update_cb callback,
+ void *user_data, int *callback_id, uid_t uid);
+
+/**
+ * @brief Unregisters a callback function
+ * @param[in] callback_id Target callback id
+ * @return 0 on success, otherwise a nagative error value
+ * @retval 0 if on successful
+ * @retval -1 if the callback was not registered or on failed
+ */
+API int rua_unregister_update_cb(int callback_id);
+API int rua_unregister_update_cb_for_uid(int callback_id, uid_t uid);
+
+/**
* @brief Initialize rua
* @return 0 on success, otherwise a nagative error value
* @retval 0 on successful
--- /dev/null
+/*
+ * Copyright (c) 2017 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.
+ */
+
+/**
+ * @file rua_dbus.h
+ * @brief RUA DBUS API declaration header file.
+ * @version 0.1
+ * @history 0.1: RUA DBUS API Declarations, structure declaration
+ */
+
+#ifndef __RUA_DBUS_H__
+#define __RUA_DBUS_H__
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <dlog.h>
+
+#ifndef API
+#define API __attribute__ ((visibility("default")))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "RUA"
+
+typedef enum
+{
+ ADD,
+ DELETE
+} update_type;
+
+int rua_dbus_send_update_signal(update_type type);
+int rua_dbus_signal_subscribe(rua_history_update_cb callback,
+ void *user_data, int *callback_id);
+int rua_dbus_signal_unsubscribe(int callback_id);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*__RUA_DBUS_H__*/
BuildRequires: pkgconfig(db-util)
BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(libtzplatform-config)
+BuildRequires: pkgconfig(gio-2.0)
%define upgrade_script_path /usr/share/upgrade/scripts
#include "rua_internal.h"
#include "rua.h"
#include "db-schema.h"
+#include "rua_dbus.h"
int rua_add_history_for_uid(char *pkg_name, char *app_path, char *arg, uid_t uid)
{
return r;
}
+int rua_register_update_cb(rua_history_update_cb callback, void *user_data, int *callback_id)
+{
+ return rua_register_update_cb_for_uid(callback, user_data, callback_id, getuid());
+}
+
+int rua_register_update_cb_for_uid(rua_history_update_cb callback, void *user_data, int *callback_id, uid_t uid)
+{
+ int r;
+
+ if (callback == NULL)
+ return -1;
+
+ r = _rua_util_check_uid(uid);
+ if (r == -1)
+ return r;
+
+ r = rua_dbus_signal_subscribe(callback, user_data, callback_id);
+
+ return r;
+}
+
+int rua_unregister_update_cb(int callback_id)
+{
+ return rua_unregister_update_cb_for_uid(callback_id, getuid());
+}
+
+int rua_unregister_update_cb_for_uid(int callback_id, uid_t uid)
+{
+ int r;
+
+ r = _rua_util_check_uid(uid);
+ if (r == -1)
+ return r;
+
+ r = rua_dbus_signal_unsubscribe(callback_id);
+
+ return r;
+}
+
int rua_history_unload_db(char ***table)
{
if (*table) {
--- /dev/null
+/*
+ * Copyright (c) 2017 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 <glib.h>
+#include <gio/gio.h>
+
+#include "rua.h"
+#include "rua_dbus.h"
+
+#define RUA_INTERFACE "org.tizen.rua"
+#define RUA_PATH "/org/tizen/rua"
+#define RUA_SIGNAL_DATA_UPDATE "dataupdate"
+
+struct cb_data
+{
+ int callback_id;
+ rua_history_update_cb callback;
+ void *user_data;
+};
+
+static GDBusConnection *conn;
+static guint s_id;
+
+static gint atomic_callback_id;
+static GHashTable* callback_hash_table;
+
+static void __foreach_callback(gpointer key, gpointer value,
+ gpointer user_data);
+static void __signal_handler(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data);
+static void __rua_dbus_init(void);
+static void __rua_dbus_exit(void);
+
+int rua_dbus_send_update_signal(update_type type)
+{
+ __rua_dbus_init();
+ GError *err = NULL;
+
+ if (g_dbus_connection_emit_signal(conn,
+ NULL,
+ RUA_PATH,
+ RUA_INTERFACE,
+ RUA_SIGNAL_DATA_UPDATE,
+ g_variant_new("(i)", type),
+ &err) == FALSE) {
+ LOGE("g_dbus_connection_emit_signal() is failed. %s",
+ err->message);
+ __rua_dbus_exit();
+ return -1;
+ }
+
+ if (g_dbus_connection_flush_sync(conn, NULL, &err) == FALSE) {
+ LOGE("g_dbus_connection_flush_sync() is failed. %s",
+ err->message);
+ __rua_dbus_exit();
+ return -1;
+ }
+
+ g_clear_error(&err);
+
+ __rua_dbus_exit();
+
+ return 0;
+}
+
+int rua_dbus_signal_subscribe(rua_history_update_cb callback,
+ void *user_data, int *callback_id)
+{
+ struct cb_data *cd = NULL;
+
+ if (s_id == 0) {
+ __rua_dbus_init();
+
+ s_id = g_dbus_connection_signal_subscribe(conn,
+ NULL,
+ RUA_INTERFACE,
+ RUA_SIGNAL_DATA_UPDATE,
+ RUA_PATH,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ __signal_handler,
+ NULL,
+ NULL);
+
+ if (s_id == 0) {
+ LOGE("g_dbus_connection_signal_subscribe() is failed.");
+ __rua_dbus_exit();
+ return -1;
+ }
+
+ if (!callback_hash_table) {
+ callback_hash_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, free);
+ if (!callback_hash_table) {
+ LOGE("out of memory : g_hash_table_new() is failed");
+ __rua_dbus_exit();
+ return -1;
+ }
+ }
+ }
+
+ cd = (struct cb_data *)malloc(sizeof(struct cb_data));
+ if (!cd) {
+ LOGE("out of memory : malloc() is failed");
+ return -1;
+ }
+
+ g_atomic_int_inc(&atomic_callback_id);
+
+ cd->callback = callback;
+ cd->user_data = user_data;
+ cd->callback_id = atomic_callback_id;
+
+ g_hash_table_insert(callback_hash_table,
+ GINT_TO_POINTER(cd->callback_id), (gpointer)cd);
+
+ *callback_id = cd->callback_id;
+
+ return 0;
+}
+
+int rua_dbus_signal_unsubscribe(int callback_id)
+{
+ gboolean result = FALSE;
+ guint table_size = 0;
+
+ result = g_hash_table_remove(callback_hash_table, GINT_TO_POINTER(callback_id));
+ if (!result) {
+ LOGE("g_hash_table_remove failed(%d is wrong)", callback_id);
+ return -1;
+ }
+
+ table_size = g_hash_table_size(callback_hash_table);
+ if (s_id && table_size == 0) {
+ g_dbus_connection_signal_unsubscribe(conn, s_id);
+ g_hash_table_destroy(callback_hash_table);
+ __rua_dbus_exit();
+ callback_hash_table = NULL;
+ s_id = 0;
+ }
+
+ return 0;
+}
+
+static void __foreach_callback(gpointer key, gpointer value,
+ gpointer user_data)
+{
+ char **table = NULL;
+ int nrows = 0;
+ int ncols = 0;
+ int r = 0;
+
+ struct cb_data *cd = (struct cb_data *)value;
+
+ r = rua_history_load_db(&table, &nrows, &ncols);
+ if (r == -1)
+ return;
+
+ if (cd->callback) {
+ cd->callback(table, nrows, ncols, cd->user_data);
+ }
+}
+
+static void __signal_handler(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ int update_type;
+
+ LOGI("__signal_handler");
+ if (g_strcmp0(signal_name, RUA_SIGNAL_DATA_UPDATE))
+ return;
+
+ g_variant_get(parameters, "(i)", &update_type);
+
+ g_hash_table_foreach(callback_hash_table, __foreach_callback, NULL);
+}
+
+static void __rua_dbus_init(void)
+{
+ if (!conn) {
+ GError *err = NULL;
+ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+ if (!conn) {
+ LOGE("g_bus_get_sync() is failed. %s", err->message);
+ g_error_free(err);
+ return;
+ }
+ }
+}
+
+static void __rua_dbus_exit(void)
+{
+ if (conn) {
+ g_object_unref(conn);
+ conn = NULL;
+ }
+}
#include "rua_internal.h"
#include "db-schema.h"
#include "rua_util.h"
+#include "rua_dbus.h"
static int __exec(sqlite3 *db, char *query)
{
result = -1;
}
+ r = rua_dbus_send_update_signal(DELETE);
+ if (r == -1) {
+ LOGE("[RUA SEND SIGNAL ERROR] \n");
+ db_util_close(db);
+ return -1;
+ }
+
if (db != NULL)
db_util_close(db);
return -1;
}
+ r = rua_dbus_send_update_signal(ADD);
+ if (r == -1) {
+ LOGE("[RUA SEND SIGNAL ERROR] \n");
+ db_util_close(db);
+ return -1;
+ }
+
db_util_close(db);
return r;
}
#include <unistd.h>
#include <sys/types.h>
#include <glib.h>
+#include <pthread.h>
/* For multi-user support */
#include <tzplatform_config.h>
#include "rua_stat.h"
#include "rua_stat_internal.h"
+static GMainLoop *mainloop = NULL;
+static pthread_t g_thread;
+
+static int callback_id_table[10] = { 0, };
+
+static gboolean run_test(int selected_number);
+static void __print_menu()
+{
+ int test_num = 0;
+ int run_next = 1;
+
+ while(run_next) {
+ printf("==========================================\n");
+ printf(" Basic test menu \n");
+ printf("==========================================\n");
+ printf(" 0. EXIT\n");
+ printf(" 1. Add rua history to DEFAULT USER(5001)\n");
+ printf(" 2. Delete history with pkgname\n");
+ printf(" 3. Load RUA history\n");
+ printf(" 4. Update RUA stat\n");
+ printf(" 5. Get RUA stat tags\n");
+ printf(" 6. Register update callback (MAX 10)\n");
+ printf(" 7. Unregister update callback\n");
+ printf("------------------------------------------\n");
+ int ret = scanf("%d", &test_num);
+ if (ret < 0) {
+ printf("scanf fail %d", ret);
+ break;
+ }
+
+ run_next = run_test(test_num);
+ }
+
+}
+
+static void __update_cb(char **table, int rows, int cols)
+{
+ struct rua_rec record;
+
+ printf("update_cb");
+ int row;
+ for (row = 0; row < rows; ++row) {
+ rua_history_get_rec(&record, table, rows, cols, row);
+ printf("pkgname : %s, time : %d \n", record.pkg_name, (int)record.launch_time);
+ }
+
+}
+
static int __add_history()
{
int ret;
return ret;
}
-static gboolean run_test(int selected_number)
+static int __register_callback()
+{
+ int ret;
+
+ int i = 0;
+ for (i = 0; i < 10; i++) {
+ if (callback_id_table[i] == 0) {
+ int output = 0;
+ ret = rua_register_update_cb(__update_cb, NULL, &output);
+ if (ret == -1) {
+ printf("__register_callback error : %d \n", ret);
+ return -1;
+ }
+
+ printf("callback id : %d \n", output);
+ callback_id_table[i] = output;
+
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int __unregister_callback()
{
- gboolean go_to_loop = TRUE;
+ int ret;
+
+ int i = 0;
+ int id = 0;
+ printf("Enter callback_id (The number from register_callback) : ");
+ scanf("%d", &id);
+
+ for (i = 0; i < 10; i++) {
+ if (callback_id_table[i] == id) {
+ ret = rua_unregister_update_cb(callback_id_table[i]);
+ if (ret == -1)
+ printf("__unregister_callback : %d \n", ret);
+ callback_id_table[i] = 0;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+
+static gboolean run_test(int selected_number)
+{
+ int r = 0;
+ gboolean loop = TRUE;
switch (selected_number) {
case 0:
- go_to_loop = FALSE;
+ g_main_loop_quit(mainloop);
+ loop = FALSE;
break;
case 1:
__get_stat_tags();
break;
+ case 6:
+ r = __register_callback();
+ if (r == -1)
+ printf("table is full");
+ break;
+
+ case 7:
+ r = __unregister_callback();
+ if (r == -1)
+ printf("id is wrong");
+
+ break;
+
default:
break;
}
- return go_to_loop;
+
+ return loop;
}
int main()
{
int ret = 0;
- int test_num;
- gboolean run_next = TRUE;
- while(run_next) {
- printf("==========================================\n");
- printf(" Basic test menu \n");
- printf("==========================================\n");
- printf(" 0. EXIT\n");
- printf(" 1. Add rua history to DEFAULT USER(5001)\n");
- printf(" 2. Delete history with pkgname\n");
- printf(" 3. Load RUA history\n");
- printf(" 4. Update RUA stat\n");
- printf(" 5. Get RUA stat tags\n");
- printf("------------------------------------------\n");
- ret = scanf("%d", &test_num);
- if (ret < 0) {
- printf("scanf fail %d", ret);
- break;
- }
+ mainloop = g_main_loop_new(NULL, FALSE);
- run_next = run_test(test_num);
+ int result = pthread_create(&g_thread, NULL, __print_menu, (void *)NULL);
+ if (result < 0)
+ {
+ printf("pthread_create failed in initialize\n");
+ return 0;
}
+
+ g_main_loop_run(mainloop);
+ g_main_loop_unref(mainloop);
+ mainloop = NULL;
+
return ret;
}