X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gps-manager%2Fgps_manager.c;h=4dcb23a29587cdb3b1cafed4b80f36b7e33fbcc7;hb=209c999100c1fd37e4e7c91b94608bd43abf0147;hp=5e976f396aa05a25cb3537c1534b5a407b61340a;hpb=76aef537743d91a75c780eb6623b7b38a4c6547f;p=framework%2Flocation%2Fgps-manager.git diff --git a/gps-manager/gps_manager.c b/gps-manager/gps_manager.c index 5e976f3..4dcb23a 100644 --- a/gps-manager/gps_manager.c +++ b/gps-manager/gps_manager.c @@ -43,6 +43,7 @@ #include "server.h" #include "last_position.h" +#include "debug_util.h" #define GEOCLUE_GPSMANAGER_DBUS_SERVICE "org.freedesktop.Geoclue.Providers.GpsManager" #define GEOCLUE_GPSMANAGER_DBUS_PATH "/org/freedesktop/Geoclue/Providers/GpsManager" @@ -50,6 +51,7 @@ typedef struct { GcProvider parent; GMainLoop *loop; + GMutex *mutex; GeoclueStatus status; pos_data_t position; @@ -59,7 +61,8 @@ typedef struct { pos_data_t last_position; sv_data_t last_satellite; - GHashTable *connections; + gboolean is_running; + gint client_count; } GeoclueGpsManager; typedef struct { @@ -82,19 +85,13 @@ G_DEFINE_TYPE_WITH_CODE(GeoclueGpsManager, geoclue_gpsmanager, GC_TYPE_PROVIDER, G_IMPLEMENT_INTERFACE(GC_TYPE_IFACE_SATELLITE, init_satellite) G_IMPLEMENT_INTERFACE(GC_TYPE_IFACE_GEOCLUE, init_geoclue)); -static void constructed(GObject * object) +static GObject* constructor (GType type, guint n_props, GObjectConstructParam *props) { - GeoclueGpsManager *gps_manager = GEOCLUE_GPSMANAGER(object); + GObject *object; - gps_manager->connections = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + object = ((GObjectClass *) geoclue_gpsmanager_parent_class)->constructor(type, n_props, props); - gps_manager->status = GEOCLUE_STATUS_UNAVAILABLE; - - memset(&gps_manager->position, 0x00, sizeof(pos_data_t)); - memset(&gps_manager->satellite, 0x00, sizeof(sv_data_t)); - memset(&gps_manager->nmea, 0x00, sizeof(nmea_data_t)); - - ((GObjectClass *) geoclue_gpsmanager_parent_class)->constructed(object); + return object; } static void finalize(GObject * object) @@ -105,9 +102,7 @@ static void finalize(GObject * object) static void dispose(GObject * object) { GeoclueGpsManager *gpsmanager = GEOCLUE_GPSMANAGER(object); - - g_hash_table_destroy(gpsmanager->connections); - + g_mutex_free(gpsmanager->mutex); ((GObjectClass *) geoclue_gpsmanager_parent_class)->dispose(object); } @@ -131,33 +126,87 @@ static gboolean get_provider_info(GcIfaceGeoclue * geoclue, gchar ** name, gchar return TRUE; } -static void print_option(gpointer key, gpointer value, gpointer data) +static void start_tracking(GeoclueGpsManager * gpsmanager) { - g_print(" %s - %s\n", (char *)key, (char *)value); + LOG_GPS(DBG_LOW, "start_tracking"); + gpsmanager->status = GEOCLUE_STATUS_ACQUIRING; + g_mutex_lock(gpsmanager->mutex); + if (request_start_session() == TRUE) { + gpsmanager->is_running = TRUE; + } else { + LOG_GPS(DBG_ERR, "Fail to request_start_session"); + } + g_mutex_unlock(gpsmanager->mutex); } -static gboolean set_options(GcIfaceGeoclue * gc, GHashTable * options, GError ** error) +static void stop_tracking(GeoclueGpsManager * gpsmanager) { - g_print("Options received---\n"); - g_hash_table_foreach(options, print_option, NULL); - return TRUE; + LOG_GPS(DBG_LOW, "stop_tracking"); + g_mutex_lock(gpsmanager->mutex); + if (request_stop_session() == TRUE) { + gpsmanager->is_running = FALSE; + } + g_mutex_unlock(gpsmanager->mutex); + gpsmanager->status = GEOCLUE_STATUS_UNAVAILABLE; } -static void shutdown(GcProvider * provider) +static gboolean set_options(GcIfaceGeoclue * gc, GHashTable * options, GError ** error) { - /* No shutdown!! */ + LOG_GPS(DBG_LOW, "set_options"); + + GeoclueGpsManager *gpsmanager = (GEOCLUE_GPSMANAGER(gc)); + gchar *value = NULL; + + value = g_hash_table_lookup(options, "CMD"); + + if (value) { + if (!g_strcmp0(value, "START")) { + g_mutex_lock(gpsmanager->mutex); + gpsmanager->client_count++; + g_mutex_unlock(gpsmanager->mutex); + + if (gpsmanager->is_running == TRUE) { + LOG_GPS(DBG_LOW, "gps-manager is already running"); + return TRUE; + } + start_tracking(gpsmanager); + } else if (!g_strcmp0(value, "STOP")) { + g_mutex_lock(gpsmanager->mutex); + gpsmanager->client_count--; + g_mutex_unlock(gpsmanager->mutex); + + if (gpsmanager->is_running == FALSE) { + return TRUE; + } + if (gpsmanager->client_count <= 0 ) { + stop_tracking(gpsmanager); + } + } + } + return TRUE; } -static void start_tracking(GeoclueGpsManager * gpsmanager) +static gboolean remove_all_clients(GeoclueGpsManager * gpsmanager) { - gpsmanager->status = GEOCLUE_STATUS_ACQUIRING; - request_start_session(); + if (gpsmanager->client_count <= 0) { + return FALSE; + } + + gpsmanager->client_count = 0; + stop_tracking(gpsmanager); + + return TRUE; } -static void stop_tracking(GeoclueGpsManager * gpsmanager) +static void shutdown(GcProvider * provider) { - request_stop_session(); - gpsmanager->status = GEOCLUE_STATUS_UNAVAILABLE; + GeoclueGpsManager *gpsmanager = (GEOCLUE_GPSMANAGER(provider)); + + if (gpsmanager->is_running) { + if (remove_all_clients(gpsmanager)) { + LOG_GPS(DBG_ERR, "<<<< Abnormal shutdown >>>>"); + } + } } static void update_position_cb(pos_data_t * pos, gps_error_t error, void *user_data) @@ -171,18 +220,16 @@ static void update_position_cb(pos_data_t * pos, gps_error_t error, void *user_d gpsmanager->status = GEOCLUE_STATUS_AVAILABLE; - fields = (GEOCLUE_POSITION_FIELDS_LATITUDE | GEOCLUE_POSITION_FIELDS_LONGITUDE | GEOCLUE_POSITION_FIELDS_ALTITUDE); - accuracy = geoclue_accuracy_new(GEOCLUE_ACCURACY_LEVEL_DETAILED, pos->hor_accuracy, pos->ver_accuracy); - gc_iface_position_emit_position_changed(GC_IFACE_POSITION(gpsmanager), - fields, pos->timestamp, pos->latitude, pos->longitude, pos->altitude, accuracy); - fields = (GEOCLUE_VELOCITY_FIELDS_SPEED | GEOCLUE_VELOCITY_FIELDS_DIRECTION); - gc_iface_velocity_emit_velocity_changed(GC_IFACE_VELOCITY(gpsmanager), fields, pos->timestamp, pos->speed, pos->bearing, 0.0); + fields = (GEOCLUE_POSITION_FIELDS_LATITUDE | GEOCLUE_POSITION_FIELDS_LONGITUDE | GEOCLUE_POSITION_FIELDS_ALTITUDE); + gc_iface_position_emit_position_changed(GC_IFACE_POSITION(gpsmanager), + fields, pos->timestamp, pos->latitude, pos->longitude, pos->altitude, accuracy); + geoclue_accuracy_free(accuracy); gc_iface_geoclue_emit_status_changed(GC_IFACE_GEOCLUE(gpsmanager), GEOCLUE_STATUS_AVAILABLE); @@ -238,100 +285,19 @@ static void update_nmea_cb(nmea_data_t * nmea, void *user_data) g_memmove(gpsmanager->nmea.data, nmea->data, nmea->len); gpsmanager->nmea.data[nmea->len] = '\0'; + timestamp = gpsmanager->position.timestamp; + gc_iface_nmea_emit_nmea_changed(GC_IFACE_NMEA(gpsmanager), timestamp, gpsmanager->nmea.data); g_free(gpsmanager->nmea.data); } -static void add_reference(GcIfaceGeoclue * gc, DBusGMethodInvocation * context) -{ - GeoclueGpsManager *gpsmanager = (GEOCLUE_GPSMANAGER(gc)); - char *sender; - int *pcount; - - sender = dbus_g_method_get_sender(context); - if (g_hash_table_size(gpsmanager->connections) == 0) { - start_tracking(gpsmanager); - } - pcount = g_hash_table_lookup(gpsmanager->connections, sender); - if (!pcount) { - pcount = g_malloc0(sizeof(int)); - g_hash_table_insert(gpsmanager->connections, sender, pcount); - } - (*pcount)++; - - g_debug("add_reference (%s) (%d)", sender, (*pcount)); - - dbus_g_method_return(context); -} - -static gboolean remove_client(GeoclueGpsManager * gpsmanager, const char *client) -{ - int *pcount; - - pcount = g_hash_table_lookup(gpsmanager->connections, client); - if (!pcount) { - return FALSE; - } - (*pcount)--; - if (*pcount == 0) { - g_hash_table_remove(gpsmanager->connections, client); - } - if (g_hash_table_size(gpsmanager->connections) == 0) { - g_debug("There is no connections!"); - stop_tracking(gpsmanager); - } - return TRUE; -} - -static gboolean remove_all_clients(GeoclueGpsManager * gpsmanager, const char *client) -{ - int *pcount; - - pcount = g_hash_table_lookup(gpsmanager->connections, client); - if (!pcount) { - return FALSE; - } - g_hash_table_remove(gpsmanager->connections, client); - if (g_hash_table_size(gpsmanager->connections) == 0) { - g_debug("There is no connections!"); - stop_tracking(gpsmanager); - } - return TRUE; -} - -static void remove_reference(GcIfaceGeoclue * gc, DBusGMethodInvocation * context) -{ - GeoclueGpsManager *gpsmanager = (GEOCLUE_GPSMANAGER(gc)); - char *sender; - - sender = dbus_g_method_get_sender(context); - if (!remove_client(gpsmanager, sender)) { - g_warning("Unreffed by client taht has not been referenced"); - } - - g_free(sender); - - dbus_g_method_return(context); -} - -static void name_owner_changed(DBusGProxy * proxy, const char *name, const char *prev_owner, const char *new_owner, void *gc) -{ - GeoclueGpsManager *gpsmanager = (GEOCLUE_GPSMANAGER(gc)); - g_debug("name_owner_changed, name:%s, prev_owner:%s, new_owner:%s", name, prev_owner, new_owner); - if (strcmp(new_owner, "") == 0 && strcmp(name, prev_owner) == 0) { - if (remove_all_clients(gpsmanager, prev_owner)) { - g_warning("Impolite client %s disconnected without unreferencing\n", prev_owner); - } - } -} - static void geoclue_gpsmanager_class_init(GeoclueGpsManagerClass * klass) { GObjectClass *o_class = (GObjectClass *) klass; GcProviderClass *p_class = (GcProviderClass *) klass; - o_class->constructed = constructed; + o_class->constructor = constructor; o_class->finalize = finalize; o_class->dispose = dispose; p_class->get_status = get_status; @@ -341,34 +307,22 @@ static void geoclue_gpsmanager_class_init(GeoclueGpsManagerClass * klass) static void geoclue_gpsmanager_init(GeoclueGpsManager * gpsmanager) { - GError *error = NULL; - DBusGProxy *driver; - guint request_ret; - GcProvider *provider; - g_debug("geoclue_gpsmanager_init"); - - g_return_if_fail(GC_IS_PROVIDER(gpsmanager)); - provider = GC_PROVIDER(gpsmanager); - g_return_if_fail(provider->connection != NULL); - - driver = dbus_g_proxy_new_for_name(provider->connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); - - if (!org_freedesktop_DBus_request_name(driver, GEOCLUE_GPSMANAGER_DBUS_SERVICE, 0, &request_ret, &error)) { - g_warning("%s was unable to register service %s: %s", - G_OBJECT_TYPE_NAME(provider), GEOCLUE_GPSMANAGER_DBUS_SERVICE, error->message); - g_error_free(error); - return; - } + LOG_GPS(DBG_LOW, "geoclue_gpsmanager_init"); - dbus_g_proxy_add_signal(driver, "NameOwnerChanged", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); - - dbus_g_proxy_connect_signal(driver, "NameOwnerChanged", G_CALLBACK(name_owner_changed), provider, NULL); - - dbus_g_connection_register_g_object(provider->connection, GEOCLUE_GPSMANAGER_DBUS_PATH, G_OBJECT(provider)); + gpsmanager->status = GEOCLUE_STATUS_UNAVAILABLE; + gpsmanager->mutex = g_mutex_new(); + memset(&gpsmanager->position, 0x00, sizeof(pos_data_t)); + memset(&gpsmanager->satellite, 0x00, sizeof(sv_data_t)); + memset(&gpsmanager->nmea, 0x00, sizeof(nmea_data_t)); memset(&gpsmanager->last_position, 0x00, sizeof(pos_data_t)); memset(&gpsmanager->last_satellite, 0x00, sizeof(sv_data_t)); + gpsmanager->is_running = FALSE; + gpsmanager->client_count = 0; + + gc_provider_set_details(GC_PROVIDER(gpsmanager), GEOCLUE_GPSMANAGER_DBUS_SERVICE, GEOCLUE_GPSMANAGER_DBUS_PATH, "gps-manager", "GPS Manager"); + gps_manager_get_last_position(&gpsmanager->last_position); } @@ -697,8 +651,6 @@ static void init_satellite(GcIfaceSatelliteClass * iface) static void init_geoclue(GcIfaceGeoclueClass * iface) { iface->get_provider_info = get_provider_info; - iface->add_reference = add_reference; - iface->remove_reference = remove_reference; } int main(int argc, char **argv) @@ -709,9 +661,12 @@ int main(int argc, char **argv) cb.sv_cb = update_satellite_cb; cb.nmea_cb = update_nmea_cb; +#if !GLIB_CHECK_VERSION (2, 31, 0) if (!g_thread_supported()) { g_thread_init(NULL); } +#endif + dbus_g_thread_init(); g_type_init();