1 /*
2 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation. nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <core/buffer_allocator.h>
31 #include <utils/debug.h>
32 #include <sync/sync.h>
33 #include <vector>
34 #include <string>
35
36 #include "hwc_buffer_sync_handler.h"
37 #include "hwc_session.h"
38 #include "hwc_debugger.h"
39
40 #define __CLASS__ "HWCSession"
41
42 namespace sdm {
43
44 using ::android::hardware::Void;
45
StartServices()46 void HWCSession::StartServices() {
47 android::status_t status = IDisplayConfig::registerAsService();
48 if (status != android::OK) {
49 DLOGW("Could not register IDisplayConfig as service (%d).", status);
50 } else {
51 DLOGI("IDisplayConfig service registration completed.");
52 }
53 }
54
MapDisplayType(IDisplayConfig::DisplayType dpy)55 int MapDisplayType(IDisplayConfig::DisplayType dpy) {
56 switch (dpy) {
57 case IDisplayConfig::DisplayType::DISPLAY_PRIMARY:
58 return qdutils::DISPLAY_PRIMARY;
59
60 case IDisplayConfig::DisplayType::DISPLAY_EXTERNAL:
61 return qdutils::DISPLAY_EXTERNAL;
62
63 case IDisplayConfig::DisplayType::DISPLAY_VIRTUAL:
64 return qdutils::DISPLAY_VIRTUAL;
65
66 default:
67 break;
68 }
69
70 return -EINVAL;
71 }
72
MapExternalStatus(IDisplayConfig::DisplayExternalStatus status)73 HWCDisplay::DisplayStatus MapExternalStatus(IDisplayConfig::DisplayExternalStatus status) {
74 switch (status) {
75 case IDisplayConfig::DisplayExternalStatus::EXTERNAL_OFFLINE:
76 return HWCDisplay::kDisplayStatusOffline;
77
78 case IDisplayConfig::DisplayExternalStatus::EXTERNAL_ONLINE:
79 return HWCDisplay::kDisplayStatusOnline;
80
81 case IDisplayConfig::DisplayExternalStatus::EXTERNAL_PAUSE:
82 return HWCDisplay::kDisplayStatusPause;
83
84 case IDisplayConfig::DisplayExternalStatus::EXTERNAL_RESUME:
85 return HWCDisplay::kDisplayStatusResume;
86
87 default:
88 break;
89 }
90
91 return HWCDisplay::kDisplayStatusInvalid;
92 }
93
94 // Methods from ::vendor::hardware::display::config::V1_0::IDisplayConfig follow.
isDisplayConnected(IDisplayConfig::DisplayType dpy,isDisplayConnected_cb _hidl_cb)95 Return<void> HWCSession::isDisplayConnected(IDisplayConfig::DisplayType dpy,
96 isDisplayConnected_cb _hidl_cb) {
97 int32_t error = -EINVAL;
98 bool connected = false;
99 int disp_id = MapDisplayType(dpy);
100 int disp_idx = GetDisplayIndex(disp_id);
101
102 if (disp_idx == -1) {
103 DLOGE("Invalid display = %d", disp_id);
104 } else {
105 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
106 connected = hwc_display_[disp_idx];
107 error = 0;
108 }
109 _hidl_cb(error, connected);
110
111 return Void();
112 }
113
SetSecondaryDisplayStatus(int disp_id,HWCDisplay::DisplayStatus status)114 int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
115 int disp_idx = GetDisplayIndex(disp_id);
116 int err = -EINVAL;
117 if (disp_idx == -1) {
118 DLOGE("Invalid display = %d", disp_id);
119 return -EINVAL;
120 }
121
122 if (disp_idx == qdutils::DISPLAY_PRIMARY) {
123 DLOGE("Not supported for this display");
124 return err;
125 }
126
127 {
128 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
129 if (!hwc_display_[disp_idx]) {
130 DLOGW("Display is not connected");
131 return err;
132 }
133 DLOGI("Display = %d, Status = %d", disp_idx, status);
134 err = hwc_display_[disp_idx]->SetDisplayStatus(status);
135 if (err != 0) {
136 return err;
137 }
138 }
139
140 if (status == HWCDisplay::kDisplayStatusResume || status == HWCDisplay::kDisplayStatusPause) {
141 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
142 if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
143 {
144 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
145 hwc_display_[active_builtin_disp_id]->ResetValidation();
146 }
147 callbacks_.Refresh(active_builtin_disp_id);
148 }
149 }
150
151 return err;
152 }
153
setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy,IDisplayConfig::DisplayExternalStatus status)154 Return<int32_t> HWCSession::setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy,
155 IDisplayConfig::DisplayExternalStatus status) {
156 return SetSecondaryDisplayStatus(MapDisplayType(dpy), MapExternalStatus(status));
157 }
158
configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,uint32_t refreshRate)159 Return<int32_t> HWCSession::configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,
160 uint32_t refreshRate) {
161 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
162 HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
163
164 if (!hwc_display) {
165 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
166 return -EINVAL;
167 }
168
169 switch (op) {
170 case IDisplayConfig::DisplayDynRefreshRateOp::DISABLE_METADATA_DYN_REFRESH_RATE:
171 return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, false);
172
173 case IDisplayConfig::DisplayDynRefreshRateOp::ENABLE_METADATA_DYN_REFRESH_RATE:
174 return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, true);
175
176 case IDisplayConfig::DisplayDynRefreshRateOp::SET_BINDER_DYN_REFRESH_RATE:
177 return hwc_display->Perform(HWCDisplayBuiltIn::SET_BINDER_DYN_REFRESH_RATE, refreshRate);
178
179 default:
180 DLOGW("Invalid operation %d", op);
181 return -EINVAL;
182 }
183
184 return 0;
185 }
186
GetConfigCount(int disp_id,uint32_t * count)187 int32_t HWCSession::GetConfigCount(int disp_id, uint32_t *count) {
188 int disp_idx = GetDisplayIndex(disp_id);
189 if (disp_idx == -1) {
190 DLOGE("Invalid display = %d", disp_id);
191 return -EINVAL;
192 }
193
194 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
195
196 if (hwc_display_[disp_idx]) {
197 return hwc_display_[disp_idx]->GetDisplayConfigCount(count);
198 }
199
200 return -EINVAL;
201 }
202
getConfigCount(IDisplayConfig::DisplayType dpy,getConfigCount_cb _hidl_cb)203 Return<void> HWCSession::getConfigCount(IDisplayConfig::DisplayType dpy,
204 getConfigCount_cb _hidl_cb) {
205 uint32_t count = 0;
206 int32_t error = GetConfigCount(MapDisplayType(dpy), &count);
207
208 _hidl_cb(error, count);
209
210 return Void();
211 }
212
GetActiveConfigIndex(int disp_id,uint32_t * config)213 int32_t HWCSession::GetActiveConfigIndex(int disp_id, uint32_t *config) {
214 int disp_idx = GetDisplayIndex(disp_id);
215 if (disp_idx == -1) {
216 DLOGE("Invalid display = %d", disp_id);
217 return -EINVAL;
218 }
219
220 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
221
222 if (hwc_display_[disp_idx]) {
223 return hwc_display_[disp_idx]->GetActiveDisplayConfig(config);
224 }
225
226 return -EINVAL;
227 }
228
getActiveConfig(IDisplayConfig::DisplayType dpy,getActiveConfig_cb _hidl_cb)229 Return<void> HWCSession::getActiveConfig(IDisplayConfig::DisplayType dpy,
230 getActiveConfig_cb _hidl_cb) {
231 uint32_t config = 0;
232 int32_t error = GetActiveConfigIndex(MapDisplayType(dpy), &config);
233
234 _hidl_cb(error, config);
235
236 return Void();
237 }
238
SetActiveConfigIndex(int disp_id,uint32_t config)239 int32_t HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) {
240 int disp_idx = GetDisplayIndex(disp_id);
241 if (disp_idx == -1) {
242 DLOGE("Invalid display = %d", disp_id);
243 return -EINVAL;
244 }
245
246 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
247 int32_t error = -EINVAL;
248 if (hwc_display_[disp_idx]) {
249 error = hwc_display_[disp_idx]->SetActiveDisplayConfig(config);
250 if (!error) {
251 Refresh(0);
252 }
253 }
254
255 return error;
256 }
257
setActiveConfig(IDisplayConfig::DisplayType dpy,uint32_t config)258 Return<int32_t> HWCSession::setActiveConfig(IDisplayConfig::DisplayType dpy, uint32_t config) {
259 return SetActiveConfigIndex(MapDisplayType(dpy), config);
260 }
261
getDisplayAttributes(uint32_t configIndex,IDisplayConfig::DisplayType dpy,getDisplayAttributes_cb _hidl_cb)262 Return<void> HWCSession::getDisplayAttributes(uint32_t configIndex,
263 IDisplayConfig::DisplayType dpy,
264 getDisplayAttributes_cb _hidl_cb) {
265 int32_t error = -EINVAL;
266 IDisplayConfig::DisplayAttributes display_attributes = {};
267 int disp_id = MapDisplayType(dpy);
268 int disp_idx = GetDisplayIndex(disp_id);
269
270 if (disp_idx == -1) {
271 DLOGE("Invalid display = %d", disp_id);
272 } else {
273 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
274 if (hwc_display_[disp_idx]) {
275 DisplayConfigVariableInfo var_info;
276 error = hwc_display_[disp_idx]->GetDisplayAttributesForConfig(INT(configIndex), &var_info);
277 if (!error) {
278 display_attributes.vsyncPeriod = var_info.vsync_period_ns;
279 display_attributes.xRes = var_info.x_pixels;
280 display_attributes.yRes = var_info.y_pixels;
281 display_attributes.xDpi = var_info.x_dpi;
282 display_attributes.yDpi = var_info.y_dpi;
283 display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
284 display_attributes.isYuv = var_info.is_yuv;
285 }
286 }
287 }
288 _hidl_cb(error, display_attributes);
289
290 return Void();
291 }
292
setPanelBrightness(uint32_t level)293 Return<int32_t> HWCSession::setPanelBrightness(uint32_t level) {
294 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
295 int32_t error = -EINVAL;
296
297 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
298 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(INT(level));
299 if (error) {
300 DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
301 }
302 }
303
304 return error;
305 }
306
GetPanelBrightness(int * level)307 int32_t HWCSession::GetPanelBrightness(int *level) {
308 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
309 int32_t error = -EINVAL;
310
311 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
312 error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(level);
313 if (error) {
314 DLOGE("Failed to get the panel brightness. Error = %d", error);
315 }
316 }
317
318 return error;
319 }
320
getPanelBrightness(getPanelBrightness_cb _hidl_cb)321 Return<void> HWCSession::getPanelBrightness(getPanelBrightness_cb _hidl_cb) {
322 int level = 0;
323 int32_t error = GetPanelBrightness(&level);
324
325 _hidl_cb(error, static_cast<uint32_t>(level));
326
327 return Void();
328 }
329
MinHdcpEncryptionLevelChanged(int disp_id,uint32_t min_enc_level)330 int32_t HWCSession::MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level) {
331 DLOGI("Display %d", disp_id);
332
333 int disp_idx = GetDisplayIndex(disp_id);
334 if (disp_idx == -1) {
335 DLOGE("Invalid display = %d", disp_id);
336 return -EINVAL;
337 }
338
339 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
340 if (disp_idx != HWC_DISPLAY_EXTERNAL) {
341 DLOGE("Not supported for display");
342 } else if (!hwc_display_[disp_idx]) {
343 DLOGW("Display is not connected");
344 } else {
345 return hwc_display_[disp_idx]->OnMinHdcpEncryptionLevelChange(min_enc_level);
346 }
347
348 return -EINVAL;
349 }
350
minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,uint32_t min_enc_level)351 Return<int32_t> HWCSession::minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,
352 uint32_t min_enc_level) {
353 return MinHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level);
354 }
355
refreshScreen()356 Return<int32_t> HWCSession::refreshScreen() {
357 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
358 Refresh(HWC_DISPLAY_PRIMARY);
359
360 return 0;
361 }
362
ControlPartialUpdate(int disp_id,bool enable)363 int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
364 int disp_idx = GetDisplayIndex(disp_id);
365 if (disp_idx == -1) {
366 DLOGE("Invalid display = %d", disp_id);
367 return -EINVAL;
368 }
369
370 if (disp_idx != HWC_DISPLAY_PRIMARY) {
371 DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_idx);
372 return -EINVAL;
373 }
374
375 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
376 HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
377 if (!hwc_display) {
378 DLOGE("primary display object is not instantiated");
379 return -EINVAL;
380 }
381
382 uint32_t pending = 0;
383 DisplayError hwc_error = hwc_display->ControlPartialUpdate(enable, &pending);
384
385 if (hwc_error == kErrorNone) {
386 if (!pending) {
387 return 0;
388 }
389 } else if (hwc_error == kErrorNotSupported) {
390 return 0;
391 } else {
392 return -EINVAL;
393 }
394
395 // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
396 Refresh(HWC_DISPLAY_PRIMARY);
397
398 // Wait until partial update control is complete
399 int32_t error = locker_[disp_idx].WaitFinite(kCommitDoneTimeoutMs);
400
401 return error;
402 }
403
controlPartialUpdate(IDisplayConfig::DisplayType dpy,bool enable)404 Return<int32_t> HWCSession::controlPartialUpdate(IDisplayConfig::DisplayType dpy, bool enable) {
405 return ControlPartialUpdate(MapDisplayType(dpy), enable);
406 }
407
toggleScreenUpdate(bool on)408 Return<int32_t> HWCSession::toggleScreenUpdate(bool on) {
409 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
410
411 int32_t error = -EINVAL;
412 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
413 error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(on);
414 if (error) {
415 DLOGE("Failed to toggle screen updates = %d. Error = %d", on, error);
416 }
417 }
418
419 return error;
420 }
421
setIdleTimeout(uint32_t value)422 Return<int32_t> HWCSession::setIdleTimeout(uint32_t value) {
423 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
424
425 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
426 hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(value);
427 return 0;
428 }
429
430 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
431 return -ENODEV;
432 }
433
getHDRCapabilities(IDisplayConfig::DisplayType dpy,getHDRCapabilities_cb _hidl_cb)434 Return<void> HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy,
435 getHDRCapabilities_cb _hidl_cb) {
436 int32_t error = -EINVAL;
437 IDisplayConfig::DisplayHDRCapabilities hdr_caps = {};
438
439 do {
440 if (!_hidl_cb) {
441 DLOGE("_hidl_cb callback not provided.");
442 break;
443 }
444
445 int disp_id = MapDisplayType(dpy);
446 int disp_idx = GetDisplayIndex(disp_id);
447 if (disp_idx == -1) {
448 DLOGE("Invalid display = %d", disp_id);
449 break;
450 }
451
452 SCOPE_LOCK(locker_[disp_id]);
453 HWCDisplay *hwc_display = hwc_display_[disp_idx];
454 if (!hwc_display) {
455 DLOGW("Display = %d is not connected.", disp_idx);
456 error = -ENODEV;
457 break;
458 }
459
460 // query number of hdr types
461 uint32_t out_num_types = 0;
462 float out_max_luminance = 0.0f;
463 float out_max_average_luminance = 0.0f;
464 float out_min_luminance = 0.0f;
465 if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, &out_max_luminance,
466 &out_max_average_luminance, &out_min_luminance)
467 != HWC2::Error::None) {
468 break;
469 }
470 if (!out_num_types) {
471 error = 0;
472 break;
473 }
474
475 // query hdr caps
476 hdr_caps.supportedHdrTypes.resize(out_num_types);
477
478 if (hwc_display->GetHdrCapabilities(&out_num_types, hdr_caps.supportedHdrTypes.data(),
479 &out_max_luminance, &out_max_average_luminance,
480 &out_min_luminance) == HWC2::Error::None) {
481 error = 0;
482 }
483 } while (false);
484
485 _hidl_cb(error, hdr_caps);
486
487 return Void();
488 }
489
setCameraLaunchStatus(uint32_t on)490 Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
491 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
492 if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
493 DLOGE("No active displays");
494 return -EINVAL;
495 }
496 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
497
498 if (null_display_mode_) {
499 return 0;
500 }
501
502 if (!core_intf_) {
503 DLOGW("core_intf_ not initialized.");
504 return -ENOENT;
505 }
506
507 if (!hwc_display_[active_builtin_disp_id]) {
508 DLOGW("Display = %d is not connected.", active_builtin_disp_id);
509 return -ENODEV;
510 }
511
512 HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
513
514 // trigger invalidate to apply new bw caps.
515 Refresh(active_builtin_disp_id);
516
517 if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
518 return -EINVAL;
519 }
520
521 new_bw_mode_ = true;
522 need_invalidate_ = true;
523 hwc_display_[active_builtin_disp_id]->ResetValidation();
524
525 return 0;
526 }
527
DisplayBWTransactionPending(bool * status)528 int32_t HWCSession::DisplayBWTransactionPending(bool *status) {
529 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
530
531 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
532 if (sync_wait(bw_mode_release_fd_, 0) < 0) {
533 DLOGI("bw_transaction_release_fd is not yet signaled: err= %s", strerror(errno));
534 *status = false;
535 }
536
537 return 0;
538 }
539
540 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
541 return -ENODEV;
542 }
543
displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb)544 Return<void> HWCSession::displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) {
545 bool status = true;
546
547 if (!_hidl_cb) {
548 DLOGE("_hidl_cb callback not provided.");
549 return Void();
550 }
551
552 int32_t error = DisplayBWTransactionPending(&status);
553
554 _hidl_cb(error, status);
555
556 return Void();
557 }
558
559 #ifdef DISPLAY_CONFIG_1_1
setDisplayAnimating(uint64_t display_id,bool animating)560 Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
561 return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
562 &HWCDisplay::SetDisplayAnimating, animating);
563 }
564 #endif
565
566 #ifdef DISPLAY_CONFIG_1_2
setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,uint32_t base,uint32_t count)567 Return<int32_t> HWCSession::setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,
568 uint32_t base, uint32_t count) {
569 return -1;
570 }
571 #endif // DISPLAY_CONFIG_1_2
572
573 #ifdef DISPLAY_CONFIG_1_3
controlIdlePowerCollapse(bool enable,bool synchronous)574 Return<int32_t> HWCSession::controlIdlePowerCollapse(bool enable, bool synchronous) {
575 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
576 if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
577 DLOGE("No active displays");
578 return -EINVAL;
579 }
580 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
581
582 if (hwc_display_[active_builtin_disp_id]) {
583 if (!enable) {
584 if (!idle_pc_ref_cnt_) {
585 auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
586 synchronous);
587 if (err != kErrorNone) {
588 return (err == kErrorNotSupported) ? 0 : -EINVAL;
589 }
590 Refresh(active_builtin_disp_id);
591 int32_t error = locker_[active_builtin_disp_id].WaitFinite(kCommitDoneTimeoutMs);
592 if (error == ETIMEDOUT) {
593 DLOGE("Timed out!! Next frame commit done event not received!!");
594 return error;
595 }
596 DLOGI("Idle PC disabled!!");
597 }
598 idle_pc_ref_cnt_++;
599 } else if (idle_pc_ref_cnt_ > 0) {
600 if (!(idle_pc_ref_cnt_ - 1)) {
601 auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
602 synchronous);
603 if (err != kErrorNone) {
604 return (err == kErrorNotSupported) ? 0 : -EINVAL;
605 }
606 DLOGI("Idle PC enabled!!");
607 }
608 idle_pc_ref_cnt_--;
609 }
610 return 0;
611 }
612
613 DLOGW("Display = %d is not connected.", active_builtin_disp_id);
614 return -ENODEV;
615 }
616 #endif // DISPLAY_CONFIG_1_3
617
618
IsWbUbwcSupported(int * value)619 int32_t HWCSession::IsWbUbwcSupported(int *value) {
620 HWDisplaysInfo hw_displays_info = {};
621 DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
622 if (error != kErrorNone) {
623 return -EINVAL;
624 }
625
626 for (auto &iter : hw_displays_info) {
627 auto &info = iter.second;
628 if (info.display_type == kVirtual && info.is_wb_ubwc_supported) {
629 *value = 1;
630 }
631 }
632
633 return error;
634 }
635
636 #ifdef DISPLAY_CONFIG_1_4
getWriteBackCapabilities(getWriteBackCapabilities_cb _hidl_cb)637 Return<void> HWCSession::getWriteBackCapabilities(getWriteBackCapabilities_cb _hidl_cb) {
638 int value = 0;
639 IDisplayConfig::WriteBackCapabilities wb_caps = {};
640 int32_t error = IsWbUbwcSupported(&value);
641 wb_caps.isWbUbwcSupported = value;
642 _hidl_cb(error, wb_caps);
643
644 return Void();
645 }
646 #endif // DISPLAY_CONFIG_1_4
647
648 #ifdef DISPLAY_CONFIG_1_5
SetDisplayDppsAdROI(uint32_t display_id,uint32_t h_start,uint32_t h_end,uint32_t v_start,uint32_t v_end,uint32_t factor_in,uint32_t factor_out)649 Return<int32_t> HWCSession::SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start,
650 uint32_t h_end, uint32_t v_start, uint32_t v_end,
651 uint32_t factor_in, uint32_t factor_out) {
652 return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
653 &HWCDisplay::SetDisplayDppsAdROI, h_start, h_end, v_start, v_end,
654 factor_in, factor_out);
655 }
656 #endif // DISPLAY_CONFIG_1_5
657
658 #ifdef DISPLAY_CONFIG_1_6
updateVSyncSourceOnPowerModeOff()659 Return<int32_t> HWCSession::updateVSyncSourceOnPowerModeOff() {
660 return 0;
661 }
662
updateVSyncSourceOnPowerModeDoze()663 Return<int32_t> HWCSession::updateVSyncSourceOnPowerModeDoze() {
664 return 0;
665 }
666 #endif
667
668 #ifdef DISPLAY_CONFIG_1_7
setPowerMode(uint32_t disp_id,PowerMode power_mode)669 Return<int32_t> HWCSession::setPowerMode(uint32_t disp_id, PowerMode power_mode) {
670 return 0;
671 }
672
isPowerModeOverrideSupported(uint32_t disp_id)673 Return<bool> HWCSession::isPowerModeOverrideSupported(uint32_t disp_id) {
674 return false;
675 }
676
isHDRSupported(uint32_t disp_id)677 Return<bool> HWCSession::isHDRSupported(uint32_t disp_id) {
678 if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
679 DLOGE("Not valid display");
680 return false;
681 }
682 return static_cast<bool>(is_hdr_display_[disp_id]);
683 }
684
isWCGSupported(uint32_t disp_id)685 Return<bool> HWCSession::isWCGSupported(uint32_t disp_id) {
686 // todo(user): Query wcg from sdm. For now assume them same.
687 return isHDRSupported(disp_id);
688 }
689
setLayerAsMask(uint32_t disp_id,uint64_t layer_id)690 Return<int32_t> HWCSession::setLayerAsMask(uint32_t disp_id, uint64_t layer_id) {
691 SCOPE_LOCK(locker_[disp_id]);
692 HWCDisplay *hwc_display = hwc_display_[disp_id];
693 if (!hwc_display) {
694 DLOGW("Display = %d is not connected.", disp_id);
695 return -EINVAL;
696 }
697
698 if (disable_mask_layer_hint_) {
699 DLOGW("Mask layer hint is disabled!");
700 return -EINVAL;
701 }
702
703 auto hwc_layer = hwc_display->GetHWCLayer(layer_id);
704 if (hwc_layer == nullptr) {
705 return -EINVAL;
706 }
707
708 hwc_layer->SetLayerAsMask();
709
710 return 0;
711 }
712
getDebugProperty(const hidl_string & prop_name,getDebugProperty_cb _hidl_cb)713 Return<void> HWCSession::getDebugProperty(const hidl_string &prop_name,
714 getDebugProperty_cb _hidl_cb) {
715 std::string vendor_prop_name = DISP_PROP_PREFIX;
716 char value[64] = {};
717 hidl_string result = "";
718 int32_t error = -EINVAL;
719
720 vendor_prop_name += prop_name.c_str();
721 if (HWCDebugHandler::Get()->GetProperty(vendor_prop_name.c_str(), value) != kErrorNone) {
722 result = value;
723 error = 0;
724 }
725
726 _hidl_cb(result, error);
727
728 return Void();
729 }
730 #endif
731
732 #ifdef DISPLAY_CONFIG_1_8
getActiveBuiltinDisplayAttributes(getDisplayAttributes_cb _hidl_cb)733 Return<void> HWCSession::getActiveBuiltinDisplayAttributes(
734 getDisplayAttributes_cb _hidl_cb) {
735 int32_t error = -EINVAL;
736 IDisplayConfig::DisplayAttributes display_attributes = {};
737 hwc2_display_t disp_id = GetActiveBuiltinDisplay();
738
739 if (disp_id >= HWCCallbacks::kNumDisplays) {
740 DLOGE("Invalid display = %d", disp_id);
741 } else {
742 if (hwc_display_[disp_id]) {
743 uint32_t config_index = 0;
744 HWC2::Error ret = hwc_display_[disp_id]->GetActiveConfig(&config_index);
745 if (ret != HWC2::Error::None) {
746 goto err;
747 }
748 DisplayConfigVariableInfo var_info;
749 error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(INT(config_index), &var_info);
750 if (!error) {
751 display_attributes.vsyncPeriod = var_info.vsync_period_ns;
752 display_attributes.xRes = var_info.x_pixels;
753 display_attributes.yRes = var_info.y_pixels;
754 display_attributes.xDpi = var_info.x_dpi;
755 display_attributes.yDpi = var_info.y_dpi;
756 display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
757 display_attributes.isYuv = var_info.is_yuv;
758 }
759 }
760 }
761
762 err:
763 _hidl_cb(error, display_attributes);
764
765 return Void();
766 }
767 #endif // DISPLAY_CONFIG_1_8
768
769 } // namespace sdm
770