Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86f5034e authored by Robert Shih's avatar Robert Shih Committed by Android (Google) Code Review
Browse files

Merge "DrmManager: locally aggregate API metrics"

parents 0f97ee5a 7bcf792d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -26,11 +26,13 @@ cc_binary {
    shared_libs: [
        "libmedia",
        "libmediametrics",
        "libcutils",
        "libutils",
        "liblog",
        "libbinder",
        "libdl",
        "libselinux",
        "libstagefright_foundation",
    ],

    static_libs: ["libdrmframeworkcommon"],
+118 −36
Original line number Diff line number Diff line
@@ -16,9 +16,10 @@

//#define LOG_NDEBUG 0
#define LOG_TAG "DrmManager(Native)"
#include "utils/Log.h"

#include <cutils/properties.h>
#include <utils/String8.h>
#include <utils/Log.h>

#include <binder/IPCThreadState.h>
#include <drm/DrmInfo.h>
@@ -37,12 +38,30 @@
#include "DrmManager.h"
#include "ReadWriteUtils.h"

#include <algorithm>

#define DECRYPT_FILE_ERROR (-1)

using namespace android;

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() :
    mDecryptSessionId(0),
    mConvertId(0) {
@@ -51,41 +70,105 @@ DrmManager::DrmManager() :
}

DrmManager::~DrmManager() {
    if (mMetricsLooper != NULL) {
        mMetricsLooper->stop();
    }
    flushEngineMetrics();
}

void DrmManager::initMetricsLooper() {
    if (mMetricsLooper != NULL) {
        return;
    }
    mMetricsLooper = new ALooper;
    mMetricsLooper->setName("DrmManagerMetricsLooper");
    mMetricsLooper->start();
    mMetricsLooper->registerHandler(this);

void DrmManager::reportEngineMetrics(
        const char func[], const String8& plugInId, const String8& mimeType) {
    IDrmEngine& engine = mPlugInManager.getPlugIn(plugInId);
    sp<AMessage> msg = new AMessage(kWhatFlushMetrics, this);
    msg->post(getMetricsFlushPeriodUs());
}

    std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create("drmmanager"));
    item->setUid(IPCThreadState::self()->getCallingUid());
    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));

    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) {
        item->setCString("description", info->getDescription().c_str());
            metrics.mDescription = info->getDescription().c_str();
        }
    }

    if (!mimeType.isEmpty()) {
        item->setCString("mime_types", mimeType.c_str());
        metrics.mMimeTypes.insert(mimeType.c_str());
    } else if (NULL != info) {
        DrmSupportInfo::MimeTypeIterator mimeIter = info->getMimeTypeIterator();
        String8 mimes;
        while (mimeIter.hasNext()) {
            mimes += mimeIter.next();
            if (mimeIter.hasNext()) {
                mimes += ",";
            metrics.mMimeTypes.insert(mimeIter.next().c_str());
        }
    }

    size_t methodId = kMethodIdMap.at(func);
    if (methodId < metrics.mMethodCounts.size()) {
        metrics.mMethodCounts[methodId]++;
    }
}
        item->setCString("mime_types", mimes.c_str());

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()) {
            ALOGE("Failed to record metrics");
        }
    }
    mPluginMetrics.clear();
}

