Collect Errors and Warnings In OEMCrypto Initialize

As a large number of provisioning errors can come from failures
initializing OEMCrypto we need to collect these  messages.
Errors and warnings were only printed to the log. This
change takes those messages and puts them into the oemcrypto
intialization mode metric.

"Mode" was chosen as most messages were about how oemcrypto
was initialized (e.g. into L3 because no L1 library was found).

Test: Ran all GTS Media Tests

Bug: 34782934
Change-Id: I1fcdd74c99011d53bdffe9609d2f4c46c222e2f6
This commit is contained in:
Aaron Vaage
2017-01-28 11:55:59 -08:00
parent edb9f00df7
commit be448ed24a
4 changed files with 131 additions and 5 deletions

View File

@@ -29,6 +29,8 @@
#include "level3.h" #include "level3.h"
#include "lock.h" #include "lock.h"
#include "log.h" #include "log.h"
#include "metrics_front_end.h"
#include "metrics_group.h"
#include "properties.h" #include "properties.h"
#include "wv_cdm_constants.h" #include "wv_cdm_constants.h"
@@ -400,6 +402,14 @@ class Adapter {
} }
OEMCryptoResult Initialize() { OEMCryptoResult Initialize() {
/*
* To avoid changing the function signature and function contract - declare
* a one-off metrics group to collect detailed information about how
* oemcrypto was intialized.
*/
wvcdm::metrics::MetricsGroup metrics;
LoadLevel3(); LoadLevel3();
std::string base_path; std::string base_path;
wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3, wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
@@ -407,24 +417,44 @@ class Adapter {
bool is_in_app = Level3_IsInApp(base_path.c_str()); bool is_in_app = Level3_IsInApp(base_path.c_str());
OEMCryptoResult result = Level3_Initialize(clear_cache_function); OEMCryptoResult result = Level3_Initialize(clear_cache_function);
if (is_in_app) { if (is_in_app) {
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_IN_APP);
return result; return result;
} }
if (force_level3()) { if (force_level3()) {
LOGW("Test code. User requested falling back to L3"); LOGW("Test code. User requested falling back to L3");
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_FORCING_L3);
return result; return result;
} }
std::string library_name; std::string library_name;
if (!wvcdm::Properties::GetOEMCryptoPath(&library_name)) { if (!wvcdm::Properties::GetOEMCryptoPath(&library_name)) {
LOGW("L1 library not specified. Falling back to L3"); LOGW("L1 library not specified. Falling back to L3");
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_NO_L1_LIBRARY_PATH);
return result; return result;
} }
level1_library_ = dlopen(library_name.c_str(), RTLD_NOW); level1_library_ = dlopen(library_name.c_str(), RTLD_NOW);
if (level1_library_ == NULL) { if (level1_library_ == NULL) {
LOGW("Could not load %s. Falling back to L3. %s", library_name.c_str(), LOGW("Could not load %s. Falling back to L3. %s", library_name.c_str(),
dlerror()); dlerror());
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_L1_OPEN_FAILED);
return result; return result;
} }
if (LoadLevel1()) { if (LoadLevel1(metrics)) {
LOGD("OEMCrypto_Initialize Level 1 success. I will use level 1."); LOGD("OEMCrypto_Initialize Level 1 success. I will use level 1.");
} else { } else {
level1_ = FunctionPointers(); // revert to all null pointers. level1_ = FunctionPointers(); // revert to all null pointers.
@@ -435,7 +465,7 @@ class Adapter {
return result; return result;
} }
bool LoadLevel1() { bool LoadLevel1(wvcdm::metrics::MetricsGroup& metrics) {
level1_valid_ = true; level1_valid_ = true;
LOOKUP(Initialize, OEMCrypto_Initialize); LOOKUP(Initialize, OEMCrypto_Initialize);
LOOKUP(Terminate, OEMCrypto_Terminate); LOOKUP(Terminate, OEMCrypto_Terminate);
@@ -462,18 +492,39 @@ class Adapter {
LOOKUP(Generic_Sign, OEMCrypto_Generic_Sign); LOOKUP(Generic_Sign, OEMCrypto_Generic_Sign);
LOOKUP(Generic_Verify, OEMCrypto_Generic_Verify); LOOKUP(Generic_Verify, OEMCrypto_Generic_Verify);
if (!level1_valid_) { if (!level1_valid_) {
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_INVALID_L1);
return false; return false;
} }
OEMCryptoResult st = level1_.Initialize(); OEMCryptoResult st = level1_.Initialize();
if (st != OEMCrypto_SUCCESS) { if (st != OEMCrypto_SUCCESS) {
LOGW("Could not initialize L1. Falling Back to L3."); LOGW("Could not initialize L1. Falling Back to L3.");
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INITIALIZE_L1);
return false; return false;
} }
level1_.version = level1_.APIVersion(); level1_.version = level1_.APIVersion();
const uint32_t kMinimumVersion = 8; const uint32_t kMinimumVersion = 8;
M_RECORD(
&metrics,
oemcrypto_l1_api_version_,
NO_TIME,
level1_.version,
kMinimumVersion);
if (level1_.version < kMinimumVersion) { if (level1_.version < kMinimumVersion) {
LOGW("liboemcrypto.so is version %d, not %d. Falling Back to L3.", LOGW("liboemcrypto.so is version %d, not %d. Falling Back to L3.",
level1_.version, kMinimumVersion); level1_.version, kMinimumVersion);
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_WRONG_L1_VERSION);
level1_.Terminate(); level1_.Terminate();
return false; return false;
} }
@@ -546,6 +597,11 @@ class Adapter {
} }
// If we have a valid keybox, initialization is done. We're good. // If we have a valid keybox, initialization is done. We're good.
if (OEMCrypto_SUCCESS == level1_.IsKeyboxValid()) { if (OEMCrypto_SUCCESS == level1_.IsKeyboxValid()) {
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_KEYBOX);
return true; return true;
} }
// If we use provisioning 3.0, initialization is done. We may not // If we use provisioning 3.0, initialization is done. We may not
@@ -553,6 +609,11 @@ class Adapter {
// will have to be caught in the future when provisioning fails. // will have to be caught in the future when provisioning fails.
if (level1_.version > 11 && if (level1_.version > 11 &&
(level1_.GetProvisioningMethod() == OEMCrypto_OEMCertificate)) { (level1_.GetProvisioningMethod() == OEMCrypto_OEMCertificate)) {
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_3_0);
return true; return true;
} }
uint8_t buffer[1]; uint8_t buffer[1];
@@ -568,6 +629,17 @@ class Adapter {
// because we still want to test OEMCrypto in that configuration. // because we still want to test OEMCrypto in that configuration.
LOGE("OEMCrypto uses cert as identification, but cdm does not!"); LOGE("OEMCrypto uses cert as identification, but cdm does not!");
LOGE("This will not work on a production device."); LOGE("This will not work on a production device.");
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_CERTIFICATE_MIX);
} else {
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_WITH_CERTIFICATE);
} }
return true; return true;
} }
@@ -576,6 +648,11 @@ class Adapter {
if (!wvcdm::Properties::GetFactoryKeyboxPath(&filename)) { if (!wvcdm::Properties::GetFactoryKeyboxPath(&filename)) {
LOGW("Bad Level 1 Keybox. Falling Back to L3."); LOGW("Bad Level 1 Keybox. Falling Back to L3.");
level1_.Terminate(); level1_.Terminate();
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_BAD_KEYBOX);
return false; return false;
} }
ssize_t size = file_system.FileSize(filename); ssize_t size = file_system.FileSize(filename);
@@ -583,6 +660,11 @@ class Adapter {
if (size <= 0 || !file) { if (size <= 0 || !file) {
LOGW("Could not open %s. Falling Back to L3.", filename.c_str()); LOGW("Could not open %s. Falling Back to L3.", filename.c_str());
level1_.Terminate(); level1_.Terminate();
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_OPEN_FACTORY_KEYBOX);
return false; return false;
} }
uint8_t keybox[size]; uint8_t keybox[size];
@@ -592,9 +674,19 @@ class Adapter {
LOGE("Could NOT install keybox from %s. Falling Back to L3.", LOGE("Could NOT install keybox from %s. Falling Back to L3.",
filename.c_str()); filename.c_str());
level1_.Terminate(); level1_.Terminate();
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INSTALL_KEYBOX);
return false; return false;
} }
LOGI("Installed keybox from %s", filename.c_str()); LOGI("Installed keybox from %s", filename.c_str());
M_RECORD(
&metrics,
oemcrypto_initialization_mode_,
NO_TIME,
wvcdm::metrics::OEMCrypto_INITIALIZED_USING_L1_INSTALLED_KEYBOX);
return true; return true;
} }

