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_daemon.h. 17 18 #include "audio_daemon.h" 19 20 #include <sysexits.h> 21 22 #include <base/bind.h> 23 #include <base/files/file_enumerator.h> 24 #include <base/files/file_path.h> 25 #include <base/time/time.h> 26 #include <binderwrapper/binder_wrapper.h> 27 #include <linux/input.h> 28 29 namespace brillo { 30 31 static const char kAPSServiceName[] = "media.audio_policy"; 32 static const char kInputDeviceDir[] = "/dev/input"; 33 34 void AudioDaemon::InitializeHandler() { 35 // Start and initialize the audio device handler. 36 audio_device_handler_ = 37 std::unique_ptr<AudioDeviceHandler>(new AudioDeviceHandler()); 38 audio_device_handler_->Init(aps_); 39 40 // Poll on all files in kInputDeviceDir. 41 base::FileEnumerator fenum(base::FilePath(kInputDeviceDir), 42 false /*recursive*/, base::FileEnumerator::FILES); 43 for (base::FilePath name = fenum.Next(); !name.empty(); name = fenum.Next()) { 44 base::File file(name, base::File::FLAG_OPEN | base::File::FLAG_READ); 45 if (file.IsValid()) { 46 MessageLoop* message_loop = MessageLoop::current(); 47 int fd = file.GetPlatformFile(); 48 // Move file to files_ and ensure that when binding we get a pointer from 49 // the object in files_. 50 files_.emplace(std::move(file)); 51 base::Closure callback = 52 base::Bind(&AudioDaemon::Callback, weak_ptr_factory_.GetWeakPtr(), 53 &files_.top()); 54 message_loop->WatchFileDescriptor(fd, MessageLoop::kWatchRead, 55 true /*persistent*/, callback); 56 } else { 57 LOG(WARNING) << "Could not open " << name.value() << " for reading. (" 58 << base::File::ErrorToString(file.error_details()) << ")"; 59 } 60 } 61 handler_initialized_ = true; 62 } 63 64 void AudioDaemon::ConnectToAPS() { 65 android::BinderWrapper* binder_wrapper = android::BinderWrapper::Get(); 66 auto binder = binder_wrapper->GetService(kAPSServiceName); 67 // If we didn't get the audio policy service, try again in 500 ms. 68 if (!binder.get()) { 69 LOG(INFO) << "Could not connect to audio policy service. Trying again..."; 70 brillo::MessageLoop::current()->PostDelayedTask( 71 base::Bind(&AudioDaemon::ConnectToAPS, weak_ptr_factory_.GetWeakPtr()), 72 base::TimeDelta::FromMilliseconds(500)); 73 return; 74 } 75 LOG(INFO) << "Connected to audio policy service."; 76 binder_wrapper->RegisterForDeathNotifications( 77 binder, 78 base::Bind(&AudioDaemon::OnAPSDisconnected, 79 weak_ptr_factory_.GetWeakPtr())); 80 VLOG(1) << "Registered death notification."; 81 aps_ = android::interface_cast<android::IAudioPolicyService>(binder); 82 if (!handler_initialized_) 83 InitializeHandler(); 84 else 85 audio_device_handler_->APSConnect(aps_); 86 } 87 88 void AudioDaemon::OnAPSDisconnected() { 89 LOG(INFO) << "Audio policy service died. Will try to reconnect."; 90 audio_device_handler_->APSDisconnect(); 91 aps_ = nullptr; 92 ConnectToAPS(); 93 } 94 95 // OnInit, we want to do the following: 96 // - Get a binder to the audio policy service. 97 // - Initialize the audio device handler. 98 // - Set up polling on files in /dev/input. 99 int AudioDaemon::OnInit() { 100 int exit_code = Daemon::OnInit(); 101 if (exit_code != EX_OK) return exit_code; 102 // Initialize a binder wrapper. 103 android::BinderWrapper::Create(); 104 // Initialize a binder watcher. 105 binder_watcher_.Init(); 106 ConnectToAPS(); 107 return EX_OK; 108 } 109 110 void AudioDaemon::Callback(base::File* file) { 111 input_event event; 112 int bytes_read = 113 file->ReadAtCurrentPos(reinterpret_cast<char*>(&event), sizeof(event)); 114 if (bytes_read != sizeof(event)) { 115 LOG(WARNING) << "Couldn't read an input event."; 116 return; 117 } 118 audio_device_handler_->ProcessEvent(event); 119 } 120 121 } // namespace brillo 122