int DrmManager::addUniqueId(bool isNative) {
    Mutex::Autolock _l(mLock);
@@ -184,7 +267,6 @@ void DrmManager::removeClient(int uniqueId) {
    for (size_t index = 0; index < plugInIdList.size(); index++) {
        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
        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);
    }
    if (NULL != constraints) {
        reportEngineMetrics(__func__, plugInId);
        recordEngineMetrics(__func__, plugInId);
    }
    return constraints;
}
@@ -211,7 +293,7 @@ DrmMetadata* DrmManager::getMetadata(int uniqueId, const String8* path) {
        meta = rDrmEngine.getMetadata(uniqueId, path);
    }
    if (NULL != meta) {
        reportEngineMetrics(__func__, plugInId);
        recordEngineMetrics(__func__, plugInId);
    }
    return meta;
}
@@ -222,7 +304,7 @@ bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mim
    bool result = (EMPTY_STRING != plugInId) ? true : false;

    if (result) {
        reportEngineMetrics(__func__, plugInId, mimeType);
        recordEngineMetrics(__func__, plugInId, mimeType);
    }

    if (0 < path.length()) {
@@ -249,7 +331,7 @@ DrmInfoStatus* DrmManager::processDrmInfo(int uniqueId, const DrmInfo* drmInfo)
        infoStatus = rDrmEngine.processDrmInfo(uniqueId, drmInfo);
    }
    if (NULL != infoStatus) {
        reportEngineMetrics(__func__, plugInId, mimeType);
        recordEngineMetrics(__func__, plugInId, mimeType);
    }
    return infoStatus;
}
@@ -263,7 +345,7 @@ bool DrmManager::canHandle(int uniqueId, const String8& path) {
        result = rDrmEngine.canHandle(uniqueId, path);

        if (result) {
            reportEngineMetrics(__func__, plugInPathList[i]);
            recordEngineMetrics(__func__, plugInPathList[i]);
            break;
        }
    }
@@ -280,7 +362,7 @@ DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoR
        info = rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
    }
    if (NULL != info) {
        reportEngineMetrics(__func__, plugInId, mimeType);
        recordEngineMetrics(__func__, plugInId, mimeType);
    }
    return info;
}
@@ -296,7 +378,7 @@ status_t DrmManager::saveRights(int uniqueId, const DrmRights& drmRights,
        result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath);
    }
    if (DRM_NO_ERROR == result) {
        reportEngineMetrics(__func__, plugInId, mimeType);
        recordEngineMetrics(__func__, plugInId, mimeType);
    }
    return result;
}
@@ -310,7 +392,7 @@ String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path, int f
        mimeType = rDrmEngine.getOriginalMimeType(uniqueId, path, fd);
    }
    if (!mimeType.isEmpty()) {
        reportEngineMetrics(__func__, plugInId, mimeType);
        recordEngineMetrics(__func__, plugInId, mimeType);
    }
    return mimeType;
}
@@ -324,7 +406,7 @@ int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String
        type = rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
    }
    if (DrmObjectType::UNKNOWN != type) {
        reportEngineMetrics(__func__, plugInId, mimeType);
        recordEngineMetrics(__func__, plugInId, mimeType);
    }
    return type;
}
@@ -338,7 +420,7 @@ int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action)
        rightsStatus = rDrmEngine.checkRightsStatus(uniqueId, path, action);
    }
    if (RightsStatus::RIGHTS_INVALID != rightsStatus) {
        reportEngineMetrics(__func__, plugInId);
        recordEngineMetrics(__func__, plugInId);
    }
    return rightsStatus;
}
@@ -385,7 +467,7 @@ status_t DrmManager::removeRights(int uniqueId, const String8& path) {
        result = rDrmEngine.removeRights(uniqueId, path);
    }
    if (DRM_NO_ERROR == result) {
        reportEngineMetrics(__func__, plugInId);
        recordEngineMetrics(__func__, plugInId);
    }
    return result;
}
@@ -399,7 +481,7 @@ status_t DrmManager::removeAllRights(int uniqueId) {
        if (DRM_NO_ERROR != result) {
            break;
        }
        reportEngineMetrics(__func__, plugInIdList[index]);
        recordEngineMetrics(__func__, plugInIdList[index]);
    }
    return result;
}
@@ -416,7 +498,7 @@ int DrmManager::openConvertSession(int uniqueId, const String8& mimeType) {
            ++mConvertId;
            convertId = mConvertId;
            mConvertSessionMap.add(convertId, &rDrmEngine);
            reportEngineMetrics(__func__, plugInId, mimeType);
            recordEngineMetrics(__func__, plugInId, mimeType);
        }
    }
    return convertId;
