summaryrefslogtreecommitdiffstats
path: root/chromeos
diff options
context:
space:
mode:
authorkcwu@chromium.org <kcwu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-31 10:00:41 +0000
committerkcwu@chromium.org <kcwu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-31 10:00:41 +0000
commit67e6a68b14d311eb758ac8a569695a141dcd6627 (patch)
tree1d41b918b40a754c82cea0810e0a1bc6b6840331 /chromeos
parent7ac8dcbec919514520a95b421da0ea53907703d1 (diff)
downloadchromium_src-67e6a68b14d311eb758ac8a569695a141dcd6627.zip
chromium_src-67e6a68b14d311eb758ac8a569695a141dcd6627.tar.gz
chromium_src-67e6a68b14d311eb758ac8a569695a141dcd6627.tar.bz2
Only enable HDCP on monitors displaying the protected video
BUG=305643 R=derat@chromium.org, dmichael@chromium.org Review URL: https://codereview.chromium.org/49513002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@232075 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos')
-rw-r--r--chromeos/display/output_configurator.cc114
-rw-r--r--chromeos/display/output_configurator.h14
-rw-r--r--chromeos/display/output_configurator_unittest.cc45
3 files changed, 121 insertions, 52 deletions
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc
index 4676246..1a3cc31 100644
--- a/chromeos/display/output_configurator.cc
+++ b/chromeos/display/output_configurator.cc
@@ -299,21 +299,72 @@ void OutputConfigurator::Start(uint32 background_color_argb) {
NotifyObservers(success, new_state);
}
+bool OutputConfigurator::ApplyProtections(const DisplayProtections& requests) {
+ for (std::vector<OutputSnapshot>::const_iterator it = cached_outputs_.begin();
+ it != cached_outputs_.end(); ++it) {
+ RROutput this_id = it->output;
+ uint32_t all_desired = 0;
+ DisplayProtections::const_iterator request_it = requests.find(
+ it->display_id);
+ if (request_it != requests.end())
+ all_desired = request_it->second;
+ switch (it->type) {
+ case OUTPUT_TYPE_UNKNOWN:
+ return false;
+ // DisplayPort, DVI, and HDMI all support HDCP.
+ case OUTPUT_TYPE_DISPLAYPORT:
+ case OUTPUT_TYPE_DVI:
+ case OUTPUT_TYPE_HDMI: {
+ HDCPState new_desired_state =
+ (all_desired & OUTPUT_PROTECTION_METHOD_HDCP) ?
+ HDCP_STATE_DESIRED : HDCP_STATE_UNDESIRED;
+ if (!delegate_->SetHDCPState(this_id, new_desired_state))
+ return false;
+ break;
+ }
+ case OUTPUT_TYPE_INTERNAL:
+ case OUTPUT_TYPE_VGA:
+ case OUTPUT_TYPE_NETWORK:
+ // No protections for these types. Do nothing.
+ break;
+ case OUTPUT_TYPE_NONE:
+ NOTREACHED();
+ break;
+ }
+ }
+
+ return true;
+}
+
OutputConfigurator::OutputProtectionClientId
OutputConfigurator::RegisterOutputProtectionClient() {
if (!configure_display_)
- return 0;
+ return kInvalidClientId;
return next_output_protection_client_id_++;
}
void OutputConfigurator::UnregisterOutputProtectionClient(
OutputProtectionClientId client_id) {
- EnableOutputProtection(client_id, OUTPUT_PROTECTION_METHOD_NONE);
+ client_protection_requests_.erase(client_id);
+
+ DisplayProtections protections;
+ for (ProtectionRequests::const_iterator it =
+ client_protection_requests_.begin();
+ it != client_protection_requests_.end();
+ ++it) {
+ for (DisplayProtections::const_iterator it2 = it->second.begin();
+ it2 != it->second.end(); ++it2) {
+ protections[it2->first] |= it2->second;
+ }
+ }
+
+ ApplyProtections(protections);
}
bool OutputConfigurator::QueryOutputProtectionStatus(
OutputProtectionClientId client_id,
+ int64 display_id,
uint32_t* link_mask,
uint32_t* protection_mask) {
if (!configure_display_)
@@ -325,6 +376,8 @@ bool OutputConfigurator::QueryOutputProtectionStatus(
for (std::vector<OutputSnapshot>::const_iterator it = cached_outputs_.begin();
it != cached_outputs_.end(); ++it) {
RROutput this_id = it->output;
+ if (it->display_id != display_id)
+ continue;
*link_mask |= it->type;
switch (it->type) {
case OUTPUT_TYPE_UNKNOWN:
@@ -356,7 +409,9 @@ bool OutputConfigurator::QueryOutputProtectionStatus(
// Don't reveal protections requested by other clients.
ProtectionRequests::iterator it = client_protection_requests_.find(client_id);
if (it != client_protection_requests_.end()) {
- uint32_t requested_mask = it->second;
+ uint32_t requested_mask = 0;
+ if (it->second.find(display_id) != it->second.end())
+ requested_mask = it->second[display_id];
*protection_mask = enabled & ~unfulfilled & requested_mask;
} else {
*protection_mask = 0;
@@ -366,52 +421,39 @@ bool OutputConfigurator::QueryOutputProtectionStatus(
bool OutputConfigurator::EnableOutputProtection(
OutputProtectionClientId client_id,
+ int64 display_id,
uint32_t desired_method_mask) {
if (!configure_display_)
return false;
- uint32_t all_desired = desired_method_mask;
+ DisplayProtections protections;
for (ProtectionRequests::const_iterator it =
client_protection_requests_.begin();
it != client_protection_requests_.end();
++it) {
- if (it->first != client_id)
- all_desired |= it->second;
+ for (DisplayProtections::const_iterator it2 = it->second.begin();
+ it2 != it->second.end(); ++it2) {
+ if (it->first == client_id && it2->first == display_id)
+ continue;
+ protections[it2->first] |= it2->second;
+ }
}
+ protections[display_id] |= desired_method_mask;
- for (std::vector<OutputSnapshot>::const_iterator it = cached_outputs_.begin();
- it != cached_outputs_.end(); ++it) {
- RROutput this_id = it->output;
- switch (it->type) {
- case OUTPUT_TYPE_UNKNOWN:
- return false;
- // DisplayPort, DVI, and HDMI all support HDCP.
- case OUTPUT_TYPE_DISPLAYPORT:
- case OUTPUT_TYPE_DVI:
- case OUTPUT_TYPE_HDMI: {
- HDCPState new_desired_state =
- (all_desired & OUTPUT_PROTECTION_METHOD_HDCP) ?
- HDCP_STATE_DESIRED : HDCP_STATE_UNDESIRED;
- if (!delegate_->SetHDCPState(this_id, new_desired_state))
- return false;
- break;
- }
- case OUTPUT_TYPE_INTERNAL:
- case OUTPUT_TYPE_VGA:
- case OUTPUT_TYPE_NETWORK:
- // No protections for these types. Do nothing.
- break;
- case OUTPUT_TYPE_NONE:
- NOTREACHED();
- break;
+ if (!ApplyProtections(protections))
+ return false;
+
+ if (desired_method_mask == OUTPUT_PROTECTION_METHOD_NONE) {
+ if (client_protection_requests_.find(client_id) !=
+ client_protection_requests_.end()) {
+ client_protection_requests_[client_id].erase(display_id);
+ if (client_protection_requests_[client_id].size() == 0)
+ client_protection_requests_.erase(client_id);
}
+ } else {
+ client_protection_requests_[client_id][display_id] = desired_method_mask;
}
- if (desired_method_mask == OUTPUT_PROTECTION_METHOD_NONE)
- client_protection_requests_.erase(client_id);
- else
- client_protection_requests_[client_id] = desired_method_mask;
-
return true;
}
diff --git a/chromeos/display/output_configurator.h b/chromeos/display/output_configurator.h
index 3491344..ef5085e 100644
--- a/chromeos/display/output_configurator.h
+++ b/chromeos/display/output_configurator.h
@@ -68,6 +68,7 @@ class CHROMEOS_EXPORT OutputConfigurator
public base::MessagePumpObserver {
public:
typedef uint64_t OutputProtectionClientId;
+ static const OutputProtectionClientId kInvalidClientId = 0;
struct ModeInfo {
ModeInfo();
@@ -413,6 +414,7 @@ class CHROMEOS_EXPORT OutputConfigurator
// Returns true on success.
bool QueryOutputProtectionStatus(
OutputProtectionClientId client_id,
+ int64 display_id,
uint32_t* link_mask,
uint32_t* protection_mask);
@@ -422,12 +424,15 @@ class CHROMEOS_EXPORT OutputConfigurator
// Returns true when the protection request has been made.
bool EnableOutputProtection(
OutputProtectionClientId client_id,
+ int64 display_id,
uint32_t desired_protection_mask);
private:
- // Mapping a client to its protection request bitmask.
- typedef std::map<chromeos::OutputConfigurator::OutputProtectionClientId,
- uint32_t> ProtectionRequests;
+ // Mapping a display_id to a protection request bitmask.
+ typedef std::map<int64, uint32_t> DisplayProtections;
+ // Mapping a client to its protection request.
+ typedef std::map<OutputProtectionClientId,
+ DisplayProtections> ProtectionRequests;
// Updates |cached_outputs_| to contain currently-connected outputs. Calls
// |delegate_->GetOutputs()| and then does additional work, like finding the
@@ -487,6 +492,9 @@ class CHROMEOS_EXPORT OutputConfigurator
float GetMirroredDisplayAreaRatio(
const OutputConfigurator::OutputSnapshot& output);
+ // Applies output protections according to requests.
+ bool ApplyProtections(const DisplayProtections& requests);
+
StateController* state_controller_;
SoftwareMirroringController* mirroring_controller_;
scoped_ptr<Delegate> delegate_;
diff --git a/chromeos/display/output_configurator_unittest.cc b/chromeos/display/output_configurator_unittest.cc
index 4e23345..28f0553 100644
--- a/chromeos/display/output_configurator_unittest.cc
+++ b/chromeos/display/output_configurator_unittest.cc
@@ -358,6 +358,7 @@ class OutputConfiguratorTest : public testing::Test {
o->is_aspect_preserving_scaling = true;
o->mode_infos[kSmallModeId] = small_mode_info;
o->has_display_id = true;
+ o->display_id = 123;
o->index = 0;
o = &outputs_[1];
@@ -371,6 +372,7 @@ class OutputConfiguratorTest : public testing::Test {
o->mode_infos[kSmallModeId] = small_mode_info;
o->mode_infos[kBigModeId] = big_mode_info;
o->has_display_id = true;
+ o->display_id = 456;
o->index = 1;
UpdateOutputs(2, false);
@@ -1120,7 +1122,9 @@ TEST_F(OutputConfiguratorTest, OutputProtection) {
EXPECT_NE(kNoActions, delegate_->GetActionsAndClear());
uint32_t link_mask = 0;
uint32_t protection_mask = 0;
- EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id, &link_mask,
+ EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id,
+ outputs_[0].display_id,
+ &link_mask,
&protection_mask));
EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_INTERNAL), link_mask);
EXPECT_EQ(static_cast<uint32_t>(OUTPUT_PROTECTION_METHOD_NONE),
@@ -1130,28 +1134,38 @@ TEST_F(OutputConfiguratorTest, OutputProtection) {
// Two outputs.
UpdateOutputs(2, true);
EXPECT_NE(kNoActions, delegate_->GetActionsAndClear());
- EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id, &link_mask,
+ EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id,
+ outputs_[1].display_id,
+ &link_mask,
&protection_mask));
- EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_INTERNAL | OUTPUT_TYPE_HDMI),
+ EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_HDMI),
link_mask);
EXPECT_EQ(static_cast<uint32_t>(OUTPUT_PROTECTION_METHOD_NONE),
protection_mask);
EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
EXPECT_TRUE(
- configurator_.EnableOutputProtection(id, OUTPUT_PROTECTION_METHOD_HDCP));
+ configurator_.EnableOutputProtection(id,
+ outputs_[1].display_id,
+ OUTPUT_PROTECTION_METHOD_HDCP));
EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output, HDCP_STATE_DESIRED),
delegate_->GetActionsAndClear());
// Enable protection.
delegate_->set_hdcp_state(HDCP_STATE_ENABLED);
- EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id, &link_mask,
+ EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(id,
+ outputs_[1].display_id,
+ &link_mask,
&protection_mask));
- EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_INTERNAL | OUTPUT_TYPE_HDMI),
- link_mask);
+ EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_HDMI), link_mask);
EXPECT_EQ(static_cast<uint32_t>(OUTPUT_PROTECTION_METHOD_HDCP),
protection_mask);
EXPECT_EQ(kNoActions, delegate_->GetActionsAndClear());
+
+ // Protections should be disabled after unregister.
+ configurator_.UnregisterOutputProtectionClient(id);
+ EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output, HDCP_STATE_UNDESIRED),
+ delegate_->GetActionsAndClear());
}
TEST_F(OutputConfiguratorTest, OutputProtectionTwoClients) {
@@ -1169,6 +1183,7 @@ TEST_F(OutputConfiguratorTest, OutputProtectionTwoClients) {
// Clients never know state enableness for methods that they didn't request.
EXPECT_TRUE(
configurator_.EnableOutputProtection(client1,
+ outputs_[1].display_id,
OUTPUT_PROTECTION_METHOD_HDCP));
EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output,
HDCP_STATE_DESIRED).c_str(),
@@ -1177,27 +1192,31 @@ TEST_F(OutputConfiguratorTest, OutputProtectionTwoClients) {
uint32_t link_mask = 0;
uint32_t protection_mask = 0;
- EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(client1, &link_mask,
+ EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(client1,
+ outputs_[1].display_id,
+ &link_mask,
&protection_mask));
- EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_INTERNAL | OUTPUT_TYPE_HDMI),
- link_mask);
+ EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_HDMI), link_mask);
EXPECT_EQ(OUTPUT_PROTECTION_METHOD_HDCP, protection_mask);
- EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(client2, &link_mask,
+ EXPECT_TRUE(configurator_.QueryOutputProtectionStatus(client2,
+ outputs_[1].display_id,
+ &link_mask,
&protection_mask));
- EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_INTERNAL | OUTPUT_TYPE_HDMI),
- link_mask);
+ EXPECT_EQ(static_cast<uint32_t>(OUTPUT_TYPE_HDMI), link_mask);
EXPECT_EQ(OUTPUT_PROTECTION_METHOD_NONE, protection_mask);
// Protections will be disabled only if no more clients request them.
EXPECT_TRUE(
configurator_.EnableOutputProtection(client2,
+ outputs_[1].display_id,
OUTPUT_PROTECTION_METHOD_NONE));
EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output,
HDCP_STATE_DESIRED).c_str(),
delegate_->GetActionsAndClear());
EXPECT_TRUE(
configurator_.EnableOutputProtection(client1,
+ outputs_[1].display_id,
OUTPUT_PROTECTION_METHOD_NONE));
EXPECT_EQ(GetSetHDCPStateAction(outputs_[1].output,
HDCP_STATE_UNDESIRED).c_str(),