Handling le connection interval
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-opp-client.c
index 74b1829..a8d159b 100644 (file)
@@ -1,11 +1,5 @@
 /*
- * Bluetooth-frwk
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact:  Hocheol Seo <hocheol.seo@samsung.com>
- *              Girishashok Joshi <girish.joshi@samsung.com>
- *              Chanyeol Park <chanyeol.park@samsung.com>
+ * Copyright (c) 2011 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.
@@ -25,7 +19,7 @@
 #include <dlog.h>
 #include <string.h>
 #include <mime_type.h>
-
+#include <aul.h>
 #include <glib.h>
 #include <gio/gio.h>
 
@@ -37,6 +31,9 @@
 #include "bt-service-util.h"
 #include "bt-service-opp-client.h"
 #include "bt-service-obex-agent.h"
+#include "bt-service-adapter.h"
+
+#define BT_MIME_TYPE_MAX_LEN   20
 
 static GSList *transfer_list = NULL;
 bt_sending_info_t *sending_info;
@@ -44,7 +41,7 @@ static int file_offset = 0;
 
 #define DBUS_TIEMOUT 20 * 1000  /* 20 Seconds */
 static gboolean __bt_sending_release();
-static void _bt_remove_session();
+static int _bt_remove_session();
 
 static int __bt_opp_client_start_sending(int request_id, char *address,
                                        char **file_name_array, int file_count);
@@ -132,12 +129,13 @@ static gboolean __bt_cancel_push_cb(gpointer data)
        return FALSE;
 }
 
-gboolean _bt_obex_client_progress(const char *transfer_path, int transferred)
+gboolean _bt_obex_client_progress(const char *transfer_path, guint64 transferred)
 {
        BT_DBG("+");
 
        int percentage_progress;
-       gint64 size;
+       int previous_progress;
+       guint64 size;
        int result = BLUETOOTH_ERROR_NONE;
        GVariant *param = NULL;
        retv_if(sending_info == NULL, TRUE);
@@ -150,22 +148,33 @@ gboolean _bt_obex_client_progress(const char *transfer_path, int transferred)
        }
 
        size = sending_info->transfer_info->size;
-
        if (size != 0)
-               percentage_progress = (int)(((gdouble)transferred /
-                               (gdouble)size) * 100);
+               percentage_progress = (int)(((gdouble)transferred /(gdouble)size) * 100);
        else
                percentage_progress = 0;
 
        sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_PROGRESS;
        sending_info->result = result;
 
+       previous_progress = (int)(((gdouble)sending_info->transfer_info->progress /(gdouble)size) * 100);
+       if (percentage_progress == previous_progress &&
+                                                       sending_info->transfer_info->progress) {
+               sending_info->transfer_info->progress = transferred;
+               return TRUE;
+       }
+               BT_DBG("Sending progress [prev %d] [curr %d]",
+                                                       previous_progress, percentage_progress);
+
+       sending_info->transfer_info->progress = transferred;
+
        /* Send the event in only error none case */
        param = g_variant_new("(istii)", result,
                                sending_info->transfer_info->file_name,
                                sending_info->transfer_info->size,
                                percentage_progress,
                                sending_info->request_id);
+
+
        _bt_send_event(BT_OPP_CLIENT_EVENT,
                        BLUETOOTH_EVENT_OPC_TRANSFER_PROGRESS,
                        param);
