2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <context_mgr.h>
18 #include "device_status_types.h"
19 #include "headphone.h"
21 #define HANDLING_DELAY 2000
22 #define MAX_HANDLING_COUNT 3
24 GENERATE_PROVIDER_COMMON_IMPL(device_status_headphone);
26 ctx::device_status_headphone::device_status_headphone()
28 , audio_jack_state(RUNTIME_INFO_AUDIO_JACK_STATUS_UNCONNECTED)
29 , bt_audio_state(false)
30 , bt_audio_callback_on(false)
31 , bt_event_handler_added(false)
32 , bt_event_handling_count(0)
36 ctx::device_status_headphone::~device_status_headphone()
40 bool ctx::device_status_headphone::is_supported()
45 void ctx::device_status_headphone::submit_trigger_item()
47 context_manager::register_trigger_item(DEVICE_ST_SUBJ_HEADPHONE, OPS_SUBSCRIBE | OPS_READ,
49 TRIG_BOOL_ITEM_DEF("IsConnected") ","
50 "\"Type\":{\"type\":\"string\",\"values\":[\"Normal\",\"Headset\",\"Bluetooth\"]}"
55 int ctx::device_status_headphone::subscribe()
57 connected = get_current_status();
60 int ret = runtime_info_set_changed_cb(RUNTIME_INFO_KEY_AUDIO_JACK_STATUS, on_audio_jack_state_changed, this);
61 IF_FAIL_RETURN(ret == RUNTIME_INFO_ERROR_NONE, ERR_OPERATION_FAILED);
63 // Bluetooth headphone
64 set_bt_audio_callback();
69 int ctx::device_status_headphone::unsubscribe()
71 runtime_info_unset_changed_cb(RUNTIME_INFO_KEY_AUDIO_JACK_STATUS);
72 unset_bt_audio_callback();
77 int ctx::device_status_headphone::read()
79 if (!being_subscribed)
80 connected = get_current_status();
83 generate_data_packet(data);
84 ctx::context_manager::reply_to_read(DEVICE_ST_SUBJ_HEADPHONE, NULL, ERR_NONE, data);
89 void ctx::device_status_headphone::set_bt_audio_callback()
91 IF_FAIL_VOID(!bt_audio_callback_on);
94 ret = bt_initialize();
95 if (ret != BT_ERROR_NONE) {
96 _W("Bluetooth initialization failed");
100 ret = bt_device_set_connection_state_changed_cb(on_bt_connection_changed, this);
101 if (ret != BT_ERROR_NONE) {
106 bt_audio_callback_on = true;
109 void ctx::device_status_headphone::unset_bt_audio_callback()
111 IF_FAIL_VOID(bt_audio_callback_on);
113 bt_device_unset_connection_state_changed_cb();
116 bt_audio_callback_on = false;
119 void ctx::device_status_headphone::set_bt_audio_state(bool state)
121 bt_audio_state = state;
124 bool ctx::device_status_headphone::get_current_status()
129 ret = runtime_info_get_value_int(RUNTIME_INFO_KEY_AUDIO_JACK_STATUS, &audio_jack_state);
130 IF_FAIL_RETURN(ret == ERR_NONE, connected);
133 bt_audio_state = false;
134 ret = bt_initialize();
135 if (ret == BT_ERROR_NONE) {
136 bt_adapter_foreach_bonded_device(on_bt_bond, this);
140 return ((audio_jack_state != RUNTIME_INFO_AUDIO_JACK_STATUS_UNCONNECTED) || bt_audio_state);
143 void ctx::device_status_headphone::generate_data_packet(ctx::json &data)
145 data.set(NULL, DEVICE_ST_IS_CONNECTED, connected ? DEVICE_ST_TRUE : DEVICE_ST_FALSE);
147 switch (audio_jack_state) {
148 case RUNTIME_INFO_AUDIO_JACK_STATUS_CONNECTED_3WIRE:
149 data.set(NULL, DEVICE_ST_TYPE, DEVICE_ST_NORMAL);
151 case RUNTIME_INFO_AUDIO_JACK_STATUS_CONNECTED_4WIRE:
152 data.set(NULL, DEVICE_ST_TYPE, DEVICE_ST_HEADSET);
156 data.set(NULL, DEVICE_ST_TYPE, DEVICE_ST_BLUETOOTH);
161 bool ctx::device_status_headphone::handle_event()
163 bool prev_state = connected;
164 connected = ((audio_jack_state != RUNTIME_INFO_AUDIO_JACK_STATUS_UNCONNECTED) || bt_audio_state);
166 IF_FAIL_RETURN(prev_state != connected, false);
169 generate_data_packet(data);
170 ctx::context_manager::publish(DEVICE_ST_SUBJ_HEADPHONE, NULL, ERR_NONE, data);
174 void ctx::device_status_headphone::handle_audio_jack_event()
176 int ret = runtime_info_get_value_int(RUNTIME_INFO_KEY_AUDIO_JACK_STATUS, &audio_jack_state);
177 IF_FAIL_VOID_TAG(ret == ERR_NONE, _E, "Getting runtime info failed");
181 void ctx::device_status_headphone::on_audio_jack_state_changed(runtime_info_key_e runtime_key, void* user_data)
184 ctx::device_status_headphone *instance = static_cast<ctx::device_status_headphone*>(user_data);
185 instance->handle_audio_jack_event();
188 void ctx::device_status_headphone::on_bt_connection_changed(bool connected, bt_device_connection_info_s *conn_info, void *user_data)
190 ctx::device_status_headphone *instance = static_cast<ctx::device_status_headphone*>(user_data);
191 IF_FAIL_VOID(connected != instance->bt_audio_state);
192 IF_FAIL_VOID(!instance->bt_event_handler_added);
195 _D("BT state checking scheduled");
196 instance->bt_event_handler_added = true;
197 instance->bt_event_handling_count = 0;
198 g_timeout_add(HANDLING_DELAY, handle_bt_event, user_data);
200 handle_bt_event(user_data);
204 gboolean ctx::device_status_headphone::handle_bt_event(gpointer data)
206 _D("BT state checking started");
207 ctx::device_status_headphone *instance = static_cast<ctx::device_status_headphone*>(data);
208 instance->bt_event_handler_added = false;
210 instance->set_bt_audio_state(false);
211 int err = bt_adapter_foreach_bonded_device(on_bt_bond, data);
212 IF_FAIL_RETURN_TAG(err == BT_ERROR_NONE, FALSE, _E, "bt_adapter_foreach_bonded_device() failed");
214 instance->bt_event_handling_count++;
216 if (instance->handle_event() || instance->bt_event_handling_count >= MAX_HANDLING_COUNT)
222 bool ctx::device_status_headphone::on_bt_bond(bt_device_info_s *device_info, void* user_data)
224 if (device_info->bt_class.major_device_class != BT_MAJOR_DEVICE_CLASS_AUDIO_VIDEO)
228 int err = bt_device_is_profile_connected(device_info->remote_address, BT_PROFILE_A2DP, &st);
229 IF_FAIL_RETURN_TAG(err == BT_ERROR_NONE, false, _E, "bt_device_is_profile_connected() failed");
232 ctx::device_status_headphone *instance = static_cast<ctx::device_status_headphone*>(user_data);
233 instance->set_bt_audio_state(true);