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 <media/AudioSystem.h> 23 24 namespace brillo { 25 26 static const char kH2WStateFile[] = "/sys/class/switch/h2w/state"; 27 28 AudioDeviceHandler::AudioDeviceHandler() { 29 headphone_ = false; 30 microphone_ = false; 31 } 32 33 AudioDeviceHandler::~AudioDeviceHandler() {} 34 35 void AudioDeviceHandler::APSDisconnect() { 36 aps_.clear(); 37 } 38 39 void AudioDeviceHandler::APSConnect( 40 android::sp<android::IAudioPolicyService> aps) { 41 aps_ = aps; 42 // Reset the state 43 connected_input_devices_.clear(); 44 connected_output_devices_.clear(); 45 // Inform audio policy service about the currently connected devices. 46 VLOG(1) << "Calling GetInitialAudioDeviceState on APSConnect."; 47 GetInitialAudioDeviceState(base::FilePath(kH2WStateFile)); 48 } 49 50 void AudioDeviceHandler::Init(android::sp<android::IAudioPolicyService> aps) { 51 aps_ = aps; 52 // Reset audio policy service state in case this service crashed and there is 53 // a mismatch between the current system state and what audio policy service 54 // was previously told. 55 VLOG(1) << "Calling DisconnectAllSupportedDevices."; 56 DisconnectAllSupportedDevices(); 57 58 // Get headphone jack state and update audio policy service with new state. 59 VLOG(1) << "Calling ReadInitialAudioDeviceState."; 60 GetInitialAudioDeviceState(base::FilePath(kH2WStateFile)); 61 } 62 63 void AudioDeviceHandler::GetInitialAudioDeviceState( 64 const base::FilePath& path) { 65 base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); 66 if (!file.IsValid()) { 67 LOG(WARNING) << "Kernel does not have wired headset support. Could not " 68 << "open " << path.value() << "( " 69 << base::File::ErrorToString(file.error_details()) << " )."; 70 return; 71 } 72 int state = 0; 73 int bytes_read = file.ReadAtCurrentPos(reinterpret_cast<char*>(&state), 1); 74 state -= '0'; 75 if (bytes_read == 0) { 76 LOG(WARNING) << "Could not read from " << path.value(); 77 return; 78 } 79 VLOG(1) << "Initial audio jack state is " << state; 80 static const int kHeadPhoneMask = 0x1; 81 bool headphone = state & kHeadPhoneMask; 82 static const int kMicrophoneMask = 0x2; 83 bool microphone = (state & kMicrophoneMask) >> 1; 84 85 UpdateAudioSystem(headphone, microphone); 86 } 87 88 void AudioDeviceHandler::NotifyAudioPolicyService( 89 audio_devices_t device, audio_policy_dev_state_t state) { 90 if (aps_ == nullptr) { 91 LOG(INFO) << "Audio device handler cannot call audio policy service. Will " 92 << "try again later."; 93 return; 94 } 95 VLOG(1) << "Calling Audio Policy Service to change " << device << " to state " 96 << state; 97 aps_->setDeviceConnectionState(device, state, "", ""); 98 } 99 100 void AudioDeviceHandler::ConnectAudioDevice(audio_devices_t device) { 101 audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_AVAILABLE; 102 NotifyAudioPolicyService(device, state); 103 if (audio_is_input_device(device)) 104 connected_input_devices_.insert(device); 105 else 106 connected_output_devices_.insert(device); 107 } 108 109 void AudioDeviceHandler::DisconnectAudioDevice(audio_devices_t device) { 110 audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; 111 NotifyAudioPolicyService(device, state); 112 if (audio_is_input_device(device)) 113 connected_input_devices_.erase(device); 114 else 115 connected_output_devices_.erase(device); 116 } 117 118 void AudioDeviceHandler::DisconnectAllSupportedDevices() { 119 for (auto device : kSupportedInputDevices_) { 120 DisconnectAudioDevice(device); 121 } 122 for (auto device : kSupportedOutputDevices_) { 123 DisconnectAudioDevice(device); 124 } 125 } 126 127 void AudioDeviceHandler::DisconnectAllConnectedDevices() { 128 while (!connected_input_devices_.empty()) { 129 audio_devices_t device = *(connected_input_devices_.begin()); 130 DisconnectAudioDevice(device); 131 } 132 while (!connected_output_devices_.empty()) { 133 audio_devices_t device = *(connected_output_devices_.begin()); 134 DisconnectAudioDevice(device); 135 } 136 } 137 138 void AudioDeviceHandler::UpdateAudioSystem(bool headphone, bool microphone) { 139 if (microphone) { 140 ConnectAudioDevice(AUDIO_DEVICE_IN_WIRED_HEADSET); 141 } 142 if (headphone && microphone) { 143 ConnectAudioDevice(AUDIO_DEVICE_OUT_WIRED_HEADSET); 144 } else if (headphone) { 145 ConnectAudioDevice(AUDIO_DEVICE_OUT_WIRED_HEADPHONE); 146 } else if (!microphone) { 147 // No devices are connected. Inform the audio policy service that all 148 // connected devices have been disconnected. 149 DisconnectAllConnectedDevices(); 150 } 151 } 152 153 void AudioDeviceHandler::ProcessEvent(const struct input_event& event) { 154 VLOG(1) << event.type << " " << event.code << " " << event.value; 155 if (event.type == EV_SW) { 156 switch (event.code) { 157 case SW_HEADPHONE_INSERT: 158 headphone_ = event.value; 159 break; 160 case SW_MICROPHONE_INSERT: 161 microphone_ = event.value; 162 break; 163 default: 164 // This event code is not supported by this handler. 165 break; 166 } 167 } else if (event.type == EV_SYN) { 168 // We have received all input events. Update the audio system. 169 UpdateAudioSystem(headphone_, microphone_); 170 // Reset the headphone and microphone flags that are used to track 171 // information across multiple calls to ProcessEvent. 172 headphone_ = false; 173 microphone_ = false; 174 } 175 } 176 177 } // namespace brillo 178