Make mediaserver listen to Codec2 services' deaths

Test: Kill media.extractor or mediaswcodec and observe logcat

Bug: 130071409

Change-Id: Ie785642da99dfe4ff13e78d878817dae3de9f34a
gugelfrei
Pawin Vongmasa 5 years ago
parent 8263e3519b
commit 270dd6a1a6

@ -99,6 +99,7 @@ cc_library {
export_shared_lib_headers: [ export_shared_lib_headers: [
"android.hardware.media.c2@1.0", "android.hardware.media.c2@1.0",
"libcodec2", "libcodec2",
"libcodec2_vndk",
"libhidlbase", "libhidlbase",
"libstagefright_bufferpool@2.0", "libstagefright_bufferpool@2.0",
"libui", "libui",

@ -31,6 +31,7 @@ cc_library {
export_shared_lib_headers: [ export_shared_lib_headers: [
"libcodec2", "libcodec2",
"libcodec2_hidl_client@1.0", "libcodec2_hidl_client@1.0",
"libcodec2_vndk",
], ],
} }

@ -75,82 +75,11 @@ namespace /* unnamed */ {
// c2_status_t value that corresponds to hwbinder transaction failure. // c2_status_t value that corresponds to hwbinder transaction failure.
constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED; constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED;
// Returns the list of IComponentStore service names that are available on the // Searches for a name in GetServiceNames() and returns the index found. If the
// device. This list is specified at the build time in manifest files.
// Note: A software service will have "_software" as a suffix.
std::vector<std::string> const& getServiceNames() {
static std::vector<std::string> sServiceNames{[]() {
using ::android::hardware::media::c2::V1_0::IComponentStore;
using ::android::hidl::manager::V1_2::IServiceManager;
while (true) {
sp<IServiceManager> serviceManager = IServiceManager::getService();
CHECK(serviceManager) << "Hardware service manager is not running.";
// There are three categories of services based on names.
std::vector<std::string> defaultNames; // Prefixed with "default"
std::vector<std::string> vendorNames; // Prefixed with "vendor"
std::vector<std::string> otherNames; // Others
Return<void> transResult;
transResult = serviceManager->listManifestByInterface(
IComponentStore::descriptor,
[&defaultNames, &vendorNames, &otherNames](
hidl_vec<hidl_string> const& instanceNames) {
for (hidl_string const& instanceName : instanceNames) {
char const* name = instanceName.c_str();
if (strncmp(name, "default", 7) == 0) {
defaultNames.emplace_back(name);
} else if (strncmp(name, "vendor", 6) == 0) {
vendorNames.emplace_back(name);
} else {
otherNames.emplace_back(name);
}
}
});
if (transResult.isOk()) {
// Sort service names in each category.
std::sort(defaultNames.begin(), defaultNames.end());
std::sort(vendorNames.begin(), vendorNames.end());
std::sort(otherNames.begin(), otherNames.end());
// Concatenate the three lists in this order: default, vendor,
// other.
std::vector<std::string>& names = defaultNames;
names.reserve(names.size() + vendorNames.size() + otherNames.size());
names.insert(names.end(),
std::make_move_iterator(vendorNames.begin()),
std::make_move_iterator(vendorNames.end()));
names.insert(names.end(),
std::make_move_iterator(otherNames.begin()),
std::make_move_iterator(otherNames.end()));
// Summarize to logcat.
if (names.empty()) {
LOG(INFO) << "No Codec2 services declared in the manifest.";
} else {
std::stringstream stringOutput;
stringOutput << "Available Codec2 services:";
for (std::string const& name : names) {
stringOutput << " \"" << name << "\"";
}
LOG(INFO) << stringOutput.str();
}
return names;
}
LOG(ERROR) << "Could not retrieve the list of service instances of "
<< IComponentStore::descriptor
<< ". Retrying...";
}
}()};
return sServiceNames;
}
// Searches for a name in getServiceNames() and returns the index found. If the
// name is not found, the returned index will be equal to // name is not found, the returned index will be equal to
// getServiceNames().size(). // GetServiceNames().size().
size_t getServiceIndex(char const* name) { size_t getServiceIndex(char const* name) {
std::vector<std::string> const& names = getServiceNames(); std::vector<std::string> const& names = Codec2Client::GetServiceNames();
size_t i = 0; size_t i = 0;
for (; i < names.size(); ++i) { for (; i < names.size(); ++i) {
if (name == names[i]) { if (name == names[i]) {
@ -175,17 +104,14 @@ class Codec2Client::Cache {
std::vector<C2Component::Traits> mTraits; std::vector<C2Component::Traits> mTraits;
std::once_flag mTraitsInitializationFlag; std::once_flag mTraitsInitializationFlag;
// The index of the service. This is based on getServiceNames(). // The index of the service. This is based on GetServiceNames().
size_t mIndex; size_t mIndex;
// A "valid" cache object must have its mIndex set with init().
bool mValid{false};
// Called by s() exactly once to initialize the cache. The index must be a // Called by s() exactly once to initialize the cache. The index must be a
// valid index into the vector returned by getServiceNames(). Calling // valid index into the vector returned by GetServiceNames(). Calling
// init(index) will associate the cache to the service with name // init(index) will associate the cache to the service with name
// getServiceNames()[index]. // GetServiceNames()[index].
void init(size_t index) { void init(size_t index) {
mIndex = index; mIndex = index;
mValid = true;
} }
public: public:
@ -195,7 +121,6 @@ public:
// If the service is unavailable but listed in the manifest, this function // If the service is unavailable but listed in the manifest, this function
// will block indefinitely. // will block indefinitely.
std::shared_ptr<Codec2Client> getClient() { std::shared_ptr<Codec2Client> getClient() {
CHECK(mValid) << "Uninitialized cache";
std::scoped_lock lock{mClientMutex}; std::scoped_lock lock{mClientMutex};
if (!mClient) { if (!mClient) {
mClient = Codec2Client::_CreateFromIndex(mIndex); mClient = Codec2Client::_CreateFromIndex(mIndex);
@ -208,7 +133,6 @@ public:
// //
// Note: This function is called only by ForAllServices(). // Note: This function is called only by ForAllServices().
void invalidate() { void invalidate() {
CHECK(mValid) << "Uninitialized cache";
std::scoped_lock lock{mClientMutex}; std::scoped_lock lock{mClientMutex};
mClient = nullptr; mClient = nullptr;
} }
@ -216,7 +140,6 @@ public:
// Returns a list of traits for components supported by the service. This // Returns a list of traits for components supported by the service. This
// list is cached. // list is cached.
std::vector<C2Component::Traits> const& getTraits() { std::vector<C2Component::Traits> const& getTraits() {
CHECK(mValid) << "Uninitialized cache";
std::call_once(mTraitsInitializationFlag, [this]() { std::call_once(mTraitsInitializationFlag, [this]() {
bool success{false}; bool success{false};
// Spin until _listComponents() is successful. // Spin until _listComponents() is successful.
@ -229,7 +152,7 @@ public:
using namespace std::chrono_literals; using namespace std::chrono_literals;
static constexpr auto kServiceRetryPeriod = 5s; static constexpr auto kServiceRetryPeriod = 5s;
LOG(INFO) << "Failed to retrieve component traits from service " LOG(INFO) << "Failed to retrieve component traits from service "
"\"" << getServiceNames()[mIndex] << "\". " "\"" << GetServiceNames()[mIndex] << "\". "
"Retrying..."; "Retrying...";
std::this_thread::sleep_for(kServiceRetryPeriod); std::this_thread::sleep_for(kServiceRetryPeriod);
} }
@ -240,7 +163,7 @@ public:
// List() returns the list of all caches. // List() returns the list of all caches.
static std::vector<Cache>& List() { static std::vector<Cache>& List() {
static std::vector<Cache> sCaches{[]() { static std::vector<Cache> sCaches{[]() {
size_t numServices = getServiceNames().size(); size_t numServices = GetServiceNames().size();
std::vector<Cache> caches(numServices); std::vector<Cache> caches(numServices);
for (size_t i = 0; i < numServices; ++i) { for (size_t i = 0; i < numServices; ++i) {
caches[i].init(i); caches[i].init(i);
@ -610,8 +533,12 @@ Codec2Client::Codec2Client(const sp<IComponentStore>& base,
} }
} }
sp<Codec2Client::Base> const& Codec2Client::getBase() const {
return mBase;
}
std::string const& Codec2Client::getServiceName() const { std::string const& Codec2Client::getServiceName() const {
return getServiceNames()[mServiceIndex]; return GetServiceNames()[mServiceIndex];
} }
c2_status_t Codec2Client::createComponent( c2_status_t Codec2Client::createComponent(
@ -807,15 +734,94 @@ std::shared_ptr<C2ParamReflector>
return std::make_shared<SimpleParamReflector>(mBase); return std::make_shared<SimpleParamReflector>(mBase);
}; };
std::vector<std::string> const& Codec2Client::GetServiceNames() {
static std::vector<std::string> sServiceNames{[]() {
using ::android::hardware::media::c2::V1_0::IComponentStore;
using ::android::hidl::manager::V1_2::IServiceManager;
while (true) {
sp<IServiceManager> serviceManager = IServiceManager::getService();
CHECK(serviceManager) << "Hardware service manager is not running.";
// There are three categories of services based on names.
std::vector<std::string> defaultNames; // Prefixed with "default"
std::vector<std::string> vendorNames; // Prefixed with "vendor"
std::vector<std::string> otherNames; // Others
Return<void> transResult;
transResult = serviceManager->listManifestByInterface(
IComponentStore::descriptor,
[&defaultNames, &vendorNames, &otherNames](
hidl_vec<hidl_string> const& instanceNames) {
for (hidl_string const& instanceName : instanceNames) {
char const* name = instanceName.c_str();
if (strncmp(name, "default", 7) == 0) {
defaultNames.emplace_back(name);
} else if (strncmp(name, "vendor", 6) == 0) {
vendorNames.emplace_back(name);
} else {
otherNames.emplace_back(name);
}
}
});
if (transResult.isOk()) {
// Sort service names in each category.
std::sort(defaultNames.begin(), defaultNames.end());
std::sort(vendorNames.begin(), vendorNames.end());
std::sort(otherNames.begin(), otherNames.end());
// Concatenate the three lists in this order: default, vendor,
// other.
std::vector<std::string>& names = defaultNames;
names.reserve(names.size() + vendorNames.size() + otherNames.size());
names.insert(names.end(),
std::make_move_iterator(vendorNames.begin()),
std::make_move_iterator(vendorNames.end()));
names.insert(names.end(),
std::make_move_iterator(otherNames.begin()),
std::make_move_iterator(otherNames.end()));
// Summarize to logcat.
if (names.empty()) {
LOG(INFO) << "No Codec2 services declared in the manifest.";
} else {
std::stringstream stringOutput;
stringOutput << "Available Codec2 services:";
for (std::string const& name : names) {
stringOutput << " \"" << name << "\"";
}
LOG(INFO) << stringOutput.str();
}
return names;
}
LOG(ERROR) << "Could not retrieve the list of service instances of "
<< IComponentStore::descriptor
<< ". Retrying...";
}
}()};
return sServiceNames;
}
std::shared_ptr<Codec2Client> Codec2Client::CreateFromService( std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
const char* name) { const char* name) {
size_t index = getServiceIndex(name); size_t index = getServiceIndex(name);
return index == getServiceNames().size() ? return index == GetServiceNames().size() ?
nullptr : _CreateFromIndex(index); nullptr : _CreateFromIndex(index);
} }
std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
CreateFromAllServices() {
std::vector<std::shared_ptr<Codec2Client>> clients(
GetServiceNames().size());
for (size_t i = GetServiceNames().size(); i > 0; ) {
--i;
clients[i] = _CreateFromIndex(i);
}
return clients;
}
std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) { std::shared_ptr<Codec2Client> Codec2Client::_CreateFromIndex(size_t index) {
std::string const& name = getServiceNames()[index]; std::string const& name = GetServiceNames()[index];
LOG(INFO) << "Creating a Codec2 client to service \"" << name << "\""; LOG(INFO) << "Creating a Codec2 client to service \"" << name << "\"";
sp<Base> baseStore = Base::getService(name); sp<Base> baseStore = Base::getService(name);
CHECK(baseStore) << "Codec2 service \"" << name << "\"" CHECK(baseStore) << "Codec2 service \"" << name << "\""
@ -958,17 +964,17 @@ std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
if (inputSurfaceSetting == 0) { if (inputSurfaceSetting == 0) {
return nullptr; return nullptr;
} }
size_t index = getServiceNames().size(); size_t index = GetServiceNames().size();
if (serviceName) { if (serviceName) {
index = getServiceIndex(serviceName); index = getServiceIndex(serviceName);
if (index == getServiceNames().size()) { if (index == GetServiceNames().size()) {
LOG(DEBUG) << "CreateInputSurface -- invalid service name: \"" LOG(DEBUG) << "CreateInputSurface -- invalid service name: \""
<< serviceName << "\""; << serviceName << "\"";
} }
} }
std::shared_ptr<Codec2Client::InputSurface> inputSurface; std::shared_ptr<Codec2Client::InputSurface> inputSurface;
if (index != getServiceNames().size()) { if (index != GetServiceNames().size()) {
std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient(); std::shared_ptr<Codec2Client> client = Cache::List()[index].getClient();
if (client->createInputSurface(&inputSurface) == C2_OK) { if (client->createInputSurface(&inputSurface) == C2_OK) {
return inputSurface; return inputSurface;

@ -143,6 +143,8 @@ struct Codec2Client : public Codec2ConfigurableClient {
typedef Codec2Client Store; typedef Codec2Client Store;
sp<Base> const& getBase() const;
std::string const& getServiceName() const; std::string const& getServiceName() const;
c2_status_t createComponent( c2_status_t createComponent(
@ -165,8 +167,17 @@ struct Codec2Client : public Codec2ConfigurableClient {
std::shared_ptr<C2ParamReflector> getParamReflector(); std::shared_ptr<C2ParamReflector> getParamReflector();
// Returns the list of IComponentStore service names that are available on
// the device. This list is specified at the build time in manifest files.
// Note: A software service will have "_software" as a suffix.
static std::vector<std::string> const& GetServiceNames();
// Create a service with a given service name.
static std::shared_ptr<Codec2Client> CreateFromService(char const* name); static std::shared_ptr<Codec2Client> CreateFromService(char const* name);
// Get clients to all services.
static std::vector<std::shared_ptr<Codec2Client>> CreateFromAllServices();
// Try to create a component with a given name from all known // Try to create a component with a given name from all known
// IComponentStore services. // IComponentStore services.
static std::shared_ptr<Component> CreateComponentByName( static std::shared_ptr<Component> CreateComponentByName(

@ -2,6 +2,7 @@ cc_library_shared {
srcs: [ srcs: [
"ActivityManager.cpp", "ActivityManager.cpp",
"DeathNotifier.cpp",
"MediaPlayerFactory.cpp", "MediaPlayerFactory.cpp",
"MediaPlayerService.cpp", "MediaPlayerService.cpp",
"MediaRecorderClient.cpp", "MediaRecorderClient.cpp",
@ -17,6 +18,7 @@ cc_library_shared {
"libaudioclient", "libaudioclient",
"libbinder", "libbinder",
"libcamera_client", "libcamera_client",
"libcodec2_client",
"libcrypto", "libcrypto",
"libcutils", "libcutils",
"libdl", "libdl",

@ -0,0 +1,80 @@
/*
* Copyright 2019 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_NDEBUG 0
#define LOG_TAG "MediaPlayerService-DeathNotifier"
#include <android-base/logging.h>
#include "DeathNotifier.h"
namespace android {
class DeathNotifier::DeathRecipient :
public IBinder::DeathRecipient,
public hardware::hidl_death_recipient {
public:
using Notify = DeathNotifier::Notify;
DeathRecipient(Notify const& notify): mNotify{notify} {
}
virtual void binderDied(wp<IBinder> const&) override {
mNotify();
}
virtual void serviceDied(uint64_t, wp<HBase> const&) override {
mNotify();
}
private:
Notify mNotify;
};
DeathNotifier::DeathNotifier(sp<IBinder> const& service, Notify const& notify)
: mService{std::in_place_index<1>, service},
mDeathRecipient{new DeathRecipient(notify)} {
service->linkToDeath(mDeathRecipient);
}
DeathNotifier::DeathNotifier(sp<HBase> const& service, Notify const& notify)
: mService{std::in_place_index<2>, service},
mDeathRecipient{new DeathRecipient(notify)} {
service->linkToDeath(mDeathRecipient, 0);
}
DeathNotifier::DeathNotifier(DeathNotifier&& other)
: mService{other.mService}, mDeathRecipient{other.mDeathRecipient} {
other.mService.emplace<0>();
other.mDeathRecipient = nullptr;
}
DeathNotifier::~DeathNotifier() {
switch (mService.index()) {
case 0:
break;
case 1:
std::get<1>(mService)->unlinkToDeath(mDeathRecipient);
break;
case 2:
std::get<2>(mService)->unlinkToDeath(mDeathRecipient);
break;
default:
CHECK(false) << "Corrupted service type during destruction.";
}
}
} // namespace android

@ -0,0 +1,48 @@
/*
* Copyright 2019 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.
*/
#ifndef ANDROID_MEDIASERVICE_DEATHNOTIFIER_H
#define ANDROID_MEDIASERVICE_DEATHNOTIFIER_H
#include <android/hidl/base/1.0/IBase.h>
#include <binder/Binder.h>
#include <hidl/HidlSupport.h>
#include <variant>
namespace android {
class DeathNotifier {
public:
using HBase = hidl::base::V1_0::IBase;
using Notify = std::function<void()>;
DeathNotifier(sp<IBinder> const& service, Notify const& notify);
DeathNotifier(sp<HBase> const& service, Notify const& notify);
DeathNotifier(DeathNotifier&& other);
~DeathNotifier();
private:
std::variant<std::monostate, sp<IBinder>, sp<HBase>> mService;
class DeathRecipient;
sp<DeathRecipient> mDeathRecipient;
};
} // namespace android
#endif // ANDROID_MEDIASERVICE_DEATHNOTIFIER_H

@ -0,0 +1,59 @@
/*
* Copyright 2019 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.
*/
#ifndef ANDROID_MEDIASERVICE_DEATHRECIPIENT_H
#define ANDROID_MEDIASERVICE_DEATHRECIPIENT_H
#include <binder/binder.h>
#include <hidl/HidlSupport.h>
#include <variant>
class DeathNotifier :
public IBinder::DeathRecipient,
public ::android::hardware::hidl_death_recipient {
public:
using Service = std::variant<
sp<IBinder> const&,
sp<android::hidl::base::V1_0::IBase> const&>;
DeathNotifier(std::variant<sp<IBinder> const&,
const sp<IBinder>& service,
const sp<MediaPlayerBase>& listener,
int which,
const std::string& name);
DeathNotifier(
const sp<android::hidl::base::V1_0::IBase>& hService,
const sp<MediaPlayerBase>& listener,
int which,
const std::string& name);
virtual ~DeathNotifier() = default;
virtual void binderDied(const wp<IBinder>& who);
virtual void serviceDied(
uint64_t cookie,
const wp<::android::hidl::base::V1_0::IBase>& who);
void unlinkToDeath();
private:
sp<IBinder> mService;
sp<android::hidl::base::V1_0::IBase> mHService; // HIDL service
wp<MediaPlayerBase> mListener;
int mWhich;
std::string mName;
};
#endif // ANDROID_MEDIASERVICE_DEATHRECIPIENT_H

@ -34,7 +34,7 @@
#include <utils/misc.h> #include <utils/misc.h>
#include <android/hardware/media/omx/1.0/IOmxStore.h> #include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/c2/1.0/IComponentStore.h> #include <android/hardware/media/c2/1.0/IComponentStore.h>
#include <binder/IPCThreadState.h> #include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h> #include <binder/IServiceManager.h>
@ -47,6 +47,7 @@
#include <utils/Timers.h> #include <utils/Timers.h>
#include <utils/Vector.h> #include <utils/Vector.h>
#include <codec2/hidl/client.h>
#include <media/IMediaHTTPService.h> #include <media/IMediaHTTPService.h>
#include <media/IRemoteDisplay.h> #include <media/IRemoteDisplay.h>
#include <media/IRemoteDisplayClient.h> #include <media/IRemoteDisplayClient.h>
@ -591,7 +592,6 @@ MediaPlayerService::Client::~Client()
if (mAudioAttributes != NULL) { if (mAudioAttributes != NULL) {
free(mAudioAttributes); free(mAudioAttributes);
} }
clearDeathNotifiers_l();
mAudioDeviceUpdatedListener.clear(); mAudioDeviceUpdatedListener.clear();
} }
@ -647,59 +647,6 @@ sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerT
return p; return p;
} }
MediaPlayerService::Client::ServiceDeathNotifier::ServiceDeathNotifier(
const sp<IBinder>& service,
const sp<MediaPlayerBase>& listener,
int which) {
mService = service;
mHService = nullptr;
mListener = listener;
mWhich = which;
}
MediaPlayerService::Client::ServiceDeathNotifier::ServiceDeathNotifier(
const sp<android::hidl::base::V1_0::IBase>& hService,
const sp<MediaPlayerBase>& listener,
int which) {
mService = nullptr;
mHService = hService;
mListener = listener;
mWhich = which;
}
MediaPlayerService::Client::ServiceDeathNotifier::~ServiceDeathNotifier() {
}
void MediaPlayerService::Client::ServiceDeathNotifier::binderDied(const wp<IBinder>& /*who*/) {
sp<MediaPlayerBase> listener = mListener.promote();
if (listener != NULL) {
listener->sendEvent(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, mWhich);
} else {
ALOGW("listener for process %d death is gone", mWhich);
}
}
void MediaPlayerService::Client::ServiceDeathNotifier::serviceDied(
uint64_t /* cookie */,
const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
sp<MediaPlayerBase> listener = mListener.promote();
if (listener != NULL) {
listener->sendEvent(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, mWhich);
} else {
ALOGW("listener for process %d death is gone", mWhich);
}
}
void MediaPlayerService::Client::ServiceDeathNotifier::unlinkToDeath() {
if (mService != nullptr) {
mService->unlinkToDeath(this);
mService = nullptr;
} else if (mHService != nullptr) {
mHService->unlinkToDeath(this);
mHService = nullptr;
}
}
void MediaPlayerService::Client::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate( void MediaPlayerService::Client::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate(
audio_io_handle_t audioIo, audio_io_handle_t audioIo,
audio_port_handle_t deviceId) { audio_port_handle_t deviceId) {
@ -711,19 +658,6 @@ void MediaPlayerService::Client::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate
} }
} }
void MediaPlayerService::Client::clearDeathNotifiers_l() {
if (mExtractorDeathListener != nullptr) {
mExtractorDeathListener->unlinkToDeath();
mExtractorDeathListener = nullptr;
}
for (const sp<ServiceDeathNotifier>& codecDeathListener : mCodecDeathListeners) {
if (codecDeathListener != nullptr) {
codecDeathListener->unlinkToDeath();
}
}
mCodecDeathListeners.clear();
}
sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre( sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
player_type playerType) player_type playerType)
{ {
@ -735,66 +669,83 @@ sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
return p; return p;
} }
std::vector<DeathNotifier> deathNotifiers;
// Listen to death of media.extractor service
sp<IServiceManager> sm = defaultServiceManager(); sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("media.extractor")); sp<IBinder> binder = sm->getService(String16("media.extractor"));
if (binder == NULL) { if (binder == NULL) {
ALOGE("extractor service not available"); ALOGE("extractor service not available");
return NULL; return NULL;
} }
sp<ServiceDeathNotifier> extractorDeathListener = deathNotifiers.emplace_back(
new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH); binder, [l = wp<MediaPlayerBase>(p)]() {
binder->linkToDeath(extractorDeathListener); sp<MediaPlayerBase> listener = l.promote();
if (listener) {
ALOGI("media.extractor died. Sending death notification.");
listener->sendEvent(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
MEDIAEXTRACTOR_PROCESS_DEATH);
} else {
ALOGW("media.extractor died without a death handler.");
}
});
std::vector<sp<ServiceDeathNotifier>> codecDeathListeners;
{ {
using ::android::hidl::base::V1_0::IBase; using ::android::hidl::base::V1_0::IBase;
// Listen to OMX's IOmxStore/default // Listen to death of OMX service
{ {
sp<IBase> store = ::android::hardware::media::omx::V1_0:: sp<IBase> base = ::android::hardware::media::omx::V1_0::
IOmxStore::getService(); IOmx::getService();
if (store == nullptr) { if (base == nullptr) {
ALOGD("OMX service is not available"); ALOGD("OMX service is not available");
} else { } else {
sp<ServiceDeathNotifier> codecDeathListener = deathNotifiers.emplace_back(
new ServiceDeathNotifier(store, p, MEDIACODEC_PROCESS_DEATH); base, [l = wp<MediaPlayerBase>(p)]() {
store->linkToDeath(codecDeathListener, 0); sp<MediaPlayerBase> listener = l.promote();
codecDeathListeners.emplace_back(codecDeathListener); if (listener) {
ALOGI("OMX service died. "
"Sending death notification.");
listener->sendEvent(
MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
MEDIACODEC_PROCESS_DEATH);
} else {
ALOGW("OMX service died without a death handler.");
}
});
} }
} }
// Listen to Codec2's IComponentStore/software // Listen to death of Codec2 services
// TODO: Listen to all Codec2 services.
{ {
sp<IBase> store = ::android::hardware::media::c2::V1_0:: for (std::shared_ptr<Codec2Client> const& client :
IComponentStore::getService(); Codec2Client::CreateFromAllServices()) {
if (store == nullptr) { sp<IBase> base = client->getBase();
ALOGD("Codec2 system service is not available"); deathNotifiers.emplace_back(
} else { base, [l = wp<MediaPlayerBase>(p),
sp<ServiceDeathNotifier> codecDeathListener = name = std::string(client->getServiceName())]() {
new ServiceDeathNotifier(store, p, MEDIACODEC_PROCESS_DEATH); sp<MediaPlayerBase> listener = l.promote();
store->linkToDeath(codecDeathListener, 0); if (listener) {
codecDeathListeners.emplace_back(codecDeathListener); ALOGI("Codec2 service \"%s\" died. "
} "Sending death notification.",
name.c_str());
store = ::android::hardware::media::c2::V1_0:: listener->sendEvent(
IComponentStore::getService("software"); MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
if (store == nullptr) { MEDIACODEC_PROCESS_DEATH);
ALOGD("Codec2 swcodec service is not available"); } else {
} else { ALOGW("Codec2 service \"%s\" died "
sp<ServiceDeathNotifier> codecDeathListener = "without a death handler.",
new ServiceDeathNotifier(store, p, MEDIACODEC_PROCESS_DEATH); name.c_str());
store->linkToDeath(codecDeathListener, 0); }
codecDeathListeners.emplace_back(codecDeathListener); });
} }
} }
} }
Mutex::Autolock lock(mLock); Mutex::Autolock lock(mLock);
clearDeathNotifiers_l(); mDeathNotifiers.clear();
mExtractorDeathListener = extractorDeathListener; mDeathNotifiers.swap(deathNotifiers);
mCodecDeathListeners.swap(codecDeathListeners);
mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p); mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p);
if (!p->hardwareOutput()) { if (!p->hardwareOutput()) {

@ -30,8 +30,6 @@
#include <media/Metadata.h> #include <media/Metadata.h>
#include <media/stagefright/foundation/ABase.h> #include <media/stagefright/foundation/ABase.h>
#include <hidl/HidlSupport.h>
#include <system/audio.h> #include <system/audio.h>
namespace android { namespace android {
@ -39,6 +37,7 @@ namespace android {
struct AudioPlaybackRate; struct AudioPlaybackRate;
class AudioTrack; class AudioTrack;
struct AVSyncSettings; struct AVSyncSettings;
class DeathNotifier;
class IDataSource; class IDataSource;
class IMediaRecorder; class IMediaRecorder;
class IMediaMetadataRetriever; class IMediaMetadataRetriever;
@ -388,33 +387,6 @@ private:
virtual status_t enableAudioDeviceCallback(bool enabled); virtual status_t enableAudioDeviceCallback(bool enabled);
private: private:
class ServiceDeathNotifier:
public IBinder::DeathRecipient,
public ::android::hardware::hidl_death_recipient
{
public:
ServiceDeathNotifier(
const sp<IBinder>& service,
const sp<MediaPlayerBase>& listener,
int which);
ServiceDeathNotifier(
const sp<android::hidl::base::V1_0::IBase>& hService,
const sp<MediaPlayerBase>& listener,
int which);
virtual ~ServiceDeathNotifier();
virtual void binderDied(const wp<IBinder>& who);
virtual void serviceDied(
uint64_t cookie,
const wp<::android::hidl::base::V1_0::IBase>& who);
void unlinkToDeath();
private:
int mWhich;
sp<IBinder> mService;
sp<android::hidl::base::V1_0::IBase> mHService; // HIDL service
wp<MediaPlayerBase> mListener;
};
class AudioDeviceUpdatedNotifier: public AudioSystem::AudioDeviceCallback class AudioDeviceUpdatedNotifier: public AudioSystem::AudioDeviceCallback
{ {
public: public:
@ -430,8 +402,6 @@ private:
wp<MediaPlayerBase> mListener; wp<MediaPlayerBase> mListener;
}; };
void clearDeathNotifiers_l();
friend class MediaPlayerService; friend class MediaPlayerService;
Client( const sp<MediaPlayerService>& service, Client( const sp<MediaPlayerService>& service,
pid_t pid, pid_t pid,
@ -506,8 +476,7 @@ private:
// getMetadata clears this set. // getMetadata clears this set.
media::Metadata::Filter mMetadataUpdated; // protected by mLock media::Metadata::Filter mMetadataUpdated; // protected by mLock
sp<ServiceDeathNotifier> mExtractorDeathListener; std::vector<DeathNotifier> mDeathNotifiers;
std::vector<sp<ServiceDeathNotifier>> mCodecDeathListeners;
sp<AudioDeviceUpdatedNotifier> mAudioDeviceUpdatedListener; sp<AudioDeviceUpdatedNotifier> mAudioDeviceUpdatedListener;
#if CALLBACK_ANTAGONIZER #if CALLBACK_ANTAGONIZER
Antagonizer* mAntagonizer; Antagonizer* mAntagonizer;

@ -18,27 +18,28 @@
#define LOG_TAG "MediaRecorderService" #define LOG_TAG "MediaRecorderService"
#include <utils/Log.h> #include <utils/Log.h>
#include <sys/types.h> #include "MediaRecorderClient.h"
#include <sys/stat.h> #include "MediaPlayerService.h"
#include <dirent.h> #include "StagefrightRecorder.h"
#include <unistd.h>
#include <string.h> #include <android/hardware/media/omx/1.0/IOmx.h>
#include <cutils/atomic.h> #include <android/hardware/media/c2/1.0/IComponentStore.h>
#include <cutils/properties.h> // for property_get
#include <binder/IPCThreadState.h> #include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h> #include <binder/IServiceManager.h>
#include <binder/MemoryHeapBase.h> #include <binder/MemoryHeapBase.h>
#include <binder/MemoryBase.h> #include <binder/MemoryBase.h>
#include <codec2/hidl/client.h>
#include <utils/String16.h> #include <cutils/atomic.h>
#include <cutils/properties.h> // for property_get
#include <gui/IGraphicBufferProducer.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <system/audio.h> #include <system/audio.h>
#include <utils/String16.h>
#include "MediaRecorderClient.h" #include <dirent.h>
#include "MediaPlayerService.h" #include <unistd.h>
#include <string.h>
#include "StagefrightRecorder.h"
#include <gui/IGraphicBufferProducer.h>
namespace android { namespace android {
@ -339,7 +340,7 @@ status_t MediaRecorderClient::release()
wp<MediaRecorderClient> client(this); wp<MediaRecorderClient> client(this);
mMediaPlayerService->removeMediaRecorderClient(client); mMediaPlayerService->removeMediaRecorderClient(client);
} }
clearDeathNotifiers_l(); mDeathNotifiers.clear();
return NO_ERROR; return NO_ERROR;
} }
@ -358,59 +359,6 @@ MediaRecorderClient::~MediaRecorderClient()
release(); release();
} }
MediaRecorderClient::ServiceDeathNotifier::ServiceDeathNotifier(
const sp<IBinder>& service,
const sp<IMediaRecorderClient>& listener,
int which) {
mService = service;
mOmx = nullptr;
mListener = listener;
mWhich = which;
}
MediaRecorderClient::ServiceDeathNotifier::ServiceDeathNotifier(
const sp<IOmx>& omx,
const sp<IMediaRecorderClient>& listener,
int which) {
mService = nullptr;
mOmx = omx;
mListener = listener;
mWhich = which;
}
MediaRecorderClient::ServiceDeathNotifier::~ServiceDeathNotifier() {
}
void MediaRecorderClient::ServiceDeathNotifier::binderDied(const wp<IBinder>& /*who*/) {
sp<IMediaRecorderClient> listener = mListener.promote();
if (listener != NULL) {
listener->notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, mWhich);
} else {
ALOGW("listener for process %d death is gone", mWhich);
}
}
void MediaRecorderClient::ServiceDeathNotifier::serviceDied(
uint64_t /* cookie */,
const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
sp<IMediaRecorderClient> listener = mListener.promote();
if (listener != NULL) {
listener->notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, mWhich);
} else {
ALOGW("listener for process %d death is gone", mWhich);
}
}
void MediaRecorderClient::ServiceDeathNotifier::unlinkToDeath() {
if (mService != nullptr) {
mService->unlinkToDeath(this);
mService = nullptr;
} else if (mOmx != nullptr) {
mOmx->unlinkToDeath(this);
mOmx = nullptr;
}
}
MediaRecorderClient::AudioDeviceUpdatedNotifier::AudioDeviceUpdatedNotifier( MediaRecorderClient::AudioDeviceUpdatedNotifier::AudioDeviceUpdatedNotifier(
const sp<IMediaRecorderClient>& listener) { const sp<IMediaRecorderClient>& listener) {
mListener = listener; mListener = listener;
@ -430,22 +378,11 @@ void MediaRecorderClient::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate(
} }
} }
void MediaRecorderClient::clearDeathNotifiers_l() {
if (mCameraDeathListener != nullptr) {
mCameraDeathListener->unlinkToDeath();
mCameraDeathListener = nullptr;
}
if (mCodecDeathListener != nullptr) {
mCodecDeathListener->unlinkToDeath();
mCodecDeathListener = nullptr;
}
}
status_t MediaRecorderClient::setListener(const sp<IMediaRecorderClient>& listener) status_t MediaRecorderClient::setListener(const sp<IMediaRecorderClient>& listener)
{ {
ALOGV("setListener"); ALOGV("setListener");
Mutex::Autolock lock(mLock); Mutex::Autolock lock(mLock);
clearDeathNotifiers_l(); mDeathNotifiers.clear();
if (mRecorder == NULL) { if (mRecorder == NULL) {
ALOGE("recorder is not initialized"); ALOGE("recorder is not initialized");
return NO_INIT; return NO_INIT;
@ -463,20 +400,73 @@ status_t MediaRecorderClient::setListener(const sp<IMediaRecorderClient>& listen
// If the device does not have a camera, do not create a death listener for it. // If the device does not have a camera, do not create a death listener for it.
if (binder != NULL) { if (binder != NULL) {
sCameraVerified = true; sCameraVerified = true;
mCameraDeathListener = new ServiceDeathNotifier(binder, listener, mDeathNotifiers.emplace_back(
MediaPlayerService::CAMERA_PROCESS_DEATH); binder, [l = wp<IMediaRecorderClient>(listener)](){
binder->linkToDeath(mCameraDeathListener); sp<IMediaRecorderClient> listener = l.promote();
if (listener) {
ALOGV("media.camera service died. "
"Sending death notification.");
listener->notify(
MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
MediaPlayerService::CAMERA_PROCESS_DEATH);
} else {
ALOGW("media.camera service died without a death handler.");
}
});
} }
sCameraChecked = true; sCameraChecked = true;
sp<IOmx> omx = IOmx::getService(); {
if (omx == nullptr) { using ::android::hidl::base::V1_0::IBase;
ALOGE("IOmx service is not available");
return NO_INIT; // Listen to OMX's IOmxStore/default
{
sp<IBase> base = ::android::hardware::media::omx::V1_0::
IOmx::getService();
if (base == nullptr) {
ALOGD("OMX service is not available");
} else {
mDeathNotifiers.emplace_back(
base, [l = wp<IMediaRecorderClient>(listener)](){
sp<IMediaRecorderClient> listener = l.promote();
if (listener) {
ALOGV("OMX service died. "
"Sending death notification.");
listener->notify(
MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
} else {
ALOGW("OMX service died without a death handler.");
}
});
}
}
// Listen to Codec2's IComponentStore instances
{
for (std::shared_ptr<Codec2Client> const& client :
Codec2Client::CreateFromAllServices()) {
sp<IBase> base = client->getBase();
mDeathNotifiers.emplace_back(
base, [l = wp<IMediaRecorderClient>(listener),
name = std::string(client->getServiceName())]() {
sp<IMediaRecorderClient> listener = l.promote();
if (listener) {
ALOGV("Codec2 service \"%s\" died. "
"Sending death notification",
name.c_str());
listener->notify(
MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED,
MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
} else {
ALOGW("Codec2 service \"%s\" died "
"without a death handler",
name.c_str());
}
});
}
}
} }
mCodecDeathListener = new ServiceDeathNotifier(omx, listener,
MediaPlayerService::MEDIACODEC_PROCESS_DEATH);
omx->linkToDeath(mCodecDeathListener, 0);
mAudioDeviceUpdatedNotifier = new AudioDeviceUpdatedNotifier(listener); mAudioDeviceUpdatedNotifier = new AudioDeviceUpdatedNotifier(listener);
mRecorder->setAudioDeviceCallback(mAudioDeviceUpdatedNotifier); mRecorder->setAudioDeviceCallback(mAudioDeviceUpdatedNotifier);

@ -18,10 +18,12 @@
#ifndef ANDROID_MEDIARECORDERCLIENT_H #ifndef ANDROID_MEDIARECORDERCLIENT_H
#define ANDROID_MEDIARECORDERCLIENT_H #define ANDROID_MEDIARECORDERCLIENT_H
#include "DeathNotifier.h"
#include <media/AudioSystem.h> #include <media/AudioSystem.h>
#include <media/IMediaRecorder.h> #include <media/IMediaRecorder.h>
#include <android/hardware/media/omx/1.0/IOmx.h> #include <vector>
namespace android { namespace android {
@ -31,34 +33,6 @@ class ICameraRecordingProxy;
class MediaRecorderClient : public BnMediaRecorder class MediaRecorderClient : public BnMediaRecorder
{ {
typedef ::android::hardware::media::omx::V1_0::IOmx IOmx;
class ServiceDeathNotifier :
public IBinder::DeathRecipient,
public ::android::hardware::hidl_death_recipient
{
public:
ServiceDeathNotifier(
const sp<IBinder>& service,
const sp<IMediaRecorderClient>& listener,
int which);
ServiceDeathNotifier(
const sp<IOmx>& omx,
const sp<IMediaRecorderClient>& listener,
int which);
virtual ~ServiceDeathNotifier();
virtual void binderDied(const wp<IBinder>& who);
virtual void serviceDied(
uint64_t cookie,
const wp<::android::hidl::base::V1_0::IBase>& who);
void unlinkToDeath();
private:
int mWhich;
sp<IBinder> mService;
sp<IOmx> mOmx;
wp<IMediaRecorderClient> mListener;
};
class AudioDeviceUpdatedNotifier: public AudioSystem::AudioDeviceCallback class AudioDeviceUpdatedNotifier: public AudioSystem::AudioDeviceCallback
{ {
public: public:
@ -71,8 +45,6 @@ class MediaRecorderClient : public BnMediaRecorder
wp<IMediaRecorderClient> mListener; wp<IMediaRecorderClient> mListener;
}; };
void clearDeathNotifiers_l();
public: public:
virtual status_t setCamera(const sp<hardware::ICamera>& camera, virtual status_t setCamera(const sp<hardware::ICamera>& camera,
const sp<ICameraRecordingProxy>& proxy); const sp<ICameraRecordingProxy>& proxy);
@ -122,8 +94,7 @@ private:
const String16& opPackageName); const String16& opPackageName);
virtual ~MediaRecorderClient(); virtual ~MediaRecorderClient();
sp<ServiceDeathNotifier> mCameraDeathListener; std::vector<DeathNotifier> mDeathNotifiers;
sp<ServiceDeathNotifier> mCodecDeathListener;
sp<AudioDeviceUpdatedNotifier> mAudioDeviceUpdatedNotifier; sp<AudioDeviceUpdatedNotifier> mAudioDeviceUpdatedNotifier;
pid_t mPid; pid_t mPid;

Loading…
Cancel
Save