Files
hardware_interfaces/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
William Escande 01d65e01d0 Fix deathRecipient of BluetoothAudioProvider
The "provider" is managed with a shared_ptr but we do not hold it and
instead are giving the raw inner pointer as binderDiedCallbackAidl.
This can randomly generate crash as the provider may be freed outside of
this code.

Replacing the provider with a context that we can manually allocate and
deallocate.
Setup AIBinder_DeathRecipient_setOnUnlinked to clean the data allocated

Bug: 245009140
Test: m android.hardware.bluetooth.audio-impl and start / stop session +
      manually kill bluetooth process during audio play
(cherry picked from https://android-review.googlesource.com/q/commit:f3faab081a543ad43e86eec6d03cd7835ef5c712)
Merged-In: I0c14c062a8bde7e532ff02f01991d66da33ec569
Change-Id: I0c14c062a8bde7e532ff02f01991d66da33ec569
2023-05-15 18:47:00 +00:00

171 lines
5.7 KiB
C++

/*
* Copyright (C) 2022 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.
*/
#define LOG_TAG "BTAudioProviderStub"
#include "BluetoothAudioProvider.h"
#include <BluetoothAudioSessionReport.h>
#include <android-base/logging.h>
namespace aidl {
namespace android {
namespace hardware {
namespace bluetooth {
namespace audio {
struct BluetoothAudioProviderContext {
SessionType session_type;
};
static void binderUnlinkedCallbackAidl(void* cookie) {
LOG(INFO) << __func__;
BluetoothAudioProviderContext* ctx =
static_cast<BluetoothAudioProviderContext*>(cookie);
delete ctx;
}
static void binderDiedCallbackAidl(void* cookie) {
LOG(INFO) << __func__;
BluetoothAudioProviderContext* ctx =
static_cast<BluetoothAudioProviderContext*>(cookie);
CHECK_NE(ctx, nullptr);
BluetoothAudioSessionReport::OnSessionEnded(ctx->session_type);
}
BluetoothAudioProvider::BluetoothAudioProvider() {
death_recipient_ = ::ndk::ScopedAIBinder_DeathRecipient(
AIBinder_DeathRecipient_new(binderDiedCallbackAidl));
AIBinder_DeathRecipient_setOnUnlinked(death_recipient_.get(),
binderUnlinkedCallbackAidl);
}
ndk::ScopedAStatus BluetoothAudioProvider::startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
const AudioConfiguration& audio_config,
const std::vector<LatencyMode>& latencyModes,
DataMQDesc* _aidl_return) {
if (host_if == nullptr) {
*_aidl_return = DataMQDesc();
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
latency_modes_ = latencyModes;
audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
stack_iface_ = host_if;
BluetoothAudioProviderContext* cookie =
new BluetoothAudioProviderContext{session_type_};
AIBinder_linkToDeath(stack_iface_->asBinder().get(), death_recipient_.get(),
cookie);
onSessionReady(_aidl_return);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothAudioProvider::endSession() {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
if (stack_iface_ != nullptr) {
BluetoothAudioSessionReport::OnSessionEnded(session_type_);
AIBinder_unlinkToDeath(stack_iface_->asBinder().get(),
death_recipient_.get(), this);
} else {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
<< " has NO session";
}
stack_iface_ = nullptr;
audio_config_ = nullptr;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothAudioProvider::streamStarted(
BluetoothAudioStatus status) {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
<< ", status=" << toString(status);
if (stack_iface_ != nullptr) {
BluetoothAudioSessionReport::ReportControlStatus(session_type_, true,
status);
} else {
LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
<< ", status=" << toString(status) << " has NO session";
}
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothAudioProvider::streamSuspended(
BluetoothAudioStatus status) {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
<< ", status=" << toString(status);
if (stack_iface_ != nullptr) {
BluetoothAudioSessionReport::ReportControlStatus(session_type_, false,
status);
} else {
LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
<< ", status=" << toString(status) << " has NO session";
}
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothAudioProvider::updateAudioConfiguration(
const AudioConfiguration& audio_config) {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
if (stack_iface_ == nullptr || audio_config_ == nullptr) {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
<< " has NO session";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
if (audio_config.getTag() != audio_config_->getTag()) {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
<< " audio config type is not match";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
BluetoothAudioSessionReport::ReportAudioConfigChanged(session_type_,
*audio_config_);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus BluetoothAudioProvider::setLowLatencyModeAllowed(
bool allowed) {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
if (stack_iface_ == nullptr) {
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
<< " has NO session";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
LOG(INFO) << __func__ << " - allowed " << allowed;
BluetoothAudioSessionReport::ReportLowLatencyModeAllowedChanged(
session_type_, allowed);
return ndk::ScopedAStatus::ok();
}
} // namespace audio
} // namespace bluetooth
} // namespace hardware
} // namespace android
} // namespace aidl