Snap for 7863959 from dd0b840b91 to tm-release

Change-Id: If061b608cf4c33914d44e7a563499b06b59cc6d4
This commit is contained in:
Android Build Coastguard Worker
2021-10-29 01:19:47 +00:00
12 changed files with 248 additions and 20 deletions

View File

@@ -360,6 +360,16 @@ class CdmEngine {
virtual void SetUserId(uint32_t user_id) { user_id_ = user_id; } virtual void SetUserId(uint32_t user_id) { user_id_ = user_id; }
virtual uint32_t GetUserId() const { return user_id_; } virtual uint32_t GetUserId() const { return user_id_; }
// Changes the rules used for calculating the fallback duration
// when OTA keybox provisioning fails.
// Default rules use fallback duration measured in days, with exponential
// backoff.
// Fast rules use fallback durations of a few seconds, without exponential
// backoff.
// This method has no effect if OTA keybox is not required.
virtual void SetDefaultOtaKeyboxFallbackDurationRules();
virtual void SetFastOtaKeyboxFallbackDurationRules();
protected: protected:
friend class CdmEngineFactory; friend class CdmEngineFactory;

View File

@@ -302,7 +302,7 @@ class CryptoSession {
// Returns a system-wide singleton instance of SystemFallbackPolicy // Returns a system-wide singleton instance of SystemFallbackPolicy
// to be used for communicating OTA keybox provisioning state between // to be used for communicating OTA keybox provisioning state between
// apps. Returns a null pointer if OTA provisioning is not supported, // apps. Returns a null pointer if OTA provisioning is not supported,
// or if the device has already been provisioned. // or not required.
static okp::SystemFallbackPolicy* GetOkpFallbackPolicy(); static okp::SystemFallbackPolicy* GetOkpFallbackPolicy();
// Generates an OTA provisioning request. // Generates an OTA provisioning request.

View File

@@ -22,13 +22,14 @@ static constexpr int64_t kSecondsPerDay = kSecondsPerHour * 24;
// Initial backoff duration. Subsequent backoff durations for the // Initial backoff duration. Subsequent backoff durations for the
// same engine will double its previous duration. // same engine will double its previous duration.
static constexpr int64_t kAverageInitialBackoffDuration = kSecondsPerDay; static constexpr int64_t kAverageInitialBackoffDuration = kSecondsPerDay;
static constexpr int64_t kInitalBackoffDurationDelta = kSecondsPerHour * 12; static constexpr int64_t kFastBackoffDuration = 30; // 30 seconds.
static constexpr int64_t kInitialBackoffDurationDelta = kSecondsPerHour * 12;
// Minimum backoff duration which an device will be required to // Minimum backoff duration which an device will be required to
// backoff the first time. // backoff the first time.
static constexpr int64_t kMinInitialBackoffDuration = static constexpr int64_t kMinInitialBackoffDuration =
kAverageInitialBackoffDuration - kInitalBackoffDurationDelta; kAverageInitialBackoffDuration - kInitialBackoffDurationDelta;
static constexpr int64_t kMaxInitialBackoffDuration = static constexpr int64_t kMaxInitialBackoffDuration =
kAverageInitialBackoffDuration + kInitalBackoffDurationDelta; kAverageInitialBackoffDuration + kInitialBackoffDurationDelta;
// SystemFallbackPolicy is a centralized OKP state manager which allows // SystemFallbackPolicy is a centralized OKP state manager which allows
// multiple CDM engines to communicate between each other. In a production // multiple CDM engines to communicate between each other. In a production
@@ -70,6 +71,9 @@ class SystemFallbackPolicy {
bool IsProvisioned(); bool IsProvisioned();
bool IsInFallbackMode(); bool IsInFallbackMode();
void SetDefaultBackoffDurationRules();
void SetFastBackoffDurationRules();
~SystemFallbackPolicy(); ~SystemFallbackPolicy();
private: private:
@@ -81,6 +85,8 @@ class SystemFallbackPolicy {
void StoreInfo(); void StoreInfo();
int64_t GenerateInitialBackoffDuration();
int64_t GetSecondsSinceBackoffStart() const; int64_t GetSecondsSinceBackoffStart() const;
void EndBackoffPeriod(); void EndBackoffPeriod();
@@ -93,6 +99,10 @@ class SystemFallbackPolicy {
SystemFallbackInfo info_; SystemFallbackInfo info_;
// When |fast_fallback_| is true, falling back only lasts a few
// seconds, and exponential backoff is disabled.
bool fast_fallback_ = false;
// Handle for the DeviceFiles instance used to store the OKP // Handle for the DeviceFiles instance used to store the OKP
// information. // information.
// Not set for test instances. // Not set for test instances.

View File

@@ -45,6 +45,7 @@ class SystemFallbackInfo {
backoff_duration_ = (duration > 0 ? duration : 0); backoff_duration_ = (duration > 0 ? duration : 0);
} }
void DoubleBackoffDuration() { backoff_duration_ *= 2; } void DoubleBackoffDuration() { backoff_duration_ *= 2; }
void ClearBackoffDuration() { backoff_duration_ = 0; }
bool HasProvisioningTime() const { return provisioning_time_ != 0; } bool HasProvisioningTime() const { return provisioning_time_ != 0; }
int64_t provisioning_time() const { return provisioning_time_; } int64_t provisioning_time() const { return provisioning_time_; }

View File

@@ -21,6 +21,7 @@
#include "device_files.h" #include "device_files.h"
#include "file_store.h" #include "file_store.h"
#include "log.h" #include "log.h"
#include "okp_fallback_policy.h"
#include "ota_keybox_provisioner.h" #include "ota_keybox_provisioner.h"
#include "properties.h" #include "properties.h"
#include "string_conversions.h" #include "string_conversions.h"
@@ -2154,4 +2155,26 @@ void CdmEngine::OkpCleanUp() {
} }
okp_provisioner_.reset(); okp_provisioner_.reset();
} }
void CdmEngine::SetDefaultOtaKeyboxFallbackDurationRules() {
OkpCheck();
std::unique_lock<std::mutex> lock(okp_mutex_);
auto* system_fallback_policy = CryptoSession::GetOkpFallbackPolicy();
if (!system_fallback_policy) {
LOGW("No system fallback policy available");
return;
}
system_fallback_policy->SetDefaultBackoffDurationRules();
}
void CdmEngine::SetFastOtaKeyboxFallbackDurationRules() {
OkpCheck();
std::unique_lock<std::mutex> lock(okp_mutex_);
auto* system_fallback_policy = CryptoSession::GetOkpFallbackPolicy();
if (!system_fallback_policy) {
LOGW("No system fallback policy available");
return;
}
system_fallback_policy->SetFastBackoffDurationRules();
}
} // namespace wvcdm } // namespace wvcdm

