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 #include "brillo_audio_service_impl.h"
30 
31 namespace brillo {
32 
33 static const char kAPSServiceName[] = "media.audio_policy";
34 static const char kInputDeviceDir[] = "/dev/input";
35 static const char kServiceName[] =
36     "android.brillo.brilloaudioservice.BrilloAudioService";
37 
~AudioDaemon()38 AudioDaemon::~AudioDaemon() {}
39 
InitializeHandlers()40 void AudioDaemon::InitializeHandlers() {
41   // Start and initialize the audio daemon handlers.
42   audio_device_handler_ =
43       std::shared_ptr<AudioDeviceHandler>(new AudioDeviceHandler());
44   audio_volume_handler_ =
45       std::unique_ptr<AudioVolumeHandler>(new AudioVolumeHandler());
46 
47   // Register a callback with the audio device handler to call when device state
48   // changes.
49   auto device_callback =
50       base::Bind(&AudioDaemon::DeviceCallback, weak_ptr_factory_.GetWeakPtr());
51   audio_device_handler_->RegisterDeviceCallback(device_callback);
52 
53   // Register a callback with the audio volume handler.
54   auto volume_callback =
55       base::Bind(&AudioDaemon::VolumeCallback, weak_ptr_factory_.GetWeakPtr());
56   audio_volume_handler_->RegisterCallback(volume_callback);
57 
58   audio_device_handler_->Init(aps_);
59   audio_volume_handler_->Init(aps_);
60 
61   // Poll on all files in kInputDeviceDir.
62   base::FileEnumerator fenum(base::FilePath(kInputDeviceDir),
63                              false /*recursive*/, base::FileEnumerator::FILES);
64   for (base::FilePath name = fenum.Next(); !name.empty(); name = fenum.Next()) {
65     base::File file(name, base::File::FLAG_OPEN | base::File::FLAG_READ);
66     if (file.IsValid()) {
67       MessageLoop* message_loop = MessageLoop::current();
68       int fd = file.GetPlatformFile();
69       // Move file to files_ and ensure that when binding we get a pointer from
70       // the object in files_.
71       files_.emplace(std::move(file));
72       base::Closure file_callback =
73           base::Bind(&AudioDaemon::EventCallback, weak_ptr_factory_.GetWeakPtr(),
74                      &files_.top());
75       message_loop->WatchFileDescriptor(fd, MessageLoop::kWatchRead,
76                                         true /*persistent*/, file_callback);
77     } else {
78       LOG(WARNING) << "Could not open " << name.value() << " for reading. ("
79                    << base::File::ErrorToString(file.error_details()) << ")";
80     }
81   }
82 
83   handlers_initialized_ = true;
84   // Once the handlers have been initialized, we can register with service
85   // manager.
86   InitializeBrilloAudioService();
87 }
88 
InitializeBrilloAudioService()89 void AudioDaemon::InitializeBrilloAudioService() {
90   brillo_audio_service_ = new BrilloAudioServiceImpl();
91   brillo_audio_service_->RegisterHandlers(
92       std::weak_ptr<AudioDeviceHandler>(audio_device_handler_),
93       std::weak_ptr<AudioVolumeHandler>(audio_volume_handler_));
94   android::BinderWrapper::Get()->RegisterService(kServiceName,
95                                                  brillo_audio_service_);
96   VLOG(1) << "Registered brilloaudioservice with the service manager.";
97 }
98 
ConnectToAPS()99 void AudioDaemon::ConnectToAPS() {
100   android::BinderWrapper* binder_wrapper = android::BinderWrapper::Get();
101   auto binder = binder_wrapper->GetService(kAPSServiceName);
102   // If we didn't get the audio policy service, try again in 500 ms.
103   if (!binder.get()) {
104     LOG(INFO) << "Could not connect to audio policy service. Trying again...";
105     brillo::MessageLoop::current()->PostDelayedTask(
106         base::Bind(&AudioDaemon::ConnectToAPS, weak_ptr_factory_.GetWeakPtr()),
107         base::TimeDelta::FromMilliseconds(500));
108     return;
109   }
110   LOG(INFO) << "Connected to audio policy service.";
111   binder_wrapper->RegisterForDeathNotifications(
112       binder,
113       base::Bind(&AudioDaemon::OnAPSDisconnected,
114                  weak_ptr_factory_.GetWeakPtr()));
115   VLOG(1) << "Registered death notification.";
116   aps_ = android::interface_cast<android::IAudioPolicyService>(binder);
117   if (!handlers_initialized_) {
118     InitializeHandlers();
119   } else {
120     audio_device_handler_->APSConnect(aps_);
121     audio_volume_handler_->APSConnect(aps_);
122   }
123 }
124 
OnAPSDisconnected()125 void AudioDaemon::OnAPSDisconnected() {
126   LOG(INFO) << "Audio policy service died. Will try to reconnect.";
127   audio_device_handler_->APSDisconnect();
128   audio_volume_handler_->APSDisconnect();
129   aps_ = nullptr;
130   ConnectToAPS();
131 }
132 
133 // OnInit, we want to do the following:
134 //   - Get a binder to the audio policy service.
135 //   - Initialize the audio device and volume handlers.
136 //   - Set up polling on files in /dev/input.
OnInit()137 int AudioDaemon::OnInit() {
138   int exit_code = Daemon::OnInit();
139   if (exit_code != EX_OK) return exit_code;
140   // Initialize a binder wrapper.
141   android::BinderWrapper::Create();
142   // Initialize a binder watcher.
143   binder_watcher_.Init();
144   ConnectToAPS();
145   return EX_OK;
146 }
147 
EventCallback(base::File * file)148 void AudioDaemon::EventCallback(base::File* file) {
149   input_event event;
150   int bytes_read =
151       file->ReadAtCurrentPos(reinterpret_cast<char*>(&event), sizeof(event));
152   if (bytes_read != sizeof(event)) {
153     LOG(WARNING) << "Couldn't read an input event.";
154     return;
155   }
156   audio_device_handler_->ProcessEvent(event);
157   audio_volume_handler_->ProcessEvent(event);
158 }
159 
DeviceCallback(AudioDeviceHandler::DeviceConnectionState state,const std::vector<int> & devices)160 void AudioDaemon::DeviceCallback(
161     AudioDeviceHandler::DeviceConnectionState state,
162     const std::vector<int>& devices) {
163   VLOG(1) << "Triggering device callback.";
164   if (!brillo_audio_service_.get()) {
165     LOG(ERROR) << "The Brillo audio service object is unavailble. Will try to "
166                << "call the clients again once the service is up.";
167     InitializeBrilloAudioService();
168     DeviceCallback(state, devices);
169     return;
170   }
171   if (state == AudioDeviceHandler::DeviceConnectionState::kDevicesConnected)
172     brillo_audio_service_->OnDevicesConnected(devices);
173   else
174     brillo_audio_service_->OnDevicesDisconnected(devices);
175 }
176 
VolumeCallback(audio_stream_type_t stream,int previous_index,int current_index)177 void AudioDaemon::VolumeCallback(audio_stream_type_t stream,
178                                  int previous_index,
179                                  int current_index) {
180   VLOG(1) << "Triggering volume button press callback.";
181   if (!brillo_audio_service_.get()) {
182     LOG(ERROR) << "The Brillo audio service object is unavailble. Will try to "
183                << "call the clients again once the service is up.";
184     InitializeBrilloAudioService();
185     VolumeCallback(stream, previous_index, current_index);
186     return;
187   }
188   brillo_audio_service_->OnVolumeChanged(stream, previous_index, current_index);
189 }
190 
191 }  // namespace brillo
192