Home | History | Annotate | Download | only in android
      1 /*
      2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/modules/audio_device/android/low_latency_event.h"
     12 
     13 #include <assert.h>
     14 
     15 #define HANDLE_EINTR(x) ({                \
     16       typeof(x) eintr_wrapper_result;     \
     17       do {                                                        \
     18         eintr_wrapper_result = (x);                               \
     19       } while (eintr_wrapper_result == -1 && errno == EINTR);     \
     20       eintr_wrapper_result;                                       \
     21     })
     22 
     23 #define IGNORE_EINTR(x) ({                \
     24       typeof(x) eintr_wrapper_result;     \
     25       do {                                                        \
     26         eintr_wrapper_result = (x);                               \
     27         if (eintr_wrapper_result == -1 && errno == EINTR) {       \
     28           eintr_wrapper_result = 0;                               \
     29         }                                                         \
     30       } while (0);                                                \
     31       eintr_wrapper_result;                                       \
     32     })
     33 
     34 namespace webrtc {
     35 
     36 const LowLatencyEvent::Handle LowLatencyEvent::kInvalidHandle = -1;
     37 const int LowLatencyEvent::kReadHandle = 0;
     38 const int LowLatencyEvent::kWriteHandle = 1;
     39 
     40 LowLatencyEvent::LowLatencyEvent() {
     41   handles_[kReadHandle] = kInvalidHandle;
     42   handles_[kWriteHandle] = kInvalidHandle;
     43 }
     44 
     45 LowLatencyEvent::~LowLatencyEvent() {
     46   Stop();
     47 }
     48 
     49 bool LowLatencyEvent::Start() {
     50   assert(handles_[kReadHandle] == kInvalidHandle);
     51   assert(handles_[kWriteHandle] == kInvalidHandle);
     52 
     53   return socketpair(AF_UNIX, SOCK_STREAM, 0, handles_) == 0;
     54 }
     55 
     56 bool LowLatencyEvent::Stop() {
     57   bool ret = Close(&handles_[kReadHandle]) && Close(&handles_[kWriteHandle]);
     58   handles_[kReadHandle] = kInvalidHandle;
     59   handles_[kWriteHandle] = kInvalidHandle;
     60   return ret;
     61 }
     62 
     63 void LowLatencyEvent::SignalEvent(int event_id, int event_msg) {
     64   WriteFd(event_id, event_msg);
     65 }
     66 
     67 void LowLatencyEvent::WaitOnEvent(int* event_id, int* event_msg) {
     68   ReadFd(event_id, event_msg);
     69 }
     70 
     71 bool LowLatencyEvent::Close(Handle* handle) {
     72   if (*handle == kInvalidHandle) {
     73     return false;
     74   }
     75   int retval = IGNORE_EINTR(close(*handle));
     76   *handle = kInvalidHandle;
     77   return retval == 0;
     78 }
     79 
     80 void LowLatencyEvent::WriteFd(int message_id, int message) {
     81   char buffer[sizeof(message_id) + sizeof(message)];
     82   size_t bytes = sizeof(buffer);
     83   memcpy(buffer, &message_id, sizeof(message_id));
     84   memcpy(&buffer[sizeof(message_id)], &message, sizeof(message));
     85   ssize_t bytes_written = HANDLE_EINTR(write(handles_[kWriteHandle], buffer,
     86                                              bytes));
     87   if (bytes_written != static_cast<ssize_t>(bytes)) {
     88     assert(false);
     89   }
     90 }
     91 
     92 void LowLatencyEvent::ReadFd(int* message_id, int* message) {
     93   char buffer[sizeof(message_id) + sizeof(message)];
     94   size_t bytes = sizeof(buffer);
     95   ssize_t bytes_read = HANDLE_EINTR(read(handles_[kReadHandle], buffer, bytes));
     96   if (bytes_read == 0) {
     97     *message_id = 0;
     98     *message = 0;
     99     return;
    100   } else if (bytes_read == static_cast<ssize_t>(bytes)) {
    101     memcpy(message_id, buffer, sizeof(*message_id));
    102     memcpy(message, &buffer[sizeof(*message_id)], sizeof(*message));
    103   } else {
    104     assert(false);
    105   }
    106 }
    107 
    108 }  // namespace webrtc
    109