Fix BT headphone state change monitor 59/43659/1
authorMu-Woong <muwoong.lee@samsung.com>
Mon, 13 Jul 2015 05:49:33 +0000 (14:49 +0900)
committerMu-Woong <muwoong.lee@samsung.com>
Mon, 13 Jul 2015 05:49:33 +0000 (14:49 +0900)
Change-Id: I41a65b525e2392e02a381ee492a560e773515dd7
Signed-off-by: Mu-Woong <muwoong.lee@samsung.com>
src/device_status/headphone.cpp
src/device_status/headphone.h

index a2c4ac1..a8bf386 100644 (file)
 
 #include "headphone.h"
 
+#define HANDLING_DELAY 2000
+#define MAX_HANDLING_COUNT 3
+
 ctx::device_status_headphone::device_status_headphone()
        : connected(false)
        , audio_jack_state(RUNTIME_INFO_AUDIO_JACK_STATUS_UNCONNECTED)
        , bt_audio_state(false)
        , bt_audio_callback_on(false)
+       , bt_event_handler_added(false)
+       , bt_event_handling_count(0)
 {
 }
 
 int ctx::device_status_headphone::subscribe(const char* subject, const char* zone)
 {
-       //FIXME: in case of TV?
        if (client_zone.empty()) {
                connected = get_current_status();
 
                // Wired headphone
-               int ret = runtime_info_set_changed_cb(RUNTIME_INFO_KEY_AUDIO_JACK_STATUS, audio_jack_cb, this);
+               int ret = runtime_info_set_changed_cb(RUNTIME_INFO_KEY_AUDIO_JACK_STATUS, on_audio_jack_state_changed, this);
                IF_FAIL_RETURN(ret == RUNTIME_INFO_ERROR_NONE, ERR_OPERATION_FAILED);
 
                // Bluetooth headphone
@@ -76,16 +80,8 @@ void ctx::device_status_headphone::set_bt_audio_callback()
                return;
        }
 
-       ret = bt_audio_initialize();
-       if (ret != BT_ERROR_NONE) {
-               bt_deinitialize();
-               _W("Bluetooth audio initialization failed");
-               return;
-       }
-
-       ret = bt_audio_set_connection_state_changed_cb(bt_audio_cb, this);
+       ret = bt_device_set_connection_state_changed_cb(on_bt_connection_changed, this);
        if (ret != BT_ERROR_NONE) {
-               bt_audio_deinitialize();
                bt_deinitialize();
                return;
        }
@@ -97,9 +93,10 @@ void ctx::device_status_headphone::unset_bt_audio_callback()
 {
        IF_FAIL_VOID(bt_audio_callback_on);
 
-       bt_audio_unset_connection_state_changed_cb();
-       bt_audio_deinitialize();
+       bt_device_unset_connection_state_changed_cb();
        bt_deinitialize();
+
+       bt_audio_callback_on = false;
 }
 
 void ctx::device_status_headphone::set_bt_audio_state(bool state)
@@ -119,7 +116,7 @@ bool ctx::device_status_headphone::get_current_status()
        bt_audio_state = false;
        ret = bt_initialize();
        if (ret == BT_ERROR_NONE) {
-               bt_adapter_foreach_bonded_device(bt_bonded_device_cb, this);
+               bt_adapter_foreach_bonded_device(on_bt_bond, this);
                bt_deinitialize();
        }
 
@@ -144,16 +141,17 @@ void ctx::device_status_headphone::generate_data_packet(ctx::json &data)
        }
 }
 
-void ctx::device_status_headphone::handle_event()
+bool ctx::device_status_headphone::handle_event()
 {
        bool prev_state = connected;
        connected = ((audio_jack_state != RUNTIME_INFO_AUDIO_JACK_STATUS_UNCONNECTED) || bt_audio_state);
 
-       IF_FAIL_VOID(prev_state != connected);
+       IF_FAIL_RETURN(prev_state != connected, false);
 
        ctx::json data;
        generate_data_packet(data);
        publish(DEVICE_ST_SUBJ_HEADPHONE, ERR_NONE, data, client_zone);
+       return true;
 }
 
 void ctx::device_status_headphone::handle_audio_jack_event()
@@ -163,42 +161,61 @@ void ctx::device_status_headphone::handle_audio_jack_event()
        handle_event();
 }
 
-void ctx::device_status_headphone::handle_bt_audio_event(bool conn)
-{
-       bt_audio_state = conn;
-       handle_event();
-}
-
-void ctx::device_status_headphone::audio_jack_cb(runtime_info_key_e runtime_key, void* user_data)
+void ctx::device_status_headphone::on_audio_jack_state_changed(runtime_info_key_e runtime_key, void* user_data)
 {
        _D("EarJack");
        ctx::device_status_headphone *instance = static_cast<ctx::device_status_headphone*>(user_data);
        instance->handle_audio_jack_event();
 }
 