View File

@@ -38,9 +38,11 @@ class MetricsFrontEnd {
#define MFE wvcdm::metrics::MetricsFrontEnd::Instance() #define MFE wvcdm::metrics::MetricsFrontEnd::Instance()
#define M_RECORD(GROUP, METRIC, ...) \ #define NO_TIME 0
#define M_RECORD(GROUP, METRIC, TIME, ...) \
if ( GROUP ) { \ if ( GROUP ) { \
( GROUP ) -> METRIC . Record( __VA_ARGS__ ); \ ( GROUP ) -> METRIC . Record( TIME, ##__VA_ARGS__ ); \
} }
#define M_TIME(CALL, GROUP, METRIC, ...) \ #define M_TIME(CALL, GROUP, METRIC, ...) \

View File

@@ -14,6 +14,25 @@
namespace wvcdm { namespace wvcdm {
namespace metrics { namespace metrics {
typedef enum OEMCryptoInitializationMode {
OEMCrypto_INITIALIZED_USING_IN_APP = 0,
OEMCrypto_INITIALIZED_FORCING_L3 = 1,
OEMCrypto_INITIALIZED_USING_L3_NO_L1_LIBRARY_PATH = 2,
OEMCrypto_INITIALIZED_USING_L3_L1_OPEN_FAILED = 3,
OEMCrypto_INITIALIZED_USING_L3_L1_LOAD_FAILED = 4,
OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INITIALIZE_L1 = 5,
OEMCrypto_INITIALIZED_USING_L3_WRONG_L1_VERSION = 6,
OEMCrypto_INITIALIZED_USING_L1_WITH_KEYBOX = 7,
OEMCrypto_INITIALIZED_USING_L1_WITH_CERTIFICATE = 8,
OEMCrypto_INITIALIZED_USING_L1_CERTIFICATE_MIX = 9,
OEMCrypto_INITIALIZED_USING_L3_BAD_KEYBOX = 10,
OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_OPEN_FACTORY_KEYBOX = 11,
OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INSTALL_KEYBOX = 12,
OEMCrypto_INITIALIZED_USING_L1_INSTALLED_KEYBOX = 13,
OEMCrypto_INITIALIZED_USING_L3_INVALID_L1 = 14,
OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_3_0 = 15
} OEMCryptoInitializationMode;
/* /*
* The metrics group is the group of all metrics that be be recorded. They * The metrics group is the group of all metrics that be be recorded. They
* are kept together to allow calls to be correlated to one another. * are kept together to allow calls to be correlated to one another.
@@ -138,6 +157,10 @@ class MetricsGroup {
EventMetric<OEMCryptoResult> oemcrypto_update_usage_table_; EventMetric<OEMCryptoResult> oemcrypto_update_usage_table_;
EventMetric<OEMCryptoResult> oemcrypto_wrap_keybox_; EventMetric<OEMCryptoResult> oemcrypto_wrap_keybox_;
/* Internal OEMCrypto Metrics */
EventMetric<OEMCryptoInitializationMode> oemcrypto_initialization_mode_;
EventMetric<uint32_t, uint32_t> oemcrypto_l1_api_version_;
MetricsGroup(); MetricsGroup();
~MetricsGroup(); ~MetricsGroup();

View File

@@ -383,7 +383,14 @@ MetricsGroup::MetricsGroup() :
"error"), "error"),
oemcrypto_wrap_keybox_( oemcrypto_wrap_keybox_(
"/drm/widevine/oemcrypto/wrap_keybox/time", "/drm/widevine/oemcrypto/wrap_keybox/time",
"error") { } "error"),
oemcrypto_initialization_mode_(
"/drm/widevine/oemcrypto/initialization_mode",
"message"),
oemcrypto_l1_api_version_(
"/drm/widevine/oemcrypto/l1_api_version",
"version",
"min_version") { }
MetricsGroup::~MetricsGroup() { MetricsGroup::~MetricsGroup() {
MetricNotification* subscriber = MFE.CreateSubscriber(); MetricNotification* subscriber = MFE.CreateSubscriber();
@@ -506,6 +513,8 @@ void MetricsGroup::Publish(MetricNotification* subscriber) {
oemcrypto_supports_usage_table_.Publish(subscriber); oemcrypto_supports_usage_table_.Publish(subscriber);
oemcrypto_update_usage_table_.Publish(subscriber); oemcrypto_update_usage_table_.Publish(subscriber);
oemcrypto_wrap_keybox_.Publish(subscriber); oemcrypto_wrap_keybox_.Publish(subscriber);
oemcrypto_initialization_mode_.Publish(subscriber);
oemcrypto_l1_api_version_.Publish(subscriber);
} }
} // metrics } // metrics
} // wvcdm } // wvcdm