C++程序  |  225行  |  7.02 KB

// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

// Implementation of brillo_audio_client.h

#include "brillo_audio_client.h"

#include <base/logging.h>
#include <binder/Status.h>
#include <binderwrapper/binder_wrapper.h>

#include "brillo_audio_client_helpers.h"
#include "brillo_audio_device_info_def.h"
#include "brillo_audio_device_info_internal.h"

using android::binder::Status;

namespace brillo {

static const char kBrilloAudioServiceName[] =
    "android.brillo.brilloaudioservice.BrilloAudioService";

std::shared_ptr<BrilloAudioClient> BrilloAudioClient::instance_ = nullptr;

int BrilloAudioClient::callback_id_counter_ = 1;

BrilloAudioClient::~BrilloAudioClient() {}

std::weak_ptr<BrilloAudioClient> BrilloAudioClient::GetClientInstance() {
  if (!instance_) {
    instance_ = std::shared_ptr<BrilloAudioClient>(new BrilloAudioClient());
    if (!instance_->Initialize()) {
      LOG(ERROR) << "Could not Initialize the brillo audio client.";
      instance_.reset();
      return instance_;
    }
  }
  return instance_;
}

android::sp<android::IBinder> BrilloAudioClient::ConnectToService(
    const std::string& service_name, const base::Closure& callback) {
  android::BinderWrapper* binder_wrapper =
      android::BinderWrapper::GetOrCreateInstance();
  auto service = binder_wrapper->GetService(service_name);
  if (!service.get()) {
    return service;
  }
  binder_wrapper->RegisterForDeathNotifications(service, callback);
  return service;
}

void BrilloAudioClient::OnBASDisconnect() {
  LOG(WARNING) << "The brillo audio service died! Please reset the "
               << "BAudioManager.";
  instance_.reset();
}

bool BrilloAudioClient::Initialize() {
  auto service = ConnectToService(
      kBrilloAudioServiceName, base::Bind(&BrilloAudioClient::OnBASDisconnect,
                                          weak_ptr_factory_.GetWeakPtr()));
  if (!service.get()) {
    LOG(ERROR) << "Could not connect to brillo audio service.";
    return false;
  }
  brillo_audio_service_ = android::interface_cast<IBrilloAudioService>(service);
  return true;
}

int BrilloAudioClient::GetDevices(int flag, std::vector<int>& devices) {
  if (!brillo_audio_service_.get()) {
    OnBASDisconnect();
    return ECONNABORTED;
  }
  auto status = brillo_audio_service_->GetDevices(flag, &devices);
  return status.serviceSpecificErrorCode();
}

int BrilloAudioClient::SetDevice(audio_policy_force_use_t usage,
                                 audio_policy_forced_cfg_t config) {
  if (!brillo_audio_service_.get()) {
    OnBASDisconnect();
    return ECONNABORTED;
  }
  auto status = brillo_audio_service_->SetDevice(usage, config);
  return status.serviceSpecificErrorCode();
}

int BrilloAudioClient::GetMaxVolumeSteps(BAudioUsage usage, int* max_steps) {
  if (!brillo_audio_service_.get()) {
    OnBASDisconnect();
    return ECONNABORTED;
  }
  auto status = brillo_audio_service_->GetMaxVolumeSteps(
      BrilloAudioClientHelpers::GetStreamType(usage), max_steps);
  return status.serviceSpecificErrorCode();
}

int BrilloAudioClient::SetMaxVolumeSteps(BAudioUsage usage, int max_steps) {
  if (!brillo_audio_service_.get()) {
    OnBASDisconnect();
    return ECONNABORTED;
  }
  auto status = brillo_audio_service_->SetMaxVolumeSteps(
      BrilloAudioClientHelpers::GetStreamType(usage), max_steps);
  return status.serviceSpecificErrorCode();
}

int BrilloAudioClient::SetVolumeIndex(BAudioUsage usage,
                                      audio_devices_t device,
                                      int index) {
  if (!brillo_audio_service_.get()) {
    OnBASDisconnect();
    return ECONNABORTED;
  }
  auto status = brillo_audio_service_->SetVolumeIndex(
      BrilloAudioClientHelpers::GetStreamType(usage), device, index);
  return status.serviceSpecificErrorCode();
}

int BrilloAudioClient::GetVolumeIndex(BAudioUsage usage,
                                      audio_devices_t device,
                                      int* index) {
  if (!brillo_audio_service_.get()) {
    OnBASDisconnect();
    return ECONNABORTED;
  }
  auto status = brillo_audio_service_->GetVolumeIndex(
      BrilloAudioClientHelpers::GetStreamType(usage), device, index);
  return status.serviceSpecificErrorCode();
}

int BrilloAudioClient::GetVolumeControlStream(BAudioUsage* usage) {
  if (!brillo_audio_service_.get()) {
    OnBASDisconnect();
    return ECONNABORTED;
  }
  int stream;
  auto status = brillo_audio_service_->GetVolumeControlStream(&stream);
  *usage = BrilloAudioClientHelpers::GetBAudioUsage(
      static_cast<audio_stream_type_t>(stream));
  return status.serviceSpecificErrorCode();
}

int BrilloAudioClient::SetVolumeControlStream(BAudioUsage usage) {
  if (!brillo_audio_service_.get()) {
    OnBASDisconnect();
    return ECONNABORTED;
  }
  auto status = brillo_audio_service_->SetVolumeControlStream(
      BrilloAudioClientHelpers::GetStreamType(usage));
  return status.serviceSpecificErrorCode();
}

int BrilloAudioClient::IncrementVolume() {
  if (!brillo_audio_service_.get()) {
    OnBASDisconnect();
    return ECONNABORTED;
  }
  auto status = brillo_audio_service_->IncrementVolume();
  return status.serviceSpecificErrorCode();
}

int BrilloAudioClient::DecrementVolume() {
  if (!brillo_audio_service_.get()) {
    OnBASDisconnect();
    return ECONNABORTED;
  }
  auto status = brillo_audio_service_->DecrementVolume();
  return status.serviceSpecificErrorCode();
}

int BrilloAudioClient::RegisterAudioCallback(
    android::sp<AudioServiceCallback> callback, int* callback_id) {
  if (!brillo_audio_service_.get()) {
    OnBASDisconnect();
    return ECONNABORTED;
  }
  if (!brillo_audio_service_->RegisterServiceCallback(callback).isOk()) {
    *callback_id = 0;
    return ECONNABORTED;
  }
  for (auto& entry : callback_map_) {
    if (entry.second->Equals(callback)) {
      LOG(ERROR) << "Callback has already been registered.";
      *callback_id = 0;
      return EINVAL;
    }
  }
  *callback_id = callback_id_counter_++;
  callback_map_.emplace(*callback_id, callback);
  return 0;
}

int BrilloAudioClient::UnregisterAudioCallback(int callback_id) {
  if (!brillo_audio_service_.get()) {
    OnBASDisconnect();
    return ECONNABORTED;
  }
  auto callback_elem = callback_map_.find(callback_id);
  if (callback_elem == callback_map_.end()) {
    // If we were passed an invalid callback_id, do nothing.
    LOG(ERROR) << "Unregister called with invalid callback ID.";
    return EINVAL;
  }
  brillo_audio_service_->UnregisterServiceCallback(callback_elem->second.get());
  callback_map_.erase(callback_elem);
  return 0;
}

}  // namespace brillo