Audio deamon: Add support of audio device events
Audio daemon will catch the events regarding the audio device changes and
transfer them to audio HAL.
Change-Id: Ida6b26142ece472a6e127904a43890ee44632d75
diff --git a/audiod/AudioDaemon.cpp b/audiod/AudioDaemon.cpp
index 2bfe391..b4857c4 100644
--- a/audiod/AudioDaemon.cpp
+++ b/audiod/AudioDaemon.cpp
@@ -30,6 +30,7 @@
#define LOG_NDEBUG 0
#define LOG_NDDEBUG 0
+#include <dirent.h>
#include <media/AudioSystem.h>
#include <sys/poll.h>
@@ -117,6 +118,89 @@
sndcardFdPair.clear();
}
+ bool AudioDaemon::getDeviceEventFDs()
+ {
+ const char* events_dir = "/sys/class/switch/";
+ DIR *dp;
+ struct dirent* in_file;
+ int fd;
+ String8 path;
+
+ if ((dp = opendir(events_dir)) == NULL) {
+ ALOGE("Cannot open switch directory to get list of audio events %s", events_dir);
+ return false;
+ }
+
+ mAudioEvents.clear();
+ mAudioEventsStatus.clear();
+
+ while ((in_file = readdir(dp)) != NULL) {
+
+ if (!strstr(in_file->d_name, "qc_"))
+ continue;
+ ALOGD(" Found event file = %s", in_file->d_name);
+ path = "/sys/class/switch/";
+ path += in_file->d_name;
+ path += "/state";
+
+ ALOGE("Opening audio event state : %s ", path.string());
+ fd = open(path.string(), O_RDONLY);
+ if (fd == -1) {
+ ALOGE("Open %s failed : %s", path.string(), strerror(errno));
+ } else {
+ mAudioEvents.push_back(std::make_pair(in_file->d_name, fd));
+ mAudioEventsStatus.push_back(std::make_pair(in_file->d_name, 0));
+ ALOGD("event status mAudioEventsStatus= %s",
+ mAudioEventsStatus[0].first.string());
+ }
+ }
+
+ ALOGV("%s: %d audio device event detected",
+ __func__,
+ mAudioEvents.size());
+
+ closedir(dp);
+ return mAudioEvents.size() > 0 ? true : false;
+
+ }
+
+ void AudioDaemon::putDeviceEventFDs()
+ {
+ unsigned int i;
+ for (i = 0; i < mAudioEvents.size(); i++) {
+ close(mAudioEvents[i].second);
+ delete(mAudioEvents[i].first);
+ }
+ mAudioEvents.clear();
+ mAudioEventsStatus.clear();
+ }
+
+ void AudioDaemon::checkEventState(int fd, int index)
+ {
+ char state_buf[2];
+ audio_event_status event_cur_state = audio_event_off;
+
+ if (!read(fd, (void *)state_buf, 1)) {
+ ALOGE("Error receiving device state event (%s)", strerror(errno));
+ } else {
+ state_buf[1] = '\0';
+ if (atoi(state_buf) != mAudioEventsStatus[index].second) {
+ ALOGD("notify audio HAL %s",
+ mAudioEvents[index].first.string());
+ mAudioEventsStatus[index].second = atoi(state_buf);
+
+ if (mAudioEventsStatus[index].second == 1)
+ event_cur_state = audio_event_on;
+ else
+ event_cur_state = audio_event_off;
+ notifyAudioSystemEventStatus(
+ mAudioEventsStatus[index].first.string(),
+ event_cur_state);
+ }
+ }
+ lseek(fd, 0, SEEK_SET);
+ }
+
status_t AudioDaemon::readyToRun() {
ALOGV("readyToRun: open snd card state node files");
@@ -151,6 +235,10 @@
}
}
+ if (!getDeviceEventFDs()) {
+ ALOGE("No audio device events detected");
+ }
+
if (audioInitDone == false) {
ALOGE("Sound Card is empty!!!");
goto thread_exit;
@@ -177,13 +265,20 @@
}
ALOGD("number of sndcards %d CPEs %d", i, cpe_cnt - CPE_MAGIC_NUM);
- pfd = new pollfd[mSndCardFd.size()];
- bzero(pfd, sizeof(*pfd) * mSndCardFd.size());
+ pfd = new pollfd[mSndCardFd.size() + mAudioEvents.size()];
+ bzero(pfd, (sizeof(*pfd) * mSndCardFd.size() +
+ sizeof(*pfd) * mAudioEvents.size()));
for (i = 0; i < mSndCardFd.size(); i++) {
pfd[i].fd = mSndCardFd[i].second;
pfd[i].events = POLLPRI;
}
+ /*insert all audio events*/
+ for(i = 0; i < mAudioEvents.size(); i++) {
+ pfd[i+mSndCardFd.size()].fd = mAudioEvents[i].second;
+ pfd[i+mSndCardFd.size()].events = POLLPRI;
+ }
+
ALOGD("read for sound card state change before while");
for (i = 0; i < mSndCardFd.size(); i++) {
if (!read(pfd[i].fd, (void *)rd_buf, 8)) {
@@ -233,9 +328,14 @@
}
}
+ ALOGE("read for event state change before while");
+ for (i = 0; i < mAudioEvents.size(); i++){
+ checkEventState(pfd[i+mSndCardFd.size()].fd, i);
+ }
+
while (1) {
ALOGD("poll() for sound card state change ");
- if (poll(pfd, mSndCardFd.size(), -1) < 0) {
+ if (poll(pfd, (mSndCardFd.size() + mAudioEvents.size()), -1) < 0) {
ALOGE("poll() failed (%s)", strerror(errno));
ret = false;
break;
@@ -290,9 +390,19 @@
}
}
}
+ for (i = 0; i < mAudioEvents.size(); i++) {
+ if (pfd[i + mSndCardFd.size()].revents & POLLPRI) {
+ ALOGE("EVENT recieved pfd[i].revents= 0x%x %d",
+ pfd[i + mSndCardFd.size()].revents,
+ mAudioEvents[i].second);
+
+ checkEventState(pfd[i + mSndCardFd.size()].fd, i);
+ }
+ }
}
putStateFDs(mSndCardFd);
+ putDeviceEventFDs();
delete [] pfd;
thread_exit:
@@ -329,4 +439,20 @@
ALOGV("%s: notifyAudioSystem : %s", __func__, str.string());
AudioSystem::setParameters(0, str);
}
+
+ void AudioDaemon::notifyAudioSystemEventStatus(const char* event,
+ audio_event_status status) {
+
+ String8 str;
+ str += AUDIO_PARAMETER_KEY_EXT_AUDIO_DEVICE;
+ str += "=";
+ str += event;
+
+ if (status == audio_event_on)
+ str += ",ON";
+ else
+ str += ",OFF";
+ ALOGD("%s: notifyAudioSystemEventStatus : %s", __func__, str.string());
+ AudioSystem::setParameters(0, str);
+ }
}
diff --git a/audiod/AudioDaemon.h b/audiod/AudioDaemon.h
index 23d78dd..3359d72 100644
--- a/audiod/AudioDaemon.h
+++ b/audiod/AudioDaemon.h
@@ -52,6 +52,10 @@
CPE_STATE
};
+enum audio_event_status {audio_event_on, audio_event_off};
+
+#define AUDIO_PARAMETER_KEY_EXT_AUDIO_DEVICE "ext_audio_device"
+
class AudioDaemon:public Thread, public IBinder :: DeathRecipient
{
/*Overrides*/
@@ -64,9 +68,13 @@
void notifyAudioSystem(int snd_card,
notify_status status,
notify_status_type type);
+ void notifyAudioSystemEventStatus(const char* event, audio_event_status status);
int mUeventSock;
bool getStateFDs(std::vector<std::pair<int,int> > &sndcardFdPair);
void putStateFDs(std::vector<std::pair<int,int> > &sndcardFdPair);
+ bool getDeviceEventFDs();
+ void putDeviceEventFDs();
+ void checkEventState(int fd, int index);
public:
AudioDaemon();
@@ -74,6 +82,11 @@
private:
std::vector<std::pair<int,int> > mSndCardFd;
+
+ //file descriptors for audio device events and their statuses
+ std::vector<std::pair<String8, int> > mAudioEvents;
+ std::vector<std::pair<String8, int> > mAudioEventsStatus;
+
};
}