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
This commit is contained in:
Tanya Finkel 2014-07-16 07:03:15 -07:00 committed by Gerrit - the friendly Code Review server
parent dddca0f1f8
commit f8d52aab10
2 changed files with 142 additions and 3 deletions

View File

@ -30,6 +30,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
#define LOG_NDEBUG 0
#define LOG_NDDEBUG 0
#include <dirent.h>
#include <media/AudioSystem.h>
#include <sys/poll.h>
@ -117,6 +118,89 @@ namespace android {
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 @@ namespace android {
}
}
if (!getDeviceEventFDs()) {
ALOGE("No audio device events detected");
}
if (audioInitDone == false) {
ALOGE("Sound Card is empty!!!");
goto thread_exit;
@ -177,13 +265,20 @@ namespace android {
}
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 @@ namespace android {
}
}
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 @@ namespace android {
}
}
}
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 @@ namespace android {
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);
}
}

View File

@ -52,6 +52,10 @@ enum notify_status_type {
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 @@ class AudioDaemon:public Thread, public IBinder :: DeathRecipient
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 @@ public:
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;
};
}