应用向 ResourceManagerService 注册资源的接口
- 接口
- ResourceManagerService 中对 addResource 信息的保存封装类
- addResource 流程
接口:
1 2 3 4 5 6 7 8 9 10 11 12 |
// frameworks/av/media/libmedia/aidl/android/media/IResourceManagerService.aidl /** * Add a client to a process with a list of resources. * * @param pid pid of the client. * @param uid uid of the client. * @param clientId an identifier that uniquely identifies the client within the pid. * @param client interface for the ResourceManagerService to call the client. * @param resources an array of resources to be added. */ void addResource(int pid, int uid, long clientId, IResourceManagerClient client, in MediaResourceParcel[] resources); |
ResourceManagerService 中对 addResource 信息的保存封装类
添加的 resource, 被保存在变量 mMap 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// frameworks/av/services/mediaresourcemanager/ResourceManagerService.h struct ResourceInfo { int64_t clientId; uid_t uid; std::shared_ptr<IResourceManagerClient> client; sp<DeathNotifier> deathNotifier; ResourceList resources;// 可以添加多个 Resource bool pendingRemoval{false}; }; // TODO: convert these to std::map typedef KeyedVector<int64_t, ResourceInfo> ResourceInfos;// 这里的 key 是 clientId, 即 MediaCodec 中 Client 的地址 typedef KeyedVector<int, ResourceInfos> PidResourceInfosMap;// PID 和 ResourceInfo 的映射关系 PidResourceInfosMap mMap;// 添加的 Resource 保存在 mMap 中 |
PidResourceInfosMap 中一个 pid 可以保存多个 ResourceInfos 队列, 所以一个应用可以添加多个 Resource
addResource 流程
1.0 MediaCodec 调用 Service->addResource
1 2 3 4 5 6 7 8 9 10 11 12 |
// frameworks/av/media/libstagefright/MediaCodec.cpp void MediaCodec::ResourceManagerServiceProxy::addResource( const MediaResourceParcel &resource) { std::vector<MediaResourceParcel> resources; resources.push_back(resource); Mutex::Autolock _l(mLock); if (mService == nullptr) { return; } mService->addResource(mPid, mUid, getId(mClient), mClient, resources); } |
调用时机:
* 编解码器创建
* start 之后
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
void MediaCodec::statsBufferSent(int64_t presentationUs) { ... if (mBatteryChecker != nullptr) { mBatteryChecker->onCodecActivity([this] () { mResourceManagerProxy->addResource(MediaResource::VideoBatteryResource()); }); } ... } // when we get a buffer back from the codec void MediaCodec::statsBufferReceived(int64_t presentationUs) { ... if (mBatteryChecker != nullptr) { mBatteryChecker->onCodecActivity([this] () { mResourceManagerProxy->addResource(MediaResource::VideoBatteryResource()); }); } ... } void MediaCodec::requestCpuBoostIfNeeded() { if (mCpuBoostRequested) { return; } ... if (totalPixel >= 1920 * 1080) { mResourceManagerProxy->addResource(MediaResource::CpuBoostResource()); mCpuBoostRequested = true; } ... } void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { ... case kWhatComponentAllocated: { ... if (mIsVideo) { // audio codec is currently ignored. mResourceManagerProxy->addResource( MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo)); } ... break; } ... case kWhatStartCompleted: { if (mState == RELEASING || mState == UNINITIALIZED) { // In case a kWhatRelease message came in and replied, // we log a warning and ignore. ALOGW("start interrupted by release, current state %d", mState); break; } CHECK_EQ(mState, STARTING); if (mIsVideo) { mResourceManagerProxy->addResource( MediaResource::GraphicMemoryResource(getGraphicBufferSize())); } setState(STARTED); postPendingRepliesAndDeferredMessages("kWhatStartCompleted"); break; } ... } } |
2.0 ResourceManagerService::addResource
将类型和 Value 进行保存
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 41 42 43 44 45 46 47 48 49 |
// frameworks/av/services/mediaresourcemanager/ResourceManagerService.cpp Status ResourceManagerService::addResource( int32_t pid, int32_t uid, int64_t clientId, const std::shared_ptr<IResourceManagerClient>& client, const std::vector<MediaResourceParcel>& resources) { String8 log = String8::format("addResource(pid %d, clientId %lld, resources %s)", pid, (long long) clientId, getString(resources).string()); mServiceLog->add(log);// 加到事件日志中 Mutex::Autolock lock(mLock); if (!mProcessInfo->isValidPid(pid)) { ALOGE("Rejected addResource call with invalid pid."); return Status::fromServiceSpecificError(BAD_VALUE); } ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);// 根据 ID 找到已经保存的 Resource 数据 // clientId 是 MediaCodec 中 Client 的地址, 每个 MediaCodec 对应同一个 clientId ResourceInfo& info = getResourceInfoForEdit(uid, clientId, client, infos); for (size_t i = 0; i < resources.size(); ++i) { const auto &res = resources[i]; const auto resType = std::tuple(res.type, res.subType, res.id); if (res.value < 0 && res.type != MediaResource::Type::kDrmSession) { ALOGW("Ignoring request to remove negative value of non-drm resource"); continue; } if (info.resources.find(resType) == info.resources.end()) {// 没找到同类型的 if (res.value <= 0) { // We can't init a new entry with negative value, although it's allowed // to merge in negative values after the initial add. ALOGW("Ignoring request to add new resource entry with value <= 0"); continue; } onFirstAdded(res, info);// 添加 resource info.resources[resType] = res; } else { mergeResources(info.resources[resType], res);// 将 value 相加 } } if (info.deathNotifier == nullptr && client != nullptr) { info.deathNotifier = new DeathNotifier(ref<ResourceManagerService>(), pid, clientId); AIBinder_linkToDeath(client->asBinder().get(), mDeathRecipient.get(), info.deathNotifier.get());// 注册死亡监听 } notifyResourceGranted(pid, resources);// 通知注册监听的应用 source 更新 return Status::ok(); } |
0 Comments