2 * mm_radio_sound_focus.c
4 * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
24 #include <mm_sound_focus.h>
25 #include <mm_sound_device.h>
26 #include "mm_radio_utils.h"
27 #include "mm_radio_priv_hal.h"
28 #include "mm_radio_sound_focus.h"
30 static void _mmradio_device_connected_cb(MMSoundDevice_t device, bool is_connected, void *user_data)
32 mm_radio_t *radio = (mm_radio_t *)user_data;
33 int result = MM_ERROR_NONE;
34 mm_sound_device_type_e type;
37 MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
38 MMRADIO_LOG_INFO("device [%d] is_connected [%d]", device, is_connected);
40 if (mm_sound_get_device_type(device, &type) != MM_ERROR_NONE) {
41 MMRADIO_LOG_ERROR("getting device type failed");
44 case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
45 case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
46 case MM_SOUND_DEVICE_TYPE_HDMI:
47 case MM_SOUND_DEVICE_TYPE_MIRRORING:
48 case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
50 MMRADIO_LOG_ERROR("sound device unplugged");
51 radio->sound_focus.by_focus_cb = MMRADIO_FOCUS_CB_POSTMSG;
52 radio->sound_focus.event_src = MM_MSG_CODE_INTERRUPTED_BY_EARJACK_UNPLUG;
54 result = _mmradio_stop(radio);
55 if (result != MM_ERROR_NONE)
56 MMRADIO_LOG_ERROR("failed to stop radio");
66 void _mmradio_sound_signal_callback(mm_sound_signal_name_t signal, int value, void *user_data)
68 mm_radio_sound_focus *sound_focus = (mm_radio_sound_focus *)user_data;
69 int ret = MM_ERROR_NONE;
71 MMRADIO_LOG_INFO("sound signal callback %d / %d", signal, value);
73 if (signal == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS) {
75 /* unregister watch callback */
76 if (sound_focus->watch_id > 0) {
77 MMRADIO_LOG_DEBUG("unset the focus watch cb %d", sound_focus->watch_id);
78 ret = mm_sound_unset_focus_watch_callback(sound_focus->watch_id);
79 sound_focus->watch_id = 0;
80 if (ret != MM_ERROR_NONE)
81 MMRADIO_LOG_ERROR("failed to mm_sound_unset_focus_watch_callback()");
83 /* unregister focus callback */
84 if (sound_focus->focus_id > 0) {
85 MMRADIO_LOG_DEBUG("unset the focus %d", sound_focus->focus_id);
86 ret = mm_sound_unregister_focus(sound_focus->focus_id);
87 sound_focus->focus_id = 0;
88 if (ret != MM_ERROR_NONE)
89 MMRADIO_LOG_ERROR("failed to mm_sound_unregister_focus() %d", sound_focus->focus_id);
91 /* unregister device connected callback */
92 if (sound_focus->device_subs_id > 0) {
93 MMRADIO_LOG_DEBUG("unset the device connected cb %d", sound_focus->device_subs_id);
94 ret = mm_sound_remove_device_connected_callback(sound_focus->device_subs_id);
95 sound_focus->device_subs_id = 0;
96 if (ret != MM_ERROR_NONE)
97 MMRADIO_LOG_ERROR("failed to mm_sound_remove_device_connected_callback()");
103 int mmradio_sound_focus_register(mm_radio_sound_focus *sound_focus,
104 mm_sound_focus_changed_cb focus_cb, mm_sound_focus_changed_watch_cb watch_cb, void *param)
106 /* read mm-session information */
107 int session_type = MM_SESSION_TYPE_MEDIA;
108 int session_flags = 0;
109 int ret = MM_ERROR_NONE;
113 MMRADIO_LOG_FENTER();
116 MMRADIO_LOG_ERROR("invalid session handle");
117 return MM_ERROR_RADIO_NOT_INITIALIZED;
119 sound_focus->cur_focus_type = FOCUS_NONE;
121 /* read session information */
122 ret = _mm_session_util_read_information(pid, &session_type, &session_flags);
123 MMRADIO_LOG_INFO("Read Session type ret:0x%X", ret);
124 if (ret == MM_ERROR_INVALID_HANDLE) {
125 MMRADIO_LOG_WARNING("subscribe_id=%d", sound_focus->subscribe_id);
126 if (sound_focus->subscribe_id == 0) {
127 ret = mm_sound_subscribe_signal_for_daemon(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, pid, &sound_focus->subscribe_id,
128 (mm_sound_signal_callback)_mmradio_sound_signal_callback, (void*)sound_focus);
129 if (ret != MM_ERROR_NONE) {
130 MMRADIO_LOG_ERROR("mm_sound_subscribe_signal is failed");
131 return MM_ERROR_POLICY_BLOCKED;
133 MMRADIO_LOG_DEBUG("register mm_sound_subscribe_signal_for_daemon subscribe_id %d", sound_focus->subscribe_id);
134 /* register watch callback */
135 ret = mm_sound_set_focus_watch_callback_for_session(pid,
136 FOCUS_FOR_BOTH, watch_cb, (void *)param, &sound_focus->watch_id);
137 if (ret != MM_ERROR_NONE) {
138 MMRADIO_LOG_ERROR("mm_sound_set_focus_watch_callback is failed");
139 return MM_ERROR_POLICY_BLOCKED;
141 MMRADIO_LOG_INFO("(%p) set focus watch callback = %d", param, sound_focus->watch_id);
143 /* register device connected callback */
144 ret = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG,
145 (mm_sound_device_connected_cb)_mmradio_device_connected_cb, (void *)param, &sound_focus->device_subs_id);
146 if (ret != MM_ERROR_NONE) {
147 MMRADIO_LOG_ERROR("mm_sound_add_device_connected_callback is failed");
148 return MM_ERROR_POLICY_BLOCKED;
150 MMRADIO_LOG_INFO("register device connected callback for the value is 0, sub_cb id %d", sound_focus->device_subs_id);
153 } else if (ret == MM_ERROR_NONE) {
154 MMRADIO_LOG_WARNING("Read Session Information success. session_type : %d flags: %d", session_type, session_flags);
155 sound_focus->session_type = session_type;
156 sound_focus->snd_session_flags = session_flags;
157 if (sound_focus->session_type == MM_SESSION_TYPE_MEDIA) {
158 if (sound_focus->snd_session_flags & MM_SESSION_OPTION_PAUSE_OTHERS) {
159 /* register focus session */
160 sound_focus->pid = pid;
161 MMRADIO_LOG_DEBUG("sound register focus pid[%d]", pid);
162 ret = mm_sound_focus_get_id(&handle);
163 if (ret != MM_ERROR_NONE) {
164 MMRADIO_LOG_ERROR("Failed to get sound focus id");
165 return MM_ERROR_POLICY_BLOCKED;
167 sound_focus->handle = handle;
169 ret = mm_sound_register_focus_for_session(handle, pid, "radio", focus_cb, param);
170 if (ret != MM_ERROR_NONE) {
171 MMRADIO_LOG_ERROR("mm_sound_register_focus_for_session is failed");
172 return MM_ERROR_POLICY_BLOCKED;
174 MMRADIO_LOG_DEBUG("(%p) register focus for session %d", param, pid);
175 /* register device_connected_cb */
176 ret = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG,
177 (mm_sound_device_connected_cb)_mmradio_device_connected_cb, (void *)param, &sound_focus->device_subs_id);
178 if (ret != MM_ERROR_NONE) {
179 MMRADIO_LOG_ERROR("mm_sound_add_device_connected_callback is failed");
180 return MM_ERROR_POLICY_BLOCKED;
182 MMRADIO_LOG_DEBUG("(%p) add device connected callback = %d", param, sound_focus->device_subs_id);
184 } else if (sound_focus->snd_session_flags & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
185 /* register device_connected_cb */
186 ret = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG,
187 (mm_sound_device_connected_cb)_mmradio_device_connected_cb, (void*)param, &sound_focus->device_subs_id);
188 if (ret != MM_ERROR_NONE) {
189 MMRADIO_LOG_ERROR("mm_sound_add_device_connected_callback is failed");
190 return MM_ERROR_POLICY_BLOCKED;
192 MMRADIO_LOG_DEBUG("add device connected callback = %d", sound_focus->device_subs_id);
193 MMRADIO_LOG_WARNING("settion flags isn't OPTION_PAUSE_OTHERS and UNINTERRUPTIBLE. skip it..");
195 /* register watch callback */
196 ret = mm_sound_set_focus_watch_callback_for_session(pid,
197 FOCUS_FOR_BOTH, watch_cb, (void*)param, &sound_focus->watch_id);
198 if (ret != MM_ERROR_NONE) {
199 MMRADIO_LOG_ERROR("mm_sound_set_focus_watch_callback is failed");
200 return MM_ERROR_POLICY_BLOCKED;
202 MMRADIO_LOG_DEBUG("set focus watch callback = %d", sound_focus->watch_id);
204 /* register device connected callback */
205 ret = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG,
206 (mm_sound_device_connected_cb)_mmradio_device_connected_cb, (void*)param, &sound_focus->device_subs_id);
207 if (ret != MM_ERROR_NONE) {
208 MMRADIO_LOG_ERROR("mm_sound_add_device_connected_callback is failed");
209 return MM_ERROR_POLICY_BLOCKED;
211 MMRADIO_LOG_INFO("(%p) add device connected callback = %d", param, sound_focus->device_subs_id);
213 } else if (sound_focus->session_type == MM_SESSION_TYPE_REPLACED_BY_STREAM) {
214 /* didn't register device connected cb */
215 MMRADIO_LOG_WARNING("this process is using stream info. skip it..");
217 MMRADIO_LOG_WARNING("seesion type is not MEDIA (%d)", sound_focus->session_type);
218 return MM_ERROR_RADIO_INTERNAL;
222 MMRADIO_LOG_WARNING("Read Session Information failed. skip sound focus register function. errorcode %x", ret);
225 MMRADIO_LOG_FLEAVE();
227 return MM_ERROR_NONE;
230 int mmradio_sound_focus_deregister(mm_radio_sound_focus *sound_focus)
233 int ret = MM_ERROR_NONE;
235 MMRADIO_LOG_FENTER();
238 MMRADIO_LOG_ERROR("invalid session handle");
239 return MM_ERROR_RADIO_NOT_INITIALIZED;
242 if (sound_focus->watch_id > 0) {
243 MMRADIO_LOG_INFO("unset the focus watch cb %d", sound_focus->watch_id);
245 ret = mm_sound_unset_focus_watch_callback(sound_focus->watch_id);
246 sound_focus->watch_id = 0;
247 if (ret != MM_ERROR_NONE)
248 MMRADIO_LOG_ERROR("failed to mm_sound_unset_focus_watch_callback() ret = %d", ret);
250 /* unregister focus callback */
251 if (sound_focus->focus_id > 0) {
252 ret = mm_sound_unregister_focus(sound_focus->focus_id);
253 sound_focus->focus_id = 0;
254 if (ret != MM_ERROR_NONE)
255 MMRADIO_LOG_ERROR("failed to mm_sound_unregister_focus() ret = %d", ret);
257 /* unregister device connected callback */
258 if (sound_focus->device_subs_id > 0) {
259 MMRADIO_LOG_INFO("unset the device connected cb %d", sound_focus->device_subs_id);
260 ret = mm_sound_remove_device_connected_callback(sound_focus->device_subs_id);
261 sound_focus->device_subs_id = 0;
262 if (ret != MM_ERROR_NONE)
263 MMRADIO_LOG_ERROR("failed to mm_sound_remove_device_connected_callback() ret = %d", ret);
266 if (sound_focus->subscribe_id > 0) {
267 MMRADIO_LOG_INFO("unset mm_sound_subscribe_signal_for_daemon %d", sound_focus->subscribe_id);
268 mm_sound_unsubscribe_signal(sound_focus->subscribe_id);
271 MMRADIO_LOG_FLEAVE();
273 return MM_ERROR_NONE;
276 int mmradio_acquire_sound_focus(mm_radio_sound_focus *sound_focus)
278 int ret = MM_ERROR_NONE;
279 mm_sound_focus_type_e focus_type = FOCUS_NONE;
280 MMRADIO_LOG_FENTER();
282 MMRADIO_LOG_ERROR("mmradio_acquire_sound_focus sound_focus->cur_focus_type : %d", sound_focus->cur_focus_type);
284 focus_type = FOCUS_FOR_BOTH & ~(sound_focus->cur_focus_type);
285 if (focus_type != FOCUS_NONE) {
286 ret = mm_sound_acquire_focus(sound_focus->handle, focus_type, NULL);
287 if (ret != MM_ERROR_NONE) {
288 MMRADIO_LOG_ERROR("mm_sound_acquire_focus is failed");
289 return MM_ERROR_POLICY_BLOCKED;
291 sound_focus->cur_focus_type = FOCUS_FOR_BOTH;
294 MMRADIO_LOG_FLEAVE();
298 int mmradio_release_sound_focus(mm_radio_sound_focus *sound_focus)
300 int ret = MM_ERROR_NONE;
301 MMRADIO_LOG_FENTER();
303 MMRADIO_LOG_ERROR("mmradio_release_sound_focus sound_focus->cur_focus_type : %d", sound_focus->cur_focus_type);
304 if (sound_focus->cur_focus_type != FOCUS_NONE) {
305 ret = mm_sound_release_focus(sound_focus->handle, sound_focus->cur_focus_type, NULL);
306 if (ret != MM_ERROR_NONE) {
307 MMRADIO_LOG_ERROR("mm_sound_release_focus is failed");
308 return MM_ERROR_POLICY_BLOCKED;
310 sound_focus->cur_focus_type = FOCUS_NONE;
313 MMRADIO_LOG_FLEAVE();
317 #define AUDIO_FOCUS_REASON_MAX 128
319 void mmradio_get_sound_focus_reason(mm_sound_focus_state_e focus_state, const char *reason_for_change, bool is_watch, enum MMMessageInterruptedCode *event_source, int *postMsg)
321 MMRADIO_LOG_FENTER();
322 MMRADIO_LOG_ERROR("mmradio_get_sound_focus_reason focus_state : %d reason_for_change :%s", focus_state, reason_for_change);
324 if (0 == strncmp(reason_for_change, "call-voice", AUDIO_FOCUS_REASON_MAX)
325 || (0 == strncmp(reason_for_change, "voip", AUDIO_FOCUS_REASON_MAX))
326 || (0 == strncmp(reason_for_change, "ringtone-voip", AUDIO_FOCUS_REASON_MAX))
327 || (0 == strncmp(reason_for_change, "ringtone-call", AUDIO_FOCUS_REASON_MAX))
329 if (focus_state == FOCUS_IS_RELEASED) {
331 *event_source = MM_MSG_CODE_INTERRUPTED_BY_CALL_END;
333 *event_source = MM_MSG_CODE_INTERRUPTED_BY_CALL_START;
334 } else if (focus_state == FOCUS_IS_ACQUIRED) {
336 *event_source = MM_MSG_CODE_INTERRUPTED_BY_CALL_START;
338 *event_source = MM_MSG_CODE_INTERRUPTED_BY_CALL_END;
341 } else if (0 == strncmp(reason_for_change, "alarm", AUDIO_FOCUS_REASON_MAX)) {
342 if (focus_state == FOCUS_IS_RELEASED) {
344 *event_source = MM_MSG_CODE_INTERRUPTED_BY_ALARM_END;
346 *event_source = MM_MSG_CODE_INTERRUPTED_BY_ALARM_START;
347 } else if (focus_state == FOCUS_IS_ACQUIRED) {
349 *event_source = MM_MSG_CODE_INTERRUPTED_BY_ALARM_START;
351 *event_source = MM_MSG_CODE_INTERRUPTED_BY_ALARM_END;
354 } else if (0 == strncmp(reason_for_change, "notification", AUDIO_FOCUS_REASON_MAX)) {
355 if (focus_state == FOCUS_IS_RELEASED) {
357 *event_source = MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_END;
359 *event_source = MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_START;
360 } else if (focus_state == FOCUS_IS_ACQUIRED) {
362 *event_source = MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_START;
364 *event_source = MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_END;
367 } else if (0 == strncmp(reason_for_change, "emergency", AUDIO_FOCUS_REASON_MAX)) {
368 if (focus_state == FOCUS_IS_RELEASED) {
370 *event_source = MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_END;
372 *event_source = MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_START;
373 } else if (focus_state == FOCUS_IS_ACQUIRED) {
375 *event_source = MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_START;
377 *event_source = MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_END;
380 } else if (0 == strncmp(reason_for_change, "media", AUDIO_FOCUS_REASON_MAX)) {
381 *event_source = MM_MSG_CODE_INTERRUPTED_BY_MEDIA;
384 *event_source = MM_MSG_CODE_INTERRUPTED_BY_MEDIA;
387 MMRADIO_LOG_FLEAVE();