1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 // #define LOG_NDEBUG 0
18 #define LOG_TAG "DrmMetricsLogger"
19
20 #include <media/MediaMetrics.h>
21 #include <media/stagefright/foundation/AString.h>
22 #include <media/stagefright/foundation/base64.h>
23 #include <mediadrm/DrmHal.h>
24 #include <mediadrm/DrmMetricsLogger.h>
25 #include <mediadrm/DrmUtils.h>
26
27 namespace android {
28
29 namespace {
30
toStdVec(Vector<uint8_t> const & sessionId)31 std::vector<uint8_t> toStdVec(Vector<uint8_t> const& sessionId) {
32 auto sessionKey = sessionId.array();
33 std::vector<uint8_t> vec(sessionKey, sessionKey + sessionId.size());
34 return vec;
35 }
36
37 } // namespace
38
DrmMetricsLogger(IDrmFrontend frontend)39 DrmMetricsLogger::DrmMetricsLogger(IDrmFrontend frontend)
40 : mImpl(sp<DrmHal>::make()), mUuid(), mObjNonce(), mFrontend(frontend) {}
41
~DrmMetricsLogger()42 DrmMetricsLogger::~DrmMetricsLogger() {}
43
MediaErrorToEnum(status_t err)44 int MediaErrorToEnum(status_t err) {
45 #define ERROR_BAD_VALUE (BAD_VALUE)
46 #define ERROR_DEAD_OBJECT (DEAD_OBJECT)
47 #define STATUS_CASE(status) \
48 case ERROR_##status: \
49 return ENUM_##status
50
51 switch (err) {
52 STATUS_CASE(DRM_UNKNOWN);
53 STATUS_CASE(DRM_NO_LICENSE);
54 STATUS_CASE(DRM_LICENSE_EXPIRED);
55 STATUS_CASE(DRM_RESOURCE_BUSY);
56 STATUS_CASE(DRM_INSUFFICIENT_OUTPUT_PROTECTION);
57 STATUS_CASE(DRM_SESSION_NOT_OPENED);
58 STATUS_CASE(DRM_CANNOT_HANDLE);
59 STATUS_CASE(DRM_INSUFFICIENT_SECURITY);
60 STATUS_CASE(DRM_FRAME_TOO_LARGE);
61 STATUS_CASE(DRM_SESSION_LOST_STATE);
62 STATUS_CASE(DRM_CERTIFICATE_MALFORMED);
63 STATUS_CASE(DRM_CERTIFICATE_MISSING);
64 STATUS_CASE(DRM_CRYPTO_LIBRARY);
65 STATUS_CASE(DRM_GENERIC_OEM);
66 STATUS_CASE(DRM_GENERIC_PLUGIN);
67 STATUS_CASE(DRM_INIT_DATA);
68 STATUS_CASE(DRM_KEY_NOT_LOADED);
69 STATUS_CASE(DRM_LICENSE_PARSE);
70 STATUS_CASE(DRM_LICENSE_POLICY);
71 STATUS_CASE(DRM_LICENSE_RELEASE);
72 STATUS_CASE(DRM_LICENSE_REQUEST_REJECTED);
73 STATUS_CASE(DRM_LICENSE_RESTORE);
74 STATUS_CASE(DRM_LICENSE_STATE);
75 STATUS_CASE(DRM_MEDIA_FRAMEWORK);
76 STATUS_CASE(DRM_PROVISIONING_CERTIFICATE);
77 STATUS_CASE(DRM_PROVISIONING_CONFIG);
78 STATUS_CASE(DRM_PROVISIONING_PARSE);
79 STATUS_CASE(DRM_PROVISIONING_REQUEST_REJECTED);
80 STATUS_CASE(DRM_PROVISIONING_RETRY);
81 STATUS_CASE(DRM_RESOURCE_CONTENTION);
82 STATUS_CASE(DRM_SECURE_STOP_RELEASE);
83 STATUS_CASE(DRM_STORAGE_READ);
84 STATUS_CASE(DRM_STORAGE_WRITE);
85 STATUS_CASE(DRM_ZERO_SUBSAMPLES);
86 STATUS_CASE(DRM_INVALID_STATE);
87 STATUS_CASE(BAD_VALUE);
88 STATUS_CASE(DRM_NOT_PROVISIONED);
89 STATUS_CASE(DRM_DEVICE_REVOKED);
90 STATUS_CASE(DRM_DECRYPT);
91 STATUS_CASE(DEAD_OBJECT);
92 #undef ERROR_BAD_VALUE
93 #undef ERROR_DEAD_OBJECT
94 #undef STATUS_CASE
95 }
96 return ENUM_DRM_UNKNOWN;
97 }
98
DrmPluginSecurityLevelToJavaSecurityLevel(DrmPlugin::SecurityLevel securityLevel)99 int DrmPluginSecurityLevelToJavaSecurityLevel(DrmPlugin::SecurityLevel securityLevel) {
100 #define STATUS_CASE(status) \
101 case DrmPlugin::k##status: \
102 return J##status
103
104 switch (securityLevel) {
105 STATUS_CASE(SecurityLevelUnknown);
106 STATUS_CASE(SecurityLevelSwSecureCrypto);
107 STATUS_CASE(SecurityLevelSwSecureDecode);
108 STATUS_CASE(SecurityLevelHwSecureCrypto);
109 STATUS_CASE(SecurityLevelHwSecureDecode);
110 STATUS_CASE(SecurityLevelHwSecureAll);
111 STATUS_CASE(SecurityLevelMax);
112 #undef STATUS_CASE
113 }
114 return static_cast<int>(securityLevel);
115 }
116
117
initCheck() const118 DrmStatus DrmMetricsLogger::initCheck() const {
119 DrmStatus status = mImpl->initCheck();
120 if (status != OK) {
121 reportMediaDrmErrored(status, __func__);
122 }
123 return status;
124 }
125
isCryptoSchemeSupported(const uint8_t uuid[IDRM_UUID_SIZE],const String8 & mimeType,DrmPlugin::SecurityLevel securityLevel,bool * result)126 DrmStatus DrmMetricsLogger::isCryptoSchemeSupported(const uint8_t uuid[IDRM_UUID_SIZE],
127 const String8& mimeType,
128 DrmPlugin::SecurityLevel securityLevel,
129 bool* result) {
130 DrmStatus status = mImpl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
131 if (status != OK) {
132 reportMediaDrmErrored(status, __func__);
133 }
134 return status;
135 }
136
createPlugin(const uint8_t uuid[IDRM_UUID_SIZE],const String8 & appPackageName)137 DrmStatus DrmMetricsLogger::createPlugin(const uint8_t uuid[IDRM_UUID_SIZE],
138 const String8& appPackageName) {
139 std::memcpy(mUuid.data(), uuid, IDRM_UUID_SIZE);
140 mUuid[0] = betoh64(mUuid[0]);
141 mUuid[1] = betoh64(mUuid[1]);
142 if (kUuidSchemeMap.count(mUuid)) {
143 mScheme = kUuidSchemeMap.at(mUuid);
144 } else {
145 mScheme = "Other";
146 }
147 if (generateNonce(&mObjNonce, kNonceSize, __func__) != OK) {
148 return ERROR_DRM_RESOURCE_BUSY;
149 }
150 DrmStatus status = mImpl->createPlugin(uuid, appPackageName);
151 if (status == OK) {
152 String8 version8;
153 if (getPropertyString(String8("version"), version8) == OK) {
154 mVersion = version8.c_str();
155 }
156 reportMediaDrmCreated();
157 } else {
158 reportMediaDrmErrored(status, __func__);
159 }
160 return status;
161 }
162
destroyPlugin()163 DrmStatus DrmMetricsLogger::destroyPlugin() {
164 DrmStatus status = mImpl->destroyPlugin();
165 if (status != OK) {
166 reportMediaDrmErrored(status, __func__);
167 }
168 return status;
169 }
170
openSession(DrmPlugin::SecurityLevel securityLevel,Vector<uint8_t> & sessionId)171 DrmStatus DrmMetricsLogger::openSession(DrmPlugin::SecurityLevel securityLevel,
172 Vector<uint8_t>& sessionId) {
173 SessionContext ctx{};
174 if (generateNonce(&ctx.mNonce, kNonceSize, __func__) != OK) {
175 return ERROR_DRM_RESOURCE_BUSY;
176 }
177 DrmStatus status = mImpl->openSession(securityLevel, sessionId);
178 if (status == OK) {
179 std::vector<uint8_t> sessionKey = toStdVec(sessionId);
180 ctx.mTargetSecurityLevel = securityLevel;
181 if (getSecurityLevel(sessionId, &ctx.mActualSecurityLevel) != OK) {
182 ctx.mActualSecurityLevel = DrmPlugin::kSecurityLevelUnknown;
183 }
184 if (!mVersion.empty()) {
185 ctx.mVersion = mVersion;
186 }
187 {
188 const std::lock_guard<std::mutex> lock(mSessionMapMutex);
189 mSessionMap.insert({sessionKey, ctx});
190 }
191 reportMediaDrmSessionOpened(sessionKey);
192 } else {
193 reportMediaDrmErrored(status, __func__);
194 }
195 return status;
196 }
197
closeSession(Vector<uint8_t> const & sessionId)198 DrmStatus DrmMetricsLogger::closeSession(Vector<uint8_t> const& sessionId) {
199 std::vector<uint8_t> sid = toStdVec(sessionId);
200 DrmStatus status = mImpl->closeSession(sessionId);
201 if (status == OK) {
202 const std::lock_guard<std::mutex> lock(mSessionMapMutex);
203 mSessionMap.erase(sid);
204 } else {
205 // TODO(b/275729711): reclaim sessions that failed to close
206 reportMediaDrmErrored(status, __func__, sid);
207 }
208 return status;
209 }
210
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)211 DrmStatus DrmMetricsLogger::getKeyRequest(Vector<uint8_t> const& sessionId,
212 Vector<uint8_t> const& initData, String8 const& mimeType,
213 DrmPlugin::KeyType keyType,
214 KeyedVector<String8, String8> const& optionalParameters,
215 Vector<uint8_t>& request, String8& defaultUrl,
216 DrmPlugin::KeyRequestType* keyRequestType) {
217 DrmStatus status =
218 mImpl->getKeyRequest(sessionId, initData, mimeType, keyType, optionalParameters,
219 request, defaultUrl, keyRequestType);
220 if (status != OK) {
221 reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
222 }
223 return status;
224 }
225
provideKeyResponse(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & response,Vector<uint8_t> & keySetId)226 DrmStatus DrmMetricsLogger::provideKeyResponse(Vector<uint8_t> const& sessionId,
227 Vector<uint8_t> const& response,
228 Vector<uint8_t>& keySetId) {
229 DrmStatus status = mImpl->provideKeyResponse(sessionId, response, keySetId);
230 if (status != OK) {
231 reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
232 }
233 return status;
234 }
235
removeKeys(Vector<uint8_t> const & keySetId)236 DrmStatus DrmMetricsLogger::removeKeys(Vector<uint8_t> const& keySetId) {
237 DrmStatus status = mImpl->removeKeys(keySetId);
238 if (status != OK) {
239 reportMediaDrmErrored(status, __func__);
240 }
241 return status;
242 }
243
restoreKeys(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & keySetId)244 DrmStatus DrmMetricsLogger::restoreKeys(Vector<uint8_t> const& sessionId,
245 Vector<uint8_t> const& keySetId) {
246 DrmStatus status = mImpl->restoreKeys(sessionId, keySetId);
247 if (status != OK) {
248 reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
249 }
250 return status;
251 }
252
queryKeyStatus(Vector<uint8_t> const & sessionId,KeyedVector<String8,String8> & infoMap) const253 DrmStatus DrmMetricsLogger::queryKeyStatus(Vector<uint8_t> const& sessionId,
254 KeyedVector<String8, String8>& infoMap) const {
255 DrmStatus status = mImpl->queryKeyStatus(sessionId, infoMap);
256 if (status != OK) {
257 reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
258 }
259 return status;
260 }
261
getProvisionRequest(String8 const & certType,String8 const & certAuthority,Vector<uint8_t> & request,String8 & defaultUrl)262 DrmStatus DrmMetricsLogger::getProvisionRequest(String8 const& certType,
263 String8 const& certAuthority,
264 Vector<uint8_t>& request, String8& defaultUrl) {
265 DrmStatus status = mImpl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
266 if (status != OK) {
267 reportMediaDrmErrored(status, __func__);
268 }
269 return status;
270 }
271
provideProvisionResponse(Vector<uint8_t> const & response,Vector<uint8_t> & certificate,Vector<uint8_t> & wrappedKey)272 DrmStatus DrmMetricsLogger::provideProvisionResponse(Vector<uint8_t> const& response,
273 Vector<uint8_t>& certificate,
274 Vector<uint8_t>& wrappedKey) {
275 DrmStatus status = mImpl->provideProvisionResponse(response, certificate, wrappedKey);
276 if (status != OK) {
277 reportMediaDrmErrored(status, __func__);
278 }
279 return status;
280 }
281
getSecureStops(List<Vector<uint8_t>> & secureStops)282 DrmStatus DrmMetricsLogger::getSecureStops(List<Vector<uint8_t>>& secureStops) {
283 DrmStatus status = mImpl->getSecureStops(secureStops);
284 if (status != OK) {
285 reportMediaDrmErrored(status, __func__);
286 }
287 return status;
288 }
289
getSecureStopIds(List<Vector<uint8_t>> & secureStopIds)290 DrmStatus DrmMetricsLogger::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
291 DrmStatus status = mImpl->getSecureStopIds(secureStopIds);
292 if (status != OK) {
293 reportMediaDrmErrored(status, __func__);
294 }
295 return status;
296 }
297
getSecureStop(Vector<uint8_t> const & ssid,Vector<uint8_t> & secureStop)298 DrmStatus DrmMetricsLogger::getSecureStop(Vector<uint8_t> const& ssid,
299 Vector<uint8_t>& secureStop) {
300 DrmStatus status = mImpl->getSecureStop(ssid, secureStop);
301 if (status != OK) {
302 reportMediaDrmErrored(status, __func__);
303 }
304 return status;
305 }
306
releaseSecureStops(Vector<uint8_t> const & ssRelease)307 DrmStatus DrmMetricsLogger::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
308 DrmStatus status = mImpl->releaseSecureStops(ssRelease);
309 if (status != OK) {
310 reportMediaDrmErrored(status, __func__);
311 }
312 return status;
313 }
314
removeSecureStop(Vector<uint8_t> const & ssid)315 DrmStatus DrmMetricsLogger::removeSecureStop(Vector<uint8_t> const& ssid) {
316 DrmStatus status = mImpl->removeSecureStop(ssid);
317 if (status != OK) {
318 reportMediaDrmErrored(status, __func__);
319 }
320 return status;
321 }
322
removeAllSecureStops()323 DrmStatus DrmMetricsLogger::removeAllSecureStops() {
324 DrmStatus status = mImpl->removeAllSecureStops();
325 if (status != OK) {
326 reportMediaDrmErrored(status, __func__);
327 }
328 return status;
329 }
330
getHdcpLevels(DrmPlugin::HdcpLevel * connectedLevel,DrmPlugin::HdcpLevel * maxLevel) const331 DrmStatus DrmMetricsLogger::getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
332 DrmPlugin::HdcpLevel* maxLevel) const {
333 DrmStatus status = mImpl->getHdcpLevels(connectedLevel, maxLevel);
334 if (status != OK) {
335 reportMediaDrmErrored(status, __func__);
336 }
337 return status;
338 }
339
getNumberOfSessions(uint32_t * currentSessions,uint32_t * maxSessions) const340 DrmStatus DrmMetricsLogger::getNumberOfSessions(uint32_t* currentSessions,
341 uint32_t* maxSessions) const {
342 DrmStatus status = mImpl->getNumberOfSessions(currentSessions, maxSessions);
343 if (status != OK) {
344 reportMediaDrmErrored(status, __func__);
345 }
346 return status;
347 }
348
getSecurityLevel(Vector<uint8_t> const & sessionId,DrmPlugin::SecurityLevel * level) const349 DrmStatus DrmMetricsLogger::getSecurityLevel(Vector<uint8_t> const& sessionId,
350 DrmPlugin::SecurityLevel* level) const {
351 DrmStatus status = mImpl->getSecurityLevel(sessionId, level);
352 if (status != OK) {
353 reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
354 }
355 return status;
356 }
357
getOfflineLicenseKeySetIds(List<Vector<uint8_t>> & keySetIds) const358 DrmStatus DrmMetricsLogger::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
359 DrmStatus status = mImpl->getOfflineLicenseKeySetIds(keySetIds);
360 if (status != OK) {
361 reportMediaDrmErrored(status, __func__);
362 }
363 return status;
364 }
365
removeOfflineLicense(Vector<uint8_t> const & keySetId)366 DrmStatus DrmMetricsLogger::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
367 DrmStatus status = mImpl->removeOfflineLicense(keySetId);
368 if (status != OK) {
369 reportMediaDrmErrored(status, __func__);
370 }
371 return status;
372 }
373
getOfflineLicenseState(Vector<uint8_t> const & keySetId,DrmPlugin::OfflineLicenseState * licenseState) const374 DrmStatus DrmMetricsLogger::getOfflineLicenseState(
375 Vector<uint8_t> const& keySetId, DrmPlugin::OfflineLicenseState* licenseState) const {
376 DrmStatus status = mImpl->getOfflineLicenseState(keySetId, licenseState);
377 if (status != OK) {
378 reportMediaDrmErrored(status, __func__);
379 }
380 return status;
381 }
382
getPropertyString(String8 const & name,String8 & value) const383 DrmStatus DrmMetricsLogger::getPropertyString(String8 const& name, String8& value) const {
384 DrmStatus status = mImpl->getPropertyString(name, value);
385 if (status != OK) {
386 reportMediaDrmErrored(status, __func__);
387 }
388 return status;
389 }
390
getPropertyByteArray(String8 const & name,Vector<uint8_t> & value) const391 DrmStatus DrmMetricsLogger::getPropertyByteArray(String8 const& name,
392 Vector<uint8_t>& value) const {
393 DrmStatus status = mImpl->getPropertyByteArray(name, value);
394 if (status != OK) {
395 reportMediaDrmErrored(status, __func__);
396 }
397 return status;
398 }
399
setPropertyString(String8 const & name,String8 const & value) const400 DrmStatus DrmMetricsLogger::setPropertyString(String8 const& name, String8 const& value) const {
401 DrmStatus status = mImpl->setPropertyString(name, value);
402 if (status != OK) {
403 reportMediaDrmErrored(status, __func__);
404 }
405 return status;
406 }
407
setPropertyByteArray(String8 const & name,Vector<uint8_t> const & value) const408 DrmStatus DrmMetricsLogger::setPropertyByteArray(String8 const& name,
409 Vector<uint8_t> const& value) const {
410 DrmStatus status = mImpl->setPropertyByteArray(name, value);
411 if (status != OK) {
412 reportMediaDrmErrored(status, __func__);
413 }
414 return status;
415 }
416
getMetrics(const sp<IDrmMetricsConsumer> & consumer)417 DrmStatus DrmMetricsLogger::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
418 DrmStatus status = mImpl->getMetrics(consumer);
419 if (status != OK) {
420 reportMediaDrmErrored(status, __func__);
421 }
422 return status;
423 }
424
setCipherAlgorithm(Vector<uint8_t> const & sessionId,String8 const & algorithm)425 DrmStatus DrmMetricsLogger::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
426 String8 const& algorithm) {
427 DrmStatus status = mImpl->setCipherAlgorithm(sessionId, algorithm);
428 if (status != OK) {
429 reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
430 }
431 return status;
432 }
433
setMacAlgorithm(Vector<uint8_t> const & sessionId,String8 const & algorithm)434 DrmStatus DrmMetricsLogger::setMacAlgorithm(Vector<uint8_t> const& sessionId,
435 String8 const& algorithm) {
436 DrmStatus status = mImpl->setMacAlgorithm(sessionId, algorithm);
437 if (status != OK) {
438 reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
439 }
440 return status;
441 }
442
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)443 DrmStatus DrmMetricsLogger::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
444 Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
445 Vector<uint8_t>& output) {
446 DrmStatus status = mImpl->encrypt(sessionId, keyId, input, iv, output);
447 if (status != OK) {
448 reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
449 }
450 return status;
451 }
452
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)453 DrmStatus DrmMetricsLogger::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
454 Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
455 Vector<uint8_t>& output) {
456 DrmStatus status = mImpl->decrypt(sessionId, keyId, input, iv, output);
457 if (status != OK) {
458 reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
459 }
460 return status;
461 }
462
sign(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & keyId,Vector<uint8_t> const & message,Vector<uint8_t> & signature)463 DrmStatus DrmMetricsLogger::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
464 Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
465 DrmStatus status = mImpl->sign(sessionId, keyId, message, signature);
466 if (status != OK) {
467 reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
468 }
469 return status;
470 }
471
verify(Vector<uint8_t> const & sessionId,Vector<uint8_t> const & keyId,Vector<uint8_t> const & message,Vector<uint8_t> const & signature,bool & match)472 DrmStatus DrmMetricsLogger::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
473 Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
474 bool& match) {
475 DrmStatus status = mImpl->verify(sessionId, keyId, message, signature, match);
476 if (status != OK) {
477 reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
478 }
479 return status;
480 }
481
signRSA(Vector<uint8_t> const & sessionId,String8 const & algorithm,Vector<uint8_t> const & message,Vector<uint8_t> const & wrappedKey,Vector<uint8_t> & signature)482 DrmStatus DrmMetricsLogger::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
483 Vector<uint8_t> const& message,
484 Vector<uint8_t> const& wrappedKey, Vector<uint8_t>& signature) {
485 DrmStatus status = mImpl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
486 if (status != OK) {
487 reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
488 }
489 return status;
490 }
491
setListener(const sp<IDrmClient> & listener)492 DrmStatus DrmMetricsLogger::setListener(const sp<IDrmClient>& listener) {
493 DrmStatus status = mImpl->setListener(listener);
494 if (status != OK) {
495 reportMediaDrmErrored(status, __func__);
496 }
497 return status;
498 }
499
requiresSecureDecoder(const char * mime,bool * required) const500 DrmStatus DrmMetricsLogger::requiresSecureDecoder(const char* mime, bool* required) const {
501 DrmStatus status = mImpl->requiresSecureDecoder(mime, required);
502 if (status != OK) {
503 reportMediaDrmErrored(status, __func__);
504 }
505 return status;
506 }
507
requiresSecureDecoder(const char * mime,DrmPlugin::SecurityLevel securityLevel,bool * required) const508 DrmStatus DrmMetricsLogger::requiresSecureDecoder(const char* mime,
509 DrmPlugin::SecurityLevel securityLevel,
510 bool* required) const {
511 DrmStatus status = mImpl->requiresSecureDecoder(mime, securityLevel, required);
512 if (status != OK) {
513 reportMediaDrmErrored(status, "requiresSecureDecoderLevel");
514 }
515 return status;
516 }
517
setPlaybackId(Vector<uint8_t> const & sessionId,const char * playbackId)518 DrmStatus DrmMetricsLogger::setPlaybackId(Vector<uint8_t> const& sessionId,
519 const char* playbackId) {
520 DrmStatus status = mImpl->setPlaybackId(sessionId, playbackId);
521 if (status != OK) {
522 reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
523 }
524 return status;
525 }
526
getLogMessages(Vector<drm::V1_4::LogMessage> & logs) const527 DrmStatus DrmMetricsLogger::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
528 DrmStatus status = mImpl->getLogMessages(logs);
529 if (status != OK) {
530 reportMediaDrmErrored(status, __func__);
531 }
532 return status;
533 }
534
getSupportedSchemes(std::vector<uint8_t> & schemes) const535 DrmStatus DrmMetricsLogger::getSupportedSchemes(std::vector<uint8_t>& schemes) const {
536 DrmStatus status = mImpl->getSupportedSchemes(schemes);
537 if (status != OK) {
538 reportMediaDrmErrored(status, __func__);
539 }
540 return status;
541 }
542
reportMediaDrmCreated() const543 void DrmMetricsLogger::reportMediaDrmCreated() const {
544 mediametrics_handle_t handle(mediametrics_create("mediadrm.created"));
545 mediametrics_setCString(handle, "scheme", mScheme.c_str());
546 mediametrics_setInt64(handle, "uuid_msb", mUuid[0]);
547 mediametrics_setInt64(handle, "uuid_lsb", mUuid[1]);
548 mediametrics_setInt32(handle, "frontend", mFrontend);
549 mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
550 mediametrics_setCString(handle, "version", mVersion.c_str());
551 mediametrics_selfRecord(handle);
552 mediametrics_delete(handle);
553 }
554
reportMediaDrmSessionOpened(const std::vector<uint8_t> & sessionId) const555 void DrmMetricsLogger::reportMediaDrmSessionOpened(const std::vector<uint8_t>& sessionId) const {
556 mediametrics_handle_t handle(mediametrics_create("mediadrm.session_opened"));
557 mediametrics_setCString(handle, "scheme", mScheme.c_str());
558 mediametrics_setInt64(handle, "uuid_msb", mUuid[0]);
559 mediametrics_setInt64(handle, "uuid_lsb", mUuid[1]);
560 mediametrics_setInt32(handle, "frontend", mFrontend);
561 mediametrics_setCString(handle, "version", mVersion.c_str());
562 mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
563 const std::lock_guard<std::mutex> lock(mSessionMapMutex);
564 auto it = mSessionMap.find(sessionId);
565 if (it != mSessionMap.end()) {
566 mediametrics_setCString(handle, "session_nonce", it->second.mNonce.c_str());
567 mediametrics_setInt32(handle, "requested_security_level",
568 DrmPluginSecurityLevelToJavaSecurityLevel(it->second.mTargetSecurityLevel));
569 mediametrics_setInt32(handle, "opened_security_level",
570 DrmPluginSecurityLevelToJavaSecurityLevel(it->second.mActualSecurityLevel));
571 }
572 mediametrics_selfRecord(handle);
573 mediametrics_delete(handle);
574 }
575
reportMediaDrmErrored(const DrmStatus & error_code,const char * api,const std::vector<uint8_t> & sessionId) const576 void DrmMetricsLogger::reportMediaDrmErrored(const DrmStatus& error_code, const char* api,
577 const std::vector<uint8_t>& sessionId) const {
578 mediametrics_handle_t handle(mediametrics_create("mediadrm.errored"));
579 mediametrics_setCString(handle, "scheme", mScheme.c_str());
580 mediametrics_setInt64(handle, "uuid_msb", mUuid[0]);
581 mediametrics_setInt64(handle, "uuid_lsb", mUuid[1]);
582 mediametrics_setInt32(handle, "frontend", mFrontend);
583 mediametrics_setCString(handle, "version", mVersion.c_str());
584 mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
585 if (!sessionId.empty()) {
586 const std::lock_guard<std::mutex> lock(mSessionMapMutex);
587 auto it = mSessionMap.find(sessionId);
588 if (it != mSessionMap.end()) {
589 mediametrics_setCString(handle, "session_nonce", it->second.mNonce.c_str());
590 mediametrics_setInt32(handle, "security_level",
591 DrmPluginSecurityLevelToJavaSecurityLevel(it->second.mActualSecurityLevel));
592 }
593 }
594 mediametrics_setCString(handle, "api", api);
595 mediametrics_setInt32(handle, "error_code", MediaErrorToEnum(error_code));
596 mediametrics_setInt32(handle, "cdm_err", error_code.getCdmErr());
597 mediametrics_setInt32(handle, "oem_err", error_code.getOemErr());
598 mediametrics_setInt32(handle, "error_context", error_code.getContext());
599 mediametrics_selfRecord(handle);
600 mediametrics_delete(handle);
601 }
602
generateNonce(std::string * out,size_t size,const char * api)603 DrmStatus DrmMetricsLogger::generateNonce(std::string* out, size_t size, const char* api) {
604 std::vector<uint8_t> buf(size);
605 ssize_t bytes = getrandom(buf.data(), size, GRND_NONBLOCK);
606 if (bytes < size) {
607 ALOGE("getrandom failed: %d", errno);
608 reportMediaDrmErrored(ERROR_DRM_RESOURCE_BUSY, api);
609 return ERROR_DRM_RESOURCE_BUSY;
610 }
611 android::AString tmp;
612 encodeBase64(buf.data(), size, &tmp);
613 out->assign(tmp.c_str());
614 return OK;
615 }
616
617 const std::map<std::array<int64_t, 2>, std::string> DrmMetricsLogger::kUuidSchemeMap {
618 {{(int64_t)0x6DD8B3C345F44A68, (int64_t)0xBF3A64168D01A4A6}, "ABV DRM (MoDRM)"},
619 {{(int64_t)0xF239E769EFA34850, (int64_t)0x9C16A903C6932EFB},
620 "Adobe Primetime DRM version 4"},
621 {{(int64_t)0x616C746963617374, (int64_t)0x2D50726F74656374}, "Alticast"},
622 {{(int64_t)0x94CE86FB07FF4F43, (int64_t)0xADB893D2FA968CA2}, "Apple FairPlay"},
623 {{(int64_t)0x279FE473512C48FE, (int64_t)0xADE8D176FEE6B40F}, "Arris Titanium"},
624 {{(int64_t)0x3D5E6D359B9A41E8, (int64_t)0xB843DD3C6E72C42C}, "ChinaDRM"},
625 {{(int64_t)0x3EA8778F77424BF9, (int64_t)0xB18BE834B2ACBD47}, "Clear Key AES-128"},
626 {{(int64_t)0xBE58615B19C44684, (int64_t)0x88B3C8C57E99E957}, "Clear Key SAMPLE-AES"},
627 {{(int64_t)0xE2719D58A985B3C9, (int64_t)0x781AB030AF78D30E}, "Clear Key DASH-IF"},
628 {{(int64_t)0x644FE7B5260F4FAD, (int64_t)0x949A0762FFB054B4}, "CMLA (OMA DRM)"},
629 {{(int64_t)0x37C332587B994C7E, (int64_t)0xB15D19AF74482154}, "Commscope Titanium V3"},
630 {{(int64_t)0x45D481CB8FE049C0, (int64_t)0xADA9AB2D2455B2F2}, "CoreCrypt"},
631 {{(int64_t)0xDCF4E3E362F15818, (int64_t)0x7BA60A6FE33FF3DD}, "DigiCAP SmartXess"},
632 {{(int64_t)0x35BF197B530E42D7, (int64_t)0x8B651B4BF415070F}, "DivX DRM Series 5"},
633 {{(int64_t)0x80A6BE7E14484C37, (int64_t)0x9E70D5AEBE04C8D2}, "Irdeto Content Protection"},
634 {{(int64_t)0x5E629AF538DA4063, (int64_t)0x897797FFBD9902D4},
635 "Marlin Adaptive Streaming Simple Profile V1.0"},
636 {{(int64_t)0x9A04F07998404286, (int64_t)0xAB92E65BE0885F95}, "Microsoft PlayReady"},
637 {{(int64_t)0x6A99532D869F5922, (int64_t)0x9A91113AB7B1E2F3}, "MobiTV DRM"},
638 {{(int64_t)0xADB41C242DBF4A6D, (int64_t)0x958B4457C0D27B95}, "Nagra MediaAccess PRM 3.0"},
639 {{(int64_t)0x1F83E1E86EE94F0D, (int64_t)0xBA2F5EC4E3ED1A66}, "SecureMedia"},
640 {{(int64_t)0x992C46E6C4374899, (int64_t)0xB6A050FA91AD0E39}, "SecureMedia SteelKnot"},
641 {{(int64_t)0xA68129D3575B4F1A, (int64_t)0x9CBA3223846CF7C3},
642 "Synamedia/Cisco/NDS VideoGuard DRM"},
643 {{(int64_t)0xAA11967FCC014A4A, (int64_t)0x8E99C5D3DDDFEA2D}, "Unitend DRM (UDRM)"},
644 {{(int64_t)0x9A27DD82FDE24725, (int64_t)0x8CBC4234AA06EC09}, "Verimatrix VCAS"},
645 {{(int64_t)0xB4413586C58CFFB0, (int64_t)0x94A5D4896C1AF6C3}, "Viaccess-Orca DRM (VODRM)"},
646 {{(int64_t)0x793B79569F944946, (int64_t)0xA94223E7EF7E44B4}, "VisionCrypt"},
647 {{(int64_t)0x1077EFECC0B24D02, (int64_t)0xACE33C1E52E2FB4B}, "W3C Common PSSH box"},
648 {{(int64_t)0xEDEF8BA979D64ACE, (int64_t)0xA3C827DCD51D21ED}, "Widevine Content Protection"},
649 };
650
651 } // namespace android