blob: 08ff548a54581716739074e6ca6bdf05c78c8a5a [file] [log] [blame]
Ralph Nathan5e788b52016-01-07 15:10:32 -08001// 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
Ralph Nathan005f6b52016-04-14 14:28:02 -070029#include "brillo_audio_service_impl.h"
Ralph Nathanb3d2a542016-02-02 14:59:27 -080030
Ralph Nathan5e788b52016-01-07 15:10:32 -080031namespace brillo {
32
33static const char kAPSServiceName[] = "media.audio_policy";
34static const char kInputDeviceDir[] = "/dev/input";
Ralph Nathanb3d2a542016-02-02 14:59:27 -080035static const char kServiceName[] =
36 "android.brillo.brilloaudioservice.BrilloAudioService";
37
38AudioDaemon::~AudioDaemon() {}
Ralph Nathan5e788b52016-01-07 15:10:32 -080039
Ralph Nathan831b4402016-03-21 14:10:56 -070040void AudioDaemon::InitializeHandlers() {
41 // Start and initialize the audio daemon handlers.
Ralph Nathan5e788b52016-01-07 15:10:32 -080042 audio_device_handler_ =
Ralph Nathanb3d2a542016-02-02 14:59:27 -080043 std::shared_ptr<AudioDeviceHandler>(new AudioDeviceHandler());
Ralph Nathan831b4402016-03-21 14:10:56 -070044 audio_volume_handler_ =
45 std::unique_ptr<AudioVolumeHandler>(new AudioVolumeHandler());
Ralph Nathanb3d2a542016-02-02 14:59:27 -080046
Ralph Nathan831b4402016-03-21 14:10:56 -070047 // Register a callback with the audio device handler to call when device state
48 // changes.
Ralph Nathanc7779812016-04-14 17:19:53 -070049 auto device_callback =
50 base::Bind(&AudioDaemon::DeviceCallback, weak_ptr_factory_.GetWeakPtr());
Ralph Nathanb3d2a542016-02-02 14:59:27 -080051 audio_device_handler_->RegisterDeviceCallback(device_callback);
52
Ralph Nathanc7779812016-04-14 17:19:53 -070053 // 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
Ralph Nathan5e788b52016-01-07 15:10:32 -080058 audio_device_handler_->Init(aps_);
Ralph Nathan831b4402016-03-21 14:10:56 -070059 audio_volume_handler_->Init(aps_);
Ralph Nathan5e788b52016-01-07 15:10:32 -080060
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));
Ralph Nathanb3d2a542016-02-02 14:59:27 -080072 base::Closure file_callback =
73 base::Bind(&AudioDaemon::EventCallback, weak_ptr_factory_.GetWeakPtr(),
Ralph Nathan5e788b52016-01-07 15:10:32 -080074 &files_.top());
75 message_loop->WatchFileDescriptor(fd, MessageLoop::kWatchRead,
Ralph Nathanb3d2a542016-02-02 14:59:27 -080076 true /*persistent*/, file_callback);
Ralph Nathan5e788b52016-01-07 15:10:32 -080077 } else {
78 LOG(WARNING) << "Could not open " << name.value() << " for reading. ("
79 << base::File::ErrorToString(file.error_details()) << ")";
80 }
81 }
Ralph Nathanb3d2a542016-02-02 14:59:27 -080082
Ralph Nathan831b4402016-03-21 14:10:56 -070083 handlers_initialized_ = true;
84 // Once the handlers have been initialized, we can register with service
Ralph Nathanb3d2a542016-02-02 14:59:27 -080085 // manager.
86 InitializeBrilloAudioService();
87}
88
89void AudioDaemon::InitializeBrilloAudioService() {
Ralph Nathan005f6b52016-04-14 14:28:02 -070090 brillo_audio_service_ = new BrilloAudioServiceImpl();
Ralph Nathanc7779812016-04-14 17:19:53 -070091 brillo_audio_service_->RegisterHandlers(
92 std::weak_ptr<AudioDeviceHandler>(audio_device_handler_),
93 std::weak_ptr<AudioVolumeHandler>(audio_volume_handler_));
Ralph Nathanb3d2a542016-02-02 14:59:27 -080094 android::BinderWrapper::Get()->RegisterService(kServiceName,
95 brillo_audio_service_);
96 VLOG(1) << "Registered brilloaudioservice with the service manager.";
Ralph Nathan5e788b52016-01-07 15:10:32 -080097}
98
99void 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);
Ralph Nathan831b4402016-03-21 14:10:56 -0700117 if (!handlers_initialized_) {
118 InitializeHandlers();
119 } else {
Ralph Nathan5e788b52016-01-07 15:10:32 -0800120 audio_device_handler_->APSConnect(aps_);
Ralph Nathan831b4402016-03-21 14:10:56 -0700121 audio_volume_handler_->APSConnect(aps_);
122 }
Ralph Nathan5e788b52016-01-07 15:10:32 -0800123}
124
125void AudioDaemon::OnAPSDisconnected() {
126 LOG(INFO) << "Audio policy service died. Will try to reconnect.";
127 audio_device_handler_->APSDisconnect();
Ralph Nathan831b4402016-03-21 14:10:56 -0700128 audio_volume_handler_->APSDisconnect();
Ralph Nathan5e788b52016-01-07 15:10:32 -0800129 aps_ = nullptr;
130 ConnectToAPS();
131}
132
133// OnInit, we want to do the following:
134// - Get a binder to the audio policy service.
Ralph Nathan831b4402016-03-21 14:10:56 -0700135// - Initialize the audio device and volume handlers.
Ralph Nathan5e788b52016-01-07 15:10:32 -0800136// - Set up polling on files in /dev/input.
137int 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
Ralph Nathanb3d2a542016-02-02 14:59:27 -0800148void AudioDaemon::EventCallback(base::File* file) {
Ralph Nathan5e788b52016-01-07 15:10:32 -0800149 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);
Ralph Nathan831b4402016-03-21 14:10:56 -0700157 audio_volume_handler_->ProcessEvent(event);
Ralph Nathan5e788b52016-01-07 15:10:32 -0800158}
159
Ralph Nathanb3d2a542016-02-02 14:59:27 -0800160void 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
Ralph Nathanc7779812016-04-14 17:19:53 -0700177void 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
Ralph Nathan5e788b52016-01-07 15:10:32 -0800191} // namespace brillo