138 lines
4.0 KiB
C++
138 lines
4.0 KiB
C++
// Copyright (C) 2020 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.
|
|
|
|
#include "AudioProxyManager.h"
|
|
|
|
#include <aidl/device/google/atv/audio_proxy/IAudioProxy.h>
|
|
#include <android-base/logging.h>
|
|
#include <android-base/thread_annotations.h>
|
|
#include <android/binder_manager.h>
|
|
|
|
#include <mutex>
|
|
|
|
#include "AudioProxyDevice.h"
|
|
#include "StreamProviderImpl.h"
|
|
|
|
using aidl::device::google::atv::audio_proxy::IAudioProxy;
|
|
using android::sp;
|
|
using android::status_t;
|
|
|
|
namespace audio_proxy {
|
|
namespace {
|
|
|
|
bool checkDevice(audio_proxy_device_t* device) {
|
|
return device && device->get_address && device->open_output_stream &&
|
|
device->close_output_stream &&
|
|
// Check v2 extension. Currently only MediaShell uses this library and
|
|
// we'll make sure the MediaShell will update to use the new API.
|
|
device->v2 && device->v2->get_service_name &&
|
|
device->v2->open_output_stream;
|
|
}
|
|
|
|
std::shared_ptr<IAudioProxy> getAudioProxyService(
|
|
const std::string& serviceName) {
|
|
std::string instanceName =
|
|
std::string(IAudioProxy::descriptor) + "/" + serviceName;
|
|
return IAudioProxy::fromBinder(
|
|
ndk::SpAIBinder(AServiceManager_getService(instanceName.c_str())));
|
|
}
|
|
|
|
class AudioProxyManagerImpl : public AudioProxyManager {
|
|
public:
|
|
AudioProxyManagerImpl();
|
|
~AudioProxyManagerImpl() override = default;
|
|
|
|
bool registerDevice(audio_proxy_device_t* device) override;
|
|
|
|
|
|
private:
|
|
static void onServiceDied(void* cookie);
|
|
bool reconnectService();
|
|
bool reconnectService_Locked() REQUIRES(mLock);
|
|
|
|
ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
|
|
|
|
std::mutex mLock;
|
|
std::shared_ptr<IAudioProxy> mService GUARDED_BY(mLock);
|
|
std::unique_ptr<AudioProxyDevice> mDevice GUARDED_BY(mLock);
|
|
};
|
|
|
|
AudioProxyManagerImpl::AudioProxyManagerImpl()
|
|
: mDeathRecipient(
|
|
AIBinder_DeathRecipient_new(AudioProxyManagerImpl::onServiceDied)) {}
|
|
|
|
bool AudioProxyManagerImpl::registerDevice(audio_proxy_device_t* device) {
|
|
if (!checkDevice(device)) {
|
|
LOG(ERROR) << "Invalid device.";
|
|
return false;
|
|
}
|
|
|
|
std::scoped_lock<std::mutex> lock(mLock);
|
|
if (mDevice) {
|
|
DCHECK(mService);
|
|
LOG(ERROR) << "Device already registered!";
|
|
return false;
|
|
}
|
|
mDevice = std::make_unique<AudioProxyDevice>(device);
|
|
|
|
DCHECK(!mService);
|
|
return reconnectService_Locked();
|
|
}
|
|
|
|
bool AudioProxyManagerImpl::reconnectService() {
|
|
std::scoped_lock<std::mutex> lock(mLock);
|
|
return reconnectService_Locked();
|
|
}
|
|
|
|
bool AudioProxyManagerImpl::reconnectService_Locked() {
|
|
DCHECK(mDevice);
|
|
|
|
auto service = getAudioProxyService(mDevice->getServiceName());
|
|
if (!service) {
|
|
LOG(ERROR) << "Failed to reconnect service";
|
|
return false;
|
|
}
|
|
|
|
binder_status_t binder_status = AIBinder_linkToDeath(
|
|
service->asBinder().get(), mDeathRecipient.get(), this);
|
|
if (binder_status != STATUS_OK) {
|
|
LOG(ERROR) << "Failed to linkToDeath " << static_cast<int>(binder_status);
|
|
return false;
|
|
}
|
|
|
|
ndk::ScopedAStatus status = service->start(
|
|
ndk::SharedRefBase::make<StreamProviderImpl>(mDevice.get()));
|
|
if (!status.isOk()) {
|
|
LOG(ERROR) << "Failed to start service.";
|
|
return false;
|
|
}
|
|
|
|
mService = std::move(service);
|
|
return true;
|
|
}
|
|
|
|
// static
|
|
void AudioProxyManagerImpl::onServiceDied(void* cookie) {
|
|
auto* manager = static_cast<AudioProxyManagerImpl*>(cookie);
|
|
manager->reconnectService();
|
|
}
|
|
|
|
} // namespace
|
|
|
|
std::unique_ptr<AudioProxyManager> createAudioProxyManager() {
|
|
return std::make_unique<AudioProxyManagerImpl>();
|
|
}
|
|
|
|
} // namespace audio_proxy
|