-void ctx::device_status_headphone::bt_audio_cb(int result, bool connected, const char *remote_address, bt_audio_profile_type_e type, void *user_data)
+void ctx::device_status_headphone::on_bt_connection_changed(bool connected, bt_device_connection_info_s *conn_info, void *user_data)
 {
-       _D("BlueTooth");
-       IF_FAIL_VOID_TAG(result == BT_ERROR_NONE, _E, "Error: %d", result);
-
        ctx::device_status_headphone *instance = static_cast<ctx::device_status_headphone*>(user_data);
-       instance->handle_bt_audio_event(connected);
+       IF_FAIL_VOID(connected != instance->bt_audio_state);
+       IF_FAIL_VOID(!instance->bt_event_handler_added);
+
+       if (connected) {
+               _D("BT state checking scheduled");
+               instance->bt_event_handler_added = true;
+               instance->bt_event_handling_count = 0;
+               g_timeout_add(HANDLING_DELAY, handle_bt_event, user_data);
+       } else {
+               handle_bt_event(user_data);
+       }
 }
 
-bool ctx::device_status_headphone::bt_bonded_device_cb(bt_device_info_s *device_info, void* user_data)
+gboolean ctx::device_status_headphone::handle_bt_event(gpointer data)
 {
-       if (device_info->bt_class.major_device_class == BT_MAJOR_DEVICE_CLASS_AUDIO_VIDEO)
-               bt_device_foreach_connected_profiles(device_info->remote_address, bt_profile_cb, user_data);
+       _D("BT state checking started");
+       ctx::device_status_headphone *instance = static_cast<ctx::device_status_headphone*>(data);
+       instance->bt_event_handler_added = false;
 
-       return true;
+       instance->set_bt_audio_state(false);
+       int err = bt_adapter_foreach_bonded_device(on_bt_bond, data);
+       IF_FAIL_RETURN_TAG(err == BT_ERROR_NONE, FALSE, _E, "bt_adapter_foreach_bonded_device() failed");
+
+       instance->bt_event_handling_count++;
+
+       if (instance->handle_event() || instance->bt_event_handling_count >= MAX_HANDLING_COUNT)
+               return FALSE;
+
+       return TRUE;
 }
 
-bool ctx::device_status_headphone::bt_profile_cb(bt_profile_e profile, void* user_data)
+bool ctx::device_status_headphone::on_bt_bond(bt_device_info_s *device_info, void* user_data)
 {
-       if (profile == BT_PROFILE_A2DP || profile == BT_PROFILE_HSP) {
+       if (device_info->bt_class.major_device_class != BT_MAJOR_DEVICE_CLASS_AUDIO_VIDEO)
+               return true;
+
+       bool st = false;
+       int err = bt_device_is_profile_connected(device_info->remote_address, BT_PROFILE_A2DP, &st);
+       IF_FAIL_RETURN_TAG(err == BT_ERROR_NONE, false, _E, "bt_device_is_profile_connected() failed");
+
+       if (st) {
                ctx::device_status_headphone *instance = static_cast<ctx::device_status_headphone*>(user_data);
                instance->set_bt_audio_state(true);
                return false;
        }
+
        return true;
 }
index e6bc290..65c5fba 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef _DEVICE_STATUS_HEADPHONE_H_
 #define _DEVICE_STATUS_HEADPNOHE_H_
 
+#include <glib.h>
 #include <runtime_info.h>
 #include <bluetooth.h>
 #include "../sub_provider_base.h"
@@ -39,6 +40,8 @@ namespace ctx {
                        int audio_jack_state;
                        bool bt_audio_state;
                        bool bt_audio_callback_on;
+                       bool bt_event_handler_added;
+                       int bt_event_handling_count;
 
                        bool get_current_status();
                        void set_bt_audio_callback();
@@ -46,14 +49,13 @@ namespace ctx {
                        void set_bt_audio_state(bool state);
 
                        void generate_data_packet(json &data);
-                       void handle_event();
+                       bool handle_event();
                        void handle_audio_jack_event();
-                       void handle_bt_audio_event(bool conn);
 
-                       static void bt_audio_cb(int result, bool connected, const char *remote_address, bt_audio_profile_type_e type, void *user_data);
-                       static void audio_jack_cb(runtime_info_key_e runtime_key, void* user_data);
-                       static bool bt_bonded_device_cb(bt_device_info_s *device_info, void* user_data);
-                       static bool bt_profile_cb(bt_profile_e profile, void* user_data);
+                       static gboolean handle_bt_event(gpointer data);
+                       static void on_audio_jack_state_changed(runtime_info_key_e runtime_key, void* user_data);
+                       static void on_bt_connection_changed(bool connected, bt_device_connection_info_s *conn_info, void *user_data);
+                       static bool on_bt_bond(bt_device_info_s *device_info, void* user_data);
        };
 }