Merge changes I5271f961,I8a75d2e1 into sc-widevine-release
* changes: Added debugOtaKeyboxFallbackDuration property. Update fallback policy for fast fallback.
This commit is contained in:
committed by
Android (Google) Code Review
commit
bc62a6f3fe
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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_; }
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user