DrmManager: locally aggregate API metrics

Aggregate DrmManager API invocation counts per plugin over at least
fixed period of time before sending metrics to mediametrics service.

The default period is 1 day; the period is configurable through the
property drmmanager.metrics.period.

Bug: 134789967
Test: dumpsys media.metrics
Change-Id: I2cf28f1dfaa485ca319360705b872eed995b3d7f
This commit is contained in:
Robert Shih
2020-02-07 15:01:57 -08:00
parent 93fb84c8d5
commit 7bcf792dd8
5 changed files with 179 additions and 42 deletions

View File

@@ -26,11 +26,13 @@ cc_binary {
shared_libs: [ shared_libs: [
"libmedia", "libmedia",
"libmediametrics", "libmediametrics",
"libcutils",
"libutils", "libutils",
"liblog", "liblog",
"libbinder", "libbinder",
"libdl", "libdl",
"libselinux", "libselinux",
"libstagefright_foundation",
], ],
static_libs: ["libdrmframeworkcommon"], static_libs: ["libdrmframeworkcommon"],

View File

@@ -16,9 +16,10 @@
//#define LOG_NDEBUG 0 //#define LOG_NDEBUG 0
#define LOG_TAG "DrmManager(Native)" #define LOG_TAG "DrmManager(Native)"
#include "utils/Log.h"
#include <cutils/properties.h>
#include <utils/String8.h> #include <utils/String8.h>
#include <utils/Log.h>
#include <binder/IPCThreadState.h> #include <binder/IPCThreadState.h>
#include <drm/DrmInfo.h> #include <drm/DrmInfo.h>
@@ -37,12 +38,30 @@
#include "DrmManager.h" #include "DrmManager.h"
#include "ReadWriteUtils.h" #include "ReadWriteUtils.h"
#include <algorithm>
#define DECRYPT_FILE_ERROR (-1) #define DECRYPT_FILE_ERROR (-1)
using namespace android; using namespace android;
const String8 DrmManager::EMPTY_STRING(""); const String8 DrmManager::EMPTY_STRING("");
const std::map<const char*, size_t> DrmManager::kMethodIdMap {
{"getConstraints" , DrmManagerMethodId::GET_CONSTRAINTS },
{"getMetadata" , DrmManagerMethodId::GET_METADATA },
{"canHandle" , DrmManagerMethodId::CAN_HANDLE },
{"processDrmInfo" , DrmManagerMethodId::PROCESS_DRM_INFO },
{"acquireDrmInfo" , DrmManagerMethodId::ACQUIRE_DRM_INFO },
{"saveRights" , DrmManagerMethodId::SAVE_RIGHTS },
{"getOriginalMimeType", DrmManagerMethodId::GET_ORIGINAL_MIME_TYPE},
{"getDrmObjectType" , DrmManagerMethodId::GET_DRM_OBJECT_TYPE },
{"checkRightsStatus" , DrmManagerMethodId::CHECK_RIGHTS_STATUS },
{"removeRights" , DrmManagerMethodId::REMOVE_RIGHTS },
{"removeAllRights" , DrmManagerMethodId::REMOVE_ALL_RIGHTS },
{"openConvertSession" , DrmManagerMethodId::OPEN_CONVERT_SESSION },
{"openDecryptSession" , DrmManagerMethodId::OPEN_DECRYPT_SESSION }
};
DrmManager::DrmManager() : DrmManager::DrmManager() :
mDecryptSessionId(0), mDecryptSessionId(0),
mConvertId(0) { mConvertId(0) {
@@ -51,41 +70,105 @@ DrmManager::DrmManager() :
} }
DrmManager::~DrmManager() { DrmManager::~DrmManager() {
if (mMetricsLooper != NULL) {
mMetricsLooper->stop();
}
flushEngineMetrics();
} }
void DrmManager::reportEngineMetrics( void DrmManager::initMetricsLooper() {
const char func[], const String8& plugInId, const String8& mimeType) { if (mMetricsLooper != NULL) {
IDrmEngine& engine = mPlugInManager.getPlugIn(plugInId); return;
}
mMetricsLooper = new ALooper;
mMetricsLooper->setName("DrmManagerMetricsLooper");
mMetricsLooper->start();
mMetricsLooper->registerHandler(this);
std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create("drmmanager")); sp<AMessage> msg = new AMessage(kWhatFlushMetrics, this);
item->setUid(IPCThreadState::self()->getCallingUid()); msg->post(getMetricsFlushPeriodUs());
item->setCString("function_name", func); }
item->setCString("plugin_id", plugInId.getPathLeaf().getBasePath().c_str());
void DrmManager::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatFlushMetrics:
{
flushEngineMetrics();
msg->post(getMetricsFlushPeriodUs());
break;
}
default:
{
ALOGW("Unrecognized message type: %zd", msg->what());
}
}
}
int64_t DrmManager::getMetricsFlushPeriodUs() {
return 1000 * 1000 * std::max(1ll, property_get_int64("drmmanager.metrics.period", 86400));
}
void DrmManager::recordEngineMetrics(
const char func[], const String8& plugInId8, const String8& mimeType) {
IDrmEngine& engine = mPlugInManager.getPlugIn(plugInId8);
std::unique_ptr<DrmSupportInfo> info(engine.getSupportInfo(0)); std::unique_ptr<DrmSupportInfo> info(engine.getSupportInfo(0));
uid_t callingUid = IPCThreadState::self()->getCallingUid();
std::string plugInId(plugInId8.getPathLeaf().getBasePath().c_str());
ALOGV("%d calling %s %s", callingUid, plugInId.c_str(), func);
Mutex::Autolock _l(mMetricsLock);
auto& metrics = mPluginMetrics[std::make_pair(callingUid, plugInId)];
if (metrics.mPluginId.empty()) {
metrics.mPluginId = plugInId;
metrics.mCallingUid = callingUid;
if (NULL != info) { if (NULL != info) {
item->setCString("description", info->getDescription().c_str()); metrics.mDescription = info->getDescription().c_str();
}
} }
if (!mimeType.isEmpty()) { if (!mimeType.isEmpty()) {
item->setCString("mime_types", mimeType.c_str()); metrics.mMimeTypes.insert(mimeType.c_str());
} else if (NULL != info) { } else if (NULL != info) {
DrmSupportInfo::MimeTypeIterator mimeIter = info->getMimeTypeIterator(); DrmSupportInfo::MimeTypeIterator mimeIter = info->getMimeTypeIterator();
String8 mimes;
while (mimeIter.hasNext()) { while (mimeIter.hasNext()) {
mimes += mimeIter.next(); metrics.mMimeTypes.insert(mimeIter.next().c_str());
if (mimeIter.hasNext()) {
mimes += ",";
} }
} }
item->setCString("mime_types", mimes.c_str());
size_t methodId = kMethodIdMap.at(func);
if (methodId < metrics.mMethodCounts.size()) {
metrics.mMethodCounts[methodId]++;
}
}
void DrmManager::flushEngineMetrics() {
using namespace std::string_literals;
Mutex::Autolock _l(mMetricsLock);
for (auto kv : mPluginMetrics) {
DrmManagerMetrics& metrics = kv.second;
std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create("drmmanager"));
item->setUid(metrics.mCallingUid);
item->setCString("plugin_id", metrics.mPluginId.c_str());
item->setCString("description", metrics.mDescription.c_str());
std::vector<std::string> mimeTypes(metrics.mMimeTypes.begin(), metrics.mMimeTypes.end());
std::string mimeTypesStr(mimeTypes.empty() ? "" : mimeTypes[0]);
for (size_t i = 1; i < mimeTypes.size() ; i++) {
mimeTypesStr.append(",").append(mimeTypes[i]);
}
item->setCString("mime_types", mimeTypesStr.c_str());
for (size_t i = 0; i < metrics.mMethodCounts.size() ; i++) {
item->setInt64(("method"s + std::to_string(i)).c_str(), metrics.mMethodCounts[i]);
} }
if (!item->selfrecord()) { if (!item->selfrecord()) {
ALOGE("Failed to record metrics"); ALOGE("Failed to record metrics");
} }
} }
mPluginMetrics.clear();
}
int DrmManager::addUniqueId(bool isNative) { int DrmManager::addUniqueId(bool isNative) {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
@@ -184,7 +267,6 @@ void DrmManager::removeClient(int uniqueId) {
for (size_t index = 0; index < plugInIdList.size(); index++) { for (size_t index = 0; index < plugInIdList.size(); index++) {
IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index)); IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
rDrmEngine.terminate(uniqueId); rDrmEngine.terminate(uniqueId);
reportEngineMetrics(__func__, plugInIdList[index]);
} }
} }
@@ -197,7 +279,7 @@ DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, co
constraints = rDrmEngine.getConstraints(uniqueId, path, action); constraints = rDrmEngine.getConstraints(uniqueId, path, action);
} }
if (NULL != constraints) { if (NULL != constraints) {
reportEngineMetrics(__func__, plugInId); recordEngineMetrics(__func__, plugInId);
} }
return constraints; return constraints;
} }
@@ -211,7 +293,7 @@ DrmMetadata* DrmManager::getMetadata(int uniqueId, const String8* path) {
meta = rDrmEngine.getMetadata(uniqueId, path); meta = rDrmEngine.getMetadata(uniqueId, path);
} }
if (NULL != meta) { if (NULL != meta) {
reportEngineMetrics(__func__, plugInId); recordEngineMetrics(__func__, plugInId);
} }
return meta; return meta;
} }
@@ -222,7 +304,7 @@ bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mim
bool result = (EMPTY_STRING != plugInId) ? true : false; bool result = (EMPTY_STRING != plugInId) ? true : false;
if (result) { if (result) {
reportEngineMetrics(__func__, plugInId, mimeType); recordEngineMetrics(__func__, plugInId, mimeType);
} }
if (0 < path.length()) { if (0 < path.length()) {
@@ -249,7 +331,7 @@ DrmInfoStatus* DrmManager::processDrmInfo(int uniqueId, const DrmInfo* drmInfo)
infoStatus = rDrmEngine.processDrmInfo(uniqueId, drmInfo); infoStatus = rDrmEngine.processDrmInfo(uniqueId, drmInfo);
} }
if (NULL != infoStatus) { if (NULL != infoStatus) {
reportEngineMetrics(__func__, plugInId, mimeType); recordEngineMetrics(__func__, plugInId, mimeType);
} }
return infoStatus; return infoStatus;
} }
@@ -263,7 +345,7 @@ bool DrmManager::canHandle(int uniqueId, const String8& path) {
result = rDrmEngine.canHandle(uniqueId, path); result = rDrmEngine.canHandle(uniqueId, path);
if (result) { if (result) {
reportEngineMetrics(__func__, plugInPathList[i]); recordEngineMetrics(__func__, plugInPathList[i]);
break; break;
} }
} }
@@ -280,7 +362,7 @@ DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoR
info = rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest); info = rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
} }
if (NULL != info) { if (NULL != info) {
reportEngineMetrics(__func__, plugInId, mimeType); recordEngineMetrics(__func__, plugInId, mimeType);
} }
return info; return info;
} }
@@ -296,7 +378,7 @@ status_t DrmManager::saveRights(int uniqueId, const DrmRights& drmRights,
result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath); result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath);
} }
if (DRM_NO_ERROR == result) { if (DRM_NO_ERROR == result) {
reportEngineMetrics(__func__, plugInId, mimeType); recordEngineMetrics(__func__, plugInId, mimeType);
} }
return result; return result;
} }
@@ -310,7 +392,7 @@ String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path, int f
mimeType = rDrmEngine.getOriginalMimeType(uniqueId, path, fd); mimeType = rDrmEngine.getOriginalMimeType(uniqueId, path, fd);
} }
if (!mimeType.isEmpty()) { if (!mimeType.isEmpty()) {
reportEngineMetrics(__func__, plugInId, mimeType); recordEngineMetrics(__func__, plugInId, mimeType);
} }
return mimeType; return mimeType;
} }
@@ -324,7 +406,7 @@ int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String
type = rDrmEngine.getDrmObjectType(uniqueId, path, mimeType); type = rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
} }
if (DrmObjectType::UNKNOWN != type) { if (DrmObjectType::UNKNOWN != type) {
reportEngineMetrics(__func__, plugInId, mimeType); recordEngineMetrics(__func__, plugInId, mimeType);
} }
return type; return type;
} }
@@ -338,7 +420,7 @@ int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action)
rightsStatus = rDrmEngine.checkRightsStatus(uniqueId, path, action); rightsStatus = rDrmEngine.checkRightsStatus(uniqueId, path, action);
} }
if (RightsStatus::RIGHTS_INVALID != rightsStatus) { if (RightsStatus::RIGHTS_INVALID != rightsStatus) {
reportEngineMetrics(__func__, plugInId); recordEngineMetrics(__func__, plugInId);
} }
return rightsStatus; return rightsStatus;
} }
@@ -385,7 +467,7 @@ status_t DrmManager::removeRights(int uniqueId, const String8& path) {
result = rDrmEngine.removeRights(uniqueId, path); result = rDrmEngine.removeRights(uniqueId, path);
} }
if (DRM_NO_ERROR == result) { if (DRM_NO_ERROR == result) {
reportEngineMetrics(__func__, plugInId); recordEngineMetrics(__func__, plugInId);
} }
return result; return result;
} }
@@ -399,7 +481,7 @@ status_t DrmManager::removeAllRights(int uniqueId) {
if (DRM_NO_ERROR != result) { if (DRM_NO_ERROR != result) {
break; break;
} }
reportEngineMetrics(__func__, plugInIdList[index]); recordEngineMetrics(__func__, plugInIdList[index]);
} }
return result; return result;
} }
@@ -416,7 +498,7 @@ int DrmManager::openConvertSession(int uniqueId, const String8& mimeType) {
++mConvertId; ++mConvertId;
convertId = mConvertId; convertId = mConvertId;
mConvertSessionMap.add(convertId, &rDrmEngine); mConvertSessionMap.add(convertId, &rDrmEngine);
reportEngineMetrics(__func__, plugInId, mimeType); recordEngineMetrics(__func__, plugInId, mimeType);
} }
} }
return convertId; return convertId;
@@ -497,7 +579,7 @@ sp<DecryptHandle> DrmManager::openDecryptSession(
if (DRM_NO_ERROR == result) { if (DRM_NO_ERROR == result) {
++mDecryptSessionId; ++mDecryptSessionId;
mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine); mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
reportEngineMetrics(__func__, plugInId, String8(mime)); recordEngineMetrics(__func__, plugInId, String8(mime));
break; break;
} }
} }
@@ -526,7 +608,7 @@ sp<DecryptHandle> DrmManager::openDecryptSession(
if (DRM_NO_ERROR == result) { if (DRM_NO_ERROR == result) {
++mDecryptSessionId; ++mDecryptSessionId;
mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine); mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
reportEngineMetrics(__func__, plugInId, String8(mime)); recordEngineMetrics(__func__, plugInId, String8(mime));
break; break;
} }
} }
@@ -556,7 +638,7 @@ sp<DecryptHandle> DrmManager::openDecryptSession(
if (DRM_NO_ERROR == result) { if (DRM_NO_ERROR == result) {
++mDecryptSessionId; ++mDecryptSessionId;
mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine); mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
reportEngineMetrics(__func__, plugInId, mimeType); recordEngineMetrics(__func__, plugInId, mimeType);
break; break;
} }
} }

