Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f8d52aab authored by Tanya Finkel's avatar Tanya Finkel Committed by Gerrit - the friendly Code Review server
Browse files

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
parent dddca0f1
Loading
Loading
Loading
Loading
+129 −3
Original line number Diff line number Diff line
@@ -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);
    }
}
+13 −0
Original line number Diff line number Diff line
@@ -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;

};

}