@@ -497,7 +579,7 @@ sp<DecryptHandle> DrmManager::openDecryptSession(
            if (DRM_NO_ERROR == result) {
                ++mDecryptSessionId;
                mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
                reportEngineMetrics(__func__, plugInId, String8(mime));
                recordEngineMetrics(__func__, plugInId, String8(mime));
                break;
            }
        }
@@ -526,7 +608,7 @@ sp<DecryptHandle> DrmManager::openDecryptSession(
            if (DRM_NO_ERROR == result) {
                ++mDecryptSessionId;
                mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
                reportEngineMetrics(__func__, plugInId, String8(mime));
                recordEngineMetrics(__func__, plugInId, String8(mime));
                break;
            }
        }
@@ -556,7 +638,7 @@ sp<DecryptHandle> DrmManager::openDecryptSession(
            if (DRM_NO_ERROR == result) {
                ++mDecryptSessionId;
                mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
                reportEngineMetrics(__func__, plugInId, mimeType);
                recordEngineMetrics(__func__, plugInId, mimeType);
                break;
            }
        }
+55 −3
Original line number Diff line number Diff line
@@ -17,13 +17,26 @@
#ifndef __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/threads.h>
#include <drm/drm_framework_common.h>

#include "IDrmEngine.h"
#include "PlugInManager.h"
#include "IDrmServiceListener.h"

#include <array>
#include <cstddef>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>

namespace android {

class IDrmManager;
@@ -40,6 +53,31 @@ class DrmInfoRequest;
class DrmSupportInfo;
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
 * functionality to corresponding DRM Engine.
@@ -47,7 +85,7 @@ class ActionDescription;
 * The DrmManagerService class creates an instance of this class.
 *
 */
class DrmManager : public IDrmEngine::OnInfoListener {
class DrmManager : public AHandler, public IDrmEngine::OnInfoListener {
public:
    DrmManager();
    virtual ~DrmManager();
@@ -134,6 +172,8 @@ public:

    void onInfo(const DrmInfoEvent& event);

    void initMetricsLooper();

private:
    String8 getSupportedPlugInId(int uniqueId, const String8& path, const String8& mimeType);

@@ -143,16 +183,24 @@ private:

    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(""));

    void flushEngineMetrics();

private:
    enum {
        kMaxNumUniqueIds = 0x1000,
        kWhatFlushMetrics = 'metr',
    };

    bool mUniqueIdArray[kMaxNumUniqueIds];
    static const String8 EMPTY_STRING;
    static const std::map<const char*, size_t> kMethodIdMap;

    int mDecryptSessionId;
    int mConvertId;
@@ -160,11 +208,15 @@ private:
    Mutex mListenerLock;
    Mutex mDecryptLock;
    Mutex mConvertLock;
    Mutex mMetricsLock;
    TPlugInManager<IDrmEngine> mPlugInManager;
    KeyedVector< DrmSupportInfo, String8 > mSupportInfoToPlugInIdMap;
    KeyedVector< int, IDrmEngine*> mConvertSessionMap;
    KeyedVector< int, sp<IDrmServiceListener> > mServiceListeners;
    KeyedVector< int, IDrmEngine*> mDecryptSessionMap;

    std::map<std::pair<uid_t, std::string>, DrmManagerMetrics> mPluginMetrics;
    sp<ALooper> mMetricsLooper;
};

};
+2 −1
Original line number Diff line number Diff line
@@ -130,13 +130,14 @@ DrmManagerService::DrmManagerService() :
        mDrmManager(NULL) {
    ALOGV("created");
    mDrmManager = new DrmManager();
    mDrmManager->initMetricsLooper();
    mDrmManager->loadPlugIns();
}

DrmManagerService::~DrmManagerService() {
    ALOGV("Destroyed");
    mDrmManager->unloadPlugIns();
    delete mDrmManager; mDrmManager = NULL;
    mDrmManager = NULL;
}

int DrmManagerService::addUniqueId(bool isNative) {
+1 −1
Original line number Diff line number Diff line
@@ -142,7 +142,7 @@ public:
    virtual status_t dump(int fd, const Vector<String16>& args);

private:
    DrmManager* mDrmManager;
    sp<DrmManager> mDrmManager;
};

};