1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 #define LOG_TAG "audio_hw_sndmonitor"
18 /*#define LOG_NDEBUG 0*/
19 #define LOG_NDDEBUG 0
20 
21 /* monitor sound card, cpe state
22 
23    audio_dev registers for a callback from this module in adev_open
24    Each stream in audio_hal registers for a callback in
25    adev_open_*_stream.
26 
27    A thread is spawned to poll() on sound card state files in /proc.
28    On observing a sound card state change, this thread invokes the
29    callbacks registered.
30 
31    Callbacks are deregistered in adev_close_*_stream and adev_close
32 */
33 #include <stdlib.h>
34 #include <dirent.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <sys/stat.h>
38 #include <sys/poll.h>
39 #include <pthread.h>
40 #include <cutils/list.h>
41 #include <cutils/hashmap.h>
42 #include <log/log.h>
43 #include <cutils/str_parms.h>
44 #include <ctype.h>
45 
46 #include "audio_hw.h"
47 #include "audio_extn.h"
48 
49 //#define MONITOR_DEVICE_EVENTS
50 #define CPE_MAGIC_NUM 0x2000
51 #define MAX_CPE_SLEEP_RETRY 2
52 #define CPE_SLEEP_WAIT 100
53 
54 #define MAX_SLEEP_RETRY 100
55 #define AUDIO_INIT_SLEEP_WAIT 100 /* 100 ms */
56 
57 #define AUDIO_PARAMETER_KEY_EXT_AUDIO_DEVICE "ext_audio_device"
58 
59 typedef enum {
60     audio_event_on,
61     audio_event_off
62 } audio_event_status;
63 
64 typedef struct {
65     int card;
66     int fd;
67     struct listnode node; // membership in sndcards list
68     card_status_t status;
69 } sndcard_t;
70 
71 typedef struct {
72     char * dev;
73     int fd;
74     int status;
75     struct listnode node; // membership in deviceevents list;
76 } dev_event_t;
77 
78 typedef void (* notifyfn)(const void * target, const char * msg);
79 
80 typedef struct {
81     const void * target;
82     notifyfn notify;
83     struct listnode cards;
84     unsigned int num_cards;
85     struct listnode dev_events;
86     unsigned int num_dev_events;
87     pthread_t monitor_thread;
88     int intpipe[2];
89     Hashmap * listeners; // from stream * -> callback func
90     bool initcheck;
91 } sndmonitor_state_t;
92 
93 static sndmonitor_state_t sndmonitor;
94 
read_state(int fd)95 static char * read_state(int fd)
96 {
97     struct stat buf;
98     if (fstat(fd, &buf) < 0)
99         return NULL;
100 
101     off_t pos = lseek(fd, 0, SEEK_CUR);
102     off_t avail = buf.st_size - pos;
103     if (avail <= 0) {
104         ALOGD("avail %ld", avail);
105         return NULL;
106     }
107 
108     char * state = (char *)calloc(avail+1, sizeof(char));
109     if (!state)
110         return NULL;
111 
112     ssize_t bytes=read(fd, state, avail);
113     if (bytes <= 0)
114         return NULL;
115 
116     // trim trailing whitespace
117     while (bytes && isspace(*(state+bytes-1))) {
118         *(state + bytes - 1) = '\0';
119         --bytes;
120     }
121     lseek(fd, 0, SEEK_SET);
122     return state;
123 }
124 
add_new_sndcard(int card,int fd)125 static int add_new_sndcard(int card, int fd)
126 {
127     sndcard_t * s = (sndcard_t *)calloc(sizeof(sndcard_t), 1);
128 
129     if (!s)
130         return -1;
131 
132     s->card = card;
133     s->fd = fd; // dup?
134 
135     char * state = read_state(fd);
136     bool online = state && !strcmp(state, "ONLINE");
137 
138     ALOGV("card %d initial state %s %d", card, state, online);
139 
140     if (state)
141         free(state);
142 
143     s->status = online ? CARD_STATUS_ONLINE : CARD_STATUS_OFFLINE;
144     list_add_tail(&sndmonitor.cards, &s->node);
145     return 0;
146 }
147 
enum_sndcards()148 static int enum_sndcards()
149 {
150     const char* cards = "/proc/asound/cards";
151     int tries = 10;
152     char *line = NULL;
153     size_t len = 0;
154     ssize_t bytes_read;
155     char path[128] = {0};
156     char *ptr, *saveptr, *card_id;
157     int line_no=0;
158     unsigned int num_cards=0, num_cpe=0;
159     FILE *fp;
160     int fd, ret;
161 
162     while (--tries) {
163         if ((fp = fopen(cards, "r")) == NULL) {
164             ALOGE("Cannot open %s file to get list of sound cards", cards);
165             usleep(100000);
166             continue;
167         }
168         break;
169     }
170 
171     if (!tries)
172         return -ENODEV;
173 
174     while ((bytes_read = getline(&line, &len, fp) != -1)) {
175         // skip every other line to to match
176         // the output format of /proc/asound/cards
177         if (line_no++ % 2)
178             continue;
179 
180         ptr = strtok_r(line, " [", &saveptr);
181         if (!ptr)
182             continue;
183 
184         card_id = strtok_r(saveptr+1, "]", &saveptr);
185         if (!card_id)
186             continue;
187 
188         // Limit to sound cards associated with ADSP
189         if ((strncasecmp(card_id, "msm", 3) != 0) &&
190             (strncasecmp(card_id, "sdm", 3) != 0) &&
191             (strncasecmp(card_id, "sdc", 3) != 0) &&
192             (strncasecmp(card_id, "apq", 3) != 0)) {
193             ALOGW("Skip over non-ADSP snd card %s", card_id);
194             continue;
195         }
196 
197         snprintf(path, sizeof(path), "/proc/asound/card%s/state", ptr);
198         ALOGV("Opening sound card state : %s", path);
199 
200         fd = open(path, O_RDONLY);
201         if (fd == -1) {
202             ALOGE("Open %s failed : %s", path, strerror(errno));
203             continue;
204         }
205 
206         ret = add_new_sndcard(atoi(ptr), fd);
207         if (ret != 0) {
208             close(fd); // card state fd ownership is taken by sndcard on success
209             continue;
210         }
211 
212         num_cards++;
213 
214         // query cpe state for this card as well
215         tries=MAX_CPE_SLEEP_RETRY;
216         snprintf(path, sizeof(path), "/proc/asound/card%s/cpe0_state", ptr);
217 
218         if (access(path, R_OK) < 0) {
219             ALOGW("access %s failed w/ err %s", path, strerror(errno));
220             continue;
221         }
222 
223         ALOGV("Open cpe state card state %s", path);
224         while (--tries) {
225             if ((fd = open(path, O_RDONLY)) < 0) {
226                 ALOGW("Open cpe state card state failed, retry : %s", path);
227                 usleep(CPE_SLEEP_WAIT*1000);
228                 continue;
229             }
230             break;
231         }
232 
233         if (!tries)
234             continue;
235 
236         ret = add_new_sndcard(CPE_MAGIC_NUM+num_cpe, fd);
237         if (ret != 0) {
238             close(fd); // card state fd ownership is taken by sndcard on success
239             continue;
240         }
241 
242         num_cpe++;
243         num_cards++;
244     }
245     if (line)
246         free(line);
247     fclose(fp);
248     ALOGV("sndmonitor registerer num_cards %d", num_cards);
249     sndmonitor.num_cards = num_cards;
250     return num_cards ? 0 : -1;
251 }
252 
free_sndcards()253 static void free_sndcards()
254 {
255     while (!list_empty(&sndmonitor.cards)) {
256         struct listnode * n = list_head(&sndmonitor.cards);
257         sndcard_t * s = node_to_item(n, sndcard_t, node);
258         list_remove(n);
259         close(s->fd);
260         free(s);
261     }
262 }
263 
add_new_dev_event(char * d_name,int fd)264 static int add_new_dev_event(char * d_name, int fd)
265 {
266     dev_event_t * d = (dev_event_t *)calloc(sizeof(dev_event_t), 1);
267 
268     if (!d)
269         return -1;
270 
271     d->dev = strdup(d_name);
272     d->fd = fd;
273     list_add_tail(&sndmonitor.dev_events, &d->node);
274     return 0;
275 }
276 
enum_dev_events()277 static int enum_dev_events()
278 {
279     const char* events_dir = "/sys/class/switch/";
280     DIR *dp;
281     struct dirent* in_file;
282     int fd;
283     char path[128] = {0};
284     unsigned int num_dev_events = 0;
285 
286     if ((dp = opendir(events_dir)) == NULL) {
287         ALOGE("Cannot open switch directory %s err %s",
288               events_dir, strerror(errno));
289         return -1;
290     }
291 
292     while ((in_file = readdir(dp)) != NULL) {
293         if (!strstr(in_file->d_name, "qc_"))
294             continue;
295 
296         snprintf(path, sizeof(path), "%s/%s/state",
297                  events_dir, in_file->d_name);
298 
299         ALOGV("Opening audio dev event state : %s ", path);
300         fd = open(path, O_RDONLY);
301         if (fd == -1) {
302             ALOGE("Open %s failed : %s", path, strerror(errno));
303         } else {
304             if (!add_new_dev_event(in_file->d_name, fd))
305                 num_dev_events++;
306         }
307     }
308     closedir(dp);
309     sndmonitor.num_dev_events = num_dev_events;
310     return num_dev_events ? 0 : -1;
311 }
312 
free_dev_events()313 static void free_dev_events()
314 {
315     while (!list_empty(&sndmonitor.dev_events)) {
316         struct listnode * n = list_head(&sndmonitor.dev_events);
317         dev_event_t * d = node_to_item(n, dev_event_t, node);
318         list_remove(n);
319         close(d->fd);
320         free(d->dev);
321         free(d);
322     }
323 }
324 
notify(const struct str_parms * params)325 static int notify(const struct str_parms * params)
326 {
327     if (!params)
328         return -1;
329 
330     char * str = str_parms_to_str((struct str_parms *)params);
331 
332     if (!str)
333         return -1;
334 
335     if (sndmonitor.notify)
336         sndmonitor.notify(sndmonitor.target, str);
337 
338     ALOGV("%s", str);
339     free(str);
340     return 0;
341 }
342 
on_dev_event(dev_event_t * dev_event)343 int on_dev_event(dev_event_t * dev_event)
344 {
345     char state_buf[2];
346     if (read(dev_event->fd, state_buf, 1) <= 0)
347         return -1;
348 
349     lseek(dev_event->fd, 0, SEEK_SET);
350     state_buf[1]='\0';
351     if (atoi(state_buf) == dev_event->status)
352         return 0;
353 
354     dev_event->status = atoi(state_buf);
355 
356     struct str_parms * params = str_parms_create();
357 
358     if (!params)
359         return -1;
360 
361     char val[32] = {0};
362     snprintf(val, sizeof(val), "%s,%s", dev_event->dev,
363              dev_event->status ? "ON" : "OFF");
364 
365     if (str_parms_add_str(params, AUDIO_PARAMETER_KEY_EXT_AUDIO_DEVICE, val) < 0)
366         return -1;
367 
368     int ret = notify(params);
369     str_parms_destroy(params);
370     return ret;
371 }
372 
on_sndcard_state_update(sndcard_t * s)373 bool on_sndcard_state_update(sndcard_t * s)
374 {
375     char rd_buf[9]={0};
376     card_status_t status;
377 
378     if (read(s->fd, rd_buf, 8) <= 0)
379         return -1;
380 
381     rd_buf[8] = '\0';
382     lseek(s->fd, 0, SEEK_SET);
383 
384     ALOGV("card num %d, new state %s", s->card, rd_buf);
385 
386     bool is_cpe = (s->card >= CPE_MAGIC_NUM);
387     if (strstr(rd_buf, "OFFLINE"))
388         status = CARD_STATUS_OFFLINE;
389     else if (strstr(rd_buf, "ONLINE"))
390         status = CARD_STATUS_ONLINE;
391     else {
392         ALOGE("unknown state");
393         return 0;
394     }
395 
396     if (status == s->status) // no change
397         return 0;
398 
399     s->status = status;
400 
401     struct str_parms * params = str_parms_create();
402 
403     if (!params)
404         return -1;
405 
406     char val[32] = {0};
407     // cpe actual card num is (card - MAGIC_NUM). so subtract accordingly
408     snprintf(val, sizeof(val), "%d,%s", s->card - (is_cpe ? CPE_MAGIC_NUM : 0),
409                  status == CARD_STATUS_ONLINE ? "ONLINE" : "OFFLINE");
410 
411     if (str_parms_add_str(params, is_cpe ? "CPE_STATUS" : "SND_CARD_STATUS",
412                           val) < 0)
413         return -1;
414 
415     int ret = notify(params);
416     str_parms_destroy(params);
417     return ret;
418 }
419 
monitor_thread_loop(void * args __unused)420 void * monitor_thread_loop(void * args __unused)
421 {
422     ALOGV("Start threadLoop()");
423     unsigned int num_poll_fds = sndmonitor.num_cards +
424                                 sndmonitor.num_dev_events + 1/*pipe*/;
425     struct pollfd * pfd = (struct pollfd *)calloc(sizeof(struct pollfd),
426                                                   num_poll_fds);
427     if (!pfd)
428         return NULL;
429 
430     pfd[0].fd = sndmonitor.intpipe[0];
431     pfd[0].events = POLLPRI|POLLIN;
432 
433     int i=1;
434     struct listnode *node;
435     list_for_each(node, &sndmonitor.cards) {
436         sndcard_t * s = node_to_item(node, sndcard_t, node);
437         pfd[i].fd = s->fd;
438         pfd[i].events = POLLPRI;
439         ++i;
440     }
441 
442     list_for_each(node, &sndmonitor.dev_events) {
443         dev_event_t * d = node_to_item(node, dev_event_t, node);
444         pfd[i].fd = d->fd;
445         pfd[i].events = POLLPRI;
446         ++i;
447     }
448 
449     while (1) {
450         if (poll(pfd, num_poll_fds, -1) < 0) {
451             int errno_ = errno;
452             ALOGE("poll() failed w/ err %s", strerror(errno));
453             switch (errno_) {
454             case EINTR:
455             case ENOMEM:
456                 sleep(2);
457                 continue;
458             default:
459                 /* above errors can be caused due to current system
460                    state .. any other error is not expected */
461                 LOG_ALWAYS_FATAL("unxpected poll() system call failure");
462                 break;
463             }
464         }
465         ALOGV("out of poll()");
466 
467 #define READY_TO_READ(p) ((p)->revents & (POLLIN|POLLPRI))
468 #define ERROR_IN_FD(p) ((p)->revents & (POLLERR|POLLHUP|POLLNVAL))
469 
470         // check if requested to exit
471         if (READY_TO_READ(&pfd[0])) {
472             char buf[2]={0};
473             read(pfd[0].fd, buf, 1);
474             if (!strcmp(buf, "Q"))
475                 break;
476         } else if (ERROR_IN_FD(&pfd[0])) {
477             // do not consider for poll again
478             // POLLERR - can this happen?
479             // POLLHUP - adev must not close pipe
480             // POLLNVAL - fd is valid
481             LOG_ALWAYS_FATAL("unxpected error in pipe poll fd 0x%x",
482                              pfd[0].revents);
483             pfd[0].fd *= -1;
484         }
485 
486         i=1;
487         list_for_each(node, &sndmonitor.cards) {
488             sndcard_t * s = node_to_item(node, sndcard_t, node);
489             if (READY_TO_READ(&pfd[i]))
490                 on_sndcard_state_update(s);
491             else if (ERROR_IN_FD(&pfd[i])) {
492                 // do not consider for poll again
493                 // POLLERR - can this happen as we are reading from a fs?
494                 // POLLHUP - not valid for cardN/state
495                 // POLLNVAL - fd is valid
496                 LOG_ALWAYS_FATAL("unxpected error in card poll fd 0x%x",
497                                  pfd[i].revents);
498                 pfd[i].fd *= -1;
499             }
500             ++i;
501         }
502 
503         list_for_each(node, &sndmonitor.dev_events) {
504             dev_event_t * d = node_to_item(node, dev_event_t, node);
505             if (READY_TO_READ(&pfd[i]))
506                 on_dev_event(d);
507             else if (ERROR_IN_FD(&pfd[i])) {
508                 // do not consider for poll again
509                 // POLLERR - can this happen as we are reading from a fs?
510                 // POLLHUP - not valid for switch/state
511                 // POLLNVAL - fd is valid
512                 LOG_ALWAYS_FATAL("unxpected error in dev poll fd 0x%x",
513                                  pfd[i].revents);
514                 pfd[i].fd *= -1;
515             }
516             ++i;
517         }
518     }
519 
520     return NULL;
521 }
522 
523 // ---- listener static APIs ---- //
hashfn(void * key)524 static int hashfn(void * key)
525 {
526     return (int)key;
527 }
528 
hasheq(void * key1,void * key2)529 static bool hasheq(void * key1, void *key2)
530 {
531     return key1 == key2;
532 }
533 
snd_cb(void * key,void * value,void * context)534 static bool snd_cb(void* key, void* value, void* context)
535 {
536     snd_mon_cb cb = (snd_mon_cb)value;
537     cb(key, context);
538     return true;
539 }
540 
snd_mon_update(const void * target __unused,const char * msg)541 static void snd_mon_update(const void * target __unused, const char * msg)
542 {
543     // target can be used to check if this message is intended for the
544     // recipient or not. (using some statically saved state)
545 
546     struct str_parms *parms = str_parms_create_str(msg);
547 
548     if (!parms)
549         return;
550 
551     hashmapLock(sndmonitor.listeners);
552     hashmapForEach(sndmonitor.listeners, snd_cb, parms);
553     hashmapUnlock(sndmonitor.listeners);
554 
555     str_parms_destroy(parms);
556 }
557 
listeners_init()558 static int listeners_init()
559 {
560     sndmonitor.listeners = hashmapCreate(5, hashfn, hasheq);
561     if (!sndmonitor.listeners)
562         return -1;
563     return 0;
564 }
565 
listeners_deinit()566 static int listeners_deinit()
567 {
568     // XXX TBD
569     return -1;
570 }
571 
add_listener(void * stream,snd_mon_cb cb)572 static int add_listener(void *stream, snd_mon_cb cb)
573 {
574     Hashmap * map = sndmonitor.listeners;
575     hashmapLock(map);
576     hashmapPut(map, stream, cb);
577     hashmapUnlock(map);
578     return 0;
579 }
580 
del_listener(void * stream)581 static int del_listener(void * stream)
582 {
583     Hashmap * map = sndmonitor.listeners;
584     hashmapLock(map);
585     hashmapRemove(map, stream);
586     hashmapUnlock(map);
587     return 0;
588 }
589 
590 // --- public APIs --- //
591 
audio_extn_snd_mon_deinit()592 int audio_extn_snd_mon_deinit()
593 {
594     if (!sndmonitor.initcheck)
595         return -1;
596 
597     write(sndmonitor.intpipe[1], "Q", 1);
598     pthread_join(sndmonitor.monitor_thread, (void **) NULL);
599     free_dev_events();
600     listeners_deinit();
601     free_sndcards();
602     close(sndmonitor.intpipe[0]);
603     close(sndmonitor.intpipe[1]);
604 
605     sndmonitor.initcheck = 0;
606     return 0;
607 }
608 
audio_extn_snd_mon_init()609 int audio_extn_snd_mon_init()
610 {
611     sndmonitor.notify = snd_mon_update;
612     sndmonitor.target = NULL; // unused for now
613     list_init(&sndmonitor.cards);
614     list_init(&sndmonitor.dev_events);
615     sndmonitor.initcheck = false;
616 
617     if (pipe(sndmonitor.intpipe) < 0)
618         goto pipe_error;
619 
620     if (enum_sndcards() < 0)
621         goto enum_sncards_error;
622 
623     if (listeners_init() < 0)
624         goto listeners_error;
625 
626 #ifdef MONITOR_DEVICE_EVENTS
627     enum_dev_events(); // failure here isn't fatal
628 #endif
629 
630     int ret = pthread_create(&sndmonitor.monitor_thread,
631                              (const pthread_attr_t *) NULL,
632                              monitor_thread_loop, NULL);
633 
634     if (ret) {
635         goto monitor_thread_create_error;
636     }
637     sndmonitor.initcheck = true;
638     return 0;
639 
640 monitor_thread_create_error:
641     listeners_deinit();
642 listeners_error:
643     free_sndcards();
644 enum_sncards_error:
645     close(sndmonitor.intpipe[0]);
646     close(sndmonitor.intpipe[1]);
647 pipe_error:
648     return -ENODEV;
649 }
650 
audio_extn_snd_mon_register_listener(void * stream,snd_mon_cb cb)651 int audio_extn_snd_mon_register_listener(void *stream, snd_mon_cb cb)
652 {
653     if (!sndmonitor.initcheck) {
654         ALOGW("sndmonitor initcheck failed, cannot register");
655         return -1;
656     }
657 
658     return add_listener(stream, cb);
659 }
660 
audio_extn_snd_mon_unregister_listener(void * stream)661 int audio_extn_snd_mon_unregister_listener(void * stream)
662 {
663     if (!sndmonitor.initcheck) {
664         ALOGW("sndmonitor initcheck failed, cannot deregister");
665         return -1;
666     }
667 
668     ALOGV("deregister listener for stream %p ", stream);
669     return del_listener(stream);
670 }
671