Home | History | Annotate | Download | only in audioservice
      1 // Copyright 2016 The Android Open Source Project
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 //
     15 
     16 // Implementation of audio_device_handler.h
     17 
     18 #include "audio_device_handler.h"
     19 
     20 #include <base/files/file.h>
     21 #include <base/logging.h>
     22 #include <brillo/message_loops/message_loop.h>
     23 #include <media/AudioSystem.h>
     24 
     25 namespace brillo {
     26 
     27 // All input devices currently supported by AudioDeviceHandler.
     28 const std::vector<audio_devices_t> AudioDeviceHandler::kSupportedInputDevices_ =
     29     {AUDIO_DEVICE_IN_WIRED_HEADSET};
     30 
     31 const std::vector<audio_devices_t>
     32     AudioDeviceHandler::kSupportedOutputDevices_ = {
     33         AUDIO_DEVICE_OUT_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADPHONE};
     34 
     35 static const char kH2WStateFile[] = "/sys/class/switch/h2w/state";
     36 
     37 AudioDeviceHandler::AudioDeviceHandler() {
     38   headphone_ = false;
     39   microphone_ = false;
     40 }
     41 
     42 AudioDeviceHandler::~AudioDeviceHandler() {}
     43 
     44 void AudioDeviceHandler::GetInputDevices(std::vector<int>* devices_list) {
     45   std::copy(connected_input_devices_.begin(),
     46             connected_input_devices_.end(),
     47             std::back_inserter(*devices_list));
     48 }
     49 
     50 void AudioDeviceHandler::GetOutputDevices(std::vector<int>* devices_list) {
     51   std::copy(connected_output_devices_.begin(),
     52             connected_output_devices_.end(),
     53             std::back_inserter(*devices_list));
     54 }
     55 
     56 void AudioDeviceHandler::RegisterDeviceCallback(
     57       base::Callback<void(DeviceConnectionState,
     58                           const std::vector<int>& )>& callback) {
     59   callback_ = callback;
     60 }
     61 
     62 void AudioDeviceHandler::TriggerCallback(DeviceConnectionState state) {
     63   // If no devices have changed, don't bother triggering a callback.
     64   if (changed_devices_.size() == 0)
     65     return;
     66   base::Closure closure = base::Bind(callback_, state, changed_devices_);
     67   MessageLoop::current()->PostTask(closure);
     68   // We can clear changed_devices_ here since base::Bind makes a copy of
     69   // changed_devices_.
     70   changed_devices_.clear();
     71 }
     72 
     73 void AudioDeviceHandler::APSDisconnect() {
     74   aps_.clear();
     75 }
     76 
     77 void AudioDeviceHandler::APSConnect(
     78     android::sp<android::IAudioPolicyService> aps) {
     79   aps_ = aps;
     80   // Reset the state
     81   connected_input_devices_.clear();
     82   connected_output_devices_.clear();
     83   // Inform audio policy service about the currently connected devices.
     84   VLOG(1) << "Calling GetInitialAudioDeviceState on APSConnect.";
     85   GetInitialAudioDeviceState(base::FilePath(kH2WStateFile));
     86 }
     87 
     88 void AudioDeviceHandler::Init(android::sp<android::IAudioPolicyService> aps) {
     89   aps_ = aps;
     90   // Reset audio policy service state in case this service crashed and there is
     91   // a mismatch between the current system state and what audio policy service
     92   // was previously told.
     93   VLOG(1) << "Calling DisconnectAllSupportedDevices.";
     94   DisconnectAllSupportedDevices();
     95   TriggerCallback(kDevicesDisconnected);
     96 
     97   // Get headphone jack state and update audio policy service with new state.
     98   VLOG(1) << "Calling ReadInitialAudioDeviceState.";
     99   GetInitialAudioDeviceState(base::FilePath(kH2WStateFile));
    100 }
    101 
    102 void AudioDeviceHandler::GetInitialAudioDeviceState(
    103     const base::FilePath& path) {
    104   base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
    105   if (!file.IsValid()) {
    106     LOG(WARNING) << "Kernel does not have wired headset support. Could not "
    107                  << "open " << path.value() << " ("
    108                  << base::File::ErrorToString(file.error_details()) << ").";
    109     return;
    110   }
    111   int state = 0;
    112   int bytes_read = file.ReadAtCurrentPos(reinterpret_cast<char*>(&state), 1);
    113   state -= '0';
    114   if (bytes_read == 0) {
    115     LOG(WARNING) << "Could not read from " << path.value();
    116     return;
    117   }
    118   VLOG(1) << "Initial audio jack state is " << state;
    119   static const int kHeadPhoneMask = 0x1;
    120   bool headphone = state & kHeadPhoneMask;
    121   static const int kMicrophoneMask = 0x2;
    122   bool microphone = (state & kMicrophoneMask) >> 1;
    123 
    124   UpdateAudioSystem(headphone, microphone);
    125 }
    126 
    127 void AudioDeviceHandler::NotifyAudioPolicyService(
    128     audio_devices_t device, audio_policy_dev_state_t state) {
    129   if (aps_ == nullptr) {
    130     LOG(INFO) << "Audio device handler cannot call audio policy service. Will "
    131               << "try again later.";
    132     return;
    133   }
    134   VLOG(1) << "Calling Audio Policy Service to change " << device << " to state "
    135           << state;
    136   aps_->setDeviceConnectionState(device, state, "", "");
    137 }
    138 
    139 int AudioDeviceHandler::SetDevice(audio_policy_force_use_t usage,
    140                                   audio_policy_forced_cfg_t config) {
    141   if (aps_ == nullptr) {
    142     LOG(WARNING) << "Audio policy service cannot be reached. Please try again.";
    143     return EAGAIN;
    144   }
    145   VLOG(1) << "Calling audio policy service to set " << usage << " to "
    146           << config;
    147   return aps_->setForceUse(usage, config);
    148 }
    149 
    150 void AudioDeviceHandler::ConnectAudioDevice(audio_devices_t device) {
    151   audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
    152   NotifyAudioPolicyService(device, state);
    153   if (audio_is_input_device(device))
    154     connected_input_devices_.insert(device);
    155   else
    156     connected_output_devices_.insert(device);
    157   changed_devices_.push_back(device);
    158 }
    159 
    160 void AudioDeviceHandler::DisconnectAudioDevice(audio_devices_t device) {
    161   audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
    162   NotifyAudioPolicyService(device, state);
    163   if (audio_is_input_device(device))
    164     connected_input_devices_.erase(device);
    165   else
    166     connected_output_devices_.erase(device);
    167   changed_devices_.push_back(device);
    168 }
    169 
    170 void AudioDeviceHandler::DisconnectAllSupportedDevices() {
    171   for (auto device : kSupportedInputDevices_) {
    172     DisconnectAudioDevice(device);
    173   }
    174   for (auto device : kSupportedOutputDevices_) {
    175     DisconnectAudioDevice(device);
    176   }
    177 }
    178 
    179 void AudioDeviceHandler::DisconnectAllConnectedDevices() {
    180   while (!connected_input_devices_.empty()) {
    181     audio_devices_t device = *(connected_input_devices_.begin());
    182     DisconnectAudioDevice(device);
    183   }
    184   while (!connected_output_devices_.empty()) {
    185     audio_devices_t device = *(connected_output_devices_.begin());
    186     DisconnectAudioDevice(device);
    187   }
    188 }
    189 
    190 void AudioDeviceHandler::UpdateAudioSystem(bool headphone, bool microphone) {
    191   if (microphone) {
    192     ConnectAudioDevice(AUDIO_DEVICE_IN_WIRED_HEADSET);
    193   }
    194   if (headphone && microphone) {
    195     ConnectAudioDevice(AUDIO_DEVICE_OUT_WIRED_HEADSET);
    196   } else if (headphone) {
    197     ConnectAudioDevice(AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
    198   } else if (!microphone) {
    199     // No devices are connected. Inform the audio policy service that all
    200     // connected devices have been disconnected.
    201     DisconnectAllConnectedDevices();
    202     TriggerCallback(kDevicesDisconnected);
    203     return;
    204   }
    205   TriggerCallback(kDevicesConnected);
    206   return;
    207 }
    208 
    209 void AudioDeviceHandler::ProcessEvent(const struct input_event& event) {
    210   VLOG(1) << event.type << " " << event.code << " " << event.value;
    211   if (event.type == EV_SW) {
    212     switch (event.code) {
    213       case SW_HEADPHONE_INSERT:
    214         headphone_ = event.value;
    215         break;
    216       case SW_MICROPHONE_INSERT:
    217         microphone_ = event.value;
    218         break;
    219       default:
    220         // This event code is not supported by this handler.
    221         break;
    222     }
    223   } else if (event.type == EV_SYN) {
    224     // We have received all input events. Update the audio system.
    225     UpdateAudioSystem(headphone_, microphone_);
    226     // Reset the headphone and microphone flags that are used to track
    227     // information across multiple calls to ProcessEvent.
    228     headphone_ = false;
    229     microphone_ = false;
    230   }
    231 }
    232 
    233 }  // namespace brillo
    234