Loading drm/libmediadrm/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -44,9 +44,11 @@ cc_library_shared { "libcutils", "libdl", "liblog", "libmedia", "libmediadrmmetrics_lite", "libmediametrics", "libmediautils", "libresourcemanagerservice", "libstagefright_foundation", "libutils", "android.hardware.drm@1.0", Loading drm/libmediadrm/DrmHal.cpp +36 −30 Original line number Diff line number Diff line Loading @@ -295,38 +295,45 @@ static status_t toStatusT_1_2(Status_V1_2 status) { } } Mutex DrmHal::mLock; struct DrmSessionClient : public DrmSessionClientInterface { explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {} virtual bool reclaimSession(const Vector<uint8_t>& sessionId) { bool DrmHal::DrmSessionClient::reclaimResource() { sp<DrmHal> drm = mDrm.promote(); if (drm == NULL) { return true; } status_t err = drm->closeSession(sessionId); status_t err = drm->closeSession(mSessionId); if (err != OK) { return false; } drm->sendEvent(EventType::SESSION_RECLAIMED, toHidlVec(sessionId), hidl_vec<uint8_t>()); toHidlVec(mSessionId), hidl_vec<uint8_t>()); return true; } protected: virtual ~DrmSessionClient() {} private: wp<DrmHal> mDrm; String8 DrmHal::DrmSessionClient::getName() { String8 name; sp<DrmHal> drm = mDrm.promote(); if (drm == NULL) { name.append("<deleted>"); } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.isEmpty()) { name.append("<Get vendor failed or is empty>"); } name.append("["); for (size_t i = 0; i < mSessionId.size(); ++i) { name.appendFormat("%02x", mSessionId[i]); } name.append("]"); return name; } DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient); }; DrmHal::DrmSessionClient::~DrmSessionClient() { DrmSessionManager::Instance()->removeSession(mSessionId); } DrmHal::DrmHal() : mDrmSessionClient(new DrmSessionClient(this)), mFactories(makeDrmFactories()), : mFactories(makeDrmFactories()), mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) { } Loading @@ -335,14 +342,13 @@ void DrmHal::closeOpenSessions() { auto openSessions = mOpenSessions; for (size_t i = 0; i < openSessions.size(); i++) { mLock.unlock(); closeSession(openSessions[i]); closeSession(openSessions[i]->mSessionId); mLock.lock(); } mOpenSessions.clear(); } DrmHal::~DrmHal() { DrmSessionManager::Instance()->removeDrm(mDrmSessionClient); } void DrmHal::cleanup() { Loading Loading @@ -748,9 +754,9 @@ status_t DrmHal::openSession(DrmPlugin::SecurityLevel level, } while (retry); if (err == OK) { DrmSessionManager::Instance()->addSession(getCallingPid(), mDrmSessionClient, sessionId); mOpenSessions.push(sessionId); sp<DrmSessionClient> client(new DrmSessionClient(this, sessionId)); DrmSessionManager::Instance()->addSession(getCallingPid(), client, sessionId); mOpenSessions.push(client); mMetrics.SetSessionStart(sessionId); } Loading @@ -767,7 +773,7 @@ status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) { if (status == Status::OK) { DrmSessionManager::Instance()->removeSession(sessionId); for (size_t i = 0; i < mOpenSessions.size(); i++) { if (mOpenSessions[i] == sessionId) { if (isEqualSessionId(mOpenSessions[i]->mSessionId, sessionId)) { mOpenSessions.removeAt(i); break; } Loading drm/libmediadrm/DrmSessionManager.cpp +103 −144 Original line number Diff line number Diff line Loading @@ -21,12 +21,17 @@ #include <binder/IPCThreadState.h> #include <binder/IProcessInfoService.h> #include <binder/IServiceManager.h> #include <media/stagefright/ProcessInfo.h> #include <mediadrm/DrmSessionClientInterface.h> #include <cutils/properties.h> #include <media/IResourceManagerClient.h> #include <media/MediaResource.h> #include <mediadrm/DrmSessionManager.h> #include <unistd.h> #include <utils/String8.h> #include <vector> #include "ResourceManagerService.h" namespace android { static String8 GetSessionIdString(const Vector<uint8_t> &sessionId) { Loading @@ -37,6 +42,35 @@ static String8 GetSessionIdString(const Vector<uint8_t> &sessionId) { return sessionIdStr; } static std::vector<uint8_t> toStdVec(const Vector<uint8_t> &vector) { const uint8_t *v = vector.array(); std::vector<uint8_t> vec(v, v + vector.size()); return vec; } static uint64_t toClientId(const sp<IResourceManagerClient>& drm) { return reinterpret_cast<int64_t>(drm.get()); } static Vector<MediaResource> toResourceVec(const Vector<uint8_t> &sessionId) { Vector<MediaResource> resources; // use UINT64_MAX to decrement through addition overflow resources.push_back(MediaResource(MediaResource::kDrmSession, toStdVec(sessionId), UINT64_MAX)); return resources; } static sp<IResourceManagerService> getResourceManagerService() { if (property_get_bool("persist.device_config.media_native.mediadrmserver", 1)) { return new ResourceManagerService(); } sp<IServiceManager> sm = defaultServiceManager(); if (sm == NULL) { return NULL; } sp<IBinder> binder = sm->getService(String16("media.resource_manager")); return interface_cast<IResourceManagerService>(binder); } bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2) { if (sessionId1.size() != sessionId2.size()) { return false; Loading @@ -51,189 +85,114 @@ bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> & sp<DrmSessionManager> DrmSessionManager::Instance() { static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager(); drmSessionManager->init(); return drmSessionManager; } DrmSessionManager::DrmSessionManager() : mProcessInfo(new ProcessInfo()), mTime(0) {} : DrmSessionManager(getResourceManagerService()) { } DrmSessionManager::DrmSessionManager(sp<ProcessInfoInterface> processInfo) : mProcessInfo(processInfo), mTime(0) {} DrmSessionManager::DrmSessionManager(const sp<IResourceManagerService> &service) : mService(service), mInitialized(false) { if (mService == NULL) { ALOGE("Failed to init ResourceManagerService"); } } DrmSessionManager::~DrmSessionManager() {} DrmSessionManager::~DrmSessionManager() { if (mService != NULL) { IInterface::asBinder(mService)->unlinkToDeath(this); } } void DrmSessionManager::addSession( int pid, const sp<DrmSessionClientInterface>& drm, const Vector<uint8_t> &sessionId) { ALOGV("addSession(pid %d, drm %p, sessionId %s)", pid, drm.get(), void DrmSessionManager::init() { Mutex::Autolock lock(mLock); if (mInitialized) { return; } mInitialized = true; if (mService != NULL) { IInterface::asBinder(mService)->linkToDeath(this); } } void DrmSessionManager::addSession(int pid, const sp<IResourceManagerClient>& drm, const Vector<uint8_t> &sessionId) { uid_t uid = IPCThreadState::self()->getCallingUid(); ALOGV("addSession(pid %d, uid %d, drm %p, sessionId %s)", pid, uid, drm.get(), GetSessionIdString(sessionId).string()); Mutex::Autolock lock(mLock); SessionInfo info; info.drm = drm; info.sessionId = sessionId; info.timeStamp = getTime_l(); ssize_t index = mSessionMap.indexOfKey(pid); if (index < 0) { // new pid SessionInfos infosForPid; infosForPid.push_back(info); mSessionMap.add(pid, infosForPid); } else { mSessionMap.editValueAt(index).push_back(info); if (mService == NULL) { return; } int64_t clientId = toClientId(drm); mSessionMap[toStdVec(sessionId)] = (SessionInfo){pid, uid, clientId}; mService->addResource(pid, uid, clientId, drm, toResourceVec(sessionId)); } void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) { ALOGV("useSession(%s)", GetSessionIdString(sessionId).string()); Mutex::Autolock lock(mLock); for (size_t i = 0; i < mSessionMap.size(); ++i) { SessionInfos& infos = mSessionMap.editValueAt(i); for (size_t j = 0; j < infos.size(); ++j) { SessionInfo& info = infos.editItemAt(j); if (isEqualSessionId(sessionId, info.sessionId)) { info.timeStamp = getTime_l(); auto it = mSessionMap.find(toStdVec(sessionId)); if (mService == NULL || it == mSessionMap.end()) { return; } } } auto info = it->second; mService->addResource(info.pid, info.uid, info.clientId, NULL, toResourceVec(sessionId)); } void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) { ALOGV("removeSession(%s)", GetSessionIdString(sessionId).string()); Mutex::Autolock lock(mLock); for (size_t i = 0; i < mSessionMap.size(); ++i) { SessionInfos& infos = mSessionMap.editValueAt(i); for (size_t j = 0; j < infos.size(); ++j) { if (isEqualSessionId(sessionId, infos[j].sessionId)) { infos.removeAt(j); auto it = mSessionMap.find(toStdVec(sessionId)); if (mService == NULL || it == mSessionMap.end()) { return; } } } } void DrmSessionManager::removeDrm(const sp<DrmSessionClientInterface>& drm) { ALOGV("removeDrm(%p)", drm.get()); Mutex::Autolock lock(mLock); bool found = false; for (size_t i = 0; i < mSessionMap.size(); ++i) { SessionInfos& infos = mSessionMap.editValueAt(i); for (size_t j = 0; j < infos.size();) { if (infos[j].drm == drm) { ALOGV("removed session (%s)", GetSessionIdString(infos[j].sessionId).string()); j = infos.removeAt(j); found = true; } else { ++j; } } if (found) { break; } } auto info = it->second; mService->removeResource(info.pid, info.clientId, toResourceVec(sessionId)); mSessionMap.erase(it); } bool DrmSessionManager::reclaimSession(int callingPid) { ALOGV("reclaimSession(%d)", callingPid); sp<DrmSessionClientInterface> drm; Vector<uint8_t> sessionId; int lowestPriorityPid; int lowestPriority; { Mutex::Autolock lock(mLock); int callingPriority; if (!mProcessInfo->getPriority(callingPid, &callingPriority)) { return false; } if (!getLowestPriority_l(&lowestPriorityPid, &lowestPriority)) { return false; } if (lowestPriority <= callingPriority) { return false; } if (!getLeastUsedSession_l(lowestPriorityPid, &drm, &sessionId)) { return false; } } // unlock early because reclaimResource might callback into removeSession mLock.lock(); sp<IResourceManagerService> service(mService); mLock.unlock(); if (drm == NULL) { if (service == NULL) { return false; } ALOGV("reclaim session(%s) opened by pid %d", GetSessionIdString(sessionId).string(), lowestPriorityPid); return drm->reclaimSession(sessionId); // cannot update mSessionMap because we do not know which sessionId is reclaimed; // we rely on IResourceManagerClient to removeSession in reclaimResource Vector<uint8_t> dummy; return service->reclaimResource(callingPid, toResourceVec(dummy)); } int64_t DrmSessionManager::getTime_l() { return mTime++; } bool DrmSessionManager::getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority) { int pid = -1; int priority = -1; for (size_t i = 0; i < mSessionMap.size(); ++i) { if (mSessionMap.valueAt(i).size() == 0) { // no opened session by this process. continue; } int tempPid = mSessionMap.keyAt(i); int tempPriority; if (!mProcessInfo->getPriority(tempPid, &tempPriority)) { // shouldn't happen. return false; } if (pid == -1) { pid = tempPid; priority = tempPriority; } else { if (tempPriority > priority) { pid = tempPid; priority = tempPriority; } } } if (pid != -1) { *lowestPriorityPid = pid; *lowestPriority = priority; } return (pid != -1); size_t DrmSessionManager::getSessionCount() const { Mutex::Autolock lock(mLock); return mSessionMap.size(); } bool DrmSessionManager::getLeastUsedSession_l( int pid, sp<DrmSessionClientInterface>* drm, Vector<uint8_t>* sessionId) { ssize_t index = mSessionMap.indexOfKey(pid); if (index < 0) { return false; bool DrmSessionManager::containsSession(const Vector<uint8_t>& sessionId) const { Mutex::Autolock lock(mLock); return mSessionMap.count(toStdVec(sessionId)); } int leastUsedIndex = -1; int64_t minTs = LLONG_MAX; const SessionInfos& infos = mSessionMap.valueAt(index); for (size_t j = 0; j < infos.size(); ++j) { if (leastUsedIndex == -1) { leastUsedIndex = j; minTs = infos[j].timeStamp; } else { if (infos[j].timeStamp < minTs) { leastUsedIndex = j; minTs = infos[j].timeStamp; } } } if (leastUsedIndex != -1) { *drm = infos[leastUsedIndex].drm; *sessionId = infos[leastUsedIndex].sessionId; } return (leastUsedIndex != -1); void DrmSessionManager::binderDied(const wp<IBinder>& /*who*/) { ALOGW("ResourceManagerService died."); Mutex::Autolock lock(mLock); mService.clear(); } } // namespace android drm/libmediadrm/include/mediadrm/DrmHal.h +23 −3 Original line number Diff line number Diff line Loading @@ -26,8 +26,10 @@ #include <android/hardware/drm/1.2/IDrmPlugin.h> #include <android/hardware/drm/1.2/IDrmPluginListener.h> #include <media/IResourceManagerService.h> #include <media/MediaAnalyticsItem.h> #include <mediadrm/DrmMetrics.h> #include <mediadrm/DrmSessionManager.h> #include <mediadrm/IDrm.h> #include <mediadrm/IDrmClient.h> #include <utils/threads.h> Loading Loading @@ -59,6 +61,26 @@ inline bool operator==(const Vector<uint8_t> &l, const Vector<uint8_t> &r) { struct DrmHal : public BnDrm, public IBinder::DeathRecipient, public IDrmPluginListener_V1_2 { struct DrmSessionClient : public BnResourceManagerClient { explicit DrmSessionClient(DrmHal* drm, const Vector<uint8_t>& sessionId) : mSessionId(sessionId), mDrm(drm) {} virtual bool reclaimResource(); virtual String8 getName(); const Vector<uint8_t> mSessionId; protected: virtual ~DrmSessionClient(); private: wp<DrmHal> mDrm; DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient); }; DrmHal(); virtual ~DrmHal(); Loading Loading @@ -193,8 +215,6 @@ struct DrmHal : public BnDrm, private: static Mutex mLock; sp<DrmSessionClientInterface> mDrmSessionClient; sp<IDrmClient> mListener; mutable Mutex mEventLock; mutable Mutex mNotifyLock; Loading @@ -208,7 +228,7 @@ private: // Mutable to allow modification within GetPropertyByteArray. mutable MediaDrmMetrics mMetrics; Vector<Vector<uint8_t>> mOpenSessions; Vector<sp<DrmSessionClient>> mOpenSessions; void closeOpenSessions(); void cleanup(); Loading drm/libmediadrm/include/mediadrm/DrmSessionManager.h +25 −20 Original line number Diff line number Diff line Loading @@ -18,56 +18,61 @@ #define DRM_SESSION_MANAGER_H_ #include <binder/IBinder.h> #include <media/IResourceManagerService.h> #include <media/stagefright/foundation/ABase.h> #include <utils/RefBase.h> #include <utils/KeyedVector.h> #include <utils/threads.h> #include <utils/Vector.h> #include <map> #include <utility> #include <vector> namespace android { class DrmSessionManagerTest; struct DrmSessionClientInterface; struct ProcessInfoInterface; class IResourceManagerClient; bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2); struct SessionInfo { sp<DrmSessionClientInterface> drm; Vector<uint8_t> sessionId; int64_t timeStamp; pid_t pid; uid_t uid; int64_t clientId; }; typedef Vector<SessionInfo > SessionInfos; typedef KeyedVector<int, SessionInfos > PidSessionInfosMap; typedef std::map<std::vector<uint8_t>, SessionInfo> SessionInfoMap; struct DrmSessionManager : public RefBase { struct DrmSessionManager : public IBinder::DeathRecipient { static sp<DrmSessionManager> Instance(); DrmSessionManager(); explicit DrmSessionManager(sp<ProcessInfoInterface> processInfo); explicit DrmSessionManager(const sp<IResourceManagerService> &service); void addSession(int pid, const sp<DrmSessionClientInterface>& drm, const Vector<uint8_t>& sessionId); void addSession(int pid, const sp<IResourceManagerClient>& drm, const Vector<uint8_t>& sessionId); void useSession(const Vector<uint8_t>& sessionId); void removeSession(const Vector<uint8_t>& sessionId); void removeDrm(const sp<DrmSessionClientInterface>& drm); bool reclaimSession(int callingPid); // sanity check APIs size_t getSessionCount() const; bool containsSession(const Vector<uint8_t>& sessionId) const; // implements DeathRecipient virtual void binderDied(const wp<IBinder>& /*who*/); protected: virtual ~DrmSessionManager(); private: friend class DrmSessionManagerTest; int64_t getTime_l(); bool getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority); bool getLeastUsedSession_l( int pid, sp<DrmSessionClientInterface>* drm, Vector<uint8_t>* sessionId); void init(); sp<ProcessInfoInterface> mProcessInfo; sp<IResourceManagerService> mService; mutable Mutex mLock; PidSessionInfosMap mSessionMap; int64_t mTime; SessionInfoMap mSessionMap; bool mInitialized; DISALLOW_EVIL_CONSTRUCTORS(DrmSessionManager); }; Loading Loading
drm/libmediadrm/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -44,9 +44,11 @@ cc_library_shared { "libcutils", "libdl", "liblog", "libmedia", "libmediadrmmetrics_lite", "libmediametrics", "libmediautils", "libresourcemanagerservice", "libstagefright_foundation", "libutils", "android.hardware.drm@1.0", Loading
drm/libmediadrm/DrmHal.cpp +36 −30 Original line number Diff line number Diff line Loading @@ -295,38 +295,45 @@ static status_t toStatusT_1_2(Status_V1_2 status) { } } Mutex DrmHal::mLock; struct DrmSessionClient : public DrmSessionClientInterface { explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {} virtual bool reclaimSession(const Vector<uint8_t>& sessionId) { bool DrmHal::DrmSessionClient::reclaimResource() { sp<DrmHal> drm = mDrm.promote(); if (drm == NULL) { return true; } status_t err = drm->closeSession(sessionId); status_t err = drm->closeSession(mSessionId); if (err != OK) { return false; } drm->sendEvent(EventType::SESSION_RECLAIMED, toHidlVec(sessionId), hidl_vec<uint8_t>()); toHidlVec(mSessionId), hidl_vec<uint8_t>()); return true; } protected: virtual ~DrmSessionClient() {} private: wp<DrmHal> mDrm; String8 DrmHal::DrmSessionClient::getName() { String8 name; sp<DrmHal> drm = mDrm.promote(); if (drm == NULL) { name.append("<deleted>"); } else if (drm->getPropertyStringInternal(String8("vendor"), name) != OK || name.isEmpty()) { name.append("<Get vendor failed or is empty>"); } name.append("["); for (size_t i = 0; i < mSessionId.size(); ++i) { name.appendFormat("%02x", mSessionId[i]); } name.append("]"); return name; } DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient); }; DrmHal::DrmSessionClient::~DrmSessionClient() { DrmSessionManager::Instance()->removeSession(mSessionId); } DrmHal::DrmHal() : mDrmSessionClient(new DrmSessionClient(this)), mFactories(makeDrmFactories()), : mFactories(makeDrmFactories()), mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) { } Loading @@ -335,14 +342,13 @@ void DrmHal::closeOpenSessions() { auto openSessions = mOpenSessions; for (size_t i = 0; i < openSessions.size(); i++) { mLock.unlock(); closeSession(openSessions[i]); closeSession(openSessions[i]->mSessionId); mLock.lock(); } mOpenSessions.clear(); } DrmHal::~DrmHal() { DrmSessionManager::Instance()->removeDrm(mDrmSessionClient); } void DrmHal::cleanup() { Loading Loading @@ -748,9 +754,9 @@ status_t DrmHal::openSession(DrmPlugin::SecurityLevel level, } while (retry); if (err == OK) { DrmSessionManager::Instance()->addSession(getCallingPid(), mDrmSessionClient, sessionId); mOpenSessions.push(sessionId); sp<DrmSessionClient> client(new DrmSessionClient(this, sessionId)); DrmSessionManager::Instance()->addSession(getCallingPid(), client, sessionId); mOpenSessions.push(client); mMetrics.SetSessionStart(sessionId); } Loading @@ -767,7 +773,7 @@ status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) { if (status == Status::OK) { DrmSessionManager::Instance()->removeSession(sessionId); for (size_t i = 0; i < mOpenSessions.size(); i++) { if (mOpenSessions[i] == sessionId) { if (isEqualSessionId(mOpenSessions[i]->mSessionId, sessionId)) { mOpenSessions.removeAt(i); break; } Loading
drm/libmediadrm/DrmSessionManager.cpp +103 −144 Original line number Diff line number Diff line Loading @@ -21,12 +21,17 @@ #include <binder/IPCThreadState.h> #include <binder/IProcessInfoService.h> #include <binder/IServiceManager.h> #include <media/stagefright/ProcessInfo.h> #include <mediadrm/DrmSessionClientInterface.h> #include <cutils/properties.h> #include <media/IResourceManagerClient.h> #include <media/MediaResource.h> #include <mediadrm/DrmSessionManager.h> #include <unistd.h> #include <utils/String8.h> #include <vector> #include "ResourceManagerService.h" namespace android { static String8 GetSessionIdString(const Vector<uint8_t> &sessionId) { Loading @@ -37,6 +42,35 @@ static String8 GetSessionIdString(const Vector<uint8_t> &sessionId) { return sessionIdStr; } static std::vector<uint8_t> toStdVec(const Vector<uint8_t> &vector) { const uint8_t *v = vector.array(); std::vector<uint8_t> vec(v, v + vector.size()); return vec; } static uint64_t toClientId(const sp<IResourceManagerClient>& drm) { return reinterpret_cast<int64_t>(drm.get()); } static Vector<MediaResource> toResourceVec(const Vector<uint8_t> &sessionId) { Vector<MediaResource> resources; // use UINT64_MAX to decrement through addition overflow resources.push_back(MediaResource(MediaResource::kDrmSession, toStdVec(sessionId), UINT64_MAX)); return resources; } static sp<IResourceManagerService> getResourceManagerService() { if (property_get_bool("persist.device_config.media_native.mediadrmserver", 1)) { return new ResourceManagerService(); } sp<IServiceManager> sm = defaultServiceManager(); if (sm == NULL) { return NULL; } sp<IBinder> binder = sm->getService(String16("media.resource_manager")); return interface_cast<IResourceManagerService>(binder); } bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2) { if (sessionId1.size() != sessionId2.size()) { return false; Loading @@ -51,189 +85,114 @@ bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> & sp<DrmSessionManager> DrmSessionManager::Instance() { static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager(); drmSessionManager->init(); return drmSessionManager; } DrmSessionManager::DrmSessionManager() : mProcessInfo(new ProcessInfo()), mTime(0) {} : DrmSessionManager(getResourceManagerService()) { } DrmSessionManager::DrmSessionManager(sp<ProcessInfoInterface> processInfo) : mProcessInfo(processInfo), mTime(0) {} DrmSessionManager::DrmSessionManager(const sp<IResourceManagerService> &service) : mService(service), mInitialized(false) { if (mService == NULL) { ALOGE("Failed to init ResourceManagerService"); } } DrmSessionManager::~DrmSessionManager() {} DrmSessionManager::~DrmSessionManager() { if (mService != NULL) { IInterface::asBinder(mService)->unlinkToDeath(this); } } void DrmSessionManager::addSession( int pid, const sp<DrmSessionClientInterface>& drm, const Vector<uint8_t> &sessionId) { ALOGV("addSession(pid %d, drm %p, sessionId %s)", pid, drm.get(), void DrmSessionManager::init() { Mutex::Autolock lock(mLock); if (mInitialized) { return; } mInitialized = true; if (mService != NULL) { IInterface::asBinder(mService)->linkToDeath(this); } } void DrmSessionManager::addSession(int pid, const sp<IResourceManagerClient>& drm, const Vector<uint8_t> &sessionId) { uid_t uid = IPCThreadState::self()->getCallingUid(); ALOGV("addSession(pid %d, uid %d, drm %p, sessionId %s)", pid, uid, drm.get(), GetSessionIdString(sessionId).string()); Mutex::Autolock lock(mLock); SessionInfo info; info.drm = drm; info.sessionId = sessionId; info.timeStamp = getTime_l(); ssize_t index = mSessionMap.indexOfKey(pid); if (index < 0) { // new pid SessionInfos infosForPid; infosForPid.push_back(info); mSessionMap.add(pid, infosForPid); } else { mSessionMap.editValueAt(index).push_back(info); if (mService == NULL) { return; } int64_t clientId = toClientId(drm); mSessionMap[toStdVec(sessionId)] = (SessionInfo){pid, uid, clientId}; mService->addResource(pid, uid, clientId, drm, toResourceVec(sessionId)); } void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) { ALOGV("useSession(%s)", GetSessionIdString(sessionId).string()); Mutex::Autolock lock(mLock); for (size_t i = 0; i < mSessionMap.size(); ++i) { SessionInfos& infos = mSessionMap.editValueAt(i); for (size_t j = 0; j < infos.size(); ++j) { SessionInfo& info = infos.editItemAt(j); if (isEqualSessionId(sessionId, info.sessionId)) { info.timeStamp = getTime_l(); auto it = mSessionMap.find(toStdVec(sessionId)); if (mService == NULL || it == mSessionMap.end()) { return; } } } auto info = it->second; mService->addResource(info.pid, info.uid, info.clientId, NULL, toResourceVec(sessionId)); } void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) { ALOGV("removeSession(%s)", GetSessionIdString(sessionId).string()); Mutex::Autolock lock(mLock); for (size_t i = 0; i < mSessionMap.size(); ++i) { SessionInfos& infos = mSessionMap.editValueAt(i); for (size_t j = 0; j < infos.size(); ++j) { if (isEqualSessionId(sessionId, infos[j].sessionId)) { infos.removeAt(j); auto it = mSessionMap.find(toStdVec(sessionId)); if (mService == NULL || it == mSessionMap.end()) { return; } } } } void DrmSessionManager::removeDrm(const sp<DrmSessionClientInterface>& drm) { ALOGV("removeDrm(%p)", drm.get()); Mutex::Autolock lock(mLock); bool found = false; for (size_t i = 0; i < mSessionMap.size(); ++i) { SessionInfos& infos = mSessionMap.editValueAt(i); for (size_t j = 0; j < infos.size();) { if (infos[j].drm == drm) { ALOGV("removed session (%s)", GetSessionIdString(infos[j].sessionId).string()); j = infos.removeAt(j); found = true; } else { ++j; } } if (found) { break; } } auto info = it->second; mService->removeResource(info.pid, info.clientId, toResourceVec(sessionId)); mSessionMap.erase(it); } bool DrmSessionManager::reclaimSession(int callingPid) { ALOGV("reclaimSession(%d)", callingPid); sp<DrmSessionClientInterface> drm; Vector<uint8_t> sessionId; int lowestPriorityPid; int lowestPriority; { Mutex::Autolock lock(mLock); int callingPriority; if (!mProcessInfo->getPriority(callingPid, &callingPriority)) { return false; } if (!getLowestPriority_l(&lowestPriorityPid, &lowestPriority)) { return false; } if (lowestPriority <= callingPriority) { return false; } if (!getLeastUsedSession_l(lowestPriorityPid, &drm, &sessionId)) { return false; } } // unlock early because reclaimResource might callback into removeSession mLock.lock(); sp<IResourceManagerService> service(mService); mLock.unlock(); if (drm == NULL) { if (service == NULL) { return false; } ALOGV("reclaim session(%s) opened by pid %d", GetSessionIdString(sessionId).string(), lowestPriorityPid); return drm->reclaimSession(sessionId); // cannot update mSessionMap because we do not know which sessionId is reclaimed; // we rely on IResourceManagerClient to removeSession in reclaimResource Vector<uint8_t> dummy; return service->reclaimResource(callingPid, toResourceVec(dummy)); } int64_t DrmSessionManager::getTime_l() { return mTime++; } bool DrmSessionManager::getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority) { int pid = -1; int priority = -1; for (size_t i = 0; i < mSessionMap.size(); ++i) { if (mSessionMap.valueAt(i).size() == 0) { // no opened session by this process. continue; } int tempPid = mSessionMap.keyAt(i); int tempPriority; if (!mProcessInfo->getPriority(tempPid, &tempPriority)) { // shouldn't happen. return false; } if (pid == -1) { pid = tempPid; priority = tempPriority; } else { if (tempPriority > priority) { pid = tempPid; priority = tempPriority; } } } if (pid != -1) { *lowestPriorityPid = pid; *lowestPriority = priority; } return (pid != -1); size_t DrmSessionManager::getSessionCount() const { Mutex::Autolock lock(mLock); return mSessionMap.size(); } bool DrmSessionManager::getLeastUsedSession_l( int pid, sp<DrmSessionClientInterface>* drm, Vector<uint8_t>* sessionId) { ssize_t index = mSessionMap.indexOfKey(pid); if (index < 0) { return false; bool DrmSessionManager::containsSession(const Vector<uint8_t>& sessionId) const { Mutex::Autolock lock(mLock); return mSessionMap.count(toStdVec(sessionId)); } int leastUsedIndex = -1; int64_t minTs = LLONG_MAX; const SessionInfos& infos = mSessionMap.valueAt(index); for (size_t j = 0; j < infos.size(); ++j) { if (leastUsedIndex == -1) { leastUsedIndex = j; minTs = infos[j].timeStamp; } else { if (infos[j].timeStamp < minTs) { leastUsedIndex = j; minTs = infos[j].timeStamp; } } } if (leastUsedIndex != -1) { *drm = infos[leastUsedIndex].drm; *sessionId = infos[leastUsedIndex].sessionId; } return (leastUsedIndex != -1); void DrmSessionManager::binderDied(const wp<IBinder>& /*who*/) { ALOGW("ResourceManagerService died."); Mutex::Autolock lock(mLock); mService.clear(); } } // namespace android
drm/libmediadrm/include/mediadrm/DrmHal.h +23 −3 Original line number Diff line number Diff line Loading @@ -26,8 +26,10 @@ #include <android/hardware/drm/1.2/IDrmPlugin.h> #include <android/hardware/drm/1.2/IDrmPluginListener.h> #include <media/IResourceManagerService.h> #include <media/MediaAnalyticsItem.h> #include <mediadrm/DrmMetrics.h> #include <mediadrm/DrmSessionManager.h> #include <mediadrm/IDrm.h> #include <mediadrm/IDrmClient.h> #include <utils/threads.h> Loading Loading @@ -59,6 +61,26 @@ inline bool operator==(const Vector<uint8_t> &l, const Vector<uint8_t> &r) { struct DrmHal : public BnDrm, public IBinder::DeathRecipient, public IDrmPluginListener_V1_2 { struct DrmSessionClient : public BnResourceManagerClient { explicit DrmSessionClient(DrmHal* drm, const Vector<uint8_t>& sessionId) : mSessionId(sessionId), mDrm(drm) {} virtual bool reclaimResource(); virtual String8 getName(); const Vector<uint8_t> mSessionId; protected: virtual ~DrmSessionClient(); private: wp<DrmHal> mDrm; DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient); }; DrmHal(); virtual ~DrmHal(); Loading Loading @@ -193,8 +215,6 @@ struct DrmHal : public BnDrm, private: static Mutex mLock; sp<DrmSessionClientInterface> mDrmSessionClient; sp<IDrmClient> mListener; mutable Mutex mEventLock; mutable Mutex mNotifyLock; Loading @@ -208,7 +228,7 @@ private: // Mutable to allow modification within GetPropertyByteArray. mutable MediaDrmMetrics mMetrics; Vector<Vector<uint8_t>> mOpenSessions; Vector<sp<DrmSessionClient>> mOpenSessions; void closeOpenSessions(); void cleanup(); Loading
drm/libmediadrm/include/mediadrm/DrmSessionManager.h +25 −20 Original line number Diff line number Diff line Loading @@ -18,56 +18,61 @@ #define DRM_SESSION_MANAGER_H_ #include <binder/IBinder.h> #include <media/IResourceManagerService.h> #include <media/stagefright/foundation/ABase.h> #include <utils/RefBase.h> #include <utils/KeyedVector.h> #include <utils/threads.h> #include <utils/Vector.h> #include <map> #include <utility> #include <vector> namespace android { class DrmSessionManagerTest; struct DrmSessionClientInterface; struct ProcessInfoInterface; class IResourceManagerClient; bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2); struct SessionInfo { sp<DrmSessionClientInterface> drm; Vector<uint8_t> sessionId; int64_t timeStamp; pid_t pid; uid_t uid; int64_t clientId; }; typedef Vector<SessionInfo > SessionInfos; typedef KeyedVector<int, SessionInfos > PidSessionInfosMap; typedef std::map<std::vector<uint8_t>, SessionInfo> SessionInfoMap; struct DrmSessionManager : public RefBase { struct DrmSessionManager : public IBinder::DeathRecipient { static sp<DrmSessionManager> Instance(); DrmSessionManager(); explicit DrmSessionManager(sp<ProcessInfoInterface> processInfo); explicit DrmSessionManager(const sp<IResourceManagerService> &service); void addSession(int pid, const sp<DrmSessionClientInterface>& drm, const Vector<uint8_t>& sessionId); void addSession(int pid, const sp<IResourceManagerClient>& drm, const Vector<uint8_t>& sessionId); void useSession(const Vector<uint8_t>& sessionId); void removeSession(const Vector<uint8_t>& sessionId); void removeDrm(const sp<DrmSessionClientInterface>& drm); bool reclaimSession(int callingPid); // sanity check APIs size_t getSessionCount() const; bool containsSession(const Vector<uint8_t>& sessionId) const; // implements DeathRecipient virtual void binderDied(const wp<IBinder>& /*who*/); protected: virtual ~DrmSessionManager(); private: friend class DrmSessionManagerTest; int64_t getTime_l(); bool getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority); bool getLeastUsedSession_l( int pid, sp<DrmSessionClientInterface>* drm, Vector<uint8_t>* sessionId); void init(); sp<ProcessInfoInterface> mProcessInfo; sp<IResourceManagerService> mService; mutable Mutex mLock; PidSessionInfosMap mSessionMap; int64_t mTime; SessionInfoMap mSessionMap; bool mInitialized; DISALLOW_EVIL_CONSTRUCTORS(DrmSessionManager); }; Loading