From 270dd6a1a6fc700dde00f982dcd87bf98e4b73a4 Mon Sep 17 00:00:00 2001 From: Pawin Vongmasa Date: Sat, 6 Apr 2019 04:41:15 -0700 Subject: [PATCH] Make mediaserver listen to Codec2 services' deaths Test: Kill media.extractor or mediaswcodec and observe logcat Bug: 130071409 Change-Id: Ie785642da99dfe4ff13e78d878817dae3de9f34a --- media/codec2/hidl/1.0/utils/Android.bp | 1 + media/codec2/hidl/client/Android.bp | 1 + media/codec2/hidl/client/client.cpp | 188 +++++++++--------- .../hidl/client/include/codec2/hidl/client.h | 11 + media/libmediaplayerservice/Android.bp | 2 + media/libmediaplayerservice/DeathNotifier.cpp | 80 ++++++++ media/libmediaplayerservice/DeathNotifier.h | 48 +++++ media/libmediaplayerservice/DeathRecipient.h | 59 ++++++ .../MediaPlayerService.cpp | 161 ++++++--------- .../MediaPlayerService.h | 35 +--- .../MediaRecorderClient.cpp | 172 ++++++++-------- .../MediaRecorderClient.h | 37 +--- 12 files changed, 442 insertions(+), 353 deletions(-) create mode 100644 media/libmediaplayerservice/DeathNotifier.cpp create mode 100644 media/libmediaplayerservice/DeathNotifier.h create mode 100644 media/libmediaplayerservice/DeathRecipient.h diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp index b2a5feef1b..b73f0c87ca 100644 --- a/media/codec2/hidl/1.0/utils/Android.bp +++ b/media/codec2/hidl/1.0/utils/Android.bp @@ -99,6 +99,7 @@ cc_library { export_shared_lib_headers: [ "android.hardware.media.c2@1.0", "libcodec2", + "libcodec2_vndk", "libhidlbase", "libstagefright_bufferpool@2.0", "libui", diff --git a/media/codec2/hidl/client/Android.bp b/media/codec2/hidl/client/Android.bp index a174008b09..6038a4043f 100644 --- a/media/codec2/hidl/client/Android.bp +++ b/media/codec2/hidl/client/Android.bp @@ -31,6 +31,7 @@ cc_library { export_shared_lib_headers: [ "libcodec2", "libcodec2_hidl_client@1.0", + "libcodec2_vndk", ], } diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp index 53adbbc6d9..6aca4a321d 100644 --- a/media/codec2/hidl/client/client.cpp +++ b/media/codec2/hidl/client/client.cpp @@ -75,82 +75,11 @@ namespace /* unnamed */ { // c2_status_t value that corresponds to hwbinder transaction failure. constexpr c2_status_t C2_TRANSACTION_FAILED = C2_CORRUPTED; -// 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. -std::vector const& getServiceNames() { - static std::vector sServiceNames{[]() { - using ::android::hardware::media::c2::V1_0::IComponentStore; - using ::android::hidl::manager::V1_2::IServiceManager; - - while (true) { - sp serviceManager = IServiceManager::getService(); - CHECK(serviceManager) << "Hardware service manager is not running."; - - // There are three categories of services based on names. - std::vector defaultNames; // Prefixed with "default" - std::vector vendorNames; // Prefixed with "vendor" - std::vector otherNames; // Others - Return transResult; - transResult = serviceManager->listManifestByInterface( - IComponentStore::descriptor, - [&defaultNames, &vendorNames, &otherNames]( - hidl_vec 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& 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 +// Searches for a name in GetServiceNames() and returns the index found. If the // name is not found, the returned index will be equal to -// getServiceNames().size(). +// GetServiceNames().size(). size_t getServiceIndex(char const* name) { - std::vector const& names = getServiceNames(); + std::vector const& names = Codec2Client::GetServiceNames(); size_t i = 0; for (; i < names.size(); ++i) { if (name == names[i]) { @@ -175,17 +104,14 @@ class Codec2Client::Cache { std::vector mTraits; 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; - // 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 - // 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 - // getServiceNames()[index]. + // GetServiceNames()[index]. void init(size_t index) { mIndex = index; - mValid = true; } public: @@ -195,7 +121,6 @@ public: // If the service is unavailable but listed in the manifest, this function // will block indefinitely. std::shared_ptr getClient() { - CHECK(mValid) << "Uninitialized cache"; std::scoped_lock lock{mClientMutex}; if (!mClient) { mClient = Codec2Client::_CreateFromIndex(mIndex); @@ -208,7 +133,6 @@ public: // // Note: This function is called only by ForAllServices(). void invalidate() { - CHECK(mValid) << "Uninitialized cache"; std::scoped_lock lock{mClientMutex}; mClient = nullptr; } @@ -216,7 +140,6 @@ public: // Returns a list of traits for components supported by the service. This // list is cached. std::vector const& getTraits() { - CHECK(mValid) << "Uninitialized cache"; std::call_once(mTraitsInitializationFlag, [this]() { bool success{false}; // Spin until _listComponents() is successful. @@ -229,7 +152,7 @@ public: using namespace std::chrono_literals; static constexpr auto kServiceRetryPeriod = 5s; LOG(INFO) << "Failed to retrieve component traits from service " - "\"" << getServiceNames()[mIndex] << "\". " + "\"" << GetServiceNames()[mIndex] << "\". " "Retrying..."; std::this_thread::sleep_for(kServiceRetryPeriod); } @@ -240,7 +163,7 @@ public: // List() returns the list of all caches. static std::vector& List() { static std::vector sCaches{[]() { - size_t numServices = getServiceNames().size(); + size_t numServices = GetServiceNames().size(); std::vector caches(numServices); for (size_t i = 0; i < numServices; ++i) { caches[i].init(i); @@ -610,8 +533,12 @@ Codec2Client::Codec2Client(const sp& base, } } +sp const& Codec2Client::getBase() const { + return mBase; +} + std::string const& Codec2Client::getServiceName() const { - return getServiceNames()[mServiceIndex]; + return GetServiceNames()[mServiceIndex]; } c2_status_t Codec2Client::createComponent( @@ -807,15 +734,94 @@ std::shared_ptr return std::make_shared(mBase); }; +std::vector const& Codec2Client::GetServiceNames() { + static std::vector sServiceNames{[]() { + using ::android::hardware::media::c2::V1_0::IComponentStore; + using ::android::hidl::manager::V1_2::IServiceManager; + + while (true) { + sp serviceManager = IServiceManager::getService(); + CHECK(serviceManager) << "Hardware service manager is not running."; + + // There are three categories of services based on names. + std::vector defaultNames; // Prefixed with "default" + std::vector vendorNames; // Prefixed with "vendor" + std::vector otherNames; // Others + Return transResult; + transResult = serviceManager->listManifestByInterface( + IComponentStore::descriptor, + [&defaultNames, &vendorNames, &otherNames]( + hidl_vec 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& 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::CreateFromService( const char* name) { size_t index = getServiceIndex(name); - return index == getServiceNames().size() ? + return index == GetServiceNames().size() ? nullptr : _CreateFromIndex(index); } +std::vector> Codec2Client:: + CreateFromAllServices() { + std::vector> clients( + GetServiceNames().size()); + for (size_t i = GetServiceNames().size(); i > 0; ) { + --i; + clients[i] = _CreateFromIndex(i); + } + return clients; +} + std::shared_ptr 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 << "\""; sp baseStore = Base::getService(name); CHECK(baseStore) << "Codec2 service \"" << name << "\"" @@ -958,17 +964,17 @@ std::shared_ptr Codec2Client::CreateInputSurface( if (inputSurfaceSetting == 0) { return nullptr; } - size_t index = getServiceNames().size(); + size_t index = GetServiceNames().size(); if (serviceName) { index = getServiceIndex(serviceName); - if (index == getServiceNames().size()) { + if (index == GetServiceNames().size()) { LOG(DEBUG) << "CreateInputSurface -- invalid service name: \"" << serviceName << "\""; } } std::shared_ptr inputSurface; - if (index != getServiceNames().size()) { + if (index != GetServiceNames().size()) { std::shared_ptr client = Cache::List()[index].getClient(); if (client->createInputSurface(&inputSurface) == C2_OK) { return inputSurface; diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h index 18517527fa..03db5154a1 100644 --- a/media/codec2/hidl/client/include/codec2/hidl/client.h +++ b/media/codec2/hidl/client/include/codec2/hidl/client.h @@ -143,6 +143,8 @@ struct Codec2Client : public Codec2ConfigurableClient { typedef Codec2Client Store; + sp const& getBase() const; + std::string const& getServiceName() const; c2_status_t createComponent( @@ -165,8 +167,17 @@ struct Codec2Client : public Codec2ConfigurableClient { std::shared_ptr 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 const& GetServiceNames(); + + // Create a service with a given service name. static std::shared_ptr CreateFromService(char const* name); + // Get clients to all services. + static std::vector> CreateFromAllServices(); + // Try to create a component with a given name from all known // IComponentStore services. static std::shared_ptr CreateComponentByName( diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp index 0776172db4..670958510c 100644 --- a/media/libmediaplayerservice/Android.bp +++ b/media/libmediaplayerservice/Android.bp @@ -2,6 +2,7 @@ cc_library_shared { srcs: [ "ActivityManager.cpp", + "DeathNotifier.cpp", "MediaPlayerFactory.cpp", "MediaPlayerService.cpp", "MediaRecorderClient.cpp", @@ -17,6 +18,7 @@ cc_library_shared { "libaudioclient", "libbinder", "libcamera_client", + "libcodec2_client", "libcrypto", "libcutils", "libdl", diff --git a/media/libmediaplayerservice/DeathNotifier.cpp b/media/libmediaplayerservice/DeathNotifier.cpp new file mode 100644 index 0000000000..d13bdf53ff --- /dev/null +++ b/media/libmediaplayerservice/DeathNotifier.cpp @@ -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 + +#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 const&) override { + mNotify(); + } + + virtual void serviceDied(uint64_t, wp const&) override { + mNotify(); + } + +private: + Notify mNotify; +}; + +DeathNotifier::DeathNotifier(sp const& service, Notify const& notify) + : mService{std::in_place_index<1>, service}, + mDeathRecipient{new DeathRecipient(notify)} { + service->linkToDeath(mDeathRecipient); +} + +DeathNotifier::DeathNotifier(sp 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 + diff --git a/media/libmediaplayerservice/DeathNotifier.h b/media/libmediaplayerservice/DeathNotifier.h new file mode 100644 index 0000000000..7bc261178c --- /dev/null +++ b/media/libmediaplayerservice/DeathNotifier.h @@ -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 +#include +#include + +#include + +namespace android { + +class DeathNotifier { +public: + using HBase = hidl::base::V1_0::IBase; + using Notify = std::function; + + DeathNotifier(sp const& service, Notify const& notify); + DeathNotifier(sp const& service, Notify const& notify); + DeathNotifier(DeathNotifier&& other); + ~DeathNotifier(); + +private: + std::variant, sp> mService; + + class DeathRecipient; + sp mDeathRecipient; +}; + +} // namespace android + +#endif // ANDROID_MEDIASERVICE_DEATHNOTIFIER_H + diff --git a/media/libmediaplayerservice/DeathRecipient.h b/media/libmediaplayerservice/DeathRecipient.h new file mode 100644 index 0000000000..bf5ae5c0f8 --- /dev/null +++ b/media/libmediaplayerservice/DeathRecipient.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 +#include + +#include + +class DeathNotifier : + public IBinder::DeathRecipient, + public ::android::hardware::hidl_death_recipient { +public: + using Service = std::variant< + sp const&, + sp const&>; + + DeathNotifier(std::variant const&, + const sp& service, + const sp& listener, + int which, + const std::string& name); + DeathNotifier( + const sp& hService, + const sp& listener, + int which, + const std::string& name); + virtual ~DeathNotifier() = default; + virtual void binderDied(const wp& who); + virtual void serviceDied( + uint64_t cookie, + const wp<::android::hidl::base::V1_0::IBase>& who); + void unlinkToDeath(); + +private: + sp mService; + sp mHService; // HIDL service + wp mListener; + int mWhich; + std::string mName; +}; + +#endif // ANDROID_MEDIASERVICE_DEATHRECIPIENT_H + diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 5061024f8f..dfd3933245 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -34,7 +34,7 @@ #include -#include +#include #include #include #include @@ -47,6 +47,7 @@ #include #include +#include #include #include #include @@ -591,7 +592,6 @@ MediaPlayerService::Client::~Client() if (mAudioAttributes != NULL) { free(mAudioAttributes); } - clearDeathNotifiers_l(); mAudioDeviceUpdatedListener.clear(); } @@ -647,59 +647,6 @@ sp MediaPlayerService::Client::createPlayer(player_type playerT return p; } -MediaPlayerService::Client::ServiceDeathNotifier::ServiceDeathNotifier( - const sp& service, - const sp& listener, - int which) { - mService = service; - mHService = nullptr; - mListener = listener; - mWhich = which; -} - -MediaPlayerService::Client::ServiceDeathNotifier::ServiceDeathNotifier( - const sp& hService, - const sp& listener, - int which) { - mService = nullptr; - mHService = hService; - mListener = listener; - mWhich = which; -} - -MediaPlayerService::Client::ServiceDeathNotifier::~ServiceDeathNotifier() { -} - -void MediaPlayerService::Client::ServiceDeathNotifier::binderDied(const wp& /*who*/) { - sp 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 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( audio_io_handle_t audioIo, 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& codecDeathListener : mCodecDeathListeners) { - if (codecDeathListener != nullptr) { - codecDeathListener->unlinkToDeath(); - } - } - mCodecDeathListeners.clear(); -} - sp MediaPlayerService::Client::setDataSource_pre( player_type playerType) { @@ -735,66 +669,83 @@ sp MediaPlayerService::Client::setDataSource_pre( return p; } + std::vector deathNotifiers; + + // Listen to death of media.extractor service sp sm = defaultServiceManager(); sp binder = sm->getService(String16("media.extractor")); if (binder == NULL) { ALOGE("extractor service not available"); return NULL; } - sp extractorDeathListener = - new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH); - binder->linkToDeath(extractorDeathListener); + deathNotifiers.emplace_back( + binder, [l = wp(p)]() { + sp 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> codecDeathListeners; { using ::android::hidl::base::V1_0::IBase; - // Listen to OMX's IOmxStore/default + // Listen to death of OMX service { - sp store = ::android::hardware::media::omx::V1_0:: - IOmxStore::getService(); - if (store == nullptr) { + sp base = ::android::hardware::media::omx::V1_0:: + IOmx::getService(); + if (base == nullptr) { ALOGD("OMX service is not available"); } else { - sp codecDeathListener = - new ServiceDeathNotifier(store, p, MEDIACODEC_PROCESS_DEATH); - store->linkToDeath(codecDeathListener, 0); - codecDeathListeners.emplace_back(codecDeathListener); + deathNotifiers.emplace_back( + base, [l = wp(p)]() { + sp listener = l.promote(); + 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 - // TODO: Listen to all Codec2 services. + // Listen to death of Codec2 services { - sp store = ::android::hardware::media::c2::V1_0:: - IComponentStore::getService(); - if (store == nullptr) { - ALOGD("Codec2 system service is not available"); - } else { - sp codecDeathListener = - new ServiceDeathNotifier(store, p, MEDIACODEC_PROCESS_DEATH); - store->linkToDeath(codecDeathListener, 0); - codecDeathListeners.emplace_back(codecDeathListener); - } - - store = ::android::hardware::media::c2::V1_0:: - IComponentStore::getService("software"); - if (store == nullptr) { - ALOGD("Codec2 swcodec service is not available"); - } else { - sp codecDeathListener = - new ServiceDeathNotifier(store, p, MEDIACODEC_PROCESS_DEATH); - store->linkToDeath(codecDeathListener, 0); - codecDeathListeners.emplace_back(codecDeathListener); + for (std::shared_ptr const& client : + Codec2Client::CreateFromAllServices()) { + sp base = client->getBase(); + deathNotifiers.emplace_back( + base, [l = wp(p), + name = std::string(client->getServiceName())]() { + sp listener = l.promote(); + if (listener) { + ALOGI("Codec2 service \"%s\" died. " + "Sending death notification.", + name.c_str()); + listener->sendEvent( + MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, + MEDIACODEC_PROCESS_DEATH); + } else { + ALOGW("Codec2 service \"%s\" died " + "without a death handler.", + name.c_str()); + } + }); } } } Mutex::Autolock lock(mLock); - clearDeathNotifiers_l(); - mExtractorDeathListener = extractorDeathListener; - mCodecDeathListeners.swap(codecDeathListeners); + mDeathNotifiers.clear(); + mDeathNotifiers.swap(deathNotifiers); mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p); if (!p->hardwareOutput()) { diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 26bfa71c25..49688ce997 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -30,8 +30,6 @@ #include #include -#include - #include namespace android { @@ -39,6 +37,7 @@ namespace android { struct AudioPlaybackRate; class AudioTrack; struct AVSyncSettings; +class DeathNotifier; class IDataSource; class IMediaRecorder; class IMediaMetadataRetriever; @@ -388,33 +387,6 @@ private: virtual status_t enableAudioDeviceCallback(bool enabled); private: - class ServiceDeathNotifier: - public IBinder::DeathRecipient, - public ::android::hardware::hidl_death_recipient - { - public: - ServiceDeathNotifier( - const sp& service, - const sp& listener, - int which); - ServiceDeathNotifier( - const sp& hService, - const sp& listener, - int which); - virtual ~ServiceDeathNotifier(); - virtual void binderDied(const wp& who); - virtual void serviceDied( - uint64_t cookie, - const wp<::android::hidl::base::V1_0::IBase>& who); - void unlinkToDeath(); - - private: - int mWhich; - sp mService; - sp mHService; // HIDL service - wp mListener; - }; - class AudioDeviceUpdatedNotifier: public AudioSystem::AudioDeviceCallback { public: @@ -430,8 +402,6 @@ private: wp mListener; }; - void clearDeathNotifiers_l(); - friend class MediaPlayerService; Client( const sp& service, pid_t pid, @@ -506,8 +476,7 @@ private: // getMetadata clears this set. media::Metadata::Filter mMetadataUpdated; // protected by mLock - sp mExtractorDeathListener; - std::vector> mCodecDeathListeners; + std::vector mDeathNotifiers; sp mAudioDeviceUpdatedListener; #if CALLBACK_ANTAGONIZER Antagonizer* mAntagonizer; diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp index 9f4265b021..703da4b98f 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.cpp +++ b/media/libmediaplayerservice/MediaRecorderClient.cpp @@ -18,27 +18,28 @@ #define LOG_TAG "MediaRecorderService" #include -#include -#include -#include -#include -#include -#include -#include // for property_get +#include "MediaRecorderClient.h" +#include "MediaPlayerService.h" +#include "StagefrightRecorder.h" + +#include +#include #include #include #include #include - -#include - +#include +#include +#include // for property_get +#include +#include +#include #include +#include -#include "MediaRecorderClient.h" -#include "MediaPlayerService.h" - -#include "StagefrightRecorder.h" -#include +#include +#include +#include namespace android { @@ -339,7 +340,7 @@ status_t MediaRecorderClient::release() wp client(this); mMediaPlayerService->removeMediaRecorderClient(client); } - clearDeathNotifiers_l(); + mDeathNotifiers.clear(); return NO_ERROR; } @@ -358,59 +359,6 @@ MediaRecorderClient::~MediaRecorderClient() release(); } -MediaRecorderClient::ServiceDeathNotifier::ServiceDeathNotifier( - const sp& service, - const sp& listener, - int which) { - mService = service; - mOmx = nullptr; - mListener = listener; - mWhich = which; -} - -MediaRecorderClient::ServiceDeathNotifier::ServiceDeathNotifier( - const sp& omx, - const sp& listener, - int which) { - mService = nullptr; - mOmx = omx; - mListener = listener; - mWhich = which; -} - -MediaRecorderClient::ServiceDeathNotifier::~ServiceDeathNotifier() { -} - -void MediaRecorderClient::ServiceDeathNotifier::binderDied(const wp& /*who*/) { - sp 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 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( const sp& 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& listener) { ALOGV("setListener"); Mutex::Autolock lock(mLock); - clearDeathNotifiers_l(); + mDeathNotifiers.clear(); if (mRecorder == NULL) { ALOGE("recorder is not initialized"); return NO_INIT; @@ -463,20 +400,73 @@ status_t MediaRecorderClient::setListener(const sp& listen // If the device does not have a camera, do not create a death listener for it. if (binder != NULL) { sCameraVerified = true; - mCameraDeathListener = new ServiceDeathNotifier(binder, listener, - MediaPlayerService::CAMERA_PROCESS_DEATH); - binder->linkToDeath(mCameraDeathListener); + mDeathNotifiers.emplace_back( + binder, [l = wp(listener)](){ + sp 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; - sp omx = IOmx::getService(); - if (omx == nullptr) { - ALOGE("IOmx service is not available"); - return NO_INIT; + { + using ::android::hidl::base::V1_0::IBase; + + // Listen to OMX's IOmxStore/default + { + sp 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(listener)](){ + sp 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 const& client : + Codec2Client::CreateFromAllServices()) { + sp base = client->getBase(); + mDeathNotifiers.emplace_back( + base, [l = wp(listener), + name = std::string(client->getServiceName())]() { + sp 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); mRecorder->setAudioDeviceCallback(mAudioDeviceUpdatedNotifier); diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h index e698819854..9e0f87779f 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.h +++ b/media/libmediaplayerservice/MediaRecorderClient.h @@ -18,10 +18,12 @@ #ifndef ANDROID_MEDIARECORDERCLIENT_H #define ANDROID_MEDIARECORDERCLIENT_H +#include "DeathNotifier.h" + #include #include -#include +#include namespace android { @@ -31,34 +33,6 @@ class ICameraRecordingProxy; 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& service, - const sp& listener, - int which); - ServiceDeathNotifier( - const sp& omx, - const sp& listener, - int which); - virtual ~ServiceDeathNotifier(); - virtual void binderDied(const wp& who); - virtual void serviceDied( - uint64_t cookie, - const wp<::android::hidl::base::V1_0::IBase>& who); - void unlinkToDeath(); - private: - int mWhich; - sp mService; - sp mOmx; - wp mListener; - }; - class AudioDeviceUpdatedNotifier: public AudioSystem::AudioDeviceCallback { public: @@ -71,8 +45,6 @@ class MediaRecorderClient : public BnMediaRecorder wp mListener; }; - void clearDeathNotifiers_l(); - public: virtual status_t setCamera(const sp& camera, const sp& proxy); @@ -122,8 +94,7 @@ private: const String16& opPackageName); virtual ~MediaRecorderClient(); - sp mCameraDeathListener; - sp mCodecDeathListener; + std::vector mDeathNotifiers; sp mAudioDeviceUpdatedNotifier; pid_t mPid;