Metrics logging IDrm implementation

Added metrics logging to IDrm implementation for
error, createPlugin and OpenSession events.

Bug: 260066511

Test: gts-tradefed run gts --abi arm64-v8a -m GtsMediaTestCases
Test: atest CtsMediaDrmFrameworkTestCases

Change-Id: Iad894347d4db7d6f1a241cc3583885ec0028846b
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 1e1a49d..7d68c5b 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -36,6 +36,7 @@
         "DrmUtils.cpp",
         "DrmHalListener.cpp",
         "DrmStatus.cpp",
+        "DrmMetricsLogger.cpp",
     ],
 
     local_include_dirs: [
diff --git a/drm/libmediadrm/DrmMetricsLogger.cpp b/drm/libmediadrm/DrmMetricsLogger.cpp
new file mode 100644
index 0000000..bcdfadf
--- /dev/null
+++ b/drm/libmediadrm/DrmMetricsLogger.cpp
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "DrmMetricsLogger"
+
+#include <media/MediaMetrics.h>
+#include <mediadrm/DrmHal.h>
+#include <mediadrm/DrmMetricsLogger.h>
+#include <mediadrm/DrmUtils.h>
+
+namespace android {
+
+namespace {
+
+std::vector<uint8_t> toStdVec(Vector<uint8_t> const& sessionId) {
+    auto sessionKey = sessionId.array();
+    std::vector<uint8_t> vec(sessionKey, sessionKey + sessionId.size());
+    return vec;
+}
+}  // namespace
+
+DrmMetricsLogger::DrmMetricsLogger(IDrmFrontend frontend)
+    : mImpl(sp<DrmHal>::make()), mUuid(), mObjNonceMsb(0), mObjNonceLsb(0), mFrontend(frontend) {}
+
+DrmMetricsLogger::~DrmMetricsLogger() {}
+
+DrmStatus DrmMetricsLogger::initCheck() const {
+    DrmStatus status = mImpl->initCheck();
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+                                                    DrmPlugin::SecurityLevel securityLevel,
+                                                    bool* result) {
+    DrmStatus status = mImpl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+    std::memcpy(mUuid, uuid, sizeof(mUuid));
+    if (checkGetRandom(&mObjNonceMsb, __func__) == OK &&
+        checkGetRandom(&mObjNonceLsb, __func__) == OK) {
+        DrmStatus status = mImpl->createPlugin(uuid, appPackageName);
+        if (status == OK) {
+            reportMediaDrmCreated();
+        } else {
+            reportMediaDrmErrored(status, __func__);
+        }
+        return status;
+    }
+    return ERROR_DRM_RESOURCE_BUSY;
+}
+
+DrmStatus DrmMetricsLogger::destroyPlugin() {
+    DrmStatus status = mImpl->destroyPlugin();
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::openSession(DrmPlugin::SecurityLevel securityLevel,
+                                        Vector<uint8_t>& sessionId) {
+    SessionContext ctx{};
+    if (checkGetRandom(&ctx.mNonceMsb, __func__) == OK &&
+        checkGetRandom(&ctx.mNonceLsb, __func__) == OK) {
+        DrmStatus status = mImpl->openSession(securityLevel, sessionId);
+        if (status == OK) {
+            std::vector<uint8_t> sessionKey = toStdVec(sessionId);
+            ctx.mTargetSecurityLevel = securityLevel;
+            if (getSecurityLevel(sessionId, &ctx.mActualSecurityLevel) != OK) {
+                ctx.mActualSecurityLevel = DrmPlugin::kSecurityLevelUnknown;
+            }
+            {
+                const std::lock_guard<std::mutex> lock(mSessionMapMutex);
+                mSessionMap.insert({sessionKey, ctx});
+            }
+            reportMediaDrmSessionOpened(sessionKey);
+        } else {
+            reportMediaDrmErrored(status, __func__);
+        }
+        return status;
+    }
+    return ERROR_DRM_RESOURCE_BUSY;
+}
+
+DrmStatus DrmMetricsLogger::closeSession(Vector<uint8_t> const& sessionId) {
+    std::vector<uint8_t> sid = toStdVec(sessionId);
+    {
+        const std::lock_guard<std::mutex> lock(mSessionMapMutex);
+        mSessionMap.erase(sid);
+    }
+    DrmStatus status = mImpl->closeSession(sessionId);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, sid);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getKeyRequest(Vector<uint8_t> const& sessionId,
+                                          Vector<uint8_t> const& initData, String8 const& mimeType,
+                                          DrmPlugin::KeyType keyType,
+                                          KeyedVector<String8, String8> const& optionalParameters,
+                                          Vector<uint8_t>& request, String8& defaultUrl,
+                                          DrmPlugin::KeyRequestType* keyRequestType) {
+    DrmStatus status =
+            mImpl->getKeyRequest(sessionId, initData, mimeType, keyType, optionalParameters,
+                                 request, defaultUrl, keyRequestType);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::provideKeyResponse(Vector<uint8_t> const& sessionId,
+                                               Vector<uint8_t> const& response,
+                                               Vector<uint8_t>& keySetId) {
+    DrmStatus status = mImpl->provideKeyResponse(sessionId, response, keySetId);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::removeKeys(Vector<uint8_t> const& keySetId) {
+    DrmStatus status = mImpl->removeKeys(keySetId);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::restoreKeys(Vector<uint8_t> const& sessionId,
+                                        Vector<uint8_t> const& keySetId) {
+    DrmStatus status = mImpl->restoreKeys(sessionId, keySetId);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::queryKeyStatus(Vector<uint8_t> const& sessionId,
+                                           KeyedVector<String8, String8>& infoMap) const {
+    DrmStatus status = mImpl->queryKeyStatus(sessionId, infoMap);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getProvisionRequest(String8 const& certType,
+                                                String8 const& certAuthority,
+                                                Vector<uint8_t>& request, String8& defaultUrl) {
+    DrmStatus status = mImpl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::provideProvisionResponse(Vector<uint8_t> const& response,
+                                                     Vector<uint8_t>& certificate,
+                                                     Vector<uint8_t>& wrappedKey) {
+    DrmStatus status = mImpl->provideProvisionResponse(response, certificate, wrappedKey);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+    DrmStatus status = mImpl->getSecureStops(secureStops);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+    DrmStatus status = mImpl->getSecureStopIds(secureStopIds);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getSecureStop(Vector<uint8_t> const& ssid,
+                                          Vector<uint8_t>& secureStop) {
+    DrmStatus status = mImpl->getSecureStop(ssid, secureStop);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+    DrmStatus status = mImpl->releaseSecureStops(ssRelease);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::removeSecureStop(Vector<uint8_t> const& ssid) {
+    DrmStatus status = mImpl->removeSecureStop(ssid);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::removeAllSecureStops() {
+    DrmStatus status = mImpl->removeAllSecureStops();
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+                                          DrmPlugin::HdcpLevel* maxLevel) const {
+    DrmStatus status = mImpl->getHdcpLevels(connectedLevel, maxLevel);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getNumberOfSessions(uint32_t* currentSessions,
+                                                uint32_t* maxSessions) const {
+    DrmStatus status = mImpl->getNumberOfSessions(currentSessions, maxSessions);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getSecurityLevel(Vector<uint8_t> const& sessionId,
+                                             DrmPlugin::SecurityLevel* level) const {
+    DrmStatus status = mImpl->getSecurityLevel(sessionId, level);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+    DrmStatus status = mImpl->getOfflineLicenseKeySetIds(keySetIds);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+    DrmStatus status = mImpl->removeOfflineLicense(keySetId);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getOfflineLicenseState(
+        Vector<uint8_t> const& keySetId, DrmPlugin::OfflineLicenseState* licenseState) const {
+    DrmStatus status = mImpl->getOfflineLicenseState(keySetId, licenseState);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getPropertyString(String8 const& name, String8& value) const {
+    DrmStatus status = mImpl->getPropertyString(name, value);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getPropertyByteArray(String8 const& name,
+                                                 Vector<uint8_t>& value) const {
+    DrmStatus status = mImpl->getPropertyByteArray(name, value);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::setPropertyString(String8 const& name, String8 const& value) const {
+    DrmStatus status = mImpl->setPropertyString(name, value);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::setPropertyByteArray(String8 const& name,
+                                                 Vector<uint8_t> const& value) const {
+    DrmStatus status = mImpl->setPropertyByteArray(name, value);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+    DrmStatus status = mImpl->getMetrics(consumer);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+                                               String8 const& algorithm) {
+    DrmStatus status = mImpl->setCipherAlgorithm(sessionId, algorithm);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::setMacAlgorithm(Vector<uint8_t> const& sessionId,
+                                            String8 const& algorithm) {
+    DrmStatus status = mImpl->setMacAlgorithm(sessionId, algorithm);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                                    Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                                    Vector<uint8_t>& output) {
+    DrmStatus status = mImpl->encrypt(sessionId, keyId, input, iv, output);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                                    Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                                    Vector<uint8_t>& output) {
+    DrmStatus status = mImpl->decrypt(sessionId, keyId, input, iv, output);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                                 Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+    DrmStatus status = mImpl->sign(sessionId, keyId, message, signature);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                                   Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+                                   bool& match) {
+    DrmStatus status = mImpl->verify(sessionId, keyId, message, signature, match);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+                                    Vector<uint8_t> const& message,
+                                    Vector<uint8_t> const& wrappedKey, Vector<uint8_t>& signature) {
+    DrmStatus status = mImpl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::setListener(const sp<IDrmClient>& listener) {
+    DrmStatus status = mImpl->setListener(listener);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::requiresSecureDecoder(const char* mime, bool* required) const {
+    DrmStatus status = mImpl->requiresSecureDecoder(mime, required);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::requiresSecureDecoder(const char* mime,
+                                                  DrmPlugin::SecurityLevel securityLevel,
+                                                  bool* required) const {
+    DrmStatus status = mImpl->requiresSecureDecoder(mime, securityLevel, required);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::setPlaybackId(Vector<uint8_t> const& sessionId,
+                                          const char* playbackId) {
+    DrmStatus status = mImpl->setPlaybackId(sessionId, playbackId);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+    DrmStatus status = mImpl->getLogMessages(logs);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getSupportedSchemes(std::vector<uint8_t>& schemes) const {
+    DrmStatus status = mImpl->getSupportedSchemes(schemes);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+void DrmMetricsLogger::reportMediaDrmCreated() const {
+    mediametrics_handle_t handle(mediametrics_create("mediadrm.created"));
+    mediametrics_setInt64(handle, "uuid_msb", be64toh(mUuid[0]));
+    mediametrics_setInt64(handle, "uuid_lsb", be64toh(mUuid[1]));
+    mediametrics_setInt32(handle, "frontend", mFrontend);
+    mediametrics_selfRecord(handle);
+    mediametrics_delete(handle);
+}
+
+void DrmMetricsLogger::reportMediaDrmSessionOpened(std::vector<uint8_t> sessionId) const {
+    mediametrics_handle_t handle(mediametrics_create("mediadrm.session_opened"));
+    mediametrics_setInt64(handle, "obj_nonce_msb", mObjNonceMsb);
+    mediametrics_setInt64(handle, "obj_nonce_lsb", mObjNonceLsb);
+    const std::lock_guard<std::mutex> lock(mSessionMapMutex);
+    auto it = mSessionMap.find(sessionId);
+    if (it != mSessionMap.end()) {
+        mediametrics_setInt64(handle, "session_nonce_msb", it->second.mNonceMsb);
+        mediametrics_setInt64(handle, "session_nonce_lsb", it->second.mNonceLsb);
+        mediametrics_setInt64(handle, "target_seucrity_level", it->second.mTargetSecurityLevel);
+        mediametrics_setInt64(handle, "actual_seucrity_level", it->second.mActualSecurityLevel);
+    }
+    mediametrics_setInt32(handle, "frontend", mFrontend);
+    mediametrics_selfRecord(handle);
+    mediametrics_delete(handle);
+}
+
+void DrmMetricsLogger::reportMediaDrmErrored(DrmStatus error_code, const char* api,
+                                             std::vector<uint8_t> sessionId) const {
+    mediametrics_handle_t handle(mediametrics_create("mediadrm.errored"));
+    mediametrics_setInt64(handle, "obj_nonce_msb", mObjNonceMsb);
+    mediametrics_setInt64(handle, "obj_nonce_lsb", mObjNonceLsb);
+    if (!sessionId.empty()) {
+        const std::lock_guard<std::mutex> lock(mSessionMapMutex);
+        auto it = mSessionMap.find(sessionId);
+        if (it != mSessionMap.end()) {
+            mediametrics_setInt64(handle, "session_nonce_msb", it->second.mNonceMsb);
+            mediametrics_setInt64(handle, "session_nonce_lsb", it->second.mNonceLsb);
+        }
+    }
+    mediametrics_setInt64(handle, "uuid_msb", be64toh(mUuid[0]));
+    mediametrics_setInt64(handle, "uuid_lsb", be64toh(mUuid[1]));
+    mediametrics_setInt32(handle, "error_code", error_code);
+    mediametrics_setCString(handle, "api", api);
+    mediametrics_setInt32(handle, "frontend", mFrontend);
+    mediametrics_selfRecord(handle);
+    mediametrics_delete(handle);
+}
+
+DrmStatus DrmMetricsLogger::checkGetRandom(int64_t* nonce, const char* api) {
+    ssize_t bytes = getrandom(nonce, sizeof(int64_t), GRND_NONBLOCK);
+    if (bytes < sizeof(int64_t)) {
+        ALOGE("getrandom failed: %d", errno);
+        reportMediaDrmErrored(ERROR_DRM_RESOURCE_BUSY, api);
+        return ERROR_DRM_RESOURCE_BUSY;
+    }
+    return OK;
+}
+
+}  // namespace android
\ No newline at end of file
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index cb103f7..a99b1d1 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -59,11 +59,11 @@
 
 namespace {
 
-template <typename Hal>
-Hal* MakeObject(status_t* pstatus) {
+template <typename Hal, typename... Ts>
+Hal* MakeObject(status_t* pstatus, Ts... args) {
     status_t err = OK;
     status_t& status = pstatus ? *pstatus : err;
-    auto obj = new Hal();
+    auto obj = new Hal(args...);
     status = obj->initCheck();
     if (status != OK && status != NO_INIT) {
         return NULL;
@@ -192,8 +192,8 @@
     return factories;
 }
 
-sp<IDrm> MakeDrm(status_t* pstatus) {
-    return MakeObject<DrmHal>(pstatus);
+sp<IDrm> MakeDrm(IDrmFrontend frontend, status_t* pstatus) {
+    return MakeObject<DrmMetricsLogger>(pstatus, frontend);
 }
 
 sp<ICrypto> MakeCrypto(status_t* pstatus) {
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalHidl.h b/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
index 45764a1..73a9e1d 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
@@ -70,7 +70,7 @@
                                               DrmPlugin::SecurityLevel level, bool* isSupported);
 
     virtual DrmStatus createPlugin(const uint8_t uuid[16],
-                                  const String8 &appPackageName);
+                                   const String8 &appPackageName);
 
     virtual DrmStatus destroyPlugin();
 
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
new file mode 100644
index 0000000..638fb35
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <mediadrm/DrmStatus.h>
+#include <mediadrm/IDrm.h>
+#include <sys/random.h>
+#include <map>
+#include <mutex>
+
+#ifndef DRM_METRICS_LOGGER_H
+#define DRM_METRICS_LOGGER_H
+
+namespace android {
+
+struct SessionContext {
+    int64_t mNonceMsb;
+    int64_t mNonceLsb;
+    int64_t mTargetSecurityLevel;
+    DrmPlugin::SecurityLevel mActualSecurityLevel;
+};
+
+class DrmMetricsLogger : public IDrm {
+  public:
+    DrmMetricsLogger(IDrmFrontend);
+
+    virtual ~DrmMetricsLogger();
+
+    virtual DrmStatus initCheck() const;
+
+    virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+                                              DrmPlugin::SecurityLevel securityLevel, bool* result);
+
+    virtual DrmStatus createPlugin(const uint8_t uuid[16], const String8& appPackageName);
+
+    virtual DrmStatus destroyPlugin();
+
+    virtual DrmStatus openSession(DrmPlugin::SecurityLevel securityLevel,
+                                  Vector<uint8_t>& sessionId);
+
+    virtual DrmStatus closeSession(Vector<uint8_t> const& sessionId);
+
+    virtual DrmStatus getKeyRequest(Vector<uint8_t> const& sessionId,
+                                    Vector<uint8_t> const& initData, String8 const& mimeType,
+                                    DrmPlugin::KeyType keyType,
+                                    KeyedVector<String8, String8> const& optionalParameters,
+                                    Vector<uint8_t>& request, String8& defaultUrl,
+                                    DrmPlugin::KeyRequestType* keyRequestType);
+
+    virtual DrmStatus provideKeyResponse(Vector<uint8_t> const& sessionId,
+                                         Vector<uint8_t> const& response,
+                                         Vector<uint8_t>& keySetId);
+
+    virtual DrmStatus removeKeys(Vector<uint8_t> const& keySetId);
+
+    virtual DrmStatus restoreKeys(Vector<uint8_t> const& sessionId,
+                                  Vector<uint8_t> const& keySetId);
+
+    virtual DrmStatus queryKeyStatus(Vector<uint8_t> const& sessionId,
+                                     KeyedVector<String8, String8>& infoMap) const;
+
+    virtual DrmStatus getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+                                          Vector<uint8_t>& request, String8& defaultUrl);
+
+    virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const& response,
+                                               Vector<uint8_t>& certificate,
+                                               Vector<uint8_t>& wrappedKey);
+
+    virtual DrmStatus getSecureStops(List<Vector<uint8_t>>& secureStops);
+    virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>>& secureStopIds);
+    virtual DrmStatus getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop);
+
+    virtual DrmStatus releaseSecureStops(Vector<uint8_t> const& ssRelease);
+    virtual DrmStatus removeSecureStop(Vector<uint8_t> const& ssid);
+    virtual DrmStatus removeAllSecureStops();
+
+    virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+                                    DrmPlugin::HdcpLevel* maxLevel) const;
+    virtual DrmStatus getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const;
+    virtual DrmStatus getSecurityLevel(Vector<uint8_t> const& sessionId,
+                                       DrmPlugin::SecurityLevel* level) const;
+
+    virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const;
+    virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const& keySetId);
+    virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+                                             DrmPlugin::OfflineLicenseState* licenseState) const;
+
+    virtual DrmStatus getPropertyString(String8 const& name, String8& value) const;
+    virtual DrmStatus getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const;
+    virtual DrmStatus setPropertyString(String8 const& name, String8 const& value) const;
+    virtual DrmStatus setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const;
+
+    virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer>& consumer);
+
+    virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+                                         String8 const& algorithm);
+
+    virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
+
+    virtual DrmStatus encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                              Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                              Vector<uint8_t>& output);
+
+    virtual DrmStatus decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                              Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                              Vector<uint8_t>& output);
+
+    virtual DrmStatus sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                           Vector<uint8_t> const& message, Vector<uint8_t>& signature);
+
+    virtual DrmStatus verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                             Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+                             bool& match);
+
+    virtual DrmStatus signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+                              Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+                              Vector<uint8_t>& signature);
+
+    virtual DrmStatus setListener(const sp<IDrmClient>& listener);
+
+    virtual DrmStatus requiresSecureDecoder(const char* mime, bool* required) const;
+
+    virtual DrmStatus requiresSecureDecoder(const char* mime,
+                                            DrmPlugin::SecurityLevel securityLevel,
+                                            bool* required) const;
+
+    virtual DrmStatus setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId);
+
+    virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const;
+
+    virtual DrmStatus getSupportedSchemes(std::vector<uint8_t>& schemes) const;
+
+    void reportMediaDrmCreated() const;
+
+    void reportMediaDrmSessionOpened(std::vector<uint8_t> sessionId) const;
+
+    void reportMediaDrmErrored(DrmStatus error_code, const char* api,
+                               std::vector<uint8_t> sessionId = std::vector<uint8_t>()) const;
+
+    DrmStatus checkGetRandom(int64_t* nonce, const char* api);
+
+  private:
+    sp<IDrm> mImpl;
+    int64_t mUuid[2] = {};
+    int64_t mObjNonceMsb, mObjNonceLsb;
+    std::map<std::vector<uint8_t>, SessionContext> mSessionMap;
+    mutable std::mutex mSessionMapMutex;
+    IDrmFrontend mFrontend;
+    DISALLOW_EVIL_CONSTRUCTORS(DrmMetricsLogger);
+};
+
+}  // namespace android
+
+#endif  // DRM_METRICS_LOGGER_H
\ No newline at end of file
diff --git a/drm/libmediadrm/include/mediadrm/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
index 3dc7485..f37d1d1 100644
--- a/drm/libmediadrm/include/mediadrm/IDrm.h
+++ b/drm/libmediadrm/include/mediadrm/IDrm.h
@@ -33,6 +33,13 @@
 }  // namespace drm
 }  // namespace hardware
 
+enum IDrmFrontend : int32_t {
+    IDRM_UNKNOWN = 0,
+    IDRM_JNI = 1,
+    IDRM_NDK = 2,
+    IDRM_NUPLAYER = 3,
+};
+
 namespace drm = ::android::hardware::drm;
 
 struct AString;
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
index 2632ebd..94cf743 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -22,6 +22,7 @@
 #include <android/hardware/drm/1.4/IDrmPlugin.h>
 #include <android/hardware/drm/1.4/types.h>
 #include <media/stagefright/MediaErrors.h>
+#include <mediadrm/DrmMetricsLogger.h>
 #include <mediadrm/DrmStatus.h>
 #include <utils/Errors.h>  // for status_t
 #include <utils/Log.h>
@@ -119,7 +120,7 @@
 
 bool UseDrmService();
 
-sp<IDrm> MakeDrm(status_t *pstatus = nullptr);
+sp<IDrm> MakeDrm(IDrmFrontend frontend = IDRM_JNI, status_t* pstatus = nullptr);
 
 sp<ICrypto> MakeCrypto(status_t *pstatus = nullptr);