View File

@@ -17,13 +17,26 @@
#ifndef __DRM_MANAGER_H__ #ifndef __DRM_MANAGER_H__
#define __DRM_MANAGER_H__ #define __DRM_MANAGER_H__
#include <drm/drm_framework_common.h>
#include <media/stagefright/foundation/AHandler.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include <sys/types.h>
#include <utils/Errors.h> #include <utils/Errors.h>
#include <utils/threads.h> #include <utils/threads.h>
#include <drm/drm_framework_common.h>
#include "IDrmEngine.h" #include "IDrmEngine.h"
#include "PlugInManager.h" #include "PlugInManager.h"
#include "IDrmServiceListener.h" #include "IDrmServiceListener.h"
#include <array>
#include <cstddef>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>
namespace android { namespace android {
class IDrmManager; class IDrmManager;
@@ -40,6 +53,31 @@ class DrmInfoRequest;
class DrmSupportInfo; class DrmSupportInfo;
class ActionDescription; class ActionDescription;
enum DrmManagerMethodId {
GET_CONSTRAINTS,
GET_METADATA,
CAN_HANDLE,
PROCESS_DRM_INFO,
ACQUIRE_DRM_INFO,
SAVE_RIGHTS,
GET_ORIGINAL_MIME_TYPE,
GET_DRM_OBJECT_TYPE,
CHECK_RIGHTS_STATUS,
REMOVE_RIGHTS,
REMOVE_ALL_RIGHTS,
OPEN_CONVERT_SESSION,
OPEN_DECRYPT_SESSION,
NUM_METHODS,
};
struct DrmManagerMetrics {
std::string mPluginId;
std::string mDescription;
std::set<std::string> mMimeTypes;
std::array<int64_t, DrmManagerMethodId::NUM_METHODS> mMethodCounts{};
uid_t mCallingUid;
};
/** /**
* This is implementation class for DRM Manager. This class delegates the * This is implementation class for DRM Manager. This class delegates the
* functionality to corresponding DRM Engine. * functionality to corresponding DRM Engine.
@@ -47,7 +85,7 @@ class ActionDescription;
* The DrmManagerService class creates an instance of this class. * The DrmManagerService class creates an instance of this class.
* *
*/ */
class DrmManager : public IDrmEngine::OnInfoListener { class DrmManager : public AHandler, public IDrmEngine::OnInfoListener {
public: public:
DrmManager(); DrmManager();
virtual ~DrmManager(); virtual ~DrmManager();
@@ -134,6 +172,8 @@ public:
void onInfo(const DrmInfoEvent& event); void onInfo(const DrmInfoEvent& event);
void initMetricsLooper();
private: private:
String8 getSupportedPlugInId(int uniqueId, const String8& path, const String8& mimeType); String8 getSupportedPlugInId(int uniqueId, const String8& path, const String8& mimeType);
@@ -143,16 +183,24 @@ private:
bool canHandle(int uniqueId, const String8& path); bool canHandle(int uniqueId, const String8& path);
void reportEngineMetrics(const char func[], void onMessageReceived(const sp<AMessage> &msg);
int64_t getMetricsFlushPeriodUs();
void recordEngineMetrics(const char func[],
const String8& plugInId, const String8& mimeType = String8("")); const String8& plugInId, const String8& mimeType = String8(""));
void flushEngineMetrics();
private: private:
enum { enum {
kMaxNumUniqueIds = 0x1000, kMaxNumUniqueIds = 0x1000,
kWhatFlushMetrics = 'metr',
}; };
bool mUniqueIdArray[kMaxNumUniqueIds]; bool mUniqueIdArray[kMaxNumUniqueIds];
static const String8 EMPTY_STRING; static const String8 EMPTY_STRING;
static const std::map<const char*, size_t> kMethodIdMap;
int mDecryptSessionId; int mDecryptSessionId;
int mConvertId; int mConvertId;
@@ -160,11 +208,15 @@ private:
Mutex mListenerLock; Mutex mListenerLock;
Mutex mDecryptLock; Mutex mDecryptLock;
Mutex mConvertLock; Mutex mConvertLock;
Mutex mMetricsLock;
TPlugInManager<IDrmEngine> mPlugInManager; TPlugInManager<IDrmEngine> mPlugInManager;
KeyedVector< DrmSupportInfo, String8 > mSupportInfoToPlugInIdMap; KeyedVector< DrmSupportInfo, String8 > mSupportInfoToPlugInIdMap;
KeyedVector< int, IDrmEngine*> mConvertSessionMap; KeyedVector< int, IDrmEngine*> mConvertSessionMap;
KeyedVector< int, sp<IDrmServiceListener> > mServiceListeners; KeyedVector< int, sp<IDrmServiceListener> > mServiceListeners;
KeyedVector< int, IDrmEngine*> mDecryptSessionMap; KeyedVector< int, IDrmEngine*> mDecryptSessionMap;
std::map<std::pair<uid_t, std::string>, DrmManagerMetrics> mPluginMetrics;
sp<ALooper> mMetricsLooper;
}; };
}; };

View File

@@ -130,13 +130,14 @@ DrmManagerService::DrmManagerService() :
mDrmManager(NULL) { mDrmManager(NULL) {
ALOGV("created"); ALOGV("created");
mDrmManager = new DrmManager(); mDrmManager = new DrmManager();
mDrmManager->initMetricsLooper();
mDrmManager->loadPlugIns(); mDrmManager->loadPlugIns();
} }
DrmManagerService::~DrmManagerService() { DrmManagerService::~DrmManagerService() {
ALOGV("Destroyed"); ALOGV("Destroyed");
mDrmManager->unloadPlugIns(); mDrmManager->unloadPlugIns();
delete mDrmManager; mDrmManager = NULL; mDrmManager = NULL;
} }
int DrmManagerService::addUniqueId(bool isNative) { int DrmManagerService::addUniqueId(bool isNative) {

View File

@@ -142,7 +142,7 @@ public:
virtual status_t dump(int fd, const Vector<String16>& args); virtual status_t dump(int fd, const Vector<String16>& args);
private: private:
DrmManager* mDrmManager; sp<DrmManager> mDrmManager;
}; };
}; };