Add more logs for debugging
[platform/core/multimedia/libmm-radio.git] / src / mm_radio_sound_focus.c
1 /*
2  * mm_radio_sound_focus.c
3  *
4  * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19
20 #include <assert.h>
21 #include <unistd.h>
22 #include <mm_debug.h>
23 #include <mm_sound.h>
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"
29
30 static void _mmradio_device_connected_cb(MMSoundDevice_t device, bool is_connected, void *user_data)
31 {
32         mm_radio_t *radio = (mm_radio_t *)user_data;
33         int result = MM_ERROR_NONE;
34         mm_sound_device_type_e type;
35
36         MMRADIO_LOG_FENTER();
37         MMRADIO_CHECK_INSTANCE_RETURN_VOID(radio);
38         MMRADIO_LOG_INFO("device [%d] is_connected [%d]", device, is_connected);
39
40         if (mm_sound_get_device_type(device, &type) != MM_ERROR_NONE) {
41                 MMRADIO_LOG_ERROR("getting device type failed");
42         } else {
43                 switch (type) {
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:
49                         if (!is_connected) {
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;
53
54                                 result = _mmradio_stop(radio);
55                                 if (result != MM_ERROR_NONE)
56                                         MMRADIO_LOG_ERROR("failed to stop radio");
57                         }
58                         break;
59                 default:
60                         break;
61                 }
62         }
63         MMRADIO_LOG_FLEAVE();
64 }
65
66 void _mmradio_sound_signal_callback(mm_sound_signal_name_t signal, int value, void *user_data)
67 {
68         mm_radio_sound_focus *sound_focus = (mm_radio_sound_focus *)user_data;
69         int ret = MM_ERROR_NONE;
70
71         MMRADIO_LOG_INFO("sound signal callback %d / %d", signal, value);
72
73         if (signal == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS) {
74                 if (value == 1) {
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()");
82                         }
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);
90                         }
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()");
98                         }
99                 }
100         }
101 }
102
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)
105 {
106         /* read mm-session information */
107         int session_type = MM_SESSION_TYPE_MEDIA;
108         int session_flags = 0;
109         int ret = MM_ERROR_NONE;
110         int pid = getpid();
111         int handle = 0;
112
113         MMRADIO_LOG_FENTER();
114
115         if (!sound_focus) {
116                 MMRADIO_LOG_ERROR("invalid session handle");
117                 return MM_ERROR_RADIO_NOT_INITIALIZED;
118         }
119         sound_focus->cur_focus_type = FOCUS_NONE;
120
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;
132                         }
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;
140                         }
141                         MMRADIO_LOG_INFO("(%p) set focus watch callback = %d", param, sound_focus->watch_id);
142
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;
149                         }
150                         MMRADIO_LOG_INFO("register device connected callback for the value is 0, sub_cb id %d", sound_focus->device_subs_id);
151                 }
152                 ret = MM_ERROR_NONE;
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;
166                                 }
167                                 sound_focus->handle = handle;
168
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;
173                                 }
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;
181                                 }
182                                 MMRADIO_LOG_DEBUG("(%p) add device connected callback = %d", param, sound_focus->device_subs_id);
183
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;
191                                 }
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..");
194                         } else {
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;
201                                 }
202                                 MMRADIO_LOG_DEBUG("set focus watch callback = %d", sound_focus->watch_id);
203
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;
210                                 }
211                                 MMRADIO_LOG_INFO("(%p) add device connected callback = %d", param, sound_focus->device_subs_id);
212                         }
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..");
216                 } else {
217                         MMRADIO_LOG_WARNING("seesion type is not MEDIA (%d)", sound_focus->session_type);
218                         return MM_ERROR_RADIO_INTERNAL;
219                 }
220                 ret = MM_ERROR_NONE;
221         } else {
222                 MMRADIO_LOG_WARNING("Read Session Information failed. skip sound focus register function. errorcode %x", ret);
223         }
224
225         MMRADIO_LOG_FLEAVE();
226
227         return MM_ERROR_NONE;
228 }
229
230 int mmradio_sound_focus_deregister(mm_radio_sound_focus *sound_focus)
231 {
232
233         int ret = MM_ERROR_NONE;
234
235         MMRADIO_LOG_FENTER();
236
237         if (!sound_focus) {
238                 MMRADIO_LOG_ERROR("invalid session handle");
239                 return MM_ERROR_RADIO_NOT_INITIALIZED;
240         }
241
242         if (sound_focus->watch_id > 0) {
243                 MMRADIO_LOG_INFO("unset the focus watch cb %d", sound_focus->watch_id);
244
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);
249         }
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);
256         }
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);
264         }
265
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);
269         }
270
271         MMRADIO_LOG_FLEAVE();
272
273         return MM_ERROR_NONE;
274 }
275
276 int mmradio_acquire_sound_focus(mm_radio_sound_focus *sound_focus)
277 {
278         int ret = MM_ERROR_NONE;
279         mm_sound_focus_type_e focus_type = FOCUS_NONE;
280         MMRADIO_LOG_FENTER();
281
282         MMRADIO_LOG_ERROR("mmradio_acquire_sound_focus sound_focus->cur_focus_type : %d", sound_focus->cur_focus_type);
283
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;
290                 }
291                 sound_focus->cur_focus_type = FOCUS_FOR_BOTH;
292         }
293
294         MMRADIO_LOG_FLEAVE();
295         return ret;
296 }
297
298 int mmradio_release_sound_focus(mm_radio_sound_focus *sound_focus)
299 {
300         int ret = MM_ERROR_NONE;
301         MMRADIO_LOG_FENTER();
302
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;
309                 }
310                 sound_focus->cur_focus_type = FOCUS_NONE;
311         }
312
313         MMRADIO_LOG_FLEAVE();
314         return ret;
315 }
316
317 #define AUDIO_FOCUS_REASON_MAX  128
318
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)
320 {
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);
323
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))
328                 ) {
329                 if (focus_state == FOCUS_IS_RELEASED) {
330                         if (is_watch)
331                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_CALL_END;
332                         else
333                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_CALL_START;
334                 } else if (focus_state == FOCUS_IS_ACQUIRED) {
335                         if (is_watch)
336                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_CALL_START;
337                         else
338                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_CALL_END;
339                 }
340                 *postMsg = true;
341         } else if (0 == strncmp(reason_for_change, "alarm", AUDIO_FOCUS_REASON_MAX)) {
342                 if (focus_state == FOCUS_IS_RELEASED) {
343                         if (is_watch)
344                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_ALARM_END;
345                         else
346                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_ALARM_START;
347                 } else if (focus_state == FOCUS_IS_ACQUIRED) {
348                         if (is_watch)
349                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_ALARM_START;
350                         else
351                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_ALARM_END;
352                 }
353                 *postMsg = true;
354         } else if (0 == strncmp(reason_for_change, "notification", AUDIO_FOCUS_REASON_MAX)) {
355                 if (focus_state == FOCUS_IS_RELEASED) {
356                         if (is_watch)
357                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_END;
358                         else
359                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_START;
360                 } else if (focus_state == FOCUS_IS_ACQUIRED) {
361                         if (is_watch)
362                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_START;
363                         else
364                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_NOTIFICATION_END;
365                 }
366                 *postMsg = true;
367         } else if (0 == strncmp(reason_for_change, "emergency", AUDIO_FOCUS_REASON_MAX)) {
368                 if (focus_state == FOCUS_IS_RELEASED) {
369                         if (is_watch)
370                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_END;
371                         else
372                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_START;
373                 } else if (focus_state == FOCUS_IS_ACQUIRED) {
374                         if (is_watch)
375                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_START;
376                         else
377                                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_EMERGENCY_END;
378                 }
379                 *postMsg = false;
380         } else if (0 == strncmp(reason_for_change, "media", AUDIO_FOCUS_REASON_MAX)) {
381                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_MEDIA;
382                 *postMsg = false;
383         } else {
384                 *event_source = MM_MSG_CODE_INTERRUPTED_BY_MEDIA;
385                 *postMsg = false;
386         }
387         MMRADIO_LOG_FLEAVE();
388 }