Loading media/libstagefright/MediaCodec.cpp +220 −96 Original line number Diff line number Diff line Loading @@ -21,9 +21,9 @@ #include <dlfcn.h> #include <inttypes.h> #include <future> #include <random> #include <set> #include <stdlib.h> #include <string> #include <C2Buffer.h> Loading Loading @@ -289,6 +289,10 @@ static const C2MemoryUsage kDefaultReadWriteUsage{ //////////////////////////////////////////////////////////////////////////////// /* * Implementation of IResourceManagerClient interrface that facilitates * MediaCodec reclaim for the ResourceManagerService. */ struct ResourceManagerClient : public BnResourceManagerClient { explicit ResourceManagerClient(MediaCodec* codec, int32_t pid, int32_t uid) : mMediaCodec(codec), mPid(pid), mUid(uid) {} Loading @@ -301,7 +305,9 @@ struct ResourceManagerClient : public BnResourceManagerClient { std::shared_ptr<IResourceManagerService> service = IResourceManagerService::fromBinder(binder); if (service == nullptr) { ALOGW("MediaCodec::ResourceManagerClient unable to find ResourceManagerService"); ALOGE("MediaCodec::ResourceManagerClient unable to find ResourceManagerService"); *_aidl_return = false; return Status::fromStatus(STATUS_INVALID_OPERATION); } ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), Loading Loading @@ -349,21 +355,25 @@ private: DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient); }; struct MediaCodec::ResourceManagerServiceProxy : public RefBase { /* * Proxy for ResourceManagerService that communicates with the * ResourceManagerService for MediaCodec */ struct MediaCodec::ResourceManagerServiceProxy : public std::enable_shared_from_this<ResourceManagerServiceProxy> { // BinderDiedContext defines the cookie that is passed as DeathRecipient. // Since this can maintain more context than a raw pointer, we can // validate the scope of ResourceManagerServiceProxy, // before deferencing it upon the binder death. struct BinderDiedContext { std::weak_ptr<ResourceManagerServiceProxy> mRMServiceProxy; }; ResourceManagerServiceProxy(pid_t pid, uid_t uid, const std::shared_ptr<IResourceManagerClient> &client); virtual ~ResourceManagerServiceProxy(); ~ResourceManagerServiceProxy(); status_t init(); // implements DeathRecipient static void BinderDiedCallback(void* cookie); void binderDied(); static Mutex sLockCookies; static std::set<void*> sCookies; static void addCookie(void* cookie); static void removeCookie(void* cookie); void addResource(const MediaResourceParcel &resource); void removeResource(const MediaResourceParcel &resource); void removeClient(); Loading @@ -379,50 +389,92 @@ struct MediaCodec::ResourceManagerServiceProxy : public RefBase { } private: Mutex mLock; // To get the binder interface to ResourceManagerService. void getService() { std::scoped_lock lock{mLock}; getService_l(); } std::shared_ptr<IResourceManagerService> getService_l(); // To add/register all the resources currently added/registered with // the ResourceManagerService. // This function will be called right after the death of the Resource // Manager to make sure that the newly started ResourceManagerService // knows about the current resource usage. void reRegisterAllResources_l(); void deinit() { std::scoped_lock lock{mLock}; // Unregistering from DeathRecipient notification. if (mService != nullptr) { AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this); mService = nullptr; } } // For binder death handling static void BinderDiedCallback(void* cookie); static void BinderUnlinkedCallback(void* cookie); void binderDied() { std::scoped_lock lock{mLock}; ALOGE("ResourceManagerService died."); mService = nullptr; mBinderDied = true; // start an async operation that will reconnect with the RM and // re-registers all the resources. mGetServiceFuture = std::async(std::launch::async, [this] { getService(); }); } private: std::mutex mLock; pid_t mPid; uid_t mUid; bool mBinderDied = false; std::string mCodecName; std::shared_ptr<IResourceManagerService> mService; /** * Reconnecting with the ResourceManagerService, after its binder interface dies, * is done asynchronously. It will also make sure that, all the resources * asssociated with this Proxy (MediaCodec) is added with the new instance * of the ResourceManagerService to persist the state of resources. * We must store the reference of the furture to guarantee real asynchronous operation. */ std::future<void> mGetServiceFuture; // To maintain the list of all the resources currently added/registered with // the ResourceManagerService. std::set<MediaResourceParcel> mMediaResourceParcel; std::shared_ptr<IResourceManagerClient> mClient; ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; std::shared_ptr<IResourceManagerService> mService; }; MediaCodec::ResourceManagerServiceProxy::ResourceManagerServiceProxy( pid_t pid, uid_t uid, const std::shared_ptr<IResourceManagerClient> &client) : mPid(pid), mUid(uid), mClient(client), mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)) { pid_t pid, uid_t uid, const std::shared_ptr<IResourceManagerClient> &client) : mPid(pid), mUid(uid), mClient(client), mDeathRecipient(::ndk::ScopedAIBinder_DeathRecipient( AIBinder_DeathRecipient_new(BinderDiedCallback))) { if (mUid == MediaCodec::kNoUid) { mUid = AIBinder_getCallingUid(); } if (mPid == MediaCodec::kNoPid) { mPid = AIBinder_getCallingPid(); } // Setting callback notification when DeathRecipient gets deleted. AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), BinderUnlinkedCallback); } MediaCodec::ResourceManagerServiceProxy::~ResourceManagerServiceProxy() { // remove the cookie, so any in-flight death notification will get dropped // by our handler. removeCookie(this); Mutex::Autolock _l(mLock); if (mService != nullptr) { AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this); mService = nullptr; } deinit(); } status_t MediaCodec::ResourceManagerServiceProxy::init() { ::ndk::SpAIBinder binder(AServiceManager_waitForService("media.resource_manager")); mService = IResourceManagerService::fromBinder(binder); if (mService == nullptr) { ALOGE("Failed to get ResourceManagerService"); return UNKNOWN_ERROR; } std::scoped_lock lock{mLock}; int callerPid = AIBinder_getCallingPid(); int callerUid = AIBinder_getCallingUid(); if (mPid != callerPid || mUid != callerUid) { // Media processes don't need special permissions to act on behalf of other processes. if (callerUid != AID_MEDIA) { Loading @@ -435,111 +487,155 @@ status_t MediaCodec::ResourceManagerServiceProxy::init() { } } mService = getService_l(); if (mService == nullptr) { return DEAD_OBJECT; } // Kill clients pending removal. mService->reclaimResourcesFromClientsPendingRemoval(mPid); return OK; } // so our handler will process the death notifications addCookie(this); std::shared_ptr<IResourceManagerService> MediaCodec::ResourceManagerServiceProxy::getService_l() { if (mService != nullptr) { return mService; } // after this, require mLock whenever using mService AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this); return OK; // Get binder interface to resource manager. ::ndk::SpAIBinder binder(AServiceManager_waitForService("media.resource_manager")); mService = IResourceManagerService::fromBinder(binder); if (mService == nullptr) { ALOGE("Failed to get ResourceManagerService"); return mService; } //static // these are no_destroy to keep them from being destroyed at process exit // where some thread calls exit() while other threads are still running. // see b/194783918 [[clang::no_destroy]] Mutex MediaCodec::ResourceManagerServiceProxy::sLockCookies; [[clang::no_destroy]] std::set<void*> MediaCodec::ResourceManagerServiceProxy::sCookies; // Create the context that is passed as cookie to the binder death notification. // The context gets deleted at BinderUnlinkedCallback. BinderDiedContext* context = new BinderDiedContext{.mRMServiceProxy = weak_from_this()}; // Register for the callbacks by linking to death notification. AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), context); //static void MediaCodec::ResourceManagerServiceProxy::addCookie(void* cookie) { Mutex::Autolock _l(sLockCookies); sCookies.insert(cookie); // If the RM was restarted, re-register all the resources. if (mBinderDied) { reRegisterAllResources_l(); mBinderDied = false; } return mService; } //static void MediaCodec::ResourceManagerServiceProxy::removeCookie(void* cookie) { Mutex::Autolock _l(sLockCookies); sCookies.erase(cookie); void MediaCodec::ResourceManagerServiceProxy::reRegisterAllResources_l() { if (mMediaResourceParcel.empty()) { ALOGV("%s:%d:%p No resources to add", __func__, __LINE__, this); return; } std::vector<MediaResourceParcel> resources; std::copy(mMediaResourceParcel.begin(), mMediaResourceParcel.end(), std::back_inserter(resources)); if (mService == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; mService->addResource(clientInfo, mClient, resources); } //static void MediaCodec::ResourceManagerServiceProxy::BinderDiedCallback(void* cookie) { Mutex::Autolock _l(sLockCookies); if (sCookies.find(cookie) != sCookies.end()) { auto thiz = static_cast<ResourceManagerServiceProxy*>(cookie); BinderDiedContext* context = reinterpret_cast<BinderDiedContext*>(cookie); // Validate the context and check if the ResourceManagerServiceProxy object is still in scope. if (context != nullptr) { std::shared_ptr<ResourceManagerServiceProxy> thiz = context->mRMServiceProxy.lock(); if (thiz != nullptr) { thiz->binderDied(); } else { ALOGI("ResourceManagerServiceProxy is out of scope already"); } } } void MediaCodec::ResourceManagerServiceProxy::binderDied() { ALOGW("ResourceManagerService died."); Mutex::Autolock _l(mLock); mService = nullptr; void MediaCodec::ResourceManagerServiceProxy::BinderUnlinkedCallback(void* cookie) { BinderDiedContext* context = reinterpret_cast<BinderDiedContext*>(cookie); // Since we don't need the context anymore, we are deleting it now. delete context; } void MediaCodec::ResourceManagerServiceProxy::addResource( const MediaResourceParcel &resource) { std::vector<MediaResourceParcel> resources; resources.push_back(resource); Mutex::Autolock _l(mLock); if (mService == nullptr) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } std::vector<MediaResourceParcel> resources; resources.push_back(resource); ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; mService->addResource(clientInfo, mClient, resources); service->addResource(clientInfo, mClient, resources); mMediaResourceParcel.emplace(resource); } void MediaCodec::ResourceManagerServiceProxy::removeResource( const MediaResourceParcel &resource) { std::vector<MediaResourceParcel> resources; resources.push_back(resource); Mutex::Autolock _l(mLock); if (mService == nullptr) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } std::vector<MediaResourceParcel> resources; resources.push_back(resource); ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; mService->removeResource(clientInfo, resources); service->removeResource(clientInfo, resources); mMediaResourceParcel.erase(resource); } void MediaCodec::ResourceManagerServiceProxy::removeClient() { Mutex::Autolock _l(mLock); if (mService == nullptr) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; mService->removeClient(clientInfo); service->removeClient(clientInfo); mMediaResourceParcel.clear(); } void MediaCodec::ResourceManagerServiceProxy::markClientForPendingRemoval() { Mutex::Autolock _l(mLock); if (mService == nullptr) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; mService->markClientForPendingRemoval(clientInfo); service->markClientForPendingRemoval(clientInfo); mMediaResourceParcel.clear(); } bool MediaCodec::ResourceManagerServiceProxy::reclaimResource( const std::vector<MediaResourceParcel> &resources) { Mutex::Autolock _l(mLock); if (mService == NULL) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Service isn't available", __func__, __LINE__, this); return false; } bool success; Loading @@ -547,43 +643,67 @@ bool MediaCodec::ResourceManagerServiceProxy::reclaimResource( .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; Status status = mService->reclaimResource(clientInfo, resources, &success); Status status = service->reclaimResource(clientInfo, resources, &success); return status.isOk() && success; } void MediaCodec::ResourceManagerServiceProxy::notifyClientCreated() { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; mService->notifyClientCreated(clientInfo); service->notifyClientCreated(clientInfo); } void MediaCodec::ResourceManagerServiceProxy::notifyClientStarted( ClientConfigParcel& clientConfig) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } clientConfig.clientInfo.pid = static_cast<int32_t>(mPid); clientConfig.clientInfo.uid = static_cast<int32_t>(mUid); clientConfig.clientInfo.id = getId(mClient); clientConfig.clientInfo.name = mCodecName; mService->notifyClientStarted(clientConfig); service->notifyClientStarted(clientConfig); } void MediaCodec::ResourceManagerServiceProxy::notifyClientStopped( ClientConfigParcel& clientConfig) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } clientConfig.clientInfo.pid = static_cast<int32_t>(mPid); clientConfig.clientInfo.uid = static_cast<int32_t>(mUid); clientConfig.clientInfo.id = getId(mClient); clientConfig.clientInfo.name = mCodecName; mService->notifyClientStopped(clientConfig); service->notifyClientStopped(clientConfig); } void MediaCodec::ResourceManagerServiceProxy::notifyClientConfigChanged( ClientConfigParcel& clientConfig) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } clientConfig.clientInfo.pid = static_cast<int32_t>(mPid); clientConfig.clientInfo.uid = static_cast<int32_t>(mUid); clientConfig.clientInfo.id = getId(mClient); clientConfig.clientInfo.name = mCodecName; mService->notifyClientConfigChanged(clientConfig); service->notifyClientConfigChanged(clientConfig); } //////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -1036,7 +1156,7 @@ MediaCodec::MediaCodec( mGetCodecBase(getCodecBase), mGetCodecInfo(getCodecInfo) { mCodecId = GenerateCodecId(); mResourceManagerProxy = new ResourceManagerServiceProxy(pid, uid, mResourceManagerProxy = std::make_shared<ResourceManagerServiceProxy>(pid, uid, ::ndk::SharedRefBase::make<ResourceManagerClient>(this, pid, uid)); if (!mGetCodecBase) { mGetCodecBase = [](const AString &name, const char *owner) { Loading Loading @@ -2225,9 +2345,11 @@ status_t MediaCodec::configure( std::vector<MediaResourceParcel> resources; resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, toMediaResourceSubType(mDomain))); if (mDomain == DOMAIN_VIDEO || mDomain == DOMAIN_IMAGE) { // Don't know the buffer size at this point, but it's fine to use 1 because // the reclaimResource call doesn't consider the requester's buffer size for now. resources.push_back(MediaResource::GraphicMemoryResource(1)); } for (int i = 0; i <= kMaxRetry; ++i) { sp<AMessage> response; err = PostAndAwaitResponse(msg, &response); Loading Loading @@ -2828,9 +2950,11 @@ status_t MediaCodec::start() { std::vector<MediaResourceParcel> resources; resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, toMediaResourceSubType(mDomain))); if (mDomain == DOMAIN_VIDEO || mDomain == DOMAIN_IMAGE) { // Don't know the buffer size at this point, but it's fine to use 1 because // the reclaimResource call doesn't consider the requester's buffer size for now. resources.push_back(MediaResource::GraphicMemoryResource(1)); } for (int i = 0; i <= kMaxRetry; ++i) { if (i > 0) { // Don't try to reclaim resource for the first time. Loading media/libstagefright/include/media/stagefright/MediaCodec.h +1 −1 Original line number Diff line number Diff line Loading @@ -472,7 +472,7 @@ private: sp<AMessage> mAsyncReleaseCompleteNotification; sp<AMessage> mOnFirstTunnelFrameReadyNotification; sp<ResourceManagerServiceProxy> mResourceManagerProxy; std::shared_ptr<ResourceManagerServiceProxy> mResourceManagerProxy; Domain mDomain; AString mLogSessionId; Loading services/mediaresourcemanager/ResourceManagerService.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -133,7 +133,7 @@ static String8 getString(const std::vector<T> &items) { } static bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType, MediaResourceParcel resource) { const MediaResourceParcel& resource) { if (type != resource.type) { return false; } Loading Loading
media/libstagefright/MediaCodec.cpp +220 −96 Original line number Diff line number Diff line Loading @@ -21,9 +21,9 @@ #include <dlfcn.h> #include <inttypes.h> #include <future> #include <random> #include <set> #include <stdlib.h> #include <string> #include <C2Buffer.h> Loading Loading @@ -289,6 +289,10 @@ static const C2MemoryUsage kDefaultReadWriteUsage{ //////////////////////////////////////////////////////////////////////////////// /* * Implementation of IResourceManagerClient interrface that facilitates * MediaCodec reclaim for the ResourceManagerService. */ struct ResourceManagerClient : public BnResourceManagerClient { explicit ResourceManagerClient(MediaCodec* codec, int32_t pid, int32_t uid) : mMediaCodec(codec), mPid(pid), mUid(uid) {} Loading @@ -301,7 +305,9 @@ struct ResourceManagerClient : public BnResourceManagerClient { std::shared_ptr<IResourceManagerService> service = IResourceManagerService::fromBinder(binder); if (service == nullptr) { ALOGW("MediaCodec::ResourceManagerClient unable to find ResourceManagerService"); ALOGE("MediaCodec::ResourceManagerClient unable to find ResourceManagerService"); *_aidl_return = false; return Status::fromStatus(STATUS_INVALID_OPERATION); } ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), Loading Loading @@ -349,21 +355,25 @@ private: DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient); }; struct MediaCodec::ResourceManagerServiceProxy : public RefBase { /* * Proxy for ResourceManagerService that communicates with the * ResourceManagerService for MediaCodec */ struct MediaCodec::ResourceManagerServiceProxy : public std::enable_shared_from_this<ResourceManagerServiceProxy> { // BinderDiedContext defines the cookie that is passed as DeathRecipient. // Since this can maintain more context than a raw pointer, we can // validate the scope of ResourceManagerServiceProxy, // before deferencing it upon the binder death. struct BinderDiedContext { std::weak_ptr<ResourceManagerServiceProxy> mRMServiceProxy; }; ResourceManagerServiceProxy(pid_t pid, uid_t uid, const std::shared_ptr<IResourceManagerClient> &client); virtual ~ResourceManagerServiceProxy(); ~ResourceManagerServiceProxy(); status_t init(); // implements DeathRecipient static void BinderDiedCallback(void* cookie); void binderDied(); static Mutex sLockCookies; static std::set<void*> sCookies; static void addCookie(void* cookie); static void removeCookie(void* cookie); void addResource(const MediaResourceParcel &resource); void removeResource(const MediaResourceParcel &resource); void removeClient(); Loading @@ -379,50 +389,92 @@ struct MediaCodec::ResourceManagerServiceProxy : public RefBase { } private: Mutex mLock; // To get the binder interface to ResourceManagerService. void getService() { std::scoped_lock lock{mLock}; getService_l(); } std::shared_ptr<IResourceManagerService> getService_l(); // To add/register all the resources currently added/registered with // the ResourceManagerService. // This function will be called right after the death of the Resource // Manager to make sure that the newly started ResourceManagerService // knows about the current resource usage. void reRegisterAllResources_l(); void deinit() { std::scoped_lock lock{mLock}; // Unregistering from DeathRecipient notification. if (mService != nullptr) { AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this); mService = nullptr; } } // For binder death handling static void BinderDiedCallback(void* cookie); static void BinderUnlinkedCallback(void* cookie); void binderDied() { std::scoped_lock lock{mLock}; ALOGE("ResourceManagerService died."); mService = nullptr; mBinderDied = true; // start an async operation that will reconnect with the RM and // re-registers all the resources. mGetServiceFuture = std::async(std::launch::async, [this] { getService(); }); } private: std::mutex mLock; pid_t mPid; uid_t mUid; bool mBinderDied = false; std::string mCodecName; std::shared_ptr<IResourceManagerService> mService; /** * Reconnecting with the ResourceManagerService, after its binder interface dies, * is done asynchronously. It will also make sure that, all the resources * asssociated with this Proxy (MediaCodec) is added with the new instance * of the ResourceManagerService to persist the state of resources. * We must store the reference of the furture to guarantee real asynchronous operation. */ std::future<void> mGetServiceFuture; // To maintain the list of all the resources currently added/registered with // the ResourceManagerService. std::set<MediaResourceParcel> mMediaResourceParcel; std::shared_ptr<IResourceManagerClient> mClient; ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient; std::shared_ptr<IResourceManagerService> mService; }; MediaCodec::ResourceManagerServiceProxy::ResourceManagerServiceProxy( pid_t pid, uid_t uid, const std::shared_ptr<IResourceManagerClient> &client) : mPid(pid), mUid(uid), mClient(client), mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)) { pid_t pid, uid_t uid, const std::shared_ptr<IResourceManagerClient> &client) : mPid(pid), mUid(uid), mClient(client), mDeathRecipient(::ndk::ScopedAIBinder_DeathRecipient( AIBinder_DeathRecipient_new(BinderDiedCallback))) { if (mUid == MediaCodec::kNoUid) { mUid = AIBinder_getCallingUid(); } if (mPid == MediaCodec::kNoPid) { mPid = AIBinder_getCallingPid(); } // Setting callback notification when DeathRecipient gets deleted. AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), BinderUnlinkedCallback); } MediaCodec::ResourceManagerServiceProxy::~ResourceManagerServiceProxy() { // remove the cookie, so any in-flight death notification will get dropped // by our handler. removeCookie(this); Mutex::Autolock _l(mLock); if (mService != nullptr) { AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this); mService = nullptr; } deinit(); } status_t MediaCodec::ResourceManagerServiceProxy::init() { ::ndk::SpAIBinder binder(AServiceManager_waitForService("media.resource_manager")); mService = IResourceManagerService::fromBinder(binder); if (mService == nullptr) { ALOGE("Failed to get ResourceManagerService"); return UNKNOWN_ERROR; } std::scoped_lock lock{mLock}; int callerPid = AIBinder_getCallingPid(); int callerUid = AIBinder_getCallingUid(); if (mPid != callerPid || mUid != callerUid) { // Media processes don't need special permissions to act on behalf of other processes. if (callerUid != AID_MEDIA) { Loading @@ -435,111 +487,155 @@ status_t MediaCodec::ResourceManagerServiceProxy::init() { } } mService = getService_l(); if (mService == nullptr) { return DEAD_OBJECT; } // Kill clients pending removal. mService->reclaimResourcesFromClientsPendingRemoval(mPid); return OK; } // so our handler will process the death notifications addCookie(this); std::shared_ptr<IResourceManagerService> MediaCodec::ResourceManagerServiceProxy::getService_l() { if (mService != nullptr) { return mService; } // after this, require mLock whenever using mService AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this); return OK; // Get binder interface to resource manager. ::ndk::SpAIBinder binder(AServiceManager_waitForService("media.resource_manager")); mService = IResourceManagerService::fromBinder(binder); if (mService == nullptr) { ALOGE("Failed to get ResourceManagerService"); return mService; } //static // these are no_destroy to keep them from being destroyed at process exit // where some thread calls exit() while other threads are still running. // see b/194783918 [[clang::no_destroy]] Mutex MediaCodec::ResourceManagerServiceProxy::sLockCookies; [[clang::no_destroy]] std::set<void*> MediaCodec::ResourceManagerServiceProxy::sCookies; // Create the context that is passed as cookie to the binder death notification. // The context gets deleted at BinderUnlinkedCallback. BinderDiedContext* context = new BinderDiedContext{.mRMServiceProxy = weak_from_this()}; // Register for the callbacks by linking to death notification. AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), context); //static void MediaCodec::ResourceManagerServiceProxy::addCookie(void* cookie) { Mutex::Autolock _l(sLockCookies); sCookies.insert(cookie); // If the RM was restarted, re-register all the resources. if (mBinderDied) { reRegisterAllResources_l(); mBinderDied = false; } return mService; } //static void MediaCodec::ResourceManagerServiceProxy::removeCookie(void* cookie) { Mutex::Autolock _l(sLockCookies); sCookies.erase(cookie); void MediaCodec::ResourceManagerServiceProxy::reRegisterAllResources_l() { if (mMediaResourceParcel.empty()) { ALOGV("%s:%d:%p No resources to add", __func__, __LINE__, this); return; } std::vector<MediaResourceParcel> resources; std::copy(mMediaResourceParcel.begin(), mMediaResourceParcel.end(), std::back_inserter(resources)); if (mService == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; mService->addResource(clientInfo, mClient, resources); } //static void MediaCodec::ResourceManagerServiceProxy::BinderDiedCallback(void* cookie) { Mutex::Autolock _l(sLockCookies); if (sCookies.find(cookie) != sCookies.end()) { auto thiz = static_cast<ResourceManagerServiceProxy*>(cookie); BinderDiedContext* context = reinterpret_cast<BinderDiedContext*>(cookie); // Validate the context and check if the ResourceManagerServiceProxy object is still in scope. if (context != nullptr) { std::shared_ptr<ResourceManagerServiceProxy> thiz = context->mRMServiceProxy.lock(); if (thiz != nullptr) { thiz->binderDied(); } else { ALOGI("ResourceManagerServiceProxy is out of scope already"); } } } void MediaCodec::ResourceManagerServiceProxy::binderDied() { ALOGW("ResourceManagerService died."); Mutex::Autolock _l(mLock); mService = nullptr; void MediaCodec::ResourceManagerServiceProxy::BinderUnlinkedCallback(void* cookie) { BinderDiedContext* context = reinterpret_cast<BinderDiedContext*>(cookie); // Since we don't need the context anymore, we are deleting it now. delete context; } void MediaCodec::ResourceManagerServiceProxy::addResource( const MediaResourceParcel &resource) { std::vector<MediaResourceParcel> resources; resources.push_back(resource); Mutex::Autolock _l(mLock); if (mService == nullptr) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } std::vector<MediaResourceParcel> resources; resources.push_back(resource); ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; mService->addResource(clientInfo, mClient, resources); service->addResource(clientInfo, mClient, resources); mMediaResourceParcel.emplace(resource); } void MediaCodec::ResourceManagerServiceProxy::removeResource( const MediaResourceParcel &resource) { std::vector<MediaResourceParcel> resources; resources.push_back(resource); Mutex::Autolock _l(mLock); if (mService == nullptr) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } std::vector<MediaResourceParcel> resources; resources.push_back(resource); ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; mService->removeResource(clientInfo, resources); service->removeResource(clientInfo, resources); mMediaResourceParcel.erase(resource); } void MediaCodec::ResourceManagerServiceProxy::removeClient() { Mutex::Autolock _l(mLock); if (mService == nullptr) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; mService->removeClient(clientInfo); service->removeClient(clientInfo); mMediaResourceParcel.clear(); } void MediaCodec::ResourceManagerServiceProxy::markClientForPendingRemoval() { Mutex::Autolock _l(mLock); if (mService == nullptr) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; mService->markClientForPendingRemoval(clientInfo); service->markClientForPendingRemoval(clientInfo); mMediaResourceParcel.clear(); } bool MediaCodec::ResourceManagerServiceProxy::reclaimResource( const std::vector<MediaResourceParcel> &resources) { Mutex::Autolock _l(mLock); if (mService == NULL) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Service isn't available", __func__, __LINE__, this); return false; } bool success; Loading @@ -547,43 +643,67 @@ bool MediaCodec::ResourceManagerServiceProxy::reclaimResource( .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; Status status = mService->reclaimResource(clientInfo, resources, &success); Status status = service->reclaimResource(clientInfo, resources, &success); return status.isOk() && success; } void MediaCodec::ResourceManagerServiceProxy::notifyClientCreated() { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid), .uid = static_cast<int32_t>(mUid), .id = getId(mClient), .name = mCodecName}; mService->notifyClientCreated(clientInfo); service->notifyClientCreated(clientInfo); } void MediaCodec::ResourceManagerServiceProxy::notifyClientStarted( ClientConfigParcel& clientConfig) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } clientConfig.clientInfo.pid = static_cast<int32_t>(mPid); clientConfig.clientInfo.uid = static_cast<int32_t>(mUid); clientConfig.clientInfo.id = getId(mClient); clientConfig.clientInfo.name = mCodecName; mService->notifyClientStarted(clientConfig); service->notifyClientStarted(clientConfig); } void MediaCodec::ResourceManagerServiceProxy::notifyClientStopped( ClientConfigParcel& clientConfig) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } clientConfig.clientInfo.pid = static_cast<int32_t>(mPid); clientConfig.clientInfo.uid = static_cast<int32_t>(mUid); clientConfig.clientInfo.id = getId(mClient); clientConfig.clientInfo.name = mCodecName; mService->notifyClientStopped(clientConfig); service->notifyClientStopped(clientConfig); } void MediaCodec::ResourceManagerServiceProxy::notifyClientConfigChanged( ClientConfigParcel& clientConfig) { std::scoped_lock lock{mLock}; std::shared_ptr<IResourceManagerService> service = getService_l(); if (service == nullptr) { ALOGW("%s:%d:%p Serice isn't available", __func__, __LINE__, this); return; } clientConfig.clientInfo.pid = static_cast<int32_t>(mPid); clientConfig.clientInfo.uid = static_cast<int32_t>(mUid); clientConfig.clientInfo.id = getId(mClient); clientConfig.clientInfo.name = mCodecName; mService->notifyClientConfigChanged(clientConfig); service->notifyClientConfigChanged(clientConfig); } //////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -1036,7 +1156,7 @@ MediaCodec::MediaCodec( mGetCodecBase(getCodecBase), mGetCodecInfo(getCodecInfo) { mCodecId = GenerateCodecId(); mResourceManagerProxy = new ResourceManagerServiceProxy(pid, uid, mResourceManagerProxy = std::make_shared<ResourceManagerServiceProxy>(pid, uid, ::ndk::SharedRefBase::make<ResourceManagerClient>(this, pid, uid)); if (!mGetCodecBase) { mGetCodecBase = [](const AString &name, const char *owner) { Loading Loading @@ -2225,9 +2345,11 @@ status_t MediaCodec::configure( std::vector<MediaResourceParcel> resources; resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, toMediaResourceSubType(mDomain))); if (mDomain == DOMAIN_VIDEO || mDomain == DOMAIN_IMAGE) { // Don't know the buffer size at this point, but it's fine to use 1 because // the reclaimResource call doesn't consider the requester's buffer size for now. resources.push_back(MediaResource::GraphicMemoryResource(1)); } for (int i = 0; i <= kMaxRetry; ++i) { sp<AMessage> response; err = PostAndAwaitResponse(msg, &response); Loading Loading @@ -2828,9 +2950,11 @@ status_t MediaCodec::start() { std::vector<MediaResourceParcel> resources; resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, toMediaResourceSubType(mDomain))); if (mDomain == DOMAIN_VIDEO || mDomain == DOMAIN_IMAGE) { // Don't know the buffer size at this point, but it's fine to use 1 because // the reclaimResource call doesn't consider the requester's buffer size for now. resources.push_back(MediaResource::GraphicMemoryResource(1)); } for (int i = 0; i <= kMaxRetry; ++i) { if (i > 0) { // Don't try to reclaim resource for the first time. Loading
media/libstagefright/include/media/stagefright/MediaCodec.h +1 −1 Original line number Diff line number Diff line Loading @@ -472,7 +472,7 @@ private: sp<AMessage> mAsyncReleaseCompleteNotification; sp<AMessage> mOnFirstTunnelFrameReadyNotification; sp<ResourceManagerServiceProxy> mResourceManagerProxy; std::shared_ptr<ResourceManagerServiceProxy> mResourceManagerProxy; Domain mDomain; AString mLogSessionId; Loading
services/mediaresourcemanager/ResourceManagerService.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -133,7 +133,7 @@ static String8 getString(const std::vector<T> &items) { } static bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType, MediaResourceParcel resource) { const MediaResourceParcel& resource) { if (type != resource.type) { return false; } Loading