@@ -197,7 +206,8 @@ gboolean _bt_obex_client_completed(const char *transfer_path, gboolean success)
        if (!success) { /*In case of remote device reject, we need to send BLUETOOTH_EVENT_OPC_DISCONNECTED */
                BT_DBG("completed with error");
                if (!sending_info->is_canceled) {
-                       param = g_variant_new("(isti)", result,
+                       param = g_variant_new("(issti)", result,
+                                               sending_info->address,
                                                sending_info->transfer_info->file_name,
                                                sending_info->transfer_info->size,
                                                sending_info->request_id);
@@ -225,7 +235,8 @@ gboolean _bt_obex_client_completed(const char *transfer_path, gboolean success)
        } else {
                BT_DBG("complete success");
                /* Send the event in only error none case */
-               param = g_variant_new("(isti)", result,
+               param = g_variant_new("(issti)", result,
+                                       sending_info->address,
                                        sending_info->transfer_info->file_name,
                                        sending_info->transfer_info->size,
                                        sending_info->request_id);
@@ -258,10 +269,10 @@ gboolean _bt_obex_client_started(const char *transfer_path)
        }
 
        /* Get the session bus. */
-       g_conn = _bt_get_session_gconn();
+       g_conn = _bt_gdbus_get_session_gconn();
        retv_if(g_conn == NULL, FALSE);
        properties_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
-                                               NULL,BT_OBEXD_DBUS_NAME,
+                                               NULL, BT_OBEXD_DBUS_NAME,
                                                transfer_path, BT_PROPERTIES_INTERFACE,
                                                NULL, &error);
 
@@ -280,7 +291,9 @@ gboolean _bt_obex_client_started(const char *transfer_path)
 
        sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_STARTED;
        sending_info->result = result;
-       param = g_variant_new("(isti)", result,
+
+       param = g_variant_new("(issti)", result,
+                               sending_info->address,
                                sending_info->transfer_info->file_name,
                                sending_info->transfer_info->size,
                                sending_info->request_id);
@@ -307,9 +320,8 @@ static void __bt_free_sending_data(gpointer data)
 
        ret_if(info == NULL);
 
-       for (i = 0; i < info->file_count; i++) {
+       for (i = 0; i < info->file_count; i++)
                g_free(info->file_path[i]);
-       }
 
        _bt_delete_request_id(info->request_id);
 
@@ -327,9 +339,13 @@ static void __bt_sending_release_cb(GDBusProxy *proxy,
        GError *error = NULL;
        int result = BLUETOOTH_ERROR_NONE;
        GVariant *param = NULL;
-       g_dbus_proxy_call_finish(proxy, res, &error);
+       GVariant *reply = NULL;
+
+       reply = g_dbus_proxy_call_finish(proxy, res, &error);
        if (proxy)
                g_object_unref(proxy);
+       if (reply)
+               g_variant_unref(reply);
 
        if (error) {
                BT_ERR("%s", error->message);
@@ -385,15 +401,15 @@ fail:
        return;
 }
 
-static void _bt_remove_session()
+static int _bt_remove_session()
 {
        GDBusConnection *g_conn;
        GDBusProxy *session_proxy;
        GError *err = NULL;
 
-       g_conn = _bt_get_session_gconn();
-       ret_if(g_conn == NULL);
-       ret_if(sending_info->session_path == NULL);
+       g_conn = _bt_gdbus_get_session_gconn();
+       retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
+       retv_if(sending_info->session_path == NULL, BLUETOOTH_ERROR_INVALID_PARAM);
 
        session_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
                                                NULL, BT_OBEXD_DBUS_NAME,
@@ -401,7 +417,7 @@ static void _bt_remove_session()
                                                BT_OBEX_CLIENT_INTERFACE,
                                                NULL, &err);
 
-       ret_if(session_proxy == NULL);
+       retv_if(session_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
 
        g_dbus_proxy_call(session_proxy, "RemoveSession",
                g_variant_new("(o)", sending_info->session_path),
@@ -410,6 +426,7 @@ static void _bt_remove_session()
                (GAsyncReadyCallback)__bt_sending_release_cb,
                NULL);
 
+       return BLUETOOTH_ERROR_NONE;
 }
 
 static gboolean __bt_sending_release()
@@ -418,7 +435,8 @@ static gboolean __bt_sending_release()
 
        retv_if(sending_info == NULL, FALSE);
 
-       _bt_remove_session();
+       retv_if(_bt_remove_session() != BLUETOOTH_ERROR_NONE, FALSE);
+
        BT_DBG("-");
        return TRUE;
 }
@@ -439,7 +457,8 @@ void _bt_opc_disconnected(const char *session_path)
                if (sending_info->transfer_info->transfer_status == BT_TRANSFER_STATUS_PROGRESS ||
                                sending_info->transfer_info->transfer_status == BT_TRANSFER_STATUS_STARTED) {
                        BT_INFO("Abnormal termination");
-                       param = g_variant_new("(isti)", sending_info->result,
+                       param = g_variant_new("(issti)", sending_info->result,
+                                               sending_info->address,
                                                sending_info->transfer_info->file_name,
                                                sending_info->transfer_info->size,
                                                sending_info->request_id);
@@ -472,13 +491,41 @@ static void __bt_send_file_cb(GDBusProxy *proxy,
        const char *transfer_name = NULL;
        const char *file_name = NULL;
        int size = 0;
-       GVariantIter *iter;
+       GVariantIter *iter = NULL;
        value = g_dbus_proxy_call_finish(proxy, res, &error);
        if (error) {
+               g_dbus_error_strip_remote_error(error);
                BT_ERR("%s", error->message);
-               g_error_free(error);
-               if (proxy)
-                       g_object_unref(proxy);
+               /* If Obex is not able to open a file then continue with other if any */
+               if (g_strcmp0("Unable to open file", error->message) == 0) {
+                       GVariant *param = NULL;
+                       gint64 size = 0;
+
+                       BT_ERR("Unable to open file [%s]", sending_info->file_name_array[file_offset]);
+
+                       param = g_variant_new("(issti)", BLUETOOTH_ERROR_NOT_FOUND,
+                                       sending_info->address,
+                                       sending_info->file_name_array[file_offset],
+                                       size,
+                                       sending_info->request_id);
+                       _bt_send_event(BT_OPP_CLIENT_EVENT,
+                                       BLUETOOTH_EVENT_OPC_TRANSFER_STARTED,
+                                       param);
+
+                       param = g_variant_new("(issti)", BLUETOOTH_ERROR_NOT_FOUND,
+                                               sending_info->address,
+                                               sending_info->file_name_array[file_offset],
+                                               size,
+                                               sending_info->request_id);
+                       _bt_send_event(BT_OPP_CLIENT_EVENT,
+                                       BLUETOOTH_EVENT_OPC_TRANSFER_COMPLETE,
+                                       param);
+                       g_error_free(error);
+                       if (proxy)
+                               g_object_unref(proxy);
+                       file_offset++;
+                       _bt_sending_files();
+               }
                return;
        }
        if (proxy)
@@ -498,13 +545,12 @@ static void __bt_send_file_cb(GDBusProxy *proxy,
                GVariant *val;
                gsize len = 0;
                while (g_variant_iter_loop(iter, "{sv}", &key, &val)) {
-                       if (g_strcmp0(key, "Name") == 0) {
-                               transfer_name = g_variant_dup_string(val,&len);
-                       } else if (g_strcmp0(key, "Filename") == 0) {
+                       if (g_strcmp0(key, "Name") == 0)
+                               transfer_name = g_variant_dup_string(val, &len);
+                       else if (g_strcmp0(key, "Filename") == 0)
                                file_name = g_variant_dup_string(val, &len);
-                       } else if (g_strcmp0(key, "Size") == 0) {
+                       else if (g_strcmp0(key, "Size") == 0)
                                size = g_variant_get_uint64(val);
-                       }
                }
                g_variant_iter_free(iter);
        }
@@ -512,11 +558,14 @@ static void __bt_send_file_cb(GDBusProxy *proxy,
        sending_info->transfer_info->transfer_name = g_strdup(transfer_name);
        sending_info->transfer_info->file_name = g_strdup(file_name);
        sending_info->transfer_info->size = size;
+       sending_info->transfer_info->progress = 0;
        sending_info->transfer_info->transfer_path = session_path;
        sending_info->transfer_info->transfer_status = BT_TRANSFER_STATUS_QUEUED;
        sending_info->result = BLUETOOTH_ERROR_NONE;
        file_offset++;
 
+       g_free((gchar *)transfer_name);
+       g_free((gchar *)file_name);
 }
 
 void _bt_sending_files(void)
@@ -526,14 +575,13 @@ void _bt_sending_files(void)
        GError *err = NULL;
        GDBusConnection *g_conn;
        GDBusProxy *client_proxy;
-       char *mimetype = NULL;
-       char *ext = NULL;
+       char mime_type[BT_MIME_TYPE_MAX_LEN + 1] = { 0 };
 
        if (sending_info == NULL)
                return;
-       if (file_offset < sending_info->file_count){
+       if (file_offset < sending_info->file_count) {
                /* Get the session bus. */
-               g_conn = _bt_get_session_gconn();
+               g_conn = _bt_gdbus_get_session_gconn();
                ret_if(g_conn == NULL);
 
                client_proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
@@ -542,15 +590,27 @@ void _bt_sending_files(void)
                                                BT_OBEX_OBJECT_PUSH_INTERFACE,
                                                NULL, &err);
                ret_if(client_proxy == NULL);
+               if (aul_get_mime_from_file(sending_info->file_name_array[file_offset],
+                               mime_type, BT_MIME_TYPE_MAX_LEN) == AUL_R_OK) {
+                               BT_DBG("MLME type = %s", mime_type);
+
+                               /* For IOPT compliance, change "text/x-iMelody" to "audio/imelody"
+                                * because few devices(multimedia players) reject the OPP put for text objects
+                                * since they support only multimedia files exchange */
+                               if (!strcasecmp(mime_type, "text/x-iMelody")) {
+                                       strncpy(mime_type, "audio/imelody", BT_MIME_TYPE_MAX_LEN);
+                                       BT_DBG("over writing mime type to  = %s", mime_type);
+                               }
+                               if (!strcasecmp(mime_type, "text/vcard")) {
+                                       strncpy(mime_type, "text/x-vcard", BT_MIME_TYPE_MAX_LEN);
+                                       BT_DBG("over writing mime type to  = %s", mime_type);
+                               }
+               }
 
                BT_DBG("Calling SendFile");
-               ext = strrchr(sending_info->file_name_array[file_offset], '.');
-
-               if (ext != NULL && (!strcmp(ext, ".imy")))
-                       mimetype = g_strdup("audio/imelody");
                g_dbus_proxy_call(client_proxy, "SendFile",
                                g_variant_new("(ss)", sending_info->file_name_array[file_offset],
-                                                               mimetype),
+                                                               mime_type),
                                G_DBUS_CALL_FLAGS_NONE,
                                DBUS_TIEMOUT, NULL,
                                (GAsyncReadyCallback)__bt_send_file_cb,
@@ -558,12 +618,10 @@ void _bt_sending_files(void)
                if (err != NULL) {
                        BT_ERR("Calling SendFile failed: [%s]\n", err->message);
                        g_clear_error(&err);
-                       g_free(mimetype);
                        return;
                }
 
-               g_free(mimetype);
-       }else{
+       } else {
                file_offset = 0;
                __bt_sending_release();
        }
@@ -583,9 +641,6 @@ static void __bt_create_session_cb(GDBusProxy *proxy,
        GVariant *param = NULL;
 
        value = g_dbus_proxy_call_finish(proxy, res, &error);
-       if (proxy)
-               g_object_unref(proxy);
-
        if (value) {
                g_variant_get(value, "(o)", &session_path);
                g_variant_unref(value);
@@ -596,12 +651,13 @@ static void __bt_create_session_cb(GDBusProxy *proxy,
                g_clear_error(&error);
 
                result = BLUETOOTH_ERROR_INTERNAL;
-       }else{
+       } else {
                BT_DBG("Session created");
-               if(sending_info != NULL)
+               if (sending_info != NULL)
                        sending_info->session_path = g_strdup(session_path);
        }
        g_free(session_path);
+       g_object_unref(proxy);
        ret_if(sending_info == NULL);
 
        sending_info->result = result;
@@ -615,11 +671,32 @@ static void __bt_create_session_cb(GDBusProxy *proxy,
 
        if (result != BLUETOOTH_ERROR_NONE) {
                BT_ERR("Calling __bt_sending_release");
-               __bt_sending_release();
+               gboolean ret = __bt_sending_release();
 
                __bt_free_sending_info(sending_info);
                sending_info = NULL;
-       }else {
+
+               if (ret == FALSE) {
+                       BT_DBG("ReleaseSession Not called");
+                       /* Operate remain works */
+                       if (g_slist_length(transfer_list) > 0) {
+                               bt_sending_data_t *data = NULL;
+
+                               data = transfer_list->data;
+                               ret_if(data == NULL);
+
+                               transfer_list = g_slist_remove(transfer_list, data);
+
+                               BT_DBG("calling __bt_opp_client_start_sending");
+
+                               if (__bt_opp_client_start_sending(data->request_id,
+                                               data->address, data->file_path,
+                                               data->file_count) != BLUETOOTH_ERROR_NONE) {
+                                       BT_ERR("Sending Enqueued Transfer Failed");
+                               }
+                       }
+               }
+       } else {
                BT_DBG("Calling sending_files");
                _bt_sending_files();
        }
@@ -641,7 +718,7 @@ static int __bt_opp_client_start_sending(int request_id, char *address,
        BT_CHECK_PARAMETER(file_name_array, return);
 
        /* Get the session bus. */
-       g_conn = _bt_get_session_gconn();
+       g_conn = _bt_gdbus_get_session_gconn();
        retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
 
        client_proxy =  g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE,
@@ -682,14 +759,25 @@ static int __bt_opp_client_start_sending(int request_id, char *address,
        _bt_opp_client_event_init();
        //_bt_obex_client_started(agent_path);
 
-       BT_DBG("Going to call CreateSession");
-
-       g_dbus_proxy_call(client_proxy, "CreateSession",
+       BT_DBG("Adapter Status %d", _bt_adapter_get_status());
+       if (_bt_adapter_get_status() == BT_ACTIVATED) {
+               BT_DBG("Going to call CreateSession");
+               g_dbus_proxy_call(client_proxy, "CreateSession",
                                                g_variant_new("(sa{sv})", address, builder),
                                                G_DBUS_CALL_FLAGS_NONE,
                                                DBUS_TIEMOUT, NULL,
                                                (GAsyncReadyCallback)__bt_create_session_cb,
                                                NULL);
+       } else {
+               GVariant *param = g_variant_new("(isi)", BLUETOOTH_ERROR_INTERNAL,
+                               sending_info->address, sending_info->request_id);
+
+               BT_DBG("Address[%s] RequestID[%d]", sending_info->address, sending_info->request_id);
+               _bt_send_event(BT_OPP_CLIENT_EVENT, BLUETOOTH_EVENT_OPC_CONNECTED,
+                                                                       param);
+               __bt_free_sending_info(sending_info);
+               sending_info = NULL;
+       }
        g_variant_builder_unref(builder);
 
        BT_DBG("-");
@@ -724,10 +812,6 @@ int _bt_opp_client_push_files(int request_id, GDBusMethodInvocation *context,
        } else {
                /* Insert data in the queue */
                data = g_malloc0(sizeof(bt_sending_data_t));
-               /* Fix : NULL_RETURNS */
-               if (data == NULL)
-                       return BLUETOOTH_ERROR_MEMORY_ALLOCATION;
-
                data->file_path = g_new0(char *, file_count + 1);
                data->address = g_strdup(address);
                data->file_count = file_count;
@@ -760,6 +844,7 @@ int _bt_opp_client_cancel_push(void)
 
        GError *err = NULL;
        int result = BLUETOOTH_ERROR_CANCEL_BY_USER;
+       GVariant *ret = NULL;
        GVariant *param = NULL;
        retv_if(sending_info == NULL, BLUETOOTH_ERROR_NOT_IN_OPERATION);
 
@@ -768,11 +853,21 @@ int _bt_opp_client_cancel_push(void)
 
        if (sending_info->transfer_info) {
 
-               g_dbus_proxy_call_sync(sending_info->transfer_info->proxy,
+               ret = g_dbus_proxy_call_sync(sending_info->transfer_info->proxy,
                                        "Cancel", NULL,
                                        G_DBUS_CALL_FLAGS_NONE, -1,
                                        NULL, &err);
-               param = g_variant_new("(isti)", result,
+               if (ret == NULL) {
+                       if (err != NULL) {
+                               BT_ERR("Cancel Error: %s\n", err->message);
+                               g_error_free(err);
+                       }
+               } else {
+                       g_variant_unref(ret);
+               }
+
+               param = g_variant_new("(issti)", result,
+                                       sending_info->address,
                                        sending_info->transfer_info->file_name,
                                        sending_info->transfer_info->size,
                                        sending_info->request_id);
@@ -834,7 +929,8 @@ void _bt_opp_client_check_pending_transfer(const char *address)
                sending_info->result = result;
 
                if (!sending_info->is_canceled) {
-                       param = g_variant_new("(isti)", result,
+                       param = g_variant_new("(issti)", result,
+                                               sending_info->address,
                                                sending_info->transfer_info->file_name,
                                                sending_info->transfer_info->size,
                                                sending_info->request_id);
@@ -857,3 +953,38 @@ void _bt_opp_client_check_pending_transfer(const char *address)
        }
        BT_DBG("-");
 }
+
+int _bt_opp_get_client_progress(guint8 *progress)
+{
+       if (sending_info == NULL || sending_info->transfer_info == NULL) {
+               BT_ERR("No Active Outbound transfer");
+               return BLUETOOTH_ERROR_NOT_FOUND;
+       }
+
+       *progress = (int)(((double)sending_info->transfer_info->progress /
+                       sending_info->transfer_info->size) * 100);
+
+       BT_DBG("Percentage: %d", *progress);
+       return BLUETOOTH_ERROR_NONE;
+}
+
+void _bt_cancel_queued_transfers(void)
+{
+       bt_sending_data_t *data = NULL;
+       GVariant *param = NULL;
+
+       BT_INFO("Cancel queued Transfers:: Length of transfer list is %d",
+                                       g_slist_length(transfer_list));
+
+       while (transfer_list) {
+               data = transfer_list->data;
+               param = g_variant_new("(isi)", BLUETOOTH_ERROR_INTERNAL,
+                               data->address, data->request_id);
+
+               BT_DBG("Address[%s] RequestID[%d]", data->address, data->request_id);
+               _bt_send_event(BT_OPP_CLIENT_EVENT, BLUETOOTH_EVENT_OPC_CONNECTED,
+                                                                       param);
+
+               transfer_list = g_slist_remove(transfer_list, data);
+       }
+}