Home | History | Annotate | Download | only in audioservice
      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