• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
InitializeHandler()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 
ConnectToAPS()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 
OnAPSDisconnected()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.
OnInit()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 
Callback(base::File * file)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