1 /*
2 * Copyright (c) 2017-2020, 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 = INT32(hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(INT32(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(int32_t & level) const307 int32_t HWCSession::GetPanelBrightness(int32_t &level) const {
308 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
309 int32_t error = -EINVAL;
310
311 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
312 error = INT32(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
GetPanelMaxBrightness(int32_t & max_brightness_level) const321 int32_t HWCSession::GetPanelMaxBrightness(int32_t &max_brightness_level) const {
322 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
323 int32_t error = -EINVAL;
324
325 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
326 error = INT32(hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelMaxBrightness(max_brightness_level));
327 if (error) {
328 DLOGE("Failed to get the panel max brightness. Error = %d", error);
329 }
330 }
331
332 return error;
333 }
334
getPanelBrightness(getPanelBrightness_cb _hidl_cb)335 Return<void> HWCSession::getPanelBrightness(getPanelBrightness_cb _hidl_cb) {
336 int32_t level = 0;
337 int32_t error = GetPanelBrightness(level);
338
339 _hidl_cb(error, static_cast<uint32_t>(level));
340
341 return Void();
342 }
343
MinHdcpEncryptionLevelChanged(int disp_id,uint32_t min_enc_level)344 int32_t HWCSession::MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level) {
345 DLOGI("Display %d", disp_id);
346
347 int disp_idx = GetDisplayIndex(disp_id);
348 if (disp_idx == -1) {
349 DLOGE("Invalid display = %d", disp_id);
350 return -EINVAL;
351 }
352
353 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
354 if (disp_idx != HWC_DISPLAY_EXTERNAL) {
355 DLOGE("Not supported for display");
356 } else if (!hwc_display_[disp_idx]) {
357 DLOGW("Display is not connected");
358 } else {
359 return hwc_display_[disp_idx]->OnMinHdcpEncryptionLevelChange(min_enc_level);
360 }
361
362 return -EINVAL;
363 }
364
minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,uint32_t min_enc_level)365 Return<int32_t> HWCSession::minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,
366 uint32_t min_enc_level) {
367 return MinHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level);
368 }
369
refreshScreen()370 Return<int32_t> HWCSession::refreshScreen() {
371 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
372 Refresh(HWC_DISPLAY_PRIMARY);
373
374 return 0;
375 }
376
ControlPartialUpdate(int disp_id,bool enable)377 int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
378 int disp_idx = GetDisplayIndex(disp_id);
379 if (disp_idx == -1) {
380 DLOGE("Invalid display = %d", disp_id);
381 return -EINVAL;
382 }
383
384 if (disp_idx != HWC_DISPLAY_PRIMARY) {
385 DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_idx);
386 return -EINVAL;
387 }
388
389 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
390 HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
391 if (!hwc_display) {
392 DLOGE("primary display object is not instantiated");
393 return -EINVAL;
394 }
395
396 uint32_t pending = 0;
397 DisplayError hwc_error = hwc_display->ControlPartialUpdate(enable, &pending);
398
399 if (hwc_error == kErrorNone) {
400 if (!pending) {
401 return 0;
402 }
403 } else if (hwc_error == kErrorNotSupported) {
404 return 0;
405 } else {
406 return -EINVAL;
407 }
408
409 // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
410 Refresh(HWC_DISPLAY_PRIMARY);
411
412 // Wait until partial update control is complete
413 int32_t error = locker_[disp_idx].WaitFinite(kCommitDoneTimeoutMs);
414
415 return error;
416 }
417
controlPartialUpdate(IDisplayConfig::DisplayType dpy,bool enable)418 Return<int32_t> HWCSession::controlPartialUpdate(IDisplayConfig::DisplayType dpy, bool enable) {
419 return ControlPartialUpdate(MapDisplayType(dpy), enable);
420 }
421
toggleScreenUpdate(bool on)422 Return<int32_t> HWCSession::toggleScreenUpdate(bool on) {
423 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
424
425 int32_t error = -EINVAL;
426 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
427 error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(on);
428 if (error) {
429 DLOGE("Failed to toggle screen updates = %d. Error = %d", on, error);
430 }
431 }
432
433 return error;
434 }
435
setIdleTimeout(uint32_t value)436 Return<int32_t> HWCSession::setIdleTimeout(uint32_t value) {
437 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
438
439 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
440 hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(value);
441 return 0;
442 }
443
444 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
445 return -ENODEV;
446 }
447
getHDRCapabilities(IDisplayConfig::DisplayType dpy,getHDRCapabilities_cb _hidl_cb)448 Return<void> HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy,
449 getHDRCapabilities_cb _hidl_cb) {
450 int32_t error = -EINVAL;
451 IDisplayConfig::DisplayHDRCapabilities hdr_caps = {};
452
453 do {
454 if (!_hidl_cb) {
455 DLOGE("_hidl_cb callback not provided.");
456 break;
457 }
458
459 int disp_id = MapDisplayType(dpy);
460 int disp_idx = GetDisplayIndex(disp_id);
461 if (disp_idx == -1) {
462 DLOGE("Invalid display = %d", disp_id);
463 break;
464 }
465
466 SCOPE_LOCK(locker_[disp_id]);
467 HWCDisplay *hwc_display = hwc_display_[disp_idx];
468 if (!hwc_display) {
469 DLOGW("Display = %d is not connected.", disp_idx);
470 error = -ENODEV;
471 break;
472 }
473
474 // query number of hdr types
475 uint32_t out_num_types = 0;
476 float out_max_luminance = 0.0f;
477 float out_max_average_luminance = 0.0f;
478 float out_min_luminance = 0.0f;
479 if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, &out_max_luminance,
480 &out_max_average_luminance, &out_min_luminance)
481 != HWC2::Error::None) {
482 break;
483 }
484 if (!out_num_types) {
485 error = 0;
486 break;
487 }
488
489 // query hdr caps
490 hdr_caps.supportedHdrTypes.resize(out_num_types);
491
492 if (hwc_display->GetHdrCapabilities(&out_num_types, hdr_caps.supportedHdrTypes.data(),
493 &out_max_luminance, &out_max_average_luminance,
494 &out_min_luminance) == HWC2::Error::None) {
495 error = 0;
496 }
497 } while (false);
498
499 _hidl_cb(error, hdr_caps);
500
501 return Void();
502 }
503
setCameraLaunchStatus(uint32_t on)504 Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
505 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
506 if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
507 DLOGE("No active displays");
508 return -EINVAL;
509 }
510 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
511
512 if (null_display_mode_) {
513 return 0;
514 }
515
516 if (!core_intf_) {
517 DLOGW("core_intf_ not initialized.");
518 return -ENOENT;
519 }
520
521 if (!hwc_display_[active_builtin_disp_id]) {
522 DLOGW("Display = %d is not connected.", active_builtin_disp_id);
523 return -ENODEV;
524 }
525
526 HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
527
528 // trigger invalidate to apply new bw caps.
529 Refresh(active_builtin_disp_id);
530
531 if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
532 return -EINVAL;
533 }
534
535 new_bw_mode_ = true;
536 need_invalidate_ = true;
537 hwc_display_[active_builtin_disp_id]->ResetValidation();
538
539 return 0;
540 }
541
DisplayBWTransactionPending(bool * status)542 int32_t HWCSession::DisplayBWTransactionPending(bool *status) {
543 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
544
545 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
546 if (sync_wait(bw_mode_release_fd_, 0) < 0) {
547 DLOGI("bw_transaction_release_fd is not yet signaled: err= %s", strerror(errno));
548 *status = false;
549 }
550
551 return 0;
552 }
553
554 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
555 return -ENODEV;
556 }
557
displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb)558 Return<void> HWCSession::displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) {
559 bool status = true;
560
561 if (!_hidl_cb) {
562 DLOGE("_hidl_cb callback not provided.");
563 return Void();
564 }
565
566 int32_t error = DisplayBWTransactionPending(&status);
567
568 _hidl_cb(error, status);
569
570 return Void();
571 }
572
setDisplayAnimating(uint64_t display_id,bool animating)573 Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
574 return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
575 &HWCDisplay::SetDisplayAnimating, animating);
576 }
577
setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,uint32_t base,uint32_t count)578 Return<int32_t> HWCSession::setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,
579 uint32_t base, uint32_t count) {
580 return -1;
581 }
582
controlIdlePowerCollapse(bool enable,bool synchronous)583 Return<int32_t> HWCSession::controlIdlePowerCollapse(bool enable, bool synchronous) {
584 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
585 if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
586 DLOGE("No active displays");
587 return -EINVAL;
588 }
589 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
590
591 if (hwc_display_[active_builtin_disp_id]) {
592 if (!enable) {
593 if (!idle_pc_ref_cnt_) {
594 auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
595 synchronous);
596 if (err != kErrorNone) {
597 return (err == kErrorNotSupported) ? 0 : -EINVAL;
598 }
599 Refresh(active_builtin_disp_id);
600 int32_t error = locker_[active_builtin_disp_id].WaitFinite(kCommitDoneTimeoutMs);
601 if (error == ETIMEDOUT) {
602 DLOGE("Timed out!! Next frame commit done event not received!!");
603 return error;
604 }
605 DLOGI("Idle PC disabled!!");
606 }
607 idle_pc_ref_cnt_++;
608 } else if (idle_pc_ref_cnt_ > 0) {
609 if (!(idle_pc_ref_cnt_ - 1)) {
610 auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
611 synchronous);
612 if (err != kErrorNone) {
613 return (err == kErrorNotSupported) ? 0 : -EINVAL;
614 }
615 DLOGI("Idle PC enabled!!");
616 }
617 idle_pc_ref_cnt_--;
618 }
619 return 0;
620 }
621
622 DLOGW("Display = %d is not connected.", active_builtin_disp_id);
623 return -ENODEV;
624 }
625
IsWbUbwcSupported(int * value)626 int32_t HWCSession::IsWbUbwcSupported(int *value) {
627 HWDisplaysInfo hw_displays_info = {};
628 DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
629 if (error != kErrorNone) {
630 return -EINVAL;
631 }
632
633 for (auto &iter : hw_displays_info) {
634 auto &info = iter.second;
635 if (info.display_type == kVirtual && info.is_wb_ubwc_supported) {
636 *value = 1;
637 }
638 }
639
640 return error;
641 }
642
getWriteBackCapabilities(getWriteBackCapabilities_cb _hidl_cb)643 Return<void> HWCSession::getWriteBackCapabilities(getWriteBackCapabilities_cb _hidl_cb) {
644 int value = 0;
645 IDisplayConfig::WriteBackCapabilities wb_caps = {};
646 int32_t error = IsWbUbwcSupported(&value);
647 wb_caps.isWbUbwcSupported = value;
648 _hidl_cb(error, wb_caps);
649
650 return Void();
651 }
652
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)653 Return<int32_t> HWCSession::SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start,
654 uint32_t h_end, uint32_t v_start, uint32_t v_end,
655 uint32_t factor_in, uint32_t factor_out) {
656 return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
657 &HWCDisplay::SetDisplayDppsAdROI, h_start, h_end, v_start, v_end,
658 factor_in, factor_out);
659 }
660
updateVSyncSourceOnPowerModeOff()661 Return<int32_t> HWCSession::updateVSyncSourceOnPowerModeOff() {
662 return 0;
663 }
664
updateVSyncSourceOnPowerModeDoze()665 Return<int32_t> HWCSession::updateVSyncSourceOnPowerModeDoze() {
666 return 0;
667 }
668
isPowerModeOverrideSupported(uint32_t disp_id)669 Return<bool> HWCSession::isPowerModeOverrideSupported(uint32_t disp_id) {
670 if (!async_powermode_ || (disp_id > HWCCallbacks::kNumRealDisplays)) {
671 return false;
672 }
673
674 return true;
675 }
676
setPowerMode(uint32_t disp_id,PowerMode power_mode)677 Return<int32_t> HWCSession::setPowerMode(uint32_t disp_id, PowerMode power_mode) {
678 SCOPE_LOCK(display_config_locker_);
679
680 if (!isPowerModeOverrideSupported(disp_id)) {
681 return 0;
682 }
683
684 DLOGI("disp_id: %d power_mode: %d", disp_id, power_mode);
685 HWCDisplay::HWCLayerStack stack = {};
686 hwc2_display_t dummy_disp_id = map_hwc_display_.at(disp_id);
687
688 {
689 // Power state transition start.
690 Locker::ScopeLock lock_power(power_state_[disp_id]);
691 Locker::ScopeLock lock_primary(locker_[disp_id]);
692 Locker::ScopeLock lock_dummy(locker_[dummy_disp_id]);
693
694 power_state_transition_[disp_id] = true;
695 // Pass on the complete stack to dummy display.
696 hwc_display_[disp_id]->GetLayerStack(&stack);
697 // Update the same stack onto dummy display.
698 hwc_display_[dummy_disp_id]->SetLayerStack(&stack);
699 }
700
701 {
702 SCOPE_LOCK(locker_[disp_id]);
703 auto mode = static_cast<HWC2::PowerMode>(power_mode);
704 hwc_display_[disp_id]->SetPowerMode(mode, false /* teardown */);
705 }
706
707 {
708 // Power state transition end.
709 Locker::ScopeLock lock_power(power_state_[disp_id]);
710 Locker::ScopeLock lock_primary(locker_[disp_id]);
711 Locker::ScopeLock lock_dummy(locker_[dummy_disp_id]);
712 // Pass on the layer stack to real display.
713 hwc_display_[dummy_disp_id]->GetLayerStack(&stack);
714 // Update the same stack onto real display.
715 hwc_display_[disp_id]->SetLayerStack(&stack);
716 // Read display has got layerstack. Update the fences.
717 hwc_display_[disp_id]->PostPowerMode();
718
719 power_state_transition_[disp_id] = false;
720 }
721
722 return 0;
723 }
724
isHDRSupported(uint32_t disp_id)725 Return<bool> HWCSession::isHDRSupported(uint32_t disp_id) {
726 if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
727 DLOGE("Not valid display");
728 return false;
729 }
730 SCOPE_LOCK(locker_[disp_id]);
731
732 if (is_hdr_display_.size() <= disp_id) {
733 DLOGW("is_hdr_display_ is not initialized for display %d!! Reporting it as HDR not supported",
734 disp_id);
735 return false;
736 }
737
738 return static_cast<bool>(is_hdr_display_[disp_id]);
739 }
740
isWCGSupported(uint32_t disp_id)741 Return<bool> HWCSession::isWCGSupported(uint32_t disp_id) {
742 // todo(user): Query wcg from sdm. For now assume them same.
743 return isHDRSupported(disp_id);
744 }
745
setLayerAsMask(uint32_t disp_id,uint64_t layer_id)746 Return<int32_t> HWCSession::setLayerAsMask(uint32_t disp_id, uint64_t layer_id) {
747 SCOPE_LOCK(locker_[disp_id]);
748 HWCDisplay *hwc_display = hwc_display_[disp_id];
749 if (!hwc_display) {
750 DLOGW("Display = %d is not connected.", disp_id);
751 return -EINVAL;
752 }
753
754 if (disable_mask_layer_hint_) {
755 DLOGW("Mask layer hint is disabled!");
756 return -EINVAL;
757 }
758
759 auto hwc_layer = hwc_display->GetHWCLayer(layer_id);
760 if (hwc_layer == nullptr) {
761 return -EINVAL;
762 }
763
764 hwc_layer->SetLayerAsMask();
765
766 return 0;
767 }
768
getDebugProperty(const hidl_string & prop_name,getDebugProperty_cb _hidl_cb)769 Return<void> HWCSession::getDebugProperty(const hidl_string &prop_name,
770 getDebugProperty_cb _hidl_cb) {
771 std::string vendor_prop_name = DISP_PROP_PREFIX;
772 char value[64] = {};
773 hidl_string result = "";
774 int32_t error = -EINVAL;
775
776 vendor_prop_name += prop_name.c_str();
777 if (HWCDebugHandler::Get()->GetProperty(vendor_prop_name.c_str(), value) == kErrorNone) {
778 result = value;
779 error = 0;
780 }
781
782 _hidl_cb(result, error);
783
784 return Void();
785 }
786
getActiveBuiltinDisplayAttributes(getDisplayAttributes_cb _hidl_cb)787 Return<void> HWCSession::getActiveBuiltinDisplayAttributes(
788 getDisplayAttributes_cb _hidl_cb) {
789 int32_t error = -EINVAL;
790 IDisplayConfig::DisplayAttributes display_attributes = {};
791 hwc2_display_t disp_id = GetActiveBuiltinDisplay();
792
793 if (disp_id >= HWCCallbacks::kNumDisplays) {
794 DLOGE("Invalid display = %d", disp_id);
795 } else {
796 if (hwc_display_[disp_id]) {
797 uint32_t config_index = 0;
798 HWC2::Error ret = hwc_display_[disp_id]->GetActiveConfig(&config_index);
799 if (ret != HWC2::Error::None) {
800 goto err;
801 }
802 DisplayConfigVariableInfo var_info;
803 error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(INT(config_index), &var_info);
804 if (!error) {
805 display_attributes.vsyncPeriod = var_info.vsync_period_ns;
806 display_attributes.xRes = var_info.x_pixels;
807 display_attributes.yRes = var_info.y_pixels;
808 display_attributes.xDpi = var_info.x_dpi;
809 display_attributes.yDpi = var_info.y_dpi;
810 display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
811 display_attributes.isYuv = var_info.is_yuv;
812 }
813 }
814 }
815
816 err:
817 _hidl_cb(error, display_attributes);
818
819 return Void();
820 }
821
setPanelLuminanceAttributes(uint32_t disp_id,float pan_min_lum,float pan_max_lum)822 Return<int32_t> HWCSession::setPanelLuminanceAttributes(uint32_t disp_id, float pan_min_lum,
823 float pan_max_lum) {
824 // currently doing only for virtual display
825 if (disp_id != qdutils::DISPLAY_VIRTUAL) {
826 return -EINVAL;
827 }
828
829 std::lock_guard<std::mutex> obj(mutex_lum_);
830 set_min_lum_ = pan_min_lum;
831 set_max_lum_ = pan_max_lum;
832 DLOGI("set max_lum %f, min_lum %f", set_max_lum_, set_min_lum_);
833
834 return 0;
835 }
836
isBuiltInDisplay(uint32_t disp_id)837 Return<bool> HWCSession::isBuiltInDisplay(uint32_t disp_id) {
838 if ((map_info_primary_.client_id == disp_id) && (map_info_primary_.disp_type == kBuiltIn))
839 return true;
840
841 for (auto &info : map_info_builtin_) {
842 if (disp_id == info.client_id) {
843 return true;
844 }
845 }
846
847 return false;
848 }
849
getSupportedDSIBitClks(uint32_t disp_id,getSupportedDSIBitClks_cb _hidl_cb)850 Return<void> HWCSession::getSupportedDSIBitClks(uint32_t disp_id,
851 getSupportedDSIBitClks_cb _hidl_cb) {
852 SCOPE_LOCK(locker_[disp_id]);
853 if (!hwc_display_[disp_id]) {
854 return Void();
855 }
856
857 std::vector<uint64_t> bit_clks;
858 hwc_display_[disp_id]->GetSupportedDSIClock(&bit_clks);
859
860 hidl_vec<uint64_t> hidl_bit_clks = bit_clks;
861 _hidl_cb(hidl_bit_clks);
862
863 return Void();
864 }
865
getDSIClk(uint32_t disp_id)866 Return<uint64_t> HWCSession::getDSIClk(uint32_t disp_id) {
867 SCOPE_LOCK(locker_[disp_id]);
868 if (!hwc_display_[disp_id]) {
869 return 0;
870 }
871
872 uint64_t bit_clk = 0;
873 hwc_display_[disp_id]->GetDynamicDSIClock(&bit_clk);
874
875 return bit_clk;
876 }
877
setDSIClk(uint32_t disp_id,uint64_t bit_clk)878 Return<int32_t> HWCSession::setDSIClk(uint32_t disp_id, uint64_t bit_clk) {
879 SCOPE_LOCK(locker_[disp_id]);
880 if (!hwc_display_[disp_id]) {
881 return -1;
882 }
883
884 return hwc_display_[disp_id]->SetDynamicDSIClock(bit_clk);
885 }
886
setCWBOutputBuffer(const::android::sp<IDisplayCWBCallback> & callback,uint32_t disp_id,const Rect & rect,bool post_processed,const hidl_handle & buffer)887 Return<int32_t> HWCSession::setCWBOutputBuffer(const ::android::sp<IDisplayCWBCallback> &callback,
888 uint32_t disp_id, const Rect &rect,
889 bool post_processed, const hidl_handle& buffer) {
890 return -1;
891 }
892
setQsyncMode(uint32_t disp_id,IDisplayConfig::QsyncMode mode)893 Return<int32_t> HWCSession::setQsyncMode(uint32_t disp_id, IDisplayConfig::QsyncMode mode) {
894 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
895 if (!hwc_display_[disp_id]) {
896 return -1;
897 }
898
899 QSyncMode qsync_mode = kQSyncModeNone;
900 switch (mode) {
901 case IDisplayConfig::QsyncMode::NONE:
902 qsync_mode = kQSyncModeNone;
903 break;
904 case IDisplayConfig::QsyncMode::WAIT_FOR_FENCES_ONE_FRAME:
905 qsync_mode = kQsyncModeOneShot;
906 break;
907 case IDisplayConfig::QsyncMode::WAIT_FOR_FENCES_EACH_FRAME:
908 qsync_mode = kQsyncModeOneShotContinuous;
909 break;
910 case IDisplayConfig::QsyncMode::WAIT_FOR_COMMIT_EACH_FRAME:
911 qsync_mode = kQSyncModeContinuous;
912 break;
913 }
914
915 hwc_display_[disp_id]->SetQSyncMode(qsync_mode);
916 return 0;
917 }
918
919 } // namespace sdm
920