ResourceManagerService (4.3) markClientForPendingRemoval 和 reclaimResourcesFromClientsPendingRemoval
markClientForPendingRemoval 标记客户端可被移除
在下一个 reclaimResourcesFromClientsPendingRemoval 被调用时,被释放。
接口:
1 2 3 4 5 6 7 8 |
// frameworks/av/media/libmedia/aidl/android/media/IResourceManagerService.aidl /** * Mark a client for pending removal * * @param pid pid from which the client's resources will be removed. * @param clientId clientId within the pid that will be removed. */ void markClientForPendingRemoval(int pid, long clientId); |
应用调用 markClientForPendingRemoval 的流程
1.0 MediaCodec 处理 kWhatRelease 消息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// frameworks/av/media/libstagefright/MediaCodec.cpp void MediaCodec::ResourceManagerServiceProxy::markClientForPendingRemoval() { Mutex::Autolock _l(mLock); if (mService == nullptr) { return; } mService->markClientForPendingRemoval(mPid, getId(mClient)); } void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { ... case kWhatRelease: { ... // 上面的流程没有释放掉,将导致继续走到这里 if (asyncNotify != nullptr) { mResourceManagerProxy->markClientForPendingRemoval(); postPendingRepliesAndDeferredMessages("kWhatRelease:async"); asyncNotifyPost.clear(); mAsyncReleaseCompleteNotification = asyncNotify; } break; } ... } } |
2.0 服务端响应
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// frameworks/av/services/mediaresourcemanager/ResourceManagerService.cpp Status ResourceManagerService::markClientForPendingRemoval(int32_t pid, int64_t clientId) { String8 log = String8::format( "markClientForPendingRemoval(pid %d, clientId %lld)", pid, (long long) clientId); mServiceLog->add(log); Mutex::Autolock lock(mLock); if (!mProcessInfo->isValidPid(pid)) { ALOGE("Rejected markClientForPendingRemoval call with invalid pid."); return Status::fromServiceSpecificError(BAD_VALUE); } ssize_t index = mMap.indexOfKey(pid); if (index < 0) { ALOGV("markClientForPendingRemoval: didn't find pid %d for clientId %lld", pid, (long long)clientId); return Status::ok(); } ResourceInfos &infos = mMap.editValueAt(index); index = infos.indexOfKey(clientId); if (index < 0) { ALOGV("markClientForPendingRemoval: didn't find clientId %lld", (long long) clientId); return Status::ok(); } ResourceInfo &info = infos.editValueAt(index); info.pendingRemoval = true;// 标记为 true,下一个同 type 的 MediaCodec 将再次触发这个 codec 的释放 return Status::ok(); } |
ResourceManagerService 中的 reclaimResourcesFromClientsPendingRemoval
回收本应用,之前调用过 markClientForPendingRemoval 的 Client
接口:
1 2 3 4 5 6 7 |
// frameworks/av/media/libmedia/aidl/android/media/IResourceManagerService.aidl /** * Reclaim resources from clients pending removal, if any. * * @param pid pid from which resources will be reclaimed. */ void reclaimResourcesFromClientsPendingRemoval(int pid); |
应用调用 reclaimResourcesFromClientsPendingRemoval 的流程
1.0 MediaCodec 调用 reclaimResourcesFromClientsPendingRemoval
MediaCodec 在 init 时调用 reclaimResourcesFromClientsPendingRemoval
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// frameworks/av/media/libstagefright/MediaCodec.cpp void MediaCodec::ResourceManagerServiceProxy::init() { ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager")); mService = IResourceManagerService::fromBinder(binder); if (mService == nullptr) { ALOGE("Failed to get ResourceManagerService"); return; } // so our handler will process the death notifications addCookie(this); // after this, require mLock whenever using mService AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this); // Kill clients pending removal. mService->reclaimResourcesFromClientsPendingRemoval(mPid); } status_t MediaCodec::init(const AString &name) { mResourceManagerProxy->init(); ... } |
2.0 ResourceManagerService::reclaimResourcesFromClientsPendingRemoval
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
// frameworks/av/services/mediaresourcemanager/ResourceManagerService.cpp Status ResourceManagerService::reclaimResourcesFromClientsPendingRemoval(int32_t pid) { String8 log = String8::format("reclaimResourcesFromClientsPendingRemoval(pid %d)", pid); mServiceLog->add(log); Vector<std::shared_ptr<IResourceManagerClient>> clients; { Mutex::Autolock lock(mLock); if (!mProcessInfo->isValidPid(pid)) { ALOGE("Rejected reclaimResourcesFromClientsPendingRemoval call with invalid pid."); return Status::fromServiceSpecificError(BAD_VALUE); } for (MediaResource::Type type : {MediaResource::Type::kSecureCodec, MediaResource::Type::kNonSecureCodec, MediaResource::Type::kGraphicMemory, MediaResource::Type::kDrmSession}) { std::shared_ptr<IResourceManagerClient> client; // 根据 pid 和 type 找到合适的 IResourceManagerClient, 见 3.0 if (getBiggestClient_l(pid, type, &client, true /* pendingRemovalOnly */)) { clients.add(client); break; } } } if (!clients.empty()) { // 通知应用释放 见 4.0 reclaimInternal(clients); } return Status::ok(); } |
3.0 ResourceManagerService::getBiggestClient_l
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
bool ResourceManagerService::getBiggestClient_l( int pid, MediaResource::Type type, std::shared_ptr<IResourceManagerClient> *client, bool pendingRemovalOnly) { ssize_t index = mMap.indexOfKey(pid);// 这个 pid, 已经 addResource 过 if (index < 0) { ALOGE_IF(!pendingRemovalOnly, "getBiggestClient_l: can't find resource info for pid %d", pid); return false; } std::shared_ptr<IResourceManagerClient> clientTemp; uint64_t largestValue = 0; const ResourceInfos &infos = mMap.valueAt(index);// 找到应用注册的所以 resource for (size_t i = 0; i < infos.size(); ++i) { const ResourceList &resources = infos[i].resources; if (pendingRemovalOnly && !infos[i].pendingRemoval) {// pendingRemovalOnly 参数传入的是 true, pendingRemoval 在实例化对象时是 false continue; } for (auto it = resources.begin(); it != resources.end(); it++) { const MediaResourceParcel &resource = it->second; if (resource.type == type) {// 类型相同 if (resource.value > largestValue) {// 找到 resource.value 最大的值 largestValue = resource.value; ALOGV("getBiggestClient_l: find client: %lld value: %lld", (long long) infos[i].clientId, (long long) resource.value); clientTemp = infos[i].client; } } } } if (clientTemp == NULL) { ALOGE_IF(!pendingRemovalOnly, "getBiggestClient_l: can't find resource type %s for pid %d", asString(type), pid); return false; } *client = clientTemp; return true; } |
4.0 调用 IResourceManagerClient 的 reclaimResource
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// frameworks/av/services/mediaresourcemanager/ResourceManagerService.cpp bool ResourceManagerService::reclaimInternal( const Vector<std::shared_ptr<IResourceManagerClient>> &clients) { if (clients.size() == 0) { return false; } std::shared_ptr<IResourceManagerClient> failedClient; for (size_t i = 0; i < clients.size(); ++i) { String8 log = String8::format("reclaimResource from client %p", clients[i].get()); mServiceLog->add(log); bool success; // 见 5.0 Status status = clients[i]->reclaimResource(&success);// 调用对应 MediaCodec 中的 reclaimResource if (!status.isOk() || !success) { failedClient = clients[i]; break; } } if (failedClient == NULL) { return true; } ... return false; } |
5.0 IResourceManagerClient.reclaimResource
以 MediaCodec 为例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// frameworks/av/media/libstagefright/MediaCodec.cpp struct ResourceManagerClient : public BnResourceManagerClient { explicit ResourceManagerClient(MediaCodec* codec) : mMediaCodec(codec) {} Status reclaimResource(bool* _aidl_return) override { sp<MediaCodec> codec = mMediaCodec.promote(); if (codec == NULL) { // codec is already gone. *_aidl_return = true; return Status::ok(); } status_t err = codec->reclaim();// 见 6.0 if (err == WOULD_BLOCK) { ALOGD("Wait for the client to release codec."); usleep(kMaxReclaimWaitTimeInUs); ALOGD("Try to reclaim again."); err = codec->reclaim(true /* force */); } if (err != OK) { ALOGW("ResourceManagerClient failed to release codec with err %d", err); } *_aidl_return = (err == OK); return Status::ok(); } ... } |
6.0 MediaCodec::reclaim
触发处理 kWhatRelease 事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// frameworks/av/media/libstagefright/MediaCodec.cpp status_t MediaCodec::reclaim(bool force) { ALOGD("MediaCodec::reclaim(%p) %s", this, mInitName.c_str()); sp<AMessage> msg = new AMessage(kWhatRelease, this); msg->setInt32("reclaimed", 1); msg->setInt32("force", force ? 1 : 0); sp<AMessage> response; status_t ret = PostAndAwaitResponse(msg, &response); if (ret == -ENOENT) { ALOGD("MediaCodec looper is gone, skip reclaim"); ret = OK; } return ret; } |
0 Comments