1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/display/chromeos/apply_content_protection_task.h"
7 #include "ui/display/chromeos/display_layout_manager.h"
8 #include "ui/display/types/display_snapshot.h"
9 #include "ui/display/types/native_display_delegate.h"
15 bool GetHDCPCapableDisplays(
16 const DisplayLayoutManager
& layout_manager
,
17 std::vector
<DisplaySnapshot
*>* hdcp_capable_displays
) {
18 for (DisplaySnapshot
* display
: layout_manager
.GetDisplayStates()) {
19 switch (display
->type()) {
20 case DISPLAY_CONNECTION_TYPE_UNKNOWN
:
22 // DisplayPort, DVI, and HDMI all support HDCP.
23 case DISPLAY_CONNECTION_TYPE_DISPLAYPORT
:
24 case DISPLAY_CONNECTION_TYPE_DVI
:
25 case DISPLAY_CONNECTION_TYPE_HDMI
:
26 hdcp_capable_displays
->push_back(display
);
28 case DISPLAY_CONNECTION_TYPE_INTERNAL
:
29 case DISPLAY_CONNECTION_TYPE_VGA
:
30 case DISPLAY_CONNECTION_TYPE_NETWORK
:
31 // No protections for these types. Do nothing.
33 case DISPLAY_CONNECTION_TYPE_NONE
:
44 ApplyContentProtectionTask::ApplyContentProtectionTask(
45 DisplayLayoutManager
* layout_manager
,
46 NativeDisplayDelegate
* native_display_delegate
,
47 const DisplayConfigurator::ContentProtections
& requests
,
48 const ResponseCallback
& callback
)
49 : layout_manager_(layout_manager
),
50 native_display_delegate_(native_display_delegate
),
55 weak_ptr_factory_(this) {
58 ApplyContentProtectionTask::~ApplyContentProtectionTask() {
61 void ApplyContentProtectionTask::Run() {
62 std::vector
<DisplaySnapshot
*> hdcp_capable_displays
;
63 if (!GetHDCPCapableDisplays(*layout_manager_
, &hdcp_capable_displays
)) {
68 pending_requests_
= hdcp_capable_displays
.size();
69 if (pending_requests_
== 0) {
74 // Need to poll the driver for updates since other applications may have
76 for (DisplaySnapshot
* display
: hdcp_capable_displays
) {
77 native_display_delegate_
->GetHDCPState(
79 base::Bind(&ApplyContentProtectionTask::OnHDCPStateUpdate
,
80 weak_ptr_factory_
.GetWeakPtr(), display
->display_id()));
84 void ApplyContentProtectionTask::OnHDCPStateUpdate(int64_t display_id
,
87 query_status_
&= success
;
88 display_hdcp_state_map_
[display_id
] = state
;
91 // Wait for all the requests before continuing.
92 if (pending_requests_
!= 0)
103 void ApplyContentProtectionTask::ApplyProtections() {
104 std::vector
<DisplaySnapshot
*> hdcp_capable_displays
;
105 if (!GetHDCPCapableDisplays(*layout_manager_
, &hdcp_capable_displays
)) {
106 callback_
.Run(false);
110 std::vector
<std::pair
<DisplaySnapshot
*, HDCPState
>> hdcp_requests
;
111 // Figure out which displays need to have their HDCP state changed.
112 for (DisplaySnapshot
* display
: hdcp_capable_displays
) {
113 uint32_t desired_mask
= GetDesiredProtectionMask(display
->display_id());
115 auto it
= display_hdcp_state_map_
.find(display
->display_id());
116 // If the display can't be found, the display configuration changed.
117 if (it
== display_hdcp_state_map_
.end()) {
118 callback_
.Run(false);
122 bool hdcp_enabled
= it
->second
!= HDCP_STATE_UNDESIRED
;
123 bool hdcp_requested
= desired_mask
& CONTENT_PROTECTION_METHOD_HDCP
;
124 if (hdcp_enabled
!= hdcp_requested
) {
125 hdcp_requests
.push_back(std::make_pair(
126 display
, hdcp_requested
? HDCP_STATE_DESIRED
: HDCP_STATE_UNDESIRED
));
130 pending_requests_
= hdcp_requests
.size();
131 // All the requested changes are the same as the current HDCP state. Nothing
132 // to do anymore, just ack the content protection change.
133 if (pending_requests_
== 0) {
138 for (const auto& pair
: hdcp_requests
) {
139 native_display_delegate_
->SetHDCPState(
140 *pair
.first
, pair
.second
,
141 base::Bind(&ApplyContentProtectionTask::OnHDCPStateApplied
,
142 weak_ptr_factory_
.GetWeakPtr()));
146 void ApplyContentProtectionTask::OnHDCPStateApplied(bool success
) {
147 query_status_
&= success
;
150 if (pending_requests_
== 0)
151 callback_
.Run(query_status_
);
154 uint32_t ApplyContentProtectionTask::GetDesiredProtectionMask(
155 int64_t display_id
) const {
156 uint32_t desired_mask
= 0;
157 // In mirror mode, protection request of all displays need to be fulfilled.
158 // In non-mirror mode, only request of client's display needs to be
160 if (layout_manager_
->IsMirroring()) {
161 for (auto pair
: requests_
)
162 desired_mask
|= pair
.second
;
164 auto it
= requests_
.find(display_id
);
165 if (it
!= requests_
.end())
166 desired_mask
= it
->second
;