View File

@@ -3041,8 +3041,6 @@ okp::SystemFallbackPolicy* CryptoSession::GetOkpFallbackPolicy() {
// If not set, then OTA keybox provisioning is not supported or // If not set, then OTA keybox provisioning is not supported or
// not needed. // not needed.
if (!okp_fallback_policy_l1_) return nullptr; if (!okp_fallback_policy_l1_) return nullptr;
// May have already been initialized.
if (okp_fallback_policy_l1_->IsProvisioned()) return nullptr;
return okp_fallback_policy_l1_.get(); return okp_fallback_policy_l1_.get();
}; };
return WithStaticFieldReadLock("GetOkpFallbackPolicy", getter); return WithStaticFieldReadLock("GetOkpFallbackPolicy", getter);
@@ -3053,8 +3051,11 @@ CdmResponseType CryptoSession::PrepareOtaProvisioningRequest(
RETURN_IF_NULL(request, PARAMETER_NULL); RETURN_IF_NULL(request, PARAMETER_NULL);
RETURN_IF_NOT_OPEN(CRYPTO_SESSION_NOT_OPEN); RETURN_IF_NOT_OPEN(CRYPTO_SESSION_NOT_OPEN);
size_t buffer_length = 0; size_t buffer_length = 0;
OEMCryptoResult status = OEMCrypto_GenerateOTARequest( OEMCryptoResult status =
oec_session_id_, nullptr, &buffer_length, use_test_key); WithOecWriteLock("PrepareOtaProvisioningRequest", [&] {
return OEMCrypto_GenerateOTARequest(
oec_session_id_, nullptr, &buffer_length, use_test_key ? 1 : 0);
});
if (status != OEMCrypto_ERROR_SHORT_BUFFER) if (status != OEMCrypto_ERROR_SHORT_BUFFER)
return MapOEMCryptoResult(status, UNKNOWN_ERROR, return MapOEMCryptoResult(status, UNKNOWN_ERROR,
"PrepareOtaProvisioningRequest"); "PrepareOtaProvisioningRequest");
@@ -3064,8 +3065,10 @@ CdmResponseType CryptoSession::PrepareOtaProvisioningRequest(
} }
request->resize(buffer_length); request->resize(buffer_length);
uint8_t* buf = reinterpret_cast<uint8_t*>(&request->front()); uint8_t* buf = reinterpret_cast<uint8_t*>(&request->front());
status = OEMCrypto_GenerateOTARequest(oec_session_id_, buf, &buffer_length, status = WithOecWriteLock("PrepareOtaProvisioningRequest", [&] {
return OEMCrypto_GenerateOTARequest(oec_session_id_, buf, &buffer_length,
use_test_key ? 1 : 0); use_test_key ? 1 : 0);
});
if (OEMCrypto_SUCCESS != status) { if (OEMCrypto_SUCCESS != status) {
request->clear(); request->clear();
} else if (buffer_length != request->size()) { } else if (buffer_length != request->size()) {
@@ -3078,9 +3081,15 @@ CdmResponseType CryptoSession::PrepareOtaProvisioningRequest(
CdmResponseType CryptoSession::LoadOtaProvisioning( CdmResponseType CryptoSession::LoadOtaProvisioning(
bool use_test_key, const std::string& response) { bool use_test_key, const std::string& response) {
RETURN_IF_NOT_OPEN(CRYPTO_SESSION_NOT_OPEN); RETURN_IF_NOT_OPEN(CRYPTO_SESSION_NOT_OPEN);
const OEMCryptoResult status = OEMCrypto_ProcessOTAKeybox( const OEMCryptoResult status = WithOecWriteLock("LoadOtaProvisioning", [&] {
oec_session_id_, reinterpret_cast<const uint8_t*>(response.data()), return OEMCrypto_ProcessOTAKeybox(
response.size(), use_test_key ? 1 : 0); oec_session_id_, reinterpret_cast<const uint8_t*>(response.data()),
response.size(), use_test_key ? 1 : 0);
});
if (status == OEMCrypto_SUCCESS) {
WithOecWriteLock("LoadOtaProvisioning",
[&] { needs_keybox_provisioning_ = false; });
}
return MapOEMCryptoResult(status, UNKNOWN_ERROR, "LoadOtaProvisioning"); return MapOEMCryptoResult(status, UNKNOWN_ERROR, "LoadOtaProvisioning");
} }

View File

@@ -16,11 +16,6 @@ namespace okp {
using UniqueLock = std::unique_lock<std::mutex>; using UniqueLock = std::unique_lock<std::mutex>;
namespace { namespace {
constexpr int64_t kErrorTime = -1; constexpr int64_t kErrorTime = -1;
int64_t GenerateInitialBackoffDuration() {
return static_cast<int64_t>(CdmRandom::RandomInRange(
kMinInitialBackoffDuration, kMaxInitialBackoffDuration));
}
} // namespace } // namespace
// static // static
@@ -131,11 +126,11 @@ void SystemFallbackPolicy::TriggerFallback() {
info_.SetFirstCheckedTime(current_time); info_.SetFirstCheckedTime(current_time);
} }
info_.SetBackoffStartTime(GetCurrentTime()); info_.SetBackoffStartTime(GetCurrentTime());
if (info_.HasBackoffDuration()) { if (!fast_fallback_ && info_.HasBackoffDuration()) {
// Doubling backoff duration for exponential backoff. // Doubling backoff duration for exponential backoff. Except when
// performing fast fallback off.
info_.DoubleBackoffDuration(); info_.DoubleBackoffDuration();
} else { } else {
// Use a random backoff period to avoid server spam across all devices.
info_.SetBackoffDuration(GenerateInitialBackoffDuration()); info_.SetBackoffDuration(GenerateInitialBackoffDuration());
} }
StoreInfo(); StoreInfo();
@@ -185,6 +180,37 @@ bool SystemFallbackPolicy::IsInFallbackMode() {
return false; // Only stored if previously in fallback and has ended. return false; // Only stored if previously in fallback and has ended.
} }
void SystemFallbackPolicy::SetDefaultBackoffDurationRules() {
UniqueLock lock(mutex_);
fast_fallback_ = false;
if (state() == SystemState::kFallbackMode) {
LOGI("Ending fallback");
EndBackoffPeriod();
}
info_.ClearBackoffDuration();
StoreInfo();
}
void SystemFallbackPolicy::SetFastBackoffDurationRules() {
UniqueLock lock(mutex_);
fast_fallback_ = true;
if (state() == SystemState::kFallbackMode) {
LOGI("Ending fallback");
EndBackoffPeriod();
}
info_.ClearBackoffDuration();
StoreInfo();
}
int64_t SystemFallbackPolicy::GenerateInitialBackoffDuration() {
if (fast_fallback_) {
return kFastBackoffDuration;
}
// Use a random backoff period to avoid server spam across all devices.
return static_cast<int64_t>(CdmRandom::RandomInRange(
kMinInitialBackoffDuration, kMaxInitialBackoffDuration));
}
int64_t SystemFallbackPolicy::GetSecondsSinceBackoffStart() const { int64_t SystemFallbackPolicy::GetSecondsSinceBackoffStart() const {
if (!info_.HasBackoffStartTime()) return 0; if (!info_.HasBackoffStartTime()) return 0;
const int64_t backoff_start_time = info_.backoff_start_time(); const int64_t backoff_start_time = info_.backoff_start_time();

View File

@@ -368,5 +368,110 @@ TEST_F(OkpFallbackPolicyTest, Restore_NeedsProvisioningAgain) {
EXPECT_FALSE(system_policy_->IsInFallbackMode()); EXPECT_FALSE(system_policy_->IsInFallbackMode());
EXPECT_EQ(system_policy_->info().first_checked_time(), kRestoreTime); EXPECT_EQ(system_policy_->info().first_checked_time(), kRestoreTime);
} }
// Setup:
// 1) Device needs OKP
// 2) App requests using fast backoff settings.
// 3) Fallback occurs
// 4) After the fast fallback duration, check for if in fallback
// Expectation:
// Policy should indicate fallback, duration should be "fast" and
// the info is updated.
// After the fast fallback duration has passed, the system should
// leave fallback state.
TEST_F(OkpFallbackPolicyTest, FastRules) {
system_policy_->SetFastBackoffDurationRules();
constexpr int64_t kFallbackTime = kInitialTime + 10;
clock_.SetTime(kFallbackTime);
system_policy_->TriggerFallback();
// Checks.
EXPECT_FALSE(system_policy_->IsProvisioned());
EXPECT_TRUE(system_policy_->IsInFallbackMode());
EXPECT_EQ(system_policy_->info().backoff_start_time(), kFallbackTime);
EXPECT_EQ(system_policy_->info().backoff_duration(), kFastBackoffDuration);
constexpr int64_t kPostFallbackTime =
kFallbackTime + kFastBackoffDuration + 5;
clock_.SetTime(kPostFallbackTime);
// Checks.
EXPECT_FALSE(system_policy_->IsProvisioned());
EXPECT_FALSE(system_policy_->IsInFallbackMode());
}
// Setup:
// 1) Device needs OKP
// 2) Fallback occurs
// 3) App requests using fast backoff settings.
// 4) Another fallback occurs
// Expectation:
// 1) Setting rules to fast should end fallback
// 2) Second fallback should have a short duration.
TEST_F(OkpFallbackPolicyTest, FastRules_AfterFallback) {
// First fallback.
constexpr int64_t kFirstFallbackTime = kInitialTime + 10;
clock_.SetTime(kFirstFallbackTime);
system_policy_->TriggerFallback();
EXPECT_TRUE(system_policy_->IsInFallbackMode());
// Set fast fallback.
system_policy_->SetFastBackoffDurationRules();
EXPECT_FALSE(system_policy_->IsInFallbackMode());
// Second fallaback.
constexpr int64_t kSecondFallbackTime = kFirstFallbackTime + 10;
clock_.SetTime(kSecondFallbackTime);
system_policy_->TriggerFallback();
EXPECT_TRUE(system_policy_->IsInFallbackMode());
// Checks.
EXPECT_FALSE(system_policy_->IsProvisioned());
EXPECT_TRUE(system_policy_->IsInFallbackMode());
EXPECT_EQ(system_policy_->info().backoff_start_time(), kSecondFallbackTime);
EXPECT_EQ(system_policy_->info().backoff_duration(), kFastBackoffDuration);
}
// Setup:
// 1) Device needs OKP
// 2) App requests using fast backoff settings.
// 3) Fallback occurs
// 4) After the fast fallback duration, check for if in fallback
// 5) Another fallback occurs
// 6) After the fast fallback duration, check for if in fallback
// Expectation:
// There should not be any exponential backoff, similar to FastRules
// in all other ways.
TEST_F(OkpFallbackPolicyTest, FastRules_FallbackTwice) {
system_policy_->SetFastBackoffDurationRules();
constexpr int64_t kFirstFallbackTime = kInitialTime + 10;
clock_.SetTime(kFirstFallbackTime);
system_policy_->TriggerFallback();
// Checks.
EXPECT_FALSE(system_policy_->IsProvisioned());
EXPECT_TRUE(system_policy_->IsInFallbackMode());
EXPECT_EQ(system_policy_->info().backoff_start_time(), kFirstFallbackTime);
EXPECT_EQ(system_policy_->info().backoff_duration(), kFastBackoffDuration);
constexpr int64_t kPostFirstFallbackTime =
kFirstFallbackTime + kFastBackoffDuration + 5;
clock_.SetTime(kPostFirstFallbackTime);
EXPECT_FALSE(system_policy_->IsProvisioned());
EXPECT_FALSE(system_policy_->IsInFallbackMode());
constexpr int64_t kSecondFallbackTime = kPostFirstFallbackTime + 10;
clock_.SetTime(kSecondFallbackTime);
system_policy_->TriggerFallback();
// Checks.
EXPECT_FALSE(system_policy_->IsProvisioned());
EXPECT_TRUE(system_policy_->IsInFallbackMode());
EXPECT_EQ(system_policy_->info().backoff_start_time(), kSecondFallbackTime);
EXPECT_EQ(system_policy_->info().backoff_duration(), kFastBackoffDuration);
constexpr int64_t kPostSecondFallbackTime =
kSecondFallbackTime + kFastBackoffDuration + 5;
clock_.SetTime(kPostSecondFallbackTime);
EXPECT_FALSE(system_policy_->IsProvisioned());
EXPECT_FALSE(system_policy_->IsInFallbackMode());
}
} // namespace okp } // namespace okp
} // namespace wvcdm } // namespace wvcdm

View File

@@ -188,6 +188,9 @@ class WvContentDecryptionModule : public android::RefBase, public TimerHandler {
virtual CdmResponseType GetSessionUserId(const CdmSessionId& session_id, virtual CdmResponseType GetSessionUserId(const CdmSessionId& session_id,
uint32_t* user_id); uint32_t* user_id);
virtual bool SetDefaultOtaKeyboxFallbackDurationRules();
virtual bool SetFastOtaKeyboxFallbackDurationRules();
private: private:
struct CdmInfo { struct CdmInfo {
CdmInfo(); CdmInfo();

View File

@@ -645,4 +645,19 @@ CdmResponseType WvContentDecryptionModule::GetSessionUserId(
*user_id = cdm_engine->GetUserId(); *user_id = cdm_engine->GetUserId();
return NO_ERROR; return NO_ERROR;
} }
bool WvContentDecryptionModule::SetDefaultOtaKeyboxFallbackDurationRules() {
CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier);
if (!cdm_engine) return false;
cdm_engine->SetDefaultOtaKeyboxFallbackDurationRules();
return true;
}
bool WvContentDecryptionModule::SetFastOtaKeyboxFallbackDurationRules() {
CdmEngine* cdm_engine = EnsureCdmForIdentifier(kDefaultCdmIdentifier);
if (!cdm_engine) return false;
cdm_engine->SetFastOtaKeyboxFallbackDurationRules();
return true;
}
} // namespace wvcdm } // namespace wvcdm

View File

@@ -689,6 +689,19 @@ status_t WVDrmPlugin::setPropertyString(const String8& name,
return mapCdmResponseType(res); return mapCdmResponseType(res);
} else if (name == "decryptHashSessionId") { } else if (name == "decryptHashSessionId") {
mDecryptHashSessionId = value.string(); mDecryptHashSessionId = value.string();
} else if (name == "debugOtaKeyboxFallbackDuration") {
bool success = false;
if (value == "default") {
success = mCDM->SetDefaultOtaKeyboxFallbackDurationRules();
} else if (value == "fast") {
success = mCDM->SetFastOtaKeyboxFallbackDurationRules();
} else {
ALOGE("Unknown OTA fallback duration value %s", value.string());
return android::BAD_VALUE;
}
if (!success) {
return android::UNKNOWN_ERROR;
}
} else if (name == "atscMode") { } else if (name == "atscMode") {
if (value == kEnable) { if (value == kEnable) {
mPropertySet.set_use_atsc_mode(true); mPropertySet.set_use_atsc_mode(true);

View File

@@ -1470,6 +1470,19 @@ Return<Status> WVDrmPlugin::setPropertyString(const hidl_string& propertyName,
ALOGE("App requested unknown ATSC mode %s", _value.c_str()); ALOGE("App requested unknown ATSC mode %s", _value.c_str());
return Status::BAD_VALUE; return Status::BAD_VALUE;
} }
} else if (name == "debugOtaKeyboxFallbackDuration") {
bool success = false;
if (value == "default") {
success = mCDM->SetDefaultOtaKeyboxFallbackDurationRules();
} else if (value == "fast") {
success = mCDM->SetFastOtaKeyboxFallbackDurationRules();
} else {
ALOGE("Unknown OTA fallback duration value %s", _value.c_str());
return Status::BAD_VALUE;
}
if (!success) {
return Status::ERROR_DRM_UNKNOWN;
}
} else { } else {
ALOGE("App set unknown string property %s", name.c_str()); ALOGE("App set unknown string property %s", name.c_str());
return Status::ERROR_DRM_CANNOT_HANDLE; return Status::ERROR_DRM_CANNOT_HANDLE;