1 /*
2 * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
5 * Copyright 2015 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #include <QService.h>
21 #include <binder/Parcel.h>
22 #include <core/buffer_allocator.h>
23 #include <cutils/properties.h>
24 #include <display_config.h>
25 #include <hardware_legacy/uevent.h>
26 #include <private/color_params.h>
27 #include <qd_utils.h>
28 #include <sync/sync.h>
29 #include <sys/prctl.h>
30 #include <sys/resource.h>
31 #include <utils/String16.h>
32 #include <utils/constants.h>
33 #include <utils/debug.h>
34 #include <QService.h>
35 #include <utils/utils.h>
36 #include <algorithm>
37 #include <utility>
38 #include <bitset>
39 #include <iterator>
40 #include <memory>
41 #include <string>
42 #include <thread>
43 #include <vector>
44
45 #include "hwc_buffer_allocator.h"
46 #include "hwc_session.h"
47 #include "hwc_debugger.h"
48
49 #define __CLASS__ "HWCSession"
50
51 #define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
52 #define HWC_UEVENT_DRM_EXT_HOTPLUG "mdss_mdp/drm/card"
53
54 #define MAX_BRIGHTNESS 255
55 #define BRIGHTNESS_FILE1 "/sys/class/leds/lcd-backlight/brightness"
56 #define BRIGHTNESS_FILE2 "/sys/class/backlight/panel0-backlight/brightness"
57
58 static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods;
59
60 hwc_module_t HAL_MODULE_INFO_SYM = {
61 .common = {
62 .tag = HARDWARE_MODULE_TAG,
63 .version_major = 3,
64 .version_minor = 0,
65 .id = HWC_HARDWARE_MODULE_ID,
66 .name = "QTI Hardware Composer Module",
67 .author = "CodeAurora Forum",
68 .methods = &g_hwc_module_methods,
69 .dso = 0,
70 .reserved = {0},
71 }
72 };
73
74 namespace sdm {
75
76 static HWCUEvent g_hwc_uevent_;
77 Locker HWCSession::locker_[HWCCallbacks::kNumDisplays];
78 bool HWCSession::power_on_pending_[HWCCallbacks::kNumDisplays];
79
80 static const int kSolidFillDelay = 100 * 1000;
81 int HWCSession::null_display_mode_ = 0;
82
83 // Map the known color modes to dataspace.
GetDataspaceFromColorMode(ColorMode mode)84 int32_t GetDataspaceFromColorMode(ColorMode mode) {
85 switch (mode) {
86 case ColorMode::SRGB:
87 case ColorMode::NATIVE:
88 return HAL_DATASPACE_V0_SRGB;
89 case ColorMode::DCI_P3:
90 return HAL_DATASPACE_DCI_P3;
91 case ColorMode::DISPLAY_P3:
92 return HAL_DATASPACE_DISPLAY_P3;
93 case ColorMode::BT2100_PQ:
94 return HAL_DATASPACE_BT2020_PQ;
95 case ColorMode::BT2100_HLG:
96 return HAL_DATASPACE_BT2020_HLG;
97 default:
98 return HAL_DATASPACE_UNKNOWN;
99 }
100 }
101
UEventThread(HWCUEvent * hwc_uevent)102 void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
103 const char *uevent_thread_name = "HWC_UeventThread";
104
105 prctl(PR_SET_NAME, uevent_thread_name, 0, 0, 0);
106 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
107
108 int status = uevent_init();
109 if (!status) {
110 std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
111 hwc_uevent->caller_cv_.notify_one();
112 DLOGE("Failed to init uevent with err %d", status);
113 return;
114 }
115
116 {
117 // Signal caller thread that worker thread is ready to listen to events.
118 std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
119 hwc_uevent->init_done_ = true;
120 hwc_uevent->caller_cv_.notify_one();
121 }
122
123 while (1) {
124 char uevent_data[PAGE_SIZE] = {};
125
126 // keep last 2 zeros to ensure double 0 termination
127 int length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
128
129 // scope of lock to this block only, so that caller is free to set event handler to nullptr;
130 {
131 std::lock_guard<std::mutex> guard(hwc_uevent->mutex_);
132 if (hwc_uevent->uevent_listener_) {
133 hwc_uevent->uevent_listener_->UEventHandler(uevent_data, length);
134 } else {
135 DLOGW("UEvent dropped. No uevent listener.");
136 }
137 }
138 }
139 }
140
HWCUEvent()141 HWCUEvent::HWCUEvent() {
142 std::unique_lock<std::mutex> caller_lock(mutex_);
143 std::thread thread(HWCUEvent::UEventThread, this);
144 thread.detach();
145 caller_cv_.wait(caller_lock);
146 }
147
Register(HWCUEventListener * uevent_listener)148 void HWCUEvent::Register(HWCUEventListener *uevent_listener) {
149 DLOGI("Set uevent listener = %p", uevent_listener);
150
151 std::lock_guard<std::mutex> obj(mutex_);
152 uevent_listener_ = uevent_listener;
153 }
154
HWCSession(const hw_module_t * module)155 HWCSession::HWCSession(const hw_module_t *module) {
156 hwc2_device_t::common.tag = HARDWARE_DEVICE_TAG;
157 hwc2_device_t::common.version = HWC_DEVICE_API_VERSION_2_0;
158 hwc2_device_t::common.module = const_cast<hw_module_t *>(module);
159 hwc2_device_t::common.close = Close;
160 hwc2_device_t::getCapabilities = GetCapabilities;
161 hwc2_device_t::getFunction = GetFunction;
162 }
163
Init()164 int HWCSession::Init() {
165 SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
166
167 int status = -EINVAL;
168 const char *qservice_name = "display.qservice";
169
170 if (!g_hwc_uevent_.InitDone()) {
171 return status;
172 }
173
174
175 #if defined(DISPLAY_CONFIG_1_2) && defined(CONFIG_BASEID_FROM_PROP)
176 char indices[kPropertyMax];
177 uint32_t index_start, index_size;
178 if (Debug::Get()->GetProperty(BUILTIN_BASEID_AND_SIZE_PROP, indices) == kErrorNone) {
179 if (std::sscanf(indices, "%d,%d", &index_start, &index_size) == 2) {
180 setDisplayIndex(IDisplayConfig::DisplayTypeExt::DISPLAY_BUILTIN,
181 index_start, index_size);
182 }
183 }
184 if (Debug::Get()->GetProperty(PLUGGABLE_BASEID_AND_SIZE_PROP, indices) == kErrorNone) {
185 if (std::sscanf(indices, "%d,%d", &index_start, &index_size) == 2) {
186 setDisplayIndex(IDisplayConfig::DisplayTypeExt::DISPLAY_PLUGGABLE,
187 index_start, index_size);
188 }
189 }
190 if (Debug::Get()->GetProperty(VIRTUAL_BASEID_AND_SIZE_PROP, indices) == kErrorNone) {
191 if (std::sscanf(indices, "%d,%d", &index_start, &index_size) == 2) {
192 setDisplayIndex(IDisplayConfig::DisplayTypeExt::DISPLAY_VIRTUAL,
193 index_start, index_size);
194 }
195 }
196 #endif
197
198 // Start QService and connect to it.
199 qService::QService::init();
200 android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>(
201 android::defaultServiceManager()->getService(android::String16(qservice_name)));
202
203 if (iqservice.get()) {
204 iqservice->connect(android::sp<qClient::IQClient>(this));
205 qservice_ = reinterpret_cast<qService::QService *>(iqservice.get());
206 } else {
207 DLOGE("Failed to acquire %s", qservice_name);
208 return -EINVAL;
209 }
210
211 StartServices();
212 HWCDebugHandler::Get()->GetProperty(ENABLE_NULL_DISPLAY_PROP, &null_display_mode_);
213 HWCDebugHandler::Get()->GetProperty(DISABLE_HOTPLUG_BWCHECK, &disable_hotplug_bwcheck_);
214 HWCDebugHandler::Get()->GetProperty(DISABLE_MASK_LAYER_HINT, &disable_mask_layer_hint_);
215
216 if (!null_display_mode_) {
217 g_hwc_uevent_.Register(this);
218 }
219
220 InitSupportedDisplaySlots();
221 // Create primary display here. Remaining builtin displays will be created after client has set
222 // display indexes which may happen sometime before callback is registered.
223 status = CreatePrimaryDisplay();
224 if (status) {
225 Deinit();
226 return status;
227 }
228
229 is_composer_up_ = true;
230
231 char const *brightness_file;
232 if (access(BRIGHTNESS_FILE1, F_OK) == 0) {
233 brightness_file = BRIGHTNESS_FILE1;
234 } else {
235 brightness_file = BRIGHTNESS_FILE2;
236 }
237 brightness_fd_ = open(brightness_file, O_WRONLY);
238 if (brightness_fd_ == -1) {
239 DLOGW("Unable to open brightness file: [%d] %s", errno, strerror(errno));
240 }
241
242 return 0;
243 }
244
Deinit()245 int HWCSession::Deinit() {
246 // Destroy all connected displays
247 DestroyDisplay(&map_info_primary_);
248
249 for (auto &map_info : map_info_builtin_) {
250 DestroyDisplay(&map_info);
251 }
252
253 for (auto &map_info : map_info_pluggable_) {
254 DestroyDisplay(&map_info);
255 }
256
257 for (auto &map_info : map_info_virtual_) {
258 DestroyDisplay(&map_info);
259 }
260
261 if (color_mgr_) {
262 color_mgr_->DestroyColorManager();
263 }
264
265 if (!null_display_mode_) {
266 g_hwc_uevent_.Register(nullptr);
267
268 DisplayError error = CoreInterface::DestroyCore();
269 if (error != kErrorNone) {
270 DLOGE("Display core de-initialization failed. Error = %d", error);
271 }
272 }
273
274 close(brightness_fd_);
275
276 return 0;
277 }
278
InitSupportedDisplaySlots()279 void HWCSession::InitSupportedDisplaySlots() {
280 // Default slots:
281 // Primary = 0, External = 1
282 // Additional external displays 2,3,...max_pluggable_count.
283 // Additional builtin displays max_pluggable_count + 1, max_pluggable_count + 2,...
284 // Last slots for virtual displays.
285 // Virtual display id is only for SF <--> HWC communication.
286 // It need not align with hwccomposer_defs
287
288 map_info_primary_.client_id = qdutils::DISPLAY_PRIMARY;
289
290 if (null_display_mode_) {
291 // Skip display slot initialization.
292 return;
293 }
294
295 DisplayError error = CoreInterface::CreateCore(&buffer_allocator_, &buffer_sync_handler_,
296 &socket_handler_, &core_intf_);
297 if (error != kErrorNone) {
298 DLOGE("Failed to create CoreInterface");
299 return;
300 }
301
302 HWDisplayInterfaceInfo hw_disp_info = {};
303 error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
304 if (error != kErrorNone) {
305 CoreInterface::DestroyCore();
306 DLOGE("Primary display type not recognized. Error = %d", error);
307 return;
308 }
309
310 int max_builtin = 0;
311 int max_pluggable = 0;
312 int max_virtual = 0;
313
314 error = core_intf_->GetMaxDisplaysSupported(kBuiltIn, &max_builtin);
315 if (error != kErrorNone) {
316 CoreInterface::DestroyCore();
317 DLOGE("Could not find maximum built-in displays supported. Error = %d", error);
318 return;
319 }
320
321 error = core_intf_->GetMaxDisplaysSupported(kPluggable, &max_pluggable);
322 if (error != kErrorNone) {
323 CoreInterface::DestroyCore();
324 DLOGE("Could not find maximum pluggable displays supported. Error = %d", error);
325 return;
326 }
327
328 error = core_intf_->GetMaxDisplaysSupported(kVirtual, &max_virtual);
329 if (error != kErrorNone) {
330 CoreInterface::DestroyCore();
331 DLOGE("Could not find maximum virtual displays supported. Error = %d", error);
332 return;
333 }
334
335 if (kPluggable == hw_disp_info.type) {
336 // If primary is a pluggable display, we have already used one pluggable display interface.
337 max_pluggable--;
338 } else {
339 max_builtin--;
340 }
341
342 // Init slots in accordance to h/w capability.
343 uint32_t disp_count = UINT32(std::min(max_pluggable, HWCCallbacks::kNumPluggable));
344 hwc2_display_t base_id = qdutils::DISPLAY_EXTERNAL;
345 map_info_pluggable_.resize(disp_count);
346 for (auto &map_info : map_info_pluggable_) {
347 map_info.client_id = base_id++;
348 }
349
350 disp_count = UINT32(std::min(max_builtin, HWCCallbacks::kNumBuiltIn));
351 map_info_builtin_.resize(disp_count);
352 for (auto &map_info : map_info_builtin_) {
353 map_info.client_id = base_id++;
354 }
355
356 disp_count = UINT32(std::min(max_virtual, HWCCallbacks::kNumVirtual));
357 map_info_virtual_.resize(disp_count);
358 for (auto &map_info : map_info_virtual_) {
359 map_info.client_id = base_id++;
360 }
361
362 // resize HDR supported map to total number of displays.
363 is_hdr_display_.resize(UINT32(base_id));
364 }
365
GetDisplayIndex(int dpy)366 int HWCSession::GetDisplayIndex(int dpy) {
367 DisplayMapInfo *map_info = nullptr;
368 switch (dpy) {
369 case qdutils::DISPLAY_PRIMARY:
370 map_info = &map_info_primary_;
371 break;
372 case qdutils::DISPLAY_EXTERNAL:
373 map_info = map_info_pluggable_.size() ? &map_info_pluggable_[0] : nullptr;
374 break;
375 case qdutils::DISPLAY_EXTERNAL_2:
376 map_info = (map_info_pluggable_.size() > 1) ? &map_info_pluggable_[1] : nullptr;
377 break;
378 case qdutils::DISPLAY_VIRTUAL:
379 map_info = map_info_virtual_.size() ? &map_info_virtual_[0] : nullptr;
380 break;
381 case qdutils::DISPLAY_BUILTIN_2:
382 map_info = map_info_builtin_.size() ? &map_info_builtin_[0] : nullptr;
383 break;
384 default:
385 DLOGW("Unknown display %d.", dpy);
386 break;
387 }
388
389 if (!map_info) {
390 DLOGE("Display index not found for display %d.", dpy);
391 return -1;
392 }
393
394 return INT(map_info->client_id);
395 }
396
Open(const hw_module_t * module,const char * name,hw_device_t ** device)397 int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
398 if (!module || !name || !device) {
399 DLOGE("Invalid parameters.");
400 return -EINVAL;
401 }
402
403 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
404 HWCSession *hwc_session = new HWCSession(module);
405 if (!hwc_session) {
406 return -ENOMEM;
407 }
408
409 int status = hwc_session->Init();
410 if (status != 0) {
411 delete hwc_session;
412 hwc_session = NULL;
413 return status;
414 }
415
416 hwc2_device_t *composer_device = hwc_session;
417 *device = reinterpret_cast<hw_device_t *>(composer_device);
418 }
419
420 return 0;
421 }
422
Close(hw_device_t * device)423 int HWCSession::Close(hw_device_t *device) {
424 if (!device) {
425 return -EINVAL;
426 }
427
428 hwc2_device_t *composer_device = reinterpret_cast<hwc2_device_t *>(device);
429 HWCSession *hwc_session = static_cast<HWCSession *>(composer_device);
430
431 hwc_session->Deinit();
432
433 return 0;
434 }
435
GetCapabilities(struct hwc2_device * device,uint32_t * outCount,int32_t * outCapabilities)436 void HWCSession::GetCapabilities(struct hwc2_device *device, uint32_t *outCount,
437 int32_t *outCapabilities) {
438 if (!outCount) {
439 return;
440 }
441
442 int value = 0;
443 bool disable_skip_validate = false;
444 if (Debug::Get()->GetProperty(DISABLE_SKIP_VALIDATE_PROP, &value) == kErrorNone) {
445 disable_skip_validate = (value == 1);
446 }
447 uint32_t count = 1 + (disable_skip_validate ? 0 : 1);
448
449 if (outCapabilities != nullptr && (*outCount >= count)) {
450 outCapabilities[0] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
451 if (!disable_skip_validate) {
452 outCapabilities[1] = HWC2_CAPABILITY_SKIP_VALIDATE;
453 }
454 }
455 *outCount = count;
456 }
457
GetDisplayBrightnessSupport(hwc2_device_t * device,hwc2_display_t display,bool * out_support)458 int32_t HWCSession::GetDisplayBrightnessSupport(hwc2_device_t *device, hwc2_display_t display,
459 bool *out_support) {
460 HWCSession *hwc_session = static_cast<HWCSession *>(device);
461 *out_support = display == HWC_DISPLAY_PRIMARY && hwc_session->brightness_fd_ != -1;
462 return INT32(HWC2::Error::None);
463 }
464
465 template <typename PFN, typename T>
AsFP(T function)466 static hwc2_function_pointer_t AsFP(T function) {
467 static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
468 return reinterpret_cast<hwc2_function_pointer_t>(function);
469 }
470
471 // HWC2 functions returned in GetFunction
472 // Defined in the same order as in the HWC2 header
473
AcceptDisplayChanges(hwc2_device_t * device,hwc2_display_t display)474 int32_t HWCSession::AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display) {
475 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::AcceptDisplayChanges);
476 }
477
CreateLayer(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t * out_layer_id)478 int32_t HWCSession::CreateLayer(hwc2_device_t *device, hwc2_display_t display,
479 hwc2_layer_t *out_layer_id) {
480 if (!out_layer_id) {
481 return HWC2_ERROR_BAD_PARAMETER;
482 }
483
484 return CallDisplayFunction(device, display, &HWCDisplay::CreateLayer, out_layer_id);
485 }
486
CreateVirtualDisplay(hwc2_device_t * device,uint32_t width,uint32_t height,int32_t * format,hwc2_display_t * out_display_id)487 int32_t HWCSession::CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
488 int32_t *format, hwc2_display_t *out_display_id) {
489 // TODO(user): Handle concurrency with HDMI
490 if (!device) {
491 return HWC2_ERROR_BAD_DISPLAY;
492 }
493
494 if (!out_display_id || !width || !height || !format) {
495 return HWC2_ERROR_BAD_PARAMETER;
496 }
497
498 HWCSession *hwc_session = static_cast<HWCSession *>(device);
499 auto status = hwc_session->CreateVirtualDisplayObj(width, height, format, out_display_id);
500 if (status == HWC2::Error::None) {
501 DLOGI("Created virtual display id:% " PRIu64 ", res: %dx%d", *out_display_id, width, height);
502 } else {
503 DLOGE("Failed to create virtual display: %s", to_string(status).c_str());
504 }
505 return INT32(status);
506 }
507
DestroyLayer(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer)508 int32_t HWCSession::DestroyLayer(hwc2_device_t *device, hwc2_display_t display,
509 hwc2_layer_t layer) {
510 return CallDisplayFunction(device, display, &HWCDisplay::DestroyLayer, layer);
511 }
512
DestroyVirtualDisplay(hwc2_device_t * device,hwc2_display_t display)513 int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
514 if (!device || display >= HWCCallbacks::kNumDisplays) {
515 return HWC2_ERROR_BAD_DISPLAY;
516 }
517
518 auto *hwc_session = static_cast<HWCSession *>(device);
519 hwc2_display_t active_builtin_disp_id = hwc_session->GetActiveBuiltinDisplay();
520
521 if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
522 Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
523 std::bitset<kSecureMax> secure_sessions = 0;
524 hwc_session->hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
525 if (secure_sessions.any()) {
526 DLOGW("Secure session is active, defer destruction of virtual display id:%" PRIu64, display);
527 hwc_session->destroy_virtual_disp_pending_ = true;
528 return HWC2_ERROR_NONE;
529 }
530 }
531
532 for (auto &map_info : hwc_session->map_info_virtual_) {
533 if (map_info.client_id == display) {
534 DLOGI("Destroying virtual display id:%" PRIu64, display);
535 hwc_session->DestroyDisplay(&map_info);
536 break;
537 }
538 }
539
540 return HWC2_ERROR_NONE;
541 }
542
Dump(hwc2_device_t * device,uint32_t * out_size,char * out_buffer)543 void HWCSession::Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer) {
544 if (!device || !out_size) {
545 return;
546 }
547
548 auto *hwc_session = static_cast<HWCSession *>(device);
549 const size_t max_dump_size = 8192;
550
551 if (out_buffer == nullptr) {
552 *out_size = max_dump_size;
553 } else {
554 std::string s {};
555 for (int id = 0; id < HWCCallbacks::kNumDisplays; id++) {
556 SCOPE_LOCK(locker_[id]);
557 if (hwc_session->hwc_display_[id]) {
558 s += hwc_session->hwc_display_[id]->Dump();
559 }
560 }
561 auto copied = s.copy(out_buffer, std::min(s.size(), max_dump_size), 0);
562 *out_size = UINT32(copied);
563 }
564 }
565
GetMaxVirtualDisplayCount(hwc2_device_t * device)566 uint32_t HWCSession::GetMaxVirtualDisplayCount(hwc2_device_t *device) {
567 if (device == nullptr) {
568 return HWC2_ERROR_BAD_PARAMETER;
569 }
570
571 return 1;
572 }
573
GetActiveConfig(hwc2_device_t * device,hwc2_display_t display,hwc2_config_t * out_config)574 static int32_t GetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
575 hwc2_config_t *out_config) {
576 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetActiveConfig, out_config);
577 }
578
GetChangedCompositionTypes(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_num_elements,hwc2_layer_t * out_layers,int32_t * out_types)579 static int32_t GetChangedCompositionTypes(hwc2_device_t *device, hwc2_display_t display,
580 uint32_t *out_num_elements, hwc2_layer_t *out_layers,
581 int32_t *out_types) {
582 // null_ptr check only for out_num_elements, as out_layers and out_types can be null.
583 if (!out_num_elements) {
584 return HWC2_ERROR_BAD_PARAMETER;
585 }
586 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetChangedCompositionTypes,
587 out_num_elements, out_layers, out_types);
588 }
589
GetClientTargetSupport(hwc2_device_t * device,hwc2_display_t display,uint32_t width,uint32_t height,int32_t format,int32_t dataspace)590 static int32_t GetClientTargetSupport(hwc2_device_t *device, hwc2_display_t display, uint32_t width,
591 uint32_t height, int32_t format, int32_t dataspace) {
592 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetClientTargetSupport,
593 width, height, format, dataspace);
594 }
595
GetColorModes(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_num_modes,int32_t * int_out_modes)596 static int32_t GetColorModes(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_num_modes,
597 int32_t /*ColorMode*/ *int_out_modes) {
598 auto out_modes = reinterpret_cast<ColorMode *>(int_out_modes);
599 if (out_num_modes == nullptr) {
600 return HWC2_ERROR_BAD_PARAMETER;
601 }
602 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetColorModes, out_num_modes,
603 out_modes);
604 }
605
GetRenderIntents(hwc2_device_t * device,hwc2_display_t display,int32_t int_mode,uint32_t * out_num_intents,int32_t * int_out_intents)606 static int32_t GetRenderIntents(hwc2_device_t *device, hwc2_display_t display,
607 int32_t /*ColorMode*/ int_mode, uint32_t *out_num_intents,
608 int32_t /*RenderIntent*/ *int_out_intents) {
609 auto mode = static_cast<ColorMode>(int_mode);
610 auto out_intents = reinterpret_cast<RenderIntent *>(int_out_intents);
611 if (out_num_intents == nullptr) {
612 return HWC2_ERROR_BAD_PARAMETER;
613 }
614
615 if (mode < ColorMode::NATIVE || mode > ColorMode::BT2100_HLG) {
616 DLOGE("Invalid ColorMode: %d", mode);
617 return HWC2_ERROR_BAD_PARAMETER;
618 }
619 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetRenderIntents, mode,
620 out_num_intents, out_intents);
621 }
622
GetDataspaceSaturationMatrix(hwc2_device_t * device,int32_t int_dataspace,float * out_matrix)623 static int32_t GetDataspaceSaturationMatrix(hwc2_device_t *device,
624 int32_t /*Dataspace*/ int_dataspace,
625 float *out_matrix) {
626 auto dataspace = static_cast<Dataspace>(int_dataspace);
627 if (device == nullptr || out_matrix == nullptr || dataspace != Dataspace::SRGB_LINEAR) {
628 return HWC2_ERROR_BAD_PARAMETER;
629 }
630 // We only have the matrix for sRGB
631 float saturation_matrix[kDataspaceSaturationMatrixCount] = { 1.0, 0.0, 0.0, 0.0, \
632 0.0, 1.0, 0.0, 0.0, \
633 0.0, 0.0, 1.0, 0.0, \
634 0.0, 0.0, 0.0, 1.0 };
635
636 // TODO(user): This value should ideally be retrieved from a QDCM configuration file
637 char value[kPropertyMax] = {};
638 if (Debug::Get()->GetProperty(DATASPACE_SATURATION_MATRIX_PROP, value) != kErrorNone) {
639 DLOGW("Undefined saturation matrix");
640 return HWC2_ERROR_BAD_CONFIG;
641 }
642 std::string value_string(value);
643 std::size_t start = 0, end = 0;
644 int index = 0;
645 while ((end = value_string.find(",", start)) != std::string::npos) {
646 saturation_matrix[index] = std::stof(value_string.substr(start, end - start));
647 start = end + 1;
648 index++;
649 // We expect a 3x3, SF needs 4x4, keep the last row/column identity
650 if ((index + 1) % 4 == 0) {
651 index++;
652 }
653 }
654 saturation_matrix[index] = std::stof(value_string.substr(start, end - start));
655 if (index < kDataspaceSaturationPropertyElements - 1) {
656 // The property must have kDataspaceSaturationPropertyElements delimited by commas
657 DLOGW("Invalid saturation matrix defined");
658 return HWC2_ERROR_BAD_CONFIG;
659 }
660 for (int32_t i = 0; i < kDataspaceSaturationMatrixCount; i += 4) {
661 DLOGD("%f %f %f %f", saturation_matrix[i], saturation_matrix[i + 1], saturation_matrix[i + 2],
662 saturation_matrix[i + 3]);
663 }
664 for (uint32_t i = 0; i < kDataspaceSaturationMatrixCount; i++) {
665 out_matrix[i] = saturation_matrix[i];
666 }
667 return HWC2_ERROR_NONE;
668 }
669
GetPerFrameMetadataKeys(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_num_keys,int32_t * int_out_keys)670 static int32_t GetPerFrameMetadataKeys(hwc2_device_t *device, hwc2_display_t display,
671 uint32_t *out_num_keys, int32_t *int_out_keys) {
672 auto out_keys = reinterpret_cast<PerFrameMetadataKey *>(int_out_keys);
673 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetPerFrameMetadataKeys,
674 out_num_keys, out_keys);
675 }
676
SetLayerPerFrameMetadata(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,uint32_t num_elements,const int32_t * int_keys,const float * metadata)677 static int32_t SetLayerPerFrameMetadata(hwc2_device_t *device, hwc2_display_t display,
678 hwc2_layer_t layer, uint32_t num_elements,
679 const int32_t *int_keys, const float *metadata) {
680 auto keys = reinterpret_cast<const PerFrameMetadataKey *>(int_keys);
681 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerPerFrameMetadata,
682 num_elements, keys, metadata);
683 }
684
SetDisplayedContentSamplingEnabled(hwc2_device_t * device,hwc2_display_t display,int32_t enabled,uint8_t component_mask,uint64_t max_frames)685 static int32_t SetDisplayedContentSamplingEnabled(hwc2_device_t* device,
686 hwc2_display_t display,
687 int32_t enabled, uint8_t component_mask,
688 uint64_t max_frames) {
689 static constexpr int32_t validComponentMask =
690 HWC2_FORMAT_COMPONENT_0 | HWC2_FORMAT_COMPONENT_1 |
691 HWC2_FORMAT_COMPONENT_2 | HWC2_FORMAT_COMPONENT_3;
692 if (component_mask & ~validComponentMask) return HWC2_ERROR_BAD_PARAMETER;
693 return HWCSession::CallDisplayFunction(device, display,
694 &HWCDisplay::SetDisplayedContentSamplingEnabled,
695 enabled, component_mask, max_frames);
696 }
697
GetDisplayedContentSamplingAttributes(hwc2_device_t * device,hwc2_display_t display,int32_t * format,int32_t * dataspace,uint8_t * supported_components)698 static int32_t GetDisplayedContentSamplingAttributes(hwc2_device_t* device,
699 hwc2_display_t display,
700 int32_t* format,
701 int32_t* dataspace,
702 uint8_t* supported_components) {
703 return HWCSession::CallDisplayFunction(device, display,
704 &HWCDisplay::GetDisplayedContentSamplingAttributes,
705 format, dataspace, supported_components);
706 }
707
GetDisplayedContentSample(hwc2_device_t * device,hwc2_display_t display,uint64_t max_frames,uint64_t timestamp,uint64_t * numFrames,int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],uint64_t * samples[NUM_HISTOGRAM_COLOR_COMPONENTS])708 static int32_t GetDisplayedContentSample(
709 hwc2_device_t* device, hwc2_display_t display, uint64_t max_frames, uint64_t timestamp,
710 uint64_t* numFrames,
711 int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],
712 uint64_t* samples[NUM_HISTOGRAM_COLOR_COMPONENTS]) {
713
714 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayedContentSample,
715 max_frames, timestamp, numFrames, samples_size, samples);
716 }
717
GetDisplayAttribute(hwc2_device_t * device,hwc2_display_t display,hwc2_config_t config,int32_t int_attribute,int32_t * out_value)718 static int32_t GetDisplayAttribute(hwc2_device_t *device, hwc2_display_t display,
719 hwc2_config_t config, int32_t int_attribute,
720 int32_t *out_value) {
721 if (out_value == nullptr || int_attribute < HWC2_ATTRIBUTE_INVALID ||
722 int_attribute > HWC2_ATTRIBUTE_DPI_Y) {
723 return HWC2_ERROR_BAD_PARAMETER;
724 }
725 auto attribute = static_cast<HWC2::Attribute>(int_attribute);
726 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayAttribute, config,
727 attribute, out_value);
728 }
729
GetDisplayConfigs(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_num_configs,hwc2_config_t * out_configs)730 static int32_t GetDisplayConfigs(hwc2_device_t *device, hwc2_display_t display,
731 uint32_t *out_num_configs, hwc2_config_t *out_configs) {
732 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayConfigs,
733 out_num_configs, out_configs);
734 }
735
GetDisplayName(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_size,char * out_name)736 static int32_t GetDisplayName(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_size,
737 char *out_name) {
738 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayName, out_size,
739 out_name);
740 }
741
GetDisplayRequests(hwc2_device_t * device,hwc2_display_t display,int32_t * out_display_requests,uint32_t * out_num_elements,hwc2_layer_t * out_layers,int32_t * out_layer_requests)742 static int32_t GetDisplayRequests(hwc2_device_t *device, hwc2_display_t display,
743 int32_t *out_display_requests, uint32_t *out_num_elements,
744 hwc2_layer_t *out_layers, int32_t *out_layer_requests) {
745 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayRequests,
746 out_display_requests, out_num_elements, out_layers,
747 out_layer_requests);
748 }
749
GetDisplayType(hwc2_device_t * device,hwc2_display_t display,int32_t * out_type)750 static int32_t GetDisplayType(hwc2_device_t *device, hwc2_display_t display, int32_t *out_type) {
751 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayType, out_type);
752 }
753
754
GetHdrCapabilities(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_num_types,int32_t * out_types,float * out_max_luminance,float * out_max_average_luminance,float * out_min_luminance)755 static int32_t GetHdrCapabilities(hwc2_device_t* device, hwc2_display_t display,
756 uint32_t* out_num_types, int32_t* out_types,
757 float* out_max_luminance, float* out_max_average_luminance,
758 float* out_min_luminance) {
759 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetHdrCapabilities,
760 out_num_types, out_types, out_max_luminance,
761 out_max_average_luminance, out_min_luminance);
762 }
763
764
GetReleaseFences(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_num_elements,hwc2_layer_t * out_layers,int32_t * out_fences)765 static int32_t GetReleaseFences(hwc2_device_t *device, hwc2_display_t display,
766 uint32_t *out_num_elements, hwc2_layer_t *out_layers,
767 int32_t *out_fences) {
768 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetReleaseFences,
769 out_num_elements, out_layers, out_fences);
770 }
771
PresentDisplay(hwc2_device_t * device,hwc2_display_t display,int32_t * out_retire_fence)772 int32_t HWCSession::PresentDisplay(hwc2_device_t *device, hwc2_display_t display,
773 int32_t *out_retire_fence) {
774 HWCSession *hwc_session = static_cast<HWCSession *>(device);
775 auto status = HWC2::Error::BadDisplay;
776 DTRACE_SCOPED();
777
778 if (!hwc_session || (display >= HWCCallbacks::kNumDisplays)) {
779 DLOGW("Invalid Display : hwc session = %s display = %" PRIu64,
780 hwc_session ? "Valid" : "NULL", display);
781 return HWC2_ERROR_BAD_DISPLAY;
782 }
783
784 hwc_session->HandleSecureSession();
785 {
786 SEQUENCE_EXIT_SCOPE_LOCK(locker_[display]);
787 if (!hwc_session->hwc_display_[display]) {
788 DLOGW("Removed Display : display = %" PRIu64, display);
789 return HWC2_ERROR_BAD_DISPLAY;
790 }
791
792 if (out_retire_fence == nullptr) {
793 return HWC2_ERROR_BAD_PARAMETER;
794 }
795
796 if (power_on_pending_[display]) {
797 status = HWC2::Error::None;
798 } else {
799 status = hwc_session->PresentDisplayInternal(display, out_retire_fence);
800 if (status == HWC2::Error::None) {
801 // Check if hwc's refresh trigger is getting exercised.
802 if (hwc_session->callbacks_.NeedsRefresh(display)) {
803 hwc_session->hwc_display_[display]->SetPendingRefresh();
804 hwc_session->callbacks_.ResetRefresh(display);
805 }
806 status = hwc_session->hwc_display_[display]->Present(out_retire_fence);
807 }
808 }
809 }
810
811 if (status != HWC2::Error::None && status != HWC2::Error::NotValidated) {
812 SEQUENCE_CANCEL_SCOPE_LOCK(locker_[display]);
813 }
814
815 hwc_session->HandlePowerOnPending(display, *out_retire_fence);
816 hwc_session->HandleHotplugPending(display, *out_retire_fence);
817 hwc_session->HandlePendingRefresh();
818
819 return INT32(status);
820 }
821
HandlePendingRefresh()822 void HWCSession::HandlePendingRefresh() {
823 if (pending_refresh_.none()) {
824 return;
825 }
826
827 for (size_t i = 0; i < pending_refresh_.size(); i++) {
828 if (pending_refresh_.test(i)) {
829 Refresh(i);
830 break;
831 }
832 }
833
834 pending_refresh_.reset();
835 }
836
RegisterCallback(hwc2_device_t * device,int32_t descriptor,hwc2_callback_data_t callback_data,hwc2_function_pointer_t pointer)837 int32_t HWCSession::RegisterCallback(hwc2_device_t *device, int32_t descriptor,
838 hwc2_callback_data_t callback_data,
839 hwc2_function_pointer_t pointer) {
840 if (!device) {
841 return HWC2_ERROR_BAD_PARAMETER;
842 }
843 HWCSession *hwc_session = static_cast<HWCSession *>(device);
844 SCOPE_LOCK(hwc_session->callbacks_lock_);
845 auto desc = static_cast<HWC2::Callback>(descriptor);
846 auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
847 if (error != HWC2::Error::None) {
848 return INT32(error);
849 }
850
851 DLOGD("%s callback: %s", pointer ? "Registering" : "Deregistering", to_string(desc).c_str());
852 if (descriptor == HWC2_CALLBACK_HOTPLUG) {
853 if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) {
854 DLOGI("Hotplugging primary...");
855 hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
856 }
857 // Create displays since they should now have their final display indices set.
858 DLOGI("Handling built-in displays...");
859 if (hwc_session->HandleBuiltInDisplays()) {
860 DLOGW("Failed handling built-in displays.");
861 }
862 DLOGI("Handling pluggable displays...");
863 int32_t err = hwc_session->HandlePluggableDisplays(false);
864 if (err) {
865 DLOGW("All displays could not be created. Error %d '%s'. Hotplug handling %s.", err,
866 strerror(abs(err)), hwc_session->hotplug_pending_event_ == kHotPlugEvent ? "deferred" :
867 "dropped");
868 }
869 hwc_session->client_connected_ = true;
870 }
871 hwc_session->need_invalidate_ = false;
872 hwc_session->callbacks_lock_.Broadcast();
873 return HWC2_ERROR_NONE;
874 }
875
SetActiveConfig(hwc2_device_t * device,hwc2_display_t display,hwc2_config_t config)876 static int32_t SetActiveConfig(hwc2_device_t *device, hwc2_display_t display,
877 hwc2_config_t config) {
878 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetActiveConfig, config);
879 }
880
SetClientTarget(hwc2_device_t * device,hwc2_display_t display,buffer_handle_t target,int32_t acquire_fence,int32_t dataspace,hwc_region_t damage)881 static int32_t SetClientTarget(hwc2_device_t *device, hwc2_display_t display,
882 buffer_handle_t target, int32_t acquire_fence,
883 int32_t dataspace, hwc_region_t damage) {
884 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetClientTarget, target,
885 acquire_fence, dataspace, damage);
886 }
887
SetColorMode(hwc2_device_t * device,hwc2_display_t display,int32_t int_mode)888 int32_t HWCSession::SetColorMode(hwc2_device_t *device, hwc2_display_t display,
889 int32_t /*ColorMode*/ int_mode) {
890 auto mode = static_cast<ColorMode>(int_mode);
891 if (mode < ColorMode::NATIVE || mode > ColorMode::BT2100_HLG) {
892 return HWC2_ERROR_BAD_PARAMETER;
893 }
894 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode);
895 }
896
SetColorModeWithRenderIntent(hwc2_device_t * device,hwc2_display_t display,int32_t int_mode,int32_t int_render_intent)897 int32_t HWCSession::SetColorModeWithRenderIntent(hwc2_device_t *device, hwc2_display_t display,
898 int32_t /*ColorMode*/ int_mode,
899 int32_t /*RenderIntent*/ int_render_intent) {
900 auto mode = static_cast<ColorMode>(int_mode);
901 if (mode < ColorMode::NATIVE || mode > ColorMode::BT2100_HLG) {
902 return HWC2_ERROR_BAD_PARAMETER;
903 }
904 auto render_intent = static_cast<RenderIntent>(int_render_intent);
905 if ((render_intent < RenderIntent::COLORIMETRIC) ||
906 (render_intent > RenderIntent::TONE_MAP_ENHANCE)) {
907 DLOGE("Invalid RenderIntent: %d", render_intent);
908 return HWC2_ERROR_BAD_PARAMETER;
909 }
910 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorModeWithRenderIntent,
911 mode, render_intent);
912 }
913
SetColorTransform(hwc2_device_t * device,hwc2_display_t display,const float * matrix,int32_t hint)914 int32_t HWCSession::SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
915 const float *matrix,
916 int32_t /*android_color_transform_t*/ hint) {
917 if (!matrix || hint < HAL_COLOR_TRANSFORM_IDENTITY ||
918 hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA) {
919 return HWC2_ERROR_BAD_PARAMETER;
920 }
921 android_color_transform_t transform_hint = static_cast<android_color_transform_t>(hint);
922 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorTransform, matrix,
923 transform_hint);
924 }
925
SetCursorPosition(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,int32_t x,int32_t y)926 static int32_t SetCursorPosition(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
927 int32_t x, int32_t y) {
928 auto status = INT32(HWC2::Error::None);
929 status = HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetCursorPosition,
930 layer, x, y);
931 if (status == INT32(HWC2::Error::None)) {
932 // Update cursor position
933 HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetCursorPosition, x, y);
934 }
935 return status;
936 }
937
SetLayerBlendMode(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,int32_t int_mode)938 static int32_t SetLayerBlendMode(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
939 int32_t int_mode) {
940 if (int_mode < HWC2_BLEND_MODE_INVALID || int_mode > HWC2_BLEND_MODE_COVERAGE) {
941 return HWC2_ERROR_BAD_PARAMETER;
942 }
943 auto mode = static_cast<HWC2::BlendMode>(int_mode);
944 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBlendMode, mode);
945 }
946
SetLayerBuffer(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,buffer_handle_t buffer,int32_t acquire_fence)947 static int32_t SetLayerBuffer(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
948 buffer_handle_t buffer, int32_t acquire_fence) {
949 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBuffer, buffer,
950 acquire_fence);
951 }
952
SetLayerColor(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,hwc_color_t color)953 static int32_t SetLayerColor(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
954 hwc_color_t color) {
955 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerColor, color);
956 }
957
SetLayerCompositionType(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,int32_t int_type)958 static int32_t SetLayerCompositionType(hwc2_device_t *device, hwc2_display_t display,
959 hwc2_layer_t layer, int32_t int_type) {
960 auto type = static_cast<HWC2::Composition>(int_type);
961 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerCompositionType,
962 type);
963 }
964
SetLayerDataspace(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,int32_t dataspace)965 static int32_t SetLayerDataspace(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
966 int32_t dataspace) {
967 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDataspace,
968 dataspace);
969 }
970
SetLayerDisplayFrame(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,hwc_rect_t frame)971 static int32_t SetLayerDisplayFrame(hwc2_device_t *device, hwc2_display_t display,
972 hwc2_layer_t layer, hwc_rect_t frame) {
973 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDisplayFrame,
974 frame);
975 }
976
SetLayerPlaneAlpha(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,float alpha)977 static int32_t SetLayerPlaneAlpha(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
978 float alpha) {
979 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerPlaneAlpha,
980 alpha);
981 }
982
SetLayerSourceCrop(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,hwc_frect_t crop)983 static int32_t SetLayerSourceCrop(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
984 hwc_frect_t crop) {
985 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSourceCrop, crop);
986 }
987
SetLayerSurfaceDamage(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,hwc_region_t damage)988 static int32_t SetLayerSurfaceDamage(hwc2_device_t *device, hwc2_display_t display,
989 hwc2_layer_t layer, hwc_region_t damage) {
990 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSurfaceDamage,
991 damage);
992 }
993
SetLayerTransform(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,int32_t int_transform)994 static int32_t SetLayerTransform(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
995 int32_t int_transform) {
996 auto transform = static_cast<HWC2::Transform>(int_transform);
997 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerTransform,
998 transform);
999 }
1000
SetLayerVisibleRegion(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,hwc_region_t visible)1001 static int32_t SetLayerVisibleRegion(hwc2_device_t *device, hwc2_display_t display,
1002 hwc2_layer_t layer, hwc_region_t visible) {
1003 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerVisibleRegion,
1004 visible);
1005 }
1006
SetLayerZOrder(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,uint32_t z)1007 static int32_t SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer,
1008 uint32_t z) {
1009 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z);
1010 }
1011
SetLayerColorTransform(hwc2_device_t * device,hwc2_display_t display,hwc2_layer_t layer,const float * matrix)1012 static int32_t SetLayerColorTransform(hwc2_device_t *device, hwc2_display_t display,
1013 hwc2_layer_t layer, const float *matrix) {
1014 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerColorTransform,
1015 matrix);
1016 }
1017
SetOutputBuffer(hwc2_device_t * device,hwc2_display_t display,buffer_handle_t buffer,int32_t releaseFence)1018 int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
1019 buffer_handle_t buffer, int32_t releaseFence) {
1020 if (!device) {
1021 return HWC2_ERROR_BAD_PARAMETER;
1022 }
1023
1024 auto *hwc_session = static_cast<HWCSession *>(device);
1025 if (INT32(display) != hwc_session->GetDisplayIndex(qdutils::DISPLAY_VIRTUAL)) {
1026 return HWC2_ERROR_UNSUPPORTED;
1027 }
1028
1029 SCOPE_LOCK(locker_[display]);
1030 if (hwc_session->hwc_display_[display]) {
1031 auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_session->hwc_display_[display]);
1032 auto status = vds->SetOutputBuffer(buffer, releaseFence);
1033 return INT32(status);
1034 } else {
1035 return HWC2_ERROR_BAD_DISPLAY;
1036 }
1037 }
1038
SetPowerMode(hwc2_device_t * device,hwc2_display_t display,int32_t int_mode)1039 int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) {
1040 if (display >= HWCCallbacks::kNumDisplays) {
1041 return HWC2_ERROR_BAD_DISPLAY;
1042 }
1043
1044 // validate device and also avoid undefined behavior in cast to HWC2::PowerMode
1045 if (!device || int_mode < HWC2_POWER_MODE_OFF || int_mode > HWC2_POWER_MODE_DOZE_SUSPEND) {
1046 return HWC2_ERROR_BAD_PARAMETER;
1047 }
1048
1049 HWCSession *hwc_session = static_cast<HWCSession *>(device);
1050 if (hwc_session->power_on_pending_[display]) {
1051 DLOGW("Set power mode is not allowed during secure display session");
1052 return HWC2_ERROR_UNSUPPORTED;
1053 }
1054
1055 auto mode = static_cast<HWC2::PowerMode>(int_mode);
1056
1057 // all displays support on/off. Check for doze modes
1058 int support = 0;
1059 auto status = hwc_session->GetDozeSupport(device, display, &support);
1060 if (status != HWC2_ERROR_NONE) {
1061 DLOGE("Failed to get doze support Error = %d", status);
1062 return INT32(status);
1063 }
1064
1065 if (!support && (mode == HWC2::PowerMode::Doze || mode == HWC2::PowerMode::DozeSuspend)) {
1066 return HWC2_ERROR_UNSUPPORTED;
1067 }
1068
1069 auto error = CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode,
1070 false /* teardown */);
1071 if (error != HWC2_ERROR_NONE) {
1072 return error;
1073 }
1074 // Reset idle pc ref count on suspend, as we enable idle pc during suspend.
1075 if (mode == HWC2::PowerMode::Off) {
1076 hwc_session->idle_pc_ref_cnt_ = 0;
1077 }
1078
1079 hwc_session->UpdateThrottlingRate();
1080
1081 // Trigger refresh for doze mode to take effect.
1082 if (mode == HWC2::PowerMode::Doze) {
1083 hwc_session->Refresh(display);
1084 // Trigger one more refresh for PP features to take effect.
1085 hwc_session->pending_refresh_.set(UINT32(display));
1086 } else {
1087 // Reset the pending refresh bit
1088 hwc_session->pending_refresh_.reset(UINT32(display));
1089 }
1090
1091 return HWC2_ERROR_NONE;
1092 }
1093
SetVsyncEnabled(hwc2_device_t * device,hwc2_display_t display,int32_t int_enabled)1094 int32_t HWCSession::SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display,
1095 int32_t int_enabled) {
1096 // avoid undefined behavior in cast to HWC2::Vsync
1097 if (int_enabled < HWC2_VSYNC_INVALID || int_enabled > HWC2_VSYNC_DISABLE) {
1098 return HWC2_ERROR_BAD_PARAMETER;
1099 }
1100
1101 auto enabled = static_cast<HWC2::Vsync>(int_enabled);
1102
1103 HWCSession *hwc_session = static_cast<HWCSession *>(device);
1104
1105 if (int_enabled == HWC2_VSYNC_ENABLE) {
1106 hwc_session->callbacks_.UpdateVsyncSource(display);
1107 }
1108
1109 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetVsyncEnabled, enabled);
1110 }
1111
GetDozeSupport(hwc2_device_t * device,hwc2_display_t display,int32_t * out_support)1112 int32_t HWCSession::GetDozeSupport(hwc2_device_t *device, hwc2_display_t display,
1113 int32_t *out_support) {
1114 if (!device || !out_support) {
1115 return HWC2_ERROR_BAD_PARAMETER;
1116 }
1117
1118 HWCSession *hwc_session = static_cast<HWCSession *>(device);
1119 HWCDisplay *hwc_display = hwc_session->hwc_display_[display];;
1120 if (display >= HWCCallbacks::kNumDisplays || (hwc_display == nullptr)) {
1121 DLOGE("Invalid Display %d Handle %s ", display, hwc_display ?
1122 "Valid" : "NULL");
1123 return HWC2_ERROR_BAD_DISPLAY;
1124 }
1125
1126 *out_support = 0;
1127 if (hwc_display->GetDisplayClass() == DISPLAY_CLASS_BUILTIN) {
1128 *out_support = 1;
1129 }
1130
1131 return HWC2_ERROR_NONE;
1132 }
1133
ValidateDisplay(hwc2_device_t * device,hwc2_display_t display,uint32_t * out_num_types,uint32_t * out_num_requests)1134 int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
1135 uint32_t *out_num_types, uint32_t *out_num_requests) {
1136 // out_num_types and out_num_requests will be non-NULL
1137 if (!device) {
1138 return HWC2_ERROR_BAD_PARAMETER;
1139 }
1140
1141 if (display >= HWCCallbacks::kNumDisplays) {
1142 return HWC2_ERROR_BAD_DISPLAY;
1143 }
1144 DTRACE_SCOPED();
1145 HWCSession *hwc_session = static_cast<HWCSession *>(device);
1146 // TODO(user): Handle secure session, handle QDCM solid fill
1147 auto status = HWC2::Error::BadDisplay;
1148 hwc_session->HandleSecureSession();
1149 {
1150 SEQUENCE_ENTRY_SCOPE_LOCK(locker_[display]);
1151 if (power_on_pending_[display]) {
1152 status = HWC2::Error::None;
1153 } else if (hwc_session->hwc_display_[display]) {
1154 hwc_session->hwc_display_[display]->SetFastPathComposition(false);
1155 status = hwc_session->ValidateDisplayInternal(display, out_num_types, out_num_requests);
1156 }
1157 }
1158
1159 // Sequence locking currently begins on Validate, so cancel the sequence lock on failures
1160 if (status != HWC2::Error::None && status != HWC2::Error::HasChanges) {
1161 SEQUENCE_CANCEL_SCOPE_LOCK(locker_[display]);
1162 }
1163
1164 return INT32(status);
1165 }
1166
GetDisplayCapabilities(hwc2_device_t * device,hwc2_display_t display,uint32_t * outNumCapabilities,uint32_t * outCapabilities)1167 int32_t HWCSession::GetDisplayCapabilities(hwc2_device_t* device, hwc2_display_t display,
1168 uint32_t* outNumCapabilities, uint32_t* outCapabilities) {
1169 if (outNumCapabilities == nullptr) {
1170 return INT32(HWC2::Error::None);
1171 }
1172
1173 bool brightness_support = false;
1174 auto status = GetDisplayBrightnessSupport(device, display, &brightness_support);
1175 if (status != HWC2_ERROR_NONE) {
1176 DLOGE("Failed to get display brightness support Error = %" PRId32 , status);
1177 return INT32(status);
1178 }
1179 int doze_support = 0;
1180 status = GetDozeSupport(device, display, &doze_support);
1181 if (status != HWC2_ERROR_NONE) {
1182 DLOGE("Failed to get doze support Error = %d", status);
1183 return INT32(status);
1184 }
1185
1186 uint32_t count = 1 + static_cast<uint32_t>(doze_support) + (brightness_support ? 1 : 0);
1187 int index = 0;
1188 if (outCapabilities != nullptr && (*outNumCapabilities >= count)) {
1189 outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
1190 if (doze_support == 1) {
1191 outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_DOZE;
1192 }
1193 if (brightness_support) {
1194 outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_BRIGHTNESS;
1195 }
1196 }
1197
1198 *outNumCapabilities = count;
1199 return INT32(HWC2::Error::None);
1200 }
1201
SetDisplayBrightness(hwc2_device_t * device,hwc2_display_t display,float brightness)1202 int32_t HWCSession::SetDisplayBrightness(hwc2_device_t *device, hwc2_display_t display,
1203 float brightness) {
1204 bool brightness_support = false;
1205 auto status = GetDisplayBrightnessSupport(device, display, &brightness_support);
1206 if (status != HWC2_ERROR_NONE) {
1207 return INT32(status);
1208 }
1209 if (!brightness_support) {
1210 return INT32(HWC2::Error::Unsupported);
1211 }
1212 int backlight = -1;
1213 if (brightness == -1.0f) {
1214 backlight = 0;
1215 } else if (brightness < 0.0f || brightness > 1.0f) {
1216 return INT32(HWC2::Error::BadParameter);
1217 } else {
1218 // 0 is reserved for "backlight off", so we scale the brightness from 1 to MAX_BRIGHTNESS.
1219 backlight = (int) ((MAX_BRIGHTNESS - 1.0f) * brightness + 1.0f);
1220 }
1221 char buff[20];
1222 int n = snprintf(buff, sizeof(buff), "%d\n", backlight);
1223 if (n < 0 || n >= sizeof(buff)) {
1224 return INT32(HWC2::Error::BadParameter);
1225 }
1226
1227 HWCSession *hwc_session = static_cast<HWCSession *>(device);
1228 long error = lseek(hwc_session->brightness_fd_, 0, SEEK_SET);
1229 if (error == -1) {
1230 DLOGW("Failed to rewind brightness file: [%d] %s", errno, strerror(errno));
1231 return INT32(HWC2::Error::NoResources);
1232 }
1233 error = write(hwc_session->brightness_fd_, buff, (size_t) n);
1234 if (error == -1) {
1235 DLOGW("Failed to write to brightness file: [%d] %s", errno, strerror(errno));
1236 return INT32(HWC2::Error::NoResources);
1237 }
1238 error = fsync(hwc_session->brightness_fd_);
1239 if (error == -1) {
1240 DLOGW("Failed to flush brightness file: [%d] %s", errno, strerror(errno));
1241 return INT32(HWC2::Error::NoResources);
1242 }
1243
1244 return INT32(HWC2::Error::None);
1245 }
1246
GetFunction(struct hwc2_device * device,int32_t int_descriptor)1247 hwc2_function_pointer_t HWCSession::GetFunction(struct hwc2_device *device,
1248 int32_t int_descriptor) {
1249 auto descriptor = static_cast<HWC2::FunctionDescriptor>(int_descriptor);
1250
1251 switch (descriptor) {
1252 case HWC2::FunctionDescriptor::AcceptDisplayChanges:
1253 return AsFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(HWCSession::AcceptDisplayChanges);
1254 case HWC2::FunctionDescriptor::CreateLayer:
1255 return AsFP<HWC2_PFN_CREATE_LAYER>(CreateLayer);
1256 case HWC2::FunctionDescriptor::CreateVirtualDisplay:
1257 return AsFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(HWCSession::CreateVirtualDisplay);
1258 case HWC2::FunctionDescriptor::DestroyLayer:
1259 return AsFP<HWC2_PFN_DESTROY_LAYER>(DestroyLayer);
1260 case HWC2::FunctionDescriptor::DestroyVirtualDisplay:
1261 return AsFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(HWCSession::DestroyVirtualDisplay);
1262 case HWC2::FunctionDescriptor::Dump:
1263 return AsFP<HWC2_PFN_DUMP>(HWCSession::Dump);
1264 case HWC2::FunctionDescriptor::GetActiveConfig:
1265 return AsFP<HWC2_PFN_GET_ACTIVE_CONFIG>(GetActiveConfig);
1266 case HWC2::FunctionDescriptor::GetChangedCompositionTypes:
1267 return AsFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(GetChangedCompositionTypes);
1268 case HWC2::FunctionDescriptor::GetClientTargetSupport:
1269 return AsFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(GetClientTargetSupport);
1270 case HWC2::FunctionDescriptor::GetColorModes:
1271 return AsFP<HWC2_PFN_GET_COLOR_MODES>(GetColorModes);
1272 case HWC2::FunctionDescriptor::GetDisplayAttribute:
1273 return AsFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(GetDisplayAttribute);
1274 case HWC2::FunctionDescriptor::GetDisplayConfigs:
1275 return AsFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(GetDisplayConfigs);
1276 case HWC2::FunctionDescriptor::GetDisplayName:
1277 return AsFP<HWC2_PFN_GET_DISPLAY_NAME>(GetDisplayName);
1278 case HWC2::FunctionDescriptor::GetDisplayRequests:
1279 return AsFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(GetDisplayRequests);
1280 case HWC2::FunctionDescriptor::GetDisplayType:
1281 return AsFP<HWC2_PFN_GET_DISPLAY_TYPE>(GetDisplayType);
1282 case HWC2::FunctionDescriptor::GetHdrCapabilities:
1283 return AsFP<HWC2_PFN_GET_HDR_CAPABILITIES>(GetHdrCapabilities);
1284 case HWC2::FunctionDescriptor::GetDozeSupport:
1285 return AsFP<HWC2_PFN_GET_DOZE_SUPPORT>(GetDozeSupport);
1286 case HWC2::FunctionDescriptor::GetMaxVirtualDisplayCount:
1287 return AsFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(HWCSession::GetMaxVirtualDisplayCount);
1288 case HWC2::FunctionDescriptor::GetReleaseFences:
1289 return AsFP<HWC2_PFN_GET_RELEASE_FENCES>(GetReleaseFences);
1290 case HWC2::FunctionDescriptor::PresentDisplay:
1291 return AsFP<HWC2_PFN_PRESENT_DISPLAY>(PresentDisplay);
1292 case HWC2::FunctionDescriptor::RegisterCallback:
1293 return AsFP<HWC2_PFN_REGISTER_CALLBACK>(RegisterCallback);
1294 case HWC2::FunctionDescriptor::SetActiveConfig:
1295 return AsFP<HWC2_PFN_SET_ACTIVE_CONFIG>(SetActiveConfig);
1296 case HWC2::FunctionDescriptor::SetClientTarget:
1297 return AsFP<HWC2_PFN_SET_CLIENT_TARGET>(SetClientTarget);
1298 case HWC2::FunctionDescriptor::SetColorMode:
1299 return AsFP<HWC2_PFN_SET_COLOR_MODE>(SetColorMode);
1300 case HWC2::FunctionDescriptor::SetColorTransform:
1301 return AsFP<HWC2_PFN_SET_COLOR_TRANSFORM>(SetColorTransform);
1302 case HWC2::FunctionDescriptor::SetCursorPosition:
1303 return AsFP<HWC2_PFN_SET_CURSOR_POSITION>(SetCursorPosition);
1304 case HWC2::FunctionDescriptor::SetLayerBlendMode:
1305 return AsFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(SetLayerBlendMode);
1306 case HWC2::FunctionDescriptor::SetLayerBuffer:
1307 return AsFP<HWC2_PFN_SET_LAYER_BUFFER>(SetLayerBuffer);
1308 case HWC2::FunctionDescriptor::SetLayerColor:
1309 return AsFP<HWC2_PFN_SET_LAYER_COLOR>(SetLayerColor);
1310 case HWC2::FunctionDescriptor::SetLayerCompositionType:
1311 return AsFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(SetLayerCompositionType);
1312 case HWC2::FunctionDescriptor::SetLayerDataspace:
1313 return AsFP<HWC2_PFN_SET_LAYER_DATASPACE>(SetLayerDataspace);
1314 case HWC2::FunctionDescriptor::SetLayerDisplayFrame:
1315 return AsFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(SetLayerDisplayFrame);
1316 case HWC2::FunctionDescriptor::SetLayerPlaneAlpha:
1317 return AsFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(SetLayerPlaneAlpha);
1318 // Sideband stream is not supported
1319 // case HWC2::FunctionDescriptor::SetLayerSidebandStream:
1320 case HWC2::FunctionDescriptor::SetLayerSourceCrop:
1321 return AsFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(SetLayerSourceCrop);
1322 case HWC2::FunctionDescriptor::SetLayerSurfaceDamage:
1323 return AsFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(SetLayerSurfaceDamage);
1324 case HWC2::FunctionDescriptor::SetLayerTransform:
1325 return AsFP<HWC2_PFN_SET_LAYER_TRANSFORM>(SetLayerTransform);
1326 case HWC2::FunctionDescriptor::SetLayerVisibleRegion:
1327 return AsFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(SetLayerVisibleRegion);
1328 case HWC2::FunctionDescriptor::SetLayerZOrder:
1329 return AsFP<HWC2_PFN_SET_LAYER_Z_ORDER>(SetLayerZOrder);
1330 case HWC2::FunctionDescriptor::SetLayerColorTransform:
1331 return AsFP<HWC2_PFN_SET_LAYER_COLOR_TRANSFORM>(SetLayerColorTransform);
1332 case HWC2::FunctionDescriptor::SetOutputBuffer:
1333 return AsFP<HWC2_PFN_SET_OUTPUT_BUFFER>(SetOutputBuffer);
1334 case HWC2::FunctionDescriptor::SetPowerMode:
1335 return AsFP<HWC2_PFN_SET_POWER_MODE>(SetPowerMode);
1336 case HWC2::FunctionDescriptor::SetVsyncEnabled:
1337 return AsFP<HWC2_PFN_SET_VSYNC_ENABLED>(SetVsyncEnabled);
1338 case HWC2::FunctionDescriptor::ValidateDisplay:
1339 return AsFP<HWC2_PFN_VALIDATE_DISPLAY>(HWCSession::ValidateDisplay);
1340 case HWC2::FunctionDescriptor::SetReadbackBuffer:
1341 return AsFP<HWC2_PFN_SET_READBACK_BUFFER>(HWCSession::SetReadbackBuffer);
1342 case HWC2::FunctionDescriptor::GetReadbackBufferAttributes:
1343 return AsFP<HWC2_PFN_GET_READBACK_BUFFER_ATTRIBUTES>(HWCSession::GetReadbackBufferAttributes);
1344 case HWC2::FunctionDescriptor::GetReadbackBufferFence:
1345 return AsFP<HWC2_PFN_GET_READBACK_BUFFER_FENCE>(HWCSession::GetReadbackBufferFence);
1346 case HWC2::FunctionDescriptor::GetRenderIntents:
1347 return AsFP<HWC2_PFN_GET_RENDER_INTENTS>(GetRenderIntents);
1348 case HWC2::FunctionDescriptor::SetColorModeWithRenderIntent:
1349 return AsFP<HWC2_PFN_SET_COLOR_MODE_WITH_RENDER_INTENT>
1350 (HWCSession::SetColorModeWithRenderIntent);
1351 case HWC2::FunctionDescriptor::GetDataspaceSaturationMatrix:
1352 return AsFP<HWC2_PFN_GET_DATASPACE_SATURATION_MATRIX>(GetDataspaceSaturationMatrix);
1353 case HWC2::FunctionDescriptor::GetPerFrameMetadataKeys:
1354 return AsFP<HWC2_PFN_GET_PER_FRAME_METADATA_KEYS>(GetPerFrameMetadataKeys);
1355 case HWC2::FunctionDescriptor::SetLayerPerFrameMetadata:
1356 return AsFP<HWC2_PFN_SET_LAYER_PER_FRAME_METADATA>(SetLayerPerFrameMetadata);
1357 case HWC2::FunctionDescriptor::GetDisplayCapabilities:
1358 return AsFP<HWC2_PFN_GET_DISPLAY_CAPABILITIES>(GetDisplayCapabilities);
1359 case HWC2::FunctionDescriptor::SetDisplayBrightness:
1360 return AsFP<HWC2_PFN_SET_DISPLAY_BRIGHTNESS>(SetDisplayBrightness);
1361 case HWC2::FunctionDescriptor::SetDisplayedContentSamplingEnabled:
1362 return AsFP<HWC2_PFN_SET_DISPLAYED_CONTENT_SAMPLING_ENABLED>(SetDisplayedContentSamplingEnabled);
1363 case HWC2::FunctionDescriptor::GetDisplayedContentSamplingAttributes:
1364 return AsFP<HWC2_PFN_GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES>(GetDisplayedContentSamplingAttributes);
1365 case HWC2::FunctionDescriptor::GetDisplayedContentSample:
1366 return AsFP<HWC2_PFN_GET_DISPLAYED_CONTENT_SAMPLE>(GetDisplayedContentSample);
1367 case HWC2::FunctionDescriptor::GetDisplayIdentificationData:
1368 return AsFP<HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA>
1369 (HWCSession::GetDisplayIdentificationData);
1370 case HWC2::FunctionDescriptor::GetDisplayBrightnessSupport:
1371 return AsFP<HWC2_PFN_GET_DISPLAY_BRIGHTNESS_SUPPORT>(HWCSession::GetDisplayBrightnessSupport);
1372 default:
1373 DLOGD("Unknown/Unimplemented function descriptor: %d (%s)", int_descriptor,
1374 to_string(descriptor).c_str());
1375 return nullptr;
1376 }
1377 return nullptr;
1378 }
1379
CreateVirtualDisplayObj(uint32_t width,uint32_t height,int32_t * format,hwc2_display_t * out_display_id)1380 HWC2::Error HWCSession::CreateVirtualDisplayObj(uint32_t width, uint32_t height, int32_t *format,
1381 hwc2_display_t *out_display_id) {
1382 if (!client_connected_) {
1383 DLOGE("Client is not ready yet.");
1384 return HWC2::Error::BadDisplay;
1385 }
1386
1387 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
1388 if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
1389 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
1390 std::bitset<kSecureMax> secure_sessions = 0;
1391 if (hwc_display_[active_builtin_disp_id]) {
1392 hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
1393 }
1394 if (secure_sessions.any()) {
1395 DLOGE("Secure session is active, cannot create virtual display.");
1396 return HWC2::Error::Unsupported;
1397 } else if (IsPluggableDisplayConnected()) {
1398 DLOGE("External session is active, cannot create virtual display.");
1399 return HWC2::Error::Unsupported;
1400 }
1401 }
1402
1403 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1404 DisplayError error = hwc_display_[HWC_DISPLAY_PRIMARY]->TeardownConcurrentWriteback();
1405 if (error) {
1406 return HWC2::Error::NoResources;
1407 }
1408 }
1409
1410 HWDisplaysInfo hw_displays_info = {};
1411 DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
1412 if (error != kErrorNone) {
1413 DLOGE("Failed to get connected display list. Error = %d", error);
1414 return HWC2::Error::BadDisplay;
1415 }
1416
1417 // Lock confined to this scope
1418 int status = -EINVAL;
1419 for (auto &iter : hw_displays_info) {
1420 auto &info = iter.second;
1421 if (info.display_type != kVirtual) {
1422 continue;
1423 }
1424
1425 for (auto &map_info : map_info_virtual_) {
1426 hwc2_display_t client_id = map_info.client_id;
1427 {
1428 SCOPE_LOCK(locker_[client_id]);
1429 auto &hwc_display = hwc_display_[client_id];
1430 if (hwc_display) {
1431 continue;
1432 }
1433
1434 status = HWCDisplayVirtual::Create(core_intf_, &buffer_allocator_, &callbacks_, client_id,
1435 info.display_id, width, height, format, &hwc_display);
1436 // TODO(user): validate width and height support
1437 if (status) {
1438 return HWC2::Error::NoResources;
1439 }
1440
1441 is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
1442 DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d", client_id, width, height);
1443
1444 *out_display_id = client_id;
1445 map_info.disp_type = info.display_type;
1446 map_info.sdm_id = info.display_id;
1447 break;
1448 }
1449 }
1450 }
1451
1452 if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
1453 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
1454 hwc_display_[active_builtin_disp_id]->ResetValidation();
1455 }
1456
1457 return HWC2::Error::None;
1458 }
1459
IsPluggableDisplayConnected()1460 bool HWCSession::IsPluggableDisplayConnected() {
1461 for (auto &map_info : map_info_pluggable_) {
1462 if (hwc_display_[map_info.client_id]) {
1463 return true;
1464 }
1465 }
1466 return false;
1467 }
1468
1469 // Qclient methods
notifyCallback(uint32_t command,const android::Parcel * input_parcel,android::Parcel * output_parcel)1470 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
1471 android::Parcel *output_parcel) {
1472 android::status_t status = -EINVAL;
1473
1474 switch (command) {
1475 case qService::IQService::DYNAMIC_DEBUG:
1476 if (!input_parcel) {
1477 DLOGE("QService command = %d: input_parcel needed.", command);
1478 break;
1479 }
1480 status = 0;
1481 DynamicDebug(input_parcel);
1482 break;
1483
1484 case qService::IQService::SCREEN_REFRESH:
1485 if (!input_parcel) {
1486 DLOGE("QService command = %d: input_parcel needed.", command);
1487 break;
1488 }
1489 status = RefreshScreen(input_parcel);
1490 break;
1491
1492 case qService::IQService::SET_IDLE_TIMEOUT:
1493 if (!input_parcel) {
1494 DLOGE("QService command = %d: input_parcel needed.", command);
1495 break;
1496 }
1497 status = setIdleTimeout(UINT32(input_parcel->readInt32()));
1498 break;
1499
1500 case qService::IQService::SET_FRAME_DUMP_CONFIG:
1501 if (!input_parcel) {
1502 DLOGE("QService command = %d: input_parcel needed.", command);
1503 break;
1504 }
1505 status = SetFrameDumpConfig(input_parcel);
1506 break;
1507
1508 case qService::IQService::SET_MAX_PIPES_PER_MIXER:
1509 if (!input_parcel) {
1510 DLOGE("QService command = %d: input_parcel needed.", command);
1511 break;
1512 }
1513 status = SetMaxMixerStages(input_parcel);
1514 break;
1515
1516 case qService::IQService::SET_DISPLAY_MODE:
1517 if (!input_parcel) {
1518 DLOGE("QService command = %d: input_parcel needed.", command);
1519 break;
1520 }
1521 status = SetDisplayMode(input_parcel);
1522 break;
1523
1524 case qService::IQService::SET_SECONDARY_DISPLAY_STATUS: {
1525 if (!input_parcel || !output_parcel) {
1526 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1527 break;
1528 }
1529 int disp_id = INT(input_parcel->readInt32());
1530 HWCDisplay::DisplayStatus disp_status =
1531 static_cast<HWCDisplay::DisplayStatus>(input_parcel->readInt32());
1532 status = SetSecondaryDisplayStatus(disp_id, disp_status);
1533 output_parcel->writeInt32(status);
1534 }
1535 break;
1536
1537 case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
1538 if (!input_parcel) {
1539 DLOGE("QService command = %d: input_parcel needed.", command);
1540 break;
1541 }
1542 status = ConfigureRefreshRate(input_parcel);
1543 break;
1544
1545 case qService::IQService::SET_VIEW_FRAME:
1546 status = 0;
1547 break;
1548
1549 case qService::IQService::TOGGLE_SCREEN_UPDATES: {
1550 if (!input_parcel || !output_parcel) {
1551 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1552 break;
1553 }
1554 int32_t input = input_parcel->readInt32();
1555 status = toggleScreenUpdate(input == 1);
1556 output_parcel->writeInt32(status);
1557 }
1558 break;
1559
1560 case qService::IQService::QDCM_SVC_CMDS:
1561 if (!input_parcel || !output_parcel) {
1562 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1563 break;
1564 }
1565 status = QdcmCMDHandler(input_parcel, output_parcel);
1566 break;
1567
1568 case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED: {
1569 if (!input_parcel || !output_parcel) {
1570 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1571 break;
1572 }
1573 int disp_id = input_parcel->readInt32();
1574 uint32_t min_enc_level = UINT32(input_parcel->readInt32());
1575 status = MinHdcpEncryptionLevelChanged(disp_id, min_enc_level);
1576 output_parcel->writeInt32(status);
1577 }
1578 break;
1579
1580 case qService::IQService::CONTROL_PARTIAL_UPDATE: {
1581 if (!input_parcel || !output_parcel) {
1582 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1583 break;
1584 }
1585 int disp_id = input_parcel->readInt32();
1586 uint32_t enable = UINT32(input_parcel->readInt32());
1587 status = ControlPartialUpdate(disp_id, enable == 1);
1588 output_parcel->writeInt32(status);
1589 }
1590 break;
1591
1592 case qService::IQService::SET_ACTIVE_CONFIG: {
1593 if (!input_parcel) {
1594 DLOGE("QService command = %d: input_parcel needed.", command);
1595 break;
1596 }
1597 uint32_t config = UINT32(input_parcel->readInt32());
1598 int disp_id = input_parcel->readInt32();
1599 status = SetActiveConfigIndex(disp_id, config);
1600 }
1601 break;
1602
1603 case qService::IQService::GET_ACTIVE_CONFIG: {
1604 if (!input_parcel || !output_parcel) {
1605 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1606 break;
1607 }
1608 int disp_id = input_parcel->readInt32();
1609 uint32_t config = 0;
1610 status = GetActiveConfigIndex(disp_id, &config);
1611 output_parcel->writeInt32(INT(config));
1612 }
1613 break;
1614
1615 case qService::IQService::GET_CONFIG_COUNT: {
1616 if (!input_parcel || !output_parcel) {
1617 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1618 break;
1619 }
1620 int disp_id = input_parcel->readInt32();
1621 uint32_t count = 0;
1622 status = GetConfigCount(disp_id, &count);
1623 output_parcel->writeInt32(INT(count));
1624 }
1625 break;
1626
1627 case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
1628 if (!input_parcel || !output_parcel) {
1629 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1630 break;
1631 }
1632 status = GetDisplayAttributesForConfig(input_parcel, output_parcel);
1633 break;
1634
1635 case qService::IQService::GET_PANEL_BRIGHTNESS: {
1636 if (!output_parcel) {
1637 DLOGE("QService command = %d: output_parcel needed.", command);
1638 break;
1639 }
1640 int level = 0;
1641 status = GetPanelBrightness(&level);
1642 output_parcel->writeInt32(level);
1643 }
1644 break;
1645
1646 case qService::IQService::SET_PANEL_BRIGHTNESS: {
1647 if (!input_parcel || !output_parcel) {
1648 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1649 break;
1650 }
1651 uint32_t level = UINT32(input_parcel->readInt32());
1652 status = setPanelBrightness(level);
1653 output_parcel->writeInt32(status);
1654 }
1655 break;
1656
1657 case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
1658 if (!input_parcel || !output_parcel) {
1659 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1660 break;
1661 }
1662 status = GetVisibleDisplayRect(input_parcel, output_parcel);
1663 break;
1664
1665 case qService::IQService::SET_CAMERA_STATUS: {
1666 if (!input_parcel) {
1667 DLOGE("QService command = %d: input_parcel needed.", command);
1668 break;
1669 }
1670 uint32_t camera_status = UINT32(input_parcel->readInt32());
1671 status = setCameraLaunchStatus(camera_status);
1672 }
1673 break;
1674
1675 case qService::IQService::GET_BW_TRANSACTION_STATUS: {
1676 if (!output_parcel) {
1677 DLOGE("QService command = %d: output_parcel needed.", command);
1678 break;
1679 }
1680 bool state = true;
1681 status = DisplayBWTransactionPending(&state);
1682 output_parcel->writeInt32(state);
1683 }
1684 break;
1685
1686 case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
1687 if (!input_parcel) {
1688 DLOGE("QService command = %d: input_parcel needed.", command);
1689 break;
1690 }
1691 status = SetMixerResolution(input_parcel);
1692 break;
1693
1694 case qService::IQService::SET_COLOR_MODE:
1695 if (!input_parcel) {
1696 DLOGE("QService command = %d: input_parcel needed.", command);
1697 break;
1698 }
1699 status = SetColorModeOverride(input_parcel);
1700 break;
1701
1702 case qService::IQService::SET_COLOR_MODE_WITH_RENDER_INTENT:
1703 if (!input_parcel) {
1704 DLOGE("QService command = %d: input_parcel needed.", command);
1705 break;
1706 }
1707 status = SetColorModeWithRenderIntentOverride(input_parcel);
1708 break;
1709
1710 case qService::IQService::SET_COLOR_MODE_BY_ID:
1711 if (!input_parcel) {
1712 DLOGE("QService command = %d: input_parcel needed.", command);
1713 break;
1714 }
1715 status = SetColorModeById(input_parcel);
1716 break;
1717
1718 case qService::IQService::GET_COMPOSER_STATUS:
1719 if (!output_parcel) {
1720 DLOGE("QService command = %d: output_parcel needed.", command);
1721 break;
1722 }
1723 status = 0;
1724 output_parcel->writeInt32(getComposerStatus());
1725 break;
1726
1727 case qService::IQService::SET_QSYNC_MODE:
1728 if (!input_parcel) {
1729 DLOGE("QService command = %d: input_parcel needed.", command);
1730 break;
1731 }
1732 status = SetQSyncMode(input_parcel);
1733 break;
1734
1735 case qService::IQService::SET_COLOR_SAMPLING_ENABLED:
1736 if (!input_parcel) {
1737 DLOGE("QService command = %d: input_parcel needed.", command);
1738 break;
1739 }
1740 status = setColorSamplingEnabled(input_parcel);
1741 break;
1742
1743 case qService::IQService::SET_IDLE_PC:
1744 if (!input_parcel) {
1745 DLOGE("QService command = %d: input_parcel needed.", command);
1746 break;
1747 }
1748 status = SetIdlePC(input_parcel);
1749 break;
1750
1751 case qService::IQService::SET_DISPLAY_DEVICE_STATUS:
1752 if (!input_parcel) {
1753 DLOGE("QService command = %d: input_parcel needed.", command);
1754 break;
1755 }
1756 status = SetDisplayDeviceStatus(input_parcel);
1757 break;
1758
1759 case qService::IQService::SET_DPPS_AD4_ROI_CONFIG:
1760 if (!input_parcel) {
1761 DLOGE("QService command = %d: input_parcel needed.", command);
1762 break;
1763 }
1764 status = SetAd4RoiConfig(input_parcel);
1765 break;
1766
1767 case qService::IQService::SET_DSI_CLK:
1768 if (!input_parcel) {
1769 DLOGE("QService command = %d: input_parcel needed.", command);
1770 break;
1771 }
1772 status = SetDsiClk(input_parcel);
1773 break;
1774
1775 case qService::IQService::GET_DSI_CLK:
1776 if (!input_parcel || !output_parcel) {
1777 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1778 break;
1779 }
1780 status = GetDsiClk(input_parcel, output_parcel);
1781 break;
1782
1783 case qService::IQService::GET_SUPPORTED_DSI_CLK:
1784 if (!input_parcel || !output_parcel) {
1785 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1786 break;
1787 }
1788 status = GetSupportedDsiClk(input_parcel, output_parcel);
1789 break;
1790
1791 case qService::IQService::SET_COLOR_MODE_FROM_CLIENT:
1792 if (!input_parcel) {
1793 DLOGE("QService command = %d: input_parcel needed.", command);
1794 break;
1795 }
1796 status = SetColorModeFromClient(input_parcel);
1797 break;
1798
1799 default:
1800 DLOGW("QService command = %d is not supported.", command);
1801 break;
1802 }
1803
1804 return status;
1805 }
1806
SetDisplayDeviceStatus(const android::Parcel * input_parcel)1807 android::status_t HWCSession::SetDisplayDeviceStatus(const android::Parcel* input_parcel) {
1808 int dpy = input_parcel->readInt32();
1809 int error = android::BAD_VALUE;
1810 auto disp_status = static_cast<HWCDisplay::DisplayStatus>(input_parcel->readInt32());
1811
1812 int disp_idx = GetDisplayIndex(dpy);
1813 if (disp_idx == -1) {
1814 DLOGE("Invalid display = %d");
1815 return android::BAD_VALUE;
1816 }
1817
1818 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1819 if (hwc_display_[disp_idx]) {
1820 error = hwc_display_[disp_idx]->SetDisplayStatus(disp_status);
1821 if (error != android::OK)
1822 DLOGW("Set disply %d status to %d failed with error %d", dpy, disp_status, error);
1823 } else {
1824 DLOGW("No display %d active", dpy);
1825 }
1826
1827 return error;
1828 }
1829
getComposerStatus()1830 android::status_t HWCSession::getComposerStatus() {
1831 return is_composer_up_;
1832 }
1833
GetDisplayAttributesForConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)1834 android::status_t HWCSession::GetDisplayAttributesForConfig(const android::Parcel *input_parcel,
1835 android::Parcel *output_parcel) {
1836 int config = input_parcel->readInt32();
1837 int dpy = input_parcel->readInt32();
1838 int error = android::BAD_VALUE;
1839 DisplayConfigVariableInfo display_attributes;
1840
1841 int disp_idx = GetDisplayIndex(dpy);
1842 if (disp_idx == -1 || config < 0) {
1843 DLOGE("Invalid display = %d, or config = %d", dpy, config);
1844 return android::BAD_VALUE;
1845 }
1846
1847 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1848 if (hwc_display_[disp_idx]) {
1849 error = hwc_display_[disp_idx]->GetDisplayAttributesForConfig(config, &display_attributes);
1850 if (error == 0) {
1851 output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
1852 output_parcel->writeInt32(INT(display_attributes.x_pixels));
1853 output_parcel->writeInt32(INT(display_attributes.y_pixels));
1854 output_parcel->writeFloat(display_attributes.x_dpi);
1855 output_parcel->writeFloat(display_attributes.y_dpi);
1856 output_parcel->writeInt32(0); // Panel type, unsupported.
1857 }
1858 }
1859
1860 return error;
1861 }
1862
setColorSamplingEnabled(const android::Parcel * input_parcel)1863 android::status_t HWCSession::setColorSamplingEnabled(const android::Parcel* input_parcel)
1864 {
1865 int dpy = input_parcel->readInt32();
1866 int enabled_cmd = input_parcel->readInt32();
1867 if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES ||
1868 enabled_cmd < 0 || enabled_cmd > 1) {
1869 return android::BAD_VALUE;
1870 }
1871
1872 SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
1873 if (!hwc_display_[dpy]) {
1874 DLOGW("No display id %i active to enable histogram event", dpy);
1875 return android::BAD_VALUE;
1876 }
1877
1878 auto error = hwc_display_[dpy]->SetDisplayedContentSamplingEnabledVndService(enabled_cmd);
1879 return (error == HWC2::Error::None) ? android::OK : android::BAD_VALUE;
1880 }
1881
ConfigureRefreshRate(const android::Parcel * input_parcel)1882 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
1883 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1884
1885 uint32_t operation = UINT32(input_parcel->readInt32());
1886 HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
1887
1888 if (!hwc_display) {
1889 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
1890 return -ENODEV;
1891 }
1892
1893 switch (operation) {
1894 case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
1895 return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, false);
1896
1897 case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
1898 return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, true);
1899
1900 case qdutils::SET_BINDER_DYN_REFRESH_RATE: {
1901 uint32_t refresh_rate = UINT32(input_parcel->readInt32());
1902 return hwc_display->Perform(HWCDisplayBuiltIn::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
1903 }
1904
1905 default:
1906 DLOGW("Invalid operation %d", operation);
1907 return -EINVAL;
1908 }
1909
1910 return 0;
1911 }
1912
SetDisplayMode(const android::Parcel * input_parcel)1913 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
1914 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1915
1916 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1917 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
1918 return -ENODEV;
1919 }
1920
1921 uint32_t mode = UINT32(input_parcel->readInt32());
1922 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayBuiltIn::SET_DISPLAY_MODE, mode);
1923 }
1924
SetMaxMixerStages(const android::Parcel * input_parcel)1925 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
1926 DisplayError error = kErrorNone;
1927 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1928 uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
1929 android::status_t status = 0;
1930
1931 for (uint32_t i = 0; i < 32 && bit_mask_display_type[i]; i++) {
1932 int disp_idx = GetDisplayIndex(INT(i));
1933 if (disp_idx == -1) {
1934 continue;
1935 }
1936 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1937 auto &hwc_display = hwc_display_[disp_idx];
1938 if (!hwc_display) {
1939 DLOGW("Display = %d is not connected.", disp_idx);
1940 status = (status)? status : -ENODEV; // Return higher priority error.
1941 continue;
1942 }
1943
1944 error = hwc_display->SetMaxMixerStages(max_mixer_stages);
1945 if (error != kErrorNone) {
1946 status = -EINVAL;
1947 }
1948 }
1949
1950 return status;
1951 }
1952
SetFrameDumpConfig(const android::Parcel * input_parcel)1953 android::status_t HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
1954 uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
1955 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1956 uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
1957 int32_t output_format = HAL_PIXEL_FORMAT_RGB_888;
1958 bool post_processed = true;
1959
1960 // Read optional user preferences: output_format and post_processed.
1961 if (input_parcel->dataPosition() != input_parcel->dataSize()) {
1962 // HAL Pixel Format for output buffer
1963 output_format = input_parcel->readInt32();
1964 }
1965 if (input_parcel->dataPosition() != input_parcel->dataSize()) {
1966 // Option to dump Layer Mixer output (0) or DSPP output (1)
1967 post_processed = (input_parcel->readInt32() != 0);
1968 }
1969
1970 android::status_t status = 0;
1971
1972 for (uint32_t i = 0; i < bit_mask_display_type.size(); i++) {
1973 if (!bit_mask_display_type[i]) {
1974 continue;
1975 }
1976 int disp_idx = GetDisplayIndex(INT(i));
1977 if (disp_idx == -1) {
1978 continue;
1979 }
1980 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1981 auto &hwc_display = hwc_display_[disp_idx];
1982 if (!hwc_display) {
1983 DLOGW("Display = %d is not connected.", disp_idx);
1984 status = (status)? status : -ENODEV; // Return higher priority error.
1985 continue;
1986 }
1987
1988 HWC2::Error error = hwc_display->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type,
1989 output_format, post_processed);
1990 if (error != HWC2::Error::None) {
1991 status = (HWC2::Error::NoResources == error) ? -ENOMEM : -EINVAL;
1992 }
1993 }
1994
1995 return status;
1996 }
1997
SetMixerResolution(const android::Parcel * input_parcel)1998 android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
1999 DisplayError error = kErrorNone;
2000 uint32_t dpy = UINT32(input_parcel->readInt32());
2001
2002 if (dpy != HWC_DISPLAY_PRIMARY) {
2003 DLOGW("Resolution change not supported for this display = %d", dpy);
2004 return -EINVAL;
2005 }
2006
2007 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
2008 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
2009 DLOGW("Primary display is not initialized");
2010 return -ENODEV;
2011 }
2012
2013 uint32_t width = UINT32(input_parcel->readInt32());
2014 uint32_t height = UINT32(input_parcel->readInt32());
2015
2016 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
2017 if (error != kErrorNone) {
2018 return -EINVAL;
2019 }
2020
2021 return 0;
2022 }
2023
SetColorModeOverride(const android::Parcel * input_parcel)2024 android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) {
2025 int display = static_cast<int>(input_parcel->readInt32());
2026 auto mode = static_cast<ColorMode>(input_parcel->readInt32());
2027 auto device = static_cast<hwc2_device_t *>(this);
2028
2029 int disp_idx = GetDisplayIndex(display);
2030 if (disp_idx == -1) {
2031 DLOGE("Invalid display = %d", display);
2032 return -EINVAL;
2033 }
2034
2035 if (mode < ColorMode::NATIVE || mode > ColorMode::BT2100_HLG) {
2036 DLOGE("Invalid ColorMode: %d", mode);
2037 return HWC2_ERROR_BAD_PARAMETER;
2038 }
2039 auto err = CallDisplayFunction(device, static_cast<hwc2_display_t>(disp_idx),
2040 &HWCDisplay::SetColorMode, mode);
2041 if (err != HWC2_ERROR_NONE)
2042 return -EINVAL;
2043
2044 return 0;
2045 }
2046
SetAd4RoiConfig(const android::Parcel * input_parcel)2047 android::status_t HWCSession::SetAd4RoiConfig(const android::Parcel *input_parcel) {
2048 auto display_id = static_cast<uint32_t>(input_parcel->readInt32());
2049 auto h_s = static_cast<uint32_t>(input_parcel->readInt32());
2050 auto h_e = static_cast<uint32_t>(input_parcel->readInt32());
2051 auto v_s = static_cast<uint32_t>(input_parcel->readInt32());
2052 auto v_e = static_cast<uint32_t>(input_parcel->readInt32());
2053 auto f_in = static_cast<uint32_t>(input_parcel->readInt32());
2054 auto f_out = static_cast<uint32_t>(input_parcel->readInt32());
2055
2056 #ifdef DISPLAY_CONFIG_1_5
2057 return static_cast<android::status_t>(SetDisplayDppsAdROI(display_id, h_s, h_e, v_s,
2058 v_e, f_in, f_out));
2059 #else
2060 auto err = CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
2061 &HWCDisplay::SetDisplayDppsAdROI, h_s, h_e, v_s, v_e,
2062 f_in, f_out);
2063 if (err != HWC2_ERROR_NONE)
2064 return -EINVAL;
2065
2066 return 0;
2067 #endif
2068 }
2069
SetColorModeWithRenderIntentOverride(const android::Parcel * input_parcel)2070 android::status_t HWCSession::SetColorModeWithRenderIntentOverride(
2071 const android::Parcel *input_parcel) {
2072 auto display = static_cast<hwc2_display_t>(input_parcel->readInt32());
2073 auto mode = static_cast<ColorMode>(input_parcel->readInt32());
2074 auto intent = static_cast<RenderIntent>(input_parcel->readInt32());
2075 auto device = static_cast<hwc2_device_t *>(this);
2076
2077 if (mode < ColorMode::NATIVE || mode > ColorMode::BT2100_HLG) {
2078 DLOGE("Invalid ColorMode: %d", mode);
2079 return HWC2_ERROR_BAD_PARAMETER;
2080 }
2081
2082 if (intent < RenderIntent::COLORIMETRIC || intent > RenderIntent::TONE_MAP_ENHANCE) {
2083 DLOGE("Invalid RenderIntent: %d", intent);
2084 return HWC2_ERROR_BAD_PARAMETER;
2085 }
2086
2087 auto err =
2088 CallDisplayFunction(device, display, &HWCDisplay::SetColorModeWithRenderIntent, mode, intent);
2089 if (err != HWC2_ERROR_NONE)
2090 return -EINVAL;
2091
2092 return 0;
2093 }
SetColorModeById(const android::Parcel * input_parcel)2094 android::status_t HWCSession::SetColorModeById(const android::Parcel *input_parcel) {
2095 int display = input_parcel->readInt32();
2096 auto mode = input_parcel->readInt32();
2097 auto device = static_cast<hwc2_device_t *>(this);
2098
2099 int disp_idx = GetDisplayIndex(display);
2100 if (disp_idx == -1) {
2101 DLOGE("Invalid display = %d", display);
2102 return -EINVAL;
2103 }
2104
2105 auto err = CallDisplayFunction(device, static_cast<hwc2_display_t>(disp_idx),
2106 &HWCDisplay::SetColorModeById, mode);
2107 if (err != HWC2_ERROR_NONE)
2108 return -EINVAL;
2109
2110 return 0;
2111 }
2112
SetColorModeFromClient(const android::Parcel * input_parcel)2113 android::status_t HWCSession::SetColorModeFromClient(const android::Parcel *input_parcel) {
2114 int display = input_parcel->readInt32();
2115 auto mode = input_parcel->readInt32();
2116 auto device = static_cast<hwc2_device_t *>(this);
2117
2118 int disp_idx = GetDisplayIndex(display);
2119 if (disp_idx == -1) {
2120 DLOGE("Invalid display = %d", display);
2121 return -EINVAL;
2122 }
2123
2124 auto err = CallDisplayFunction(device, static_cast<hwc2_display_t>(disp_idx),
2125 &HWCDisplay::SetColorModeFromClientApi, mode);
2126 if (err != HWC2_ERROR_NONE)
2127 return -EINVAL;
2128
2129 Refresh(static_cast<hwc2_display_t>(disp_idx));
2130
2131 return 0;
2132 }
2133
RefreshScreen(const android::Parcel * input_parcel)2134 android::status_t HWCSession::RefreshScreen(const android::Parcel *input_parcel) {
2135 int display = input_parcel->readInt32();
2136
2137 int disp_idx = GetDisplayIndex(display);
2138 if (disp_idx == -1) {
2139 DLOGE("Invalid display = %d", display);
2140 return -EINVAL;
2141 }
2142
2143 Refresh(static_cast<hwc2_display_t>(disp_idx));
2144
2145 return 0;
2146 }
2147
DynamicDebug(const android::Parcel * input_parcel)2148 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
2149 int type = input_parcel->readInt32();
2150 bool enable = (input_parcel->readInt32() > 0);
2151 DLOGI("type = %d enable = %d", type, enable);
2152 int verbose_level = input_parcel->readInt32();
2153
2154 switch (type) {
2155 case qService::IQService::DEBUG_ALL:
2156 HWCDebugHandler::DebugAll(enable, verbose_level);
2157 break;
2158
2159 case qService::IQService::DEBUG_MDPCOMP:
2160 HWCDebugHandler::DebugStrategy(enable, verbose_level);
2161 HWCDebugHandler::DebugCompManager(enable, verbose_level);
2162 break;
2163
2164 case qService::IQService::DEBUG_PIPE_LIFECYCLE:
2165 HWCDebugHandler::DebugResources(enable, verbose_level);
2166 HWCDebugHandler::DebugQos(enable, verbose_level);
2167 break;
2168
2169 case qService::IQService::DEBUG_DRIVER_CONFIG:
2170 HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
2171 break;
2172
2173 case qService::IQService::DEBUG_ROTATOR:
2174 HWCDebugHandler::DebugResources(enable, verbose_level);
2175 HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
2176 HWCDebugHandler::DebugRotator(enable, verbose_level);
2177 HWCDebugHandler::DebugQos(enable, verbose_level);
2178 break;
2179
2180 case qService::IQService::DEBUG_QDCM:
2181 HWCDebugHandler::DebugQdcm(enable, verbose_level);
2182 break;
2183
2184 case qService::IQService::DEBUG_SCALAR:
2185 HWCDebugHandler::DebugScalar(enable, verbose_level);
2186 break;
2187
2188 case qService::IQService::DEBUG_CLIENT:
2189 HWCDebugHandler::DebugClient(enable, verbose_level);
2190 break;
2191
2192 case qService::IQService::DEBUG_DISPLAY:
2193 HWCDebugHandler::DebugDisplay(enable, verbose_level);
2194 break;
2195
2196 default:
2197 DLOGW("type = %d is not supported", type);
2198 }
2199 }
2200
QdcmCMDDispatch(uint32_t display_id,const PPDisplayAPIPayload & req_payload,PPDisplayAPIPayload * resp_payload,PPPendingParams * pending_action)2201 android::status_t HWCSession::QdcmCMDDispatch(uint32_t display_id,
2202 const PPDisplayAPIPayload &req_payload,
2203 PPDisplayAPIPayload *resp_payload,
2204 PPPendingParams *pending_action) {
2205 int ret = 0;
2206 bool is_physical_display = false;
2207
2208 if (display_id >= HWCCallbacks::kNumDisplays || !hwc_display_[display_id]) {
2209 DLOGW("Invalid display id or display = %d is not connected.", display_id);
2210 return -ENODEV;
2211 }
2212
2213 if (display_id == map_info_primary_.client_id) {
2214 is_physical_display = true;
2215 } else {
2216 for (auto &map_info : map_info_builtin_) {
2217 if (map_info.client_id == display_id) {
2218 is_physical_display = true;
2219 break;
2220 }
2221 }
2222 }
2223
2224 if (!is_physical_display) {
2225 DLOGW("Skipping QDCM command dispatch on display = %d", display_id);
2226 return ret;
2227 }
2228
2229 ret = hwc_display_[display_id]->ColorSVCRequestRoute(req_payload,
2230 resp_payload,
2231 pending_action);
2232
2233 return ret;
2234 }
2235
QdcmCMDHandler(const android::Parcel * input_parcel,android::Parcel * output_parcel)2236 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
2237 android::Parcel *output_parcel) {
2238 int ret = 0;
2239 int32_t *brightness_value = NULL;
2240 uint32_t display_id(0);
2241 PPPendingParams pending_action;
2242 PPDisplayAPIPayload resp_payload, req_payload;
2243 uint8_t *disp_id = NULL;
2244 bool invalidate_needed = true;
2245 int32_t *mode_id = NULL;
2246
2247 if (!color_mgr_) {
2248 DLOGW("color_mgr_ not initialized.");
2249 return -ENOENT;
2250 }
2251
2252 pending_action.action = kNoAction;
2253 pending_action.params = NULL;
2254
2255 // Read display_id, payload_size and payload from in_parcel.
2256 ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
2257 if (!ret) {
2258 ret = QdcmCMDDispatch(display_id, req_payload, &resp_payload, &pending_action);
2259 }
2260
2261 if (ret) {
2262 output_parcel->writeInt32(ret); // first field in out parcel indicates return code.
2263 req_payload.DestroyPayload();
2264 resp_payload.DestroyPayload();
2265 return ret;
2266 }
2267
2268 if (kNoAction != pending_action.action) {
2269 int32_t action = pending_action.action;
2270 int count = -1;
2271 while (action > 0) {
2272 count++;
2273 int32_t bit = (action & 1);
2274 action = action >> 1;
2275
2276 if (!bit)
2277 continue;
2278
2279 DLOGV_IF(kTagQDCM, "pending action = %d, display_id = %d", BITMAP(count), display_id);
2280 switch (BITMAP(count)) {
2281 case kInvalidating:
2282 {
2283 invalidate_needed = false;
2284 Refresh(display_id);
2285 }
2286 break;
2287 case kEnterQDCMMode:
2288 ret = color_mgr_->EnableQDCMMode(true, hwc_display_[display_id]);
2289 break;
2290 case kExitQDCMMode:
2291 ret = color_mgr_->EnableQDCMMode(false, hwc_display_[display_id]);
2292 break;
2293 case kApplySolidFill:
2294 {
2295 SCOPE_LOCK(locker_[display_id]);
2296 ret = color_mgr_->SetSolidFill(pending_action.params,
2297 true, hwc_display_[display_id]);
2298 }
2299 Refresh(display_id);
2300 usleep(kSolidFillDelay);
2301 break;
2302 case kDisableSolidFill:
2303 {
2304 SCOPE_LOCK(locker_[display_id]);
2305 ret = color_mgr_->SetSolidFill(pending_action.params,
2306 false, hwc_display_[display_id]);
2307 }
2308 Refresh(display_id);
2309 usleep(kSolidFillDelay);
2310 break;
2311 case kSetPanelBrightness:
2312 brightness_value = reinterpret_cast<int32_t *>(resp_payload.payload);
2313 if (brightness_value == NULL) {
2314 DLOGE("Brightness value is Null");
2315 ret = -EINVAL;
2316 } else {
2317 ret = hwc_display_[display_id]->SetPanelBrightness(*brightness_value);
2318 }
2319 break;
2320 case kEnableFrameCapture:
2321 ret = color_mgr_->SetFrameCapture(pending_action.params, true,
2322 hwc_display_[display_id]);
2323 Refresh(display_id);
2324 break;
2325 case kDisableFrameCapture:
2326 ret = color_mgr_->SetFrameCapture(pending_action.params, false,
2327 hwc_display_[display_id]);
2328 break;
2329 case kConfigureDetailedEnhancer:
2330 ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
2331 hwc_display_[display_id]);
2332 Refresh(display_id);
2333 break;
2334 case kModeSet:
2335 ret = static_cast<int>
2336 (hwc_display_[display_id]->RestoreColorTransform());
2337 Refresh(display_id);
2338 break;
2339 case kNoAction:
2340 break;
2341 case kMultiDispProc:
2342 for (auto &map_info : map_info_builtin_) {
2343 uint32_t id = UINT32(map_info.client_id);
2344 if (id < HWCCallbacks::kNumDisplays && hwc_display_[id]) {
2345 int result = 0;
2346 resp_payload.DestroyPayload();
2347 result = hwc_display_[id]->ColorSVCRequestRoute(req_payload,
2348 &resp_payload,
2349 &pending_action);
2350 if (result) {
2351 DLOGW("Failed to dispatch action to disp %d ret %d", id, result);
2352 ret = result;
2353 }
2354 }
2355 }
2356 break;
2357 case kMultiDispGetId:
2358 ret = resp_payload.CreatePayloadBytes(HWCCallbacks::kNumDisplays, &disp_id);
2359 if (ret) {
2360 DLOGW("Unable to create response payload!");
2361 } else {
2362 for (int i = 0; i < HWCCallbacks::kNumDisplays; i++) {
2363 disp_id[i] = HWCCallbacks::kNumDisplays;
2364 }
2365 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
2366 disp_id[HWC_DISPLAY_PRIMARY] = HWC_DISPLAY_PRIMARY;
2367 }
2368 for (auto &map_info : map_info_builtin_) {
2369 uint64_t id = map_info.client_id;
2370 if (id < HWCCallbacks::kNumDisplays && hwc_display_[id]) {
2371 disp_id[id] = (uint8_t)id;
2372 }
2373 }
2374 }
2375 break;
2376 case kSetModeFromClient:
2377 {
2378 SCOPE_LOCK(locker_[display_id]);
2379 mode_id = reinterpret_cast<int32_t *>(resp_payload.payload);
2380 if (mode_id) {
2381 ret = static_cast<int>(hwc_display_[display_id]->SetColorModeFromClientApi(*mode_id));
2382 } else {
2383 DLOGE("mode_id is Null");
2384 ret = -EINVAL;
2385 }
2386 }
2387 if (!ret) {
2388 Refresh(display_id);
2389 }
2390 break;
2391 default:
2392 DLOGW("Invalid pending action = %d!", pending_action.action);
2393 break;
2394 }
2395 }
2396 }
2397 // for display API getter case, marshall returned params into out_parcel.
2398 output_parcel->writeInt32(ret);
2399 HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
2400 req_payload.DestroyPayload();
2401 resp_payload.DestroyPayload();
2402
2403 SEQUENCE_WAIT_SCOPE_LOCK(locker_[display_id]);
2404 if (invalidate_needed) {
2405 hwc_display_[display_id]->ResetValidation();
2406 }
2407
2408 return ret;
2409 }
2410
GetEventValue(const char * uevent_data,int length,const char * event_info)2411 int GetEventValue(const char *uevent_data, int length, const char *event_info) {
2412 const char *iterator_str = uevent_data;
2413 while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
2414 const char *pstr = strstr(iterator_str, event_info);
2415 if (pstr != NULL) {
2416 return (atoi(iterator_str + strlen(event_info)));
2417 }
2418 iterator_str += strlen(iterator_str) + 1;
2419 }
2420
2421 return -1;
2422 }
2423
GetTokenValue(const char * uevent_data,int length,const char * token)2424 const char *GetTokenValue(const char *uevent_data, int length, const char *token) {
2425 const char *iterator_str = uevent_data;
2426 const char *pstr = NULL;
2427 while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
2428 pstr = strstr(iterator_str, token);
2429 if (pstr) {
2430 break;
2431 }
2432 iterator_str += strlen(iterator_str) + 1;
2433 }
2434
2435 if (pstr)
2436 pstr = pstr+strlen(token);
2437
2438 return pstr;
2439 }
2440
SetDsiClk(const android::Parcel * input_parcel)2441 android::status_t HWCSession::SetDsiClk(const android::Parcel *input_parcel) {
2442 int disp_id = input_parcel->readInt32();
2443 uint64_t clk = UINT64(input_parcel->readInt64());
2444 if (disp_id < 0 || !hwc_display_[disp_id]) {
2445 return -EINVAL;
2446 }
2447
2448 return hwc_display_[disp_id]->SetDynamicDSIClock(clk);
2449 }
2450
GetDsiClk(const android::Parcel * input_parcel,android::Parcel * output_parcel)2451 android::status_t HWCSession::GetDsiClk(const android::Parcel *input_parcel,
2452 android::Parcel *output_parcel) {
2453 int disp_id = input_parcel->readInt32();
2454 if (disp_id < 0 || !hwc_display_[disp_id]) {
2455 return -EINVAL;
2456 }
2457
2458 uint64_t bitrate = 0;
2459 hwc_display_[disp_id]->GetDynamicDSIClock(&bitrate);
2460 output_parcel->writeUint64(bitrate);
2461
2462 return 0;
2463 }
2464
GetSupportedDsiClk(const android::Parcel * input_parcel,android::Parcel * output_parcel)2465 android::status_t HWCSession::GetSupportedDsiClk(const android::Parcel *input_parcel,
2466 android::Parcel *output_parcel) {
2467 int disp_id = input_parcel->readInt32();
2468 if (disp_id < 0 || !hwc_display_[disp_id]) {
2469 return -EINVAL;
2470 }
2471
2472 std::vector<uint64_t> bit_rates;
2473 hwc_display_[disp_id]->GetSupportedDSIClock(&bit_rates);
2474 output_parcel->writeInt32(INT32(bit_rates.size()));
2475 for (auto &bit_rate : bit_rates) {
2476 output_parcel->writeUint64(bit_rate);
2477 }
2478
2479 return 0;
2480 }
2481
UEventHandler(const char * uevent_data,int length)2482 void HWCSession::UEventHandler(const char *uevent_data, int length) {
2483 // Drop hotplug uevents until SurfaceFlinger (the client) is connected. The equivalent of hotplug
2484 // uevent handling will be done once when SurfaceFlinger connects, at RegisterCallback(). Since
2485 // HandlePluggableDisplays() reads the latest connection states of all displays, no uevent is
2486 // lost.
2487 if (client_connected_ && strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
2488 // MST hotplug will not carry connection status/test pattern etc.
2489 // Pluggable display handler will check all connection status' and take action accordingly.
2490 const char *str_status = GetTokenValue(uevent_data, length, "status=");
2491 const char *str_mst = GetTokenValue(uevent_data, length, "MST_HOTPLUG=");
2492 if (!str_status && !str_mst) {
2493 return;
2494 }
2495
2496 hpd_bpp_ = GetEventValue(uevent_data, length, "bpp=");
2497 hpd_pattern_ = GetEventValue(uevent_data, length, "pattern=");
2498 DLOGI("Uevent = %s, status = %s, MST_HOTPLUG = %s, bpp = %d, pattern = %d", uevent_data,
2499 str_status ? str_status : "NULL", str_mst ? str_mst : "NULL", hpd_bpp_, hpd_pattern_);
2500
2501 hwc2_display_t virtual_display_index =
2502 (hwc2_display_t)GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
2503
2504 std::bitset<kSecureMax> secure_sessions = 0;
2505 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
2506 if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
2507 Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
2508 hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
2509 }
2510 if (secure_sessions[kSecureDisplay] || hwc_display_[virtual_display_index]) {
2511 // Defer hotplug handling.
2512 SCOPE_LOCK(pluggable_handler_lock_);
2513 DLOGI("Marking hotplug pending...");
2514 hotplug_pending_event_ = kHotPlugEvent;
2515 } else {
2516 // Handle hotplug.
2517 int32_t err = HandlePluggableDisplays(true);
2518 if (err) {
2519 DLOGW("Hotplug handling failed. Error %d '%s'. Hotplug handling %s.", err,
2520 strerror(abs(err)), (hotplug_pending_event_ == kHotPlugEvent) ?
2521 "deferred" : "dropped");
2522 }
2523 }
2524
2525 if (str_status) {
2526 bool connected = (strncmp(str_status, "connected", strlen("connected")) == 0);
2527 DLOGI("Connected = %d", connected);
2528 // Pass on legacy HDMI hot-plug event.
2529 qservice_->onHdmiHotplug(INT(connected));
2530 }
2531 }
2532 }
2533
GetVsyncPeriod(int disp)2534 int HWCSession::GetVsyncPeriod(int disp) {
2535 SCOPE_LOCK(locker_[disp]);
2536 // default value
2537 int32_t vsync_period = 1000000000l / 60;
2538 auto attribute = HWC2::Attribute::VsyncPeriod;
2539
2540 if (hwc_display_[disp]) {
2541 hwc_display_[disp]->GetDisplayAttribute(0, attribute, &vsync_period);
2542 }
2543
2544 return vsync_period;
2545 }
2546
GetVisibleDisplayRect(const android::Parcel * input_parcel,android::Parcel * output_parcel)2547 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
2548 android::Parcel *output_parcel) {
2549 int disp_idx = GetDisplayIndex(input_parcel->readInt32());
2550 if (disp_idx == -1) {
2551 DLOGE("Invalid display = %d", disp_idx);
2552 return android::BAD_VALUE;
2553 }
2554
2555 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
2556 if (!hwc_display_[disp_idx]) {
2557 return android::NO_INIT;
2558 }
2559
2560 hwc_rect_t visible_rect = {0, 0, 0, 0};
2561 int error = hwc_display_[disp_idx]->GetVisibleDisplayRect(&visible_rect);
2562 if (error < 0) {
2563 return error;
2564 }
2565
2566 output_parcel->writeInt32(visible_rect.left);
2567 output_parcel->writeInt32(visible_rect.top);
2568 output_parcel->writeInt32(visible_rect.right);
2569 output_parcel->writeInt32(visible_rect.bottom);
2570
2571 return android::NO_ERROR;
2572 }
2573
Refresh(hwc2_display_t display)2574 void HWCSession::Refresh(hwc2_display_t display) {
2575 SCOPE_LOCK(callbacks_lock_);
2576 HWC2::Error err = callbacks_.Refresh(display);
2577 while (err != HWC2::Error::None) {
2578 callbacks_lock_.Wait();
2579 err = callbacks_.Refresh(display);
2580 }
2581 }
2582
HotPlug(hwc2_display_t display,HWC2::Connection state)2583 void HWCSession::HotPlug(hwc2_display_t display, HWC2::Connection state) {
2584 SCOPE_LOCK(callbacks_lock_);
2585 HWC2::Error err = callbacks_.Hotplug(display, state);
2586 while (err != HWC2::Error::None) {
2587 callbacks_lock_.Wait();
2588 err = callbacks_.Hotplug(display, state);
2589 }
2590 }
2591
CreatePrimaryDisplay()2592 int HWCSession::CreatePrimaryDisplay() {
2593 int status = -EINVAL;
2594 HWDisplaysInfo hw_displays_info = {};
2595
2596 if (null_display_mode_) {
2597 HWDisplayInfo hw_info = {};
2598 hw_info.display_type = kBuiltIn;
2599 hw_info.is_connected = 1;
2600 hw_info.is_primary = 1;
2601 hw_info.is_wb_ubwc_supported = 0;
2602 hw_info.display_id = 1;
2603 hw_displays_info[hw_info.display_id] = hw_info;
2604 } else {
2605 DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
2606 if (error != kErrorNone) {
2607 DLOGE("Failed to get connected display list. Error = %d", error);
2608 return status;
2609 }
2610 }
2611
2612 for (auto &iter : hw_displays_info) {
2613 auto &info = iter.second;
2614 if (!info.is_primary) {
2615 continue;
2616 }
2617
2618 // todo (user): If primary display is not connected (e.g. hdmi as primary), a NULL display
2619 // need to be created. SF expects primary display hotplug during callback registration unlike
2620 // previous implementation where first hotplug could be notified anytime.
2621 if (!info.is_connected) {
2622 DLOGE("Primary display is not connected. Not supported at present.");
2623 break;
2624 }
2625
2626 auto hwc_display = &hwc_display_[HWC_DISPLAY_PRIMARY];
2627 hwc2_display_t client_id = map_info_primary_.client_id;
2628
2629 DLOGI("Create primary display type = %d, sdm id = %d, client id = %d", info.display_type,
2630 info.display_id, client_id);
2631 if (info.display_type == kBuiltIn) {
2632 status = HWCDisplayBuiltIn::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
2633 qservice_, client_id, info.display_id, hwc_display);
2634 } else if (info.display_type == kPluggable) {
2635 status = HWCDisplayPluggable::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
2636 qservice_, client_id, info.display_id, 0, 0, false,
2637 hwc_display);
2638 } else {
2639 DLOGE("Spurious primary display type = %d", info.display_type);
2640 break;
2641 }
2642
2643 if (!status) {
2644 is_hdr_display_[UINT32(client_id)] = HasHDRSupport(*hwc_display);
2645 DLOGI("Primary display created.");
2646 map_info_primary_.disp_type = info.display_type;
2647 map_info_primary_.sdm_id = info.display_id;
2648
2649 color_mgr_ = HWCColorManager::CreateColorManager(&buffer_allocator_);
2650 if (!color_mgr_) {
2651 DLOGW("Failed to load HWCColorManager.");
2652 }
2653 } else {
2654 DLOGE("Primary display creation failed.");
2655 }
2656
2657 // Primary display is found, no need to parse more.
2658 break;
2659 }
2660
2661 return status;
2662 }
2663
HandleBuiltInDisplays()2664 int HWCSession::HandleBuiltInDisplays() {
2665 if (null_display_mode_) {
2666 DLOGW("Skipped BuiltIn display handling in null-display mode");
2667 return 0;
2668 }
2669
2670 HWDisplaysInfo hw_displays_info = {};
2671 DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
2672 if (error != kErrorNone) {
2673 DLOGE("Failed to get connected display list. Error = %d", error);
2674 return -EINVAL;
2675 }
2676
2677 int status = 0;
2678 for (auto &iter : hw_displays_info) {
2679 auto &info = iter.second;
2680
2681 // Do not recreate primary display.
2682 if (info.is_primary || info.display_type != kBuiltIn) {
2683 continue;
2684 }
2685
2686 for (auto &map_info : map_info_builtin_) {
2687 hwc2_display_t client_id = map_info.client_id;
2688
2689 {
2690 SCOPE_LOCK(locker_[client_id]);
2691 // Lock confined to this scope
2692 if (hwc_display_[client_id]) {
2693 continue;
2694 }
2695
2696 DLOGI("Create builtin display, sdm id = %d, client id = %d", info.display_id, client_id);
2697 status = HWCDisplayBuiltIn::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
2698 qservice_, client_id, info.display_id,
2699 &hwc_display_[client_id]);
2700 if (status) {
2701 DLOGE("Builtin display creation failed.");
2702 break;
2703 }
2704 is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display_[client_id]);
2705 DLOGI("Builtin display created: sdm id = %d, client id = %d", info.display_id, client_id);
2706 map_info.disp_type = info.display_type;
2707 map_info.sdm_id = info.display_id;
2708 }
2709
2710 DLOGI("Hotplugging builtin display, sdm id = %d, client id = %d", info.display_id, client_id);
2711 callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
2712 break;
2713 }
2714 }
2715
2716 return status;
2717 }
2718
HandlePluggableDisplays(bool delay_hotplug)2719 int HWCSession::HandlePluggableDisplays(bool delay_hotplug) {
2720 SCOPE_LOCK(pluggable_handler_lock_);
2721 if (null_display_mode_) {
2722 DLOGW("Skipped pluggable display handling in null-display mode");
2723 return 0;
2724 }
2725
2726 DLOGI("Handling hotplug...");
2727 HWDisplaysInfo hw_displays_info = {};
2728 DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
2729 if (error != kErrorNone) {
2730 DLOGE("Failed to get connected display list. Error = %d", error);
2731 return -EINVAL;
2732 }
2733
2734 int status = HandleDisconnectedDisplays(&hw_displays_info);
2735 if (status) {
2736 DLOGE("All displays could not be disconnected.");
2737 return status;
2738 }
2739
2740 status = HandleConnectedDisplays(&hw_displays_info, delay_hotplug);
2741 if (status) {
2742 switch (status) {
2743 case -EAGAIN:
2744 case -ENODEV:
2745 // Errors like device removal or deferral for which we want to try another hotplug handling.
2746 hotplug_pending_event_ = kHotPlugEvent;
2747 status = 0;
2748 break;
2749 default:
2750 // Real errors we want to flag and stop hotplug handling.
2751 hotplug_pending_event_ = kHotPlugNone;
2752 DLOGE("All displays could not be connected. Error %d '%s'.", status, strerror(abs(status)));
2753 }
2754 DLOGI("Handling hotplug... %s", (kHotPlugNone ==hotplug_pending_event_) ?
2755 "Stopped." : "Done. Hotplug events pending.");
2756 return status;
2757 }
2758
2759 hotplug_pending_event_ = kHotPlugNone;
2760
2761 DLOGI("Handling hotplug... Done.");
2762 return 0;
2763 }
2764
HandleConnectedDisplays(HWDisplaysInfo * hw_displays_info,bool delay_hotplug)2765 int HWCSession::HandleConnectedDisplays(HWDisplaysInfo *hw_displays_info, bool delay_hotplug) {
2766 int status = 0;
2767 std::vector<hwc2_display_t> pending_hotplugs = {};
2768
2769 for (auto &iter : *hw_displays_info) {
2770 auto &info = iter.second;
2771
2772 // Do not recreate primary display or if display is not connected.
2773 if (info.is_primary || info.display_type != kPluggable || !info.is_connected) {
2774 continue;
2775 }
2776
2777 // Check if we are already using the display.
2778 auto display_used = std::find_if(map_info_pluggable_.begin(), map_info_pluggable_.end(),
2779 [&](auto &p) {
2780 return (p.sdm_id == info.display_id);
2781 });
2782 if (display_used != map_info_pluggable_.end()) {
2783 // Display is already used in a slot.
2784 continue;
2785 }
2786
2787 // Count active pluggable display slots and slots with no commits.
2788 bool first_commit_pending = false;
2789 std::for_each(map_info_pluggable_.begin(), map_info_pluggable_.end(),
2790 [&](auto &p) {
2791 SCOPE_LOCK(locker_[p.client_id]);
2792 if (hwc_display_[p.client_id]) {
2793 if (!hwc_display_[p.client_id]->IsFirstCommitDone()) {
2794 DLOGI("Display commit pending on display %d-1", p.sdm_id);
2795 first_commit_pending = true;
2796 }
2797 }
2798 });
2799
2800 if (!disable_hotplug_bwcheck_ && first_commit_pending) {
2801 // Hotplug bandwidth check is accomplished by creating and hotplugging a new display after
2802 // a display commit has happened on previous hotplugged displays. This allows the driver to
2803 // return updated modes for the new display based on available link bandwidth.
2804 DLOGI("Pending display commit on one of the displays. Deferring display creation.");
2805 status = -EAGAIN;
2806 if (client_connected_) {
2807 // Trigger a display refresh since we depend on PresentDisplay() to handle pending hotplugs.
2808 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
2809 if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
2810 active_builtin_disp_id = HWC_DISPLAY_PRIMARY;
2811 }
2812 Refresh(active_builtin_disp_id);
2813 }
2814 break;
2815 }
2816
2817 // find an empty slot to create display.
2818 for (auto &map_info : map_info_pluggable_) {
2819 hwc2_display_t client_id = map_info.client_id;
2820
2821 // Lock confined to this scope
2822 {
2823 SCOPE_LOCK(locker_[client_id]);
2824 auto &hwc_display = hwc_display_[client_id];
2825 if (hwc_display) {
2826 // Display slot is already used.
2827 continue;
2828 }
2829
2830 DLOGI("Create pluggable display, sdm id = %d, client id = %d", info.display_id, client_id);
2831
2832 // Test pattern generation ?
2833 map_info.test_pattern = (hpd_bpp_ > 0) && (hpd_pattern_ > 0);
2834 int err = 0;
2835 if (!map_info.test_pattern) {
2836 err = HWCDisplayPluggable::Create(core_intf_, &buffer_allocator_,
2837 &callbacks_, this, qservice_, client_id,
2838 info.display_id, 0, 0, false, &hwc_display);
2839 } else {
2840 err = HWCDisplayPluggableTest::Create(core_intf_, &buffer_allocator_,
2841 &callbacks_, this, qservice_, client_id,
2842 info.display_id, UINT32(hpd_bpp_),
2843 UINT32(hpd_pattern_), &hwc_display);
2844 }
2845
2846 if (err) {
2847 DLOGW("Pluggable display creation failed/aborted. Error %d '%s'.", err,
2848 strerror(abs(err)));
2849 status = err;
2850 // Attempt creating remaining pluggable displays.
2851 break;
2852 }
2853
2854 is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
2855 DLOGI("Created pluggable display successfully: sdm id = %d, client id = %d",
2856 info.display_id, client_id);
2857 }
2858
2859 map_info.disp_type = info.display_type;
2860 map_info.sdm_id = info.display_id;
2861
2862 pending_hotplugs.push_back((hwc2_display_t)client_id);
2863
2864 // Display is created for this sdm id, move to next connected display.
2865 break;
2866 }
2867 }
2868
2869 // No display was created.
2870 if (!pending_hotplugs.size()) {
2871 return status;
2872 }
2873
2874 // Active builtin display needs revalidation
2875 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
2876 if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
2877 {
2878 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
2879 hwc_display_[active_builtin_disp_id]->ResetValidation();
2880 }
2881
2882 if (client_connected_) {
2883 Refresh(active_builtin_disp_id);
2884 }
2885
2886 // Do not sleep if this method is called from client thread.
2887 if (delay_hotplug) {
2888 // wait sufficient time to ensure resources are available for new display connection.
2889 usleep(UINT32(GetVsyncPeriod(INT32(active_builtin_disp_id))) * 2 / 1000);
2890 }
2891 }
2892
2893 for (auto client_id : pending_hotplugs) {
2894 DLOGI("Notify hotplug display connected: client id = %d", client_id);
2895 callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
2896 }
2897
2898 return status;
2899 }
2900
HasHDRSupport(HWCDisplay * hwc_display)2901 bool HWCSession::HasHDRSupport(HWCDisplay *hwc_display) {
2902 // query number of hdr types
2903 uint32_t out_num_types = 0;
2904 float out_max_luminance = 0.0f;
2905 float out_max_average_luminance = 0.0f;
2906 float out_min_luminance = 0.0f;
2907 if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, &out_max_luminance,
2908 &out_max_average_luminance, &out_min_luminance)
2909 != HWC2::Error::None) {
2910 return false;
2911 }
2912
2913 return (out_num_types > 0);
2914 }
2915
HandleDisconnectedDisplays(HWDisplaysInfo * hw_displays_info)2916 int HWCSession::HandleDisconnectedDisplays(HWDisplaysInfo *hw_displays_info) {
2917 // Destroy pluggable displays which were connected earlier but got disconnected now.
2918 for (auto &map_info : map_info_pluggable_) {
2919 bool disconnect = true; // disconnect in case display id is not found in list.
2920
2921 for (auto &iter : *hw_displays_info) {
2922 auto &info = iter.second;
2923 if (info.display_id != map_info.sdm_id) {
2924 continue;
2925 }
2926 if (info.is_connected) {
2927 disconnect = false;
2928 }
2929 break;
2930 }
2931
2932 if (disconnect) {
2933 DestroyDisplay(&map_info);
2934 }
2935 }
2936
2937 return 0;
2938 }
2939
DestroyDisplay(DisplayMapInfo * map_info)2940 void HWCSession::DestroyDisplay(DisplayMapInfo *map_info) {
2941 switch (map_info->disp_type) {
2942 case kPluggable:
2943 DestroyPluggableDisplay(map_info);
2944 break;
2945 default:
2946 DestroyNonPluggableDisplay(map_info);
2947 break;
2948 }
2949 }
2950
DestroyPluggableDisplay(DisplayMapInfo * map_info)2951 void HWCSession::DestroyPluggableDisplay(DisplayMapInfo *map_info) {
2952 hwc2_display_t client_id = map_info->client_id;
2953
2954 DLOGI("Notify hotplug display disconnected: client id = %d", client_id);
2955 callbacks_.Hotplug(client_id, HWC2::Connection::Disconnected);
2956
2957 // Trigger refresh to make sure disconnect event received/updated properly by SurfaceFlinger.
2958 Refresh(HWC_DISPLAY_PRIMARY);
2959
2960 // wait for sufficient time to ensure sufficient resources are available to process
2961 // connection.
2962 usleep(UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY)) * 2 / 1000);
2963
2964 {
2965 SCOPE_LOCK(locker_[client_id]);
2966 auto &hwc_display = hwc_display_[client_id];
2967 if (!hwc_display) {
2968 return;
2969 }
2970 DLOGI("Destroy display %d-%d, client id = %d", map_info->sdm_id, map_info->disp_type,
2971 client_id);
2972
2973 is_hdr_display_[UINT32(client_id)] = false;
2974 if (!map_info->test_pattern) {
2975 HWCDisplayPluggable::Destroy(hwc_display);
2976 } else {
2977 HWCDisplayPluggableTest::Destroy(hwc_display);
2978 }
2979
2980 hwc_display = nullptr;
2981 map_info->Reset();
2982 }
2983 }
2984
DestroyNonPluggableDisplay(DisplayMapInfo * map_info)2985 void HWCSession::DestroyNonPluggableDisplay(DisplayMapInfo *map_info) {
2986 hwc2_display_t client_id = map_info->client_id;
2987
2988 SCOPE_LOCK(locker_[client_id]);
2989 auto &hwc_display = hwc_display_[client_id];
2990 if (!hwc_display) {
2991 return;
2992 }
2993 DLOGI("Destroy display %d-%d, client id = %d", map_info->sdm_id, map_info->disp_type,
2994 client_id);
2995 is_hdr_display_[UINT32(client_id)] = false;
2996 switch (map_info->disp_type) {
2997 case kBuiltIn:
2998 HWCDisplayBuiltIn::Destroy(hwc_display);
2999 break;
3000 default:
3001 HWCDisplayVirtual::Destroy(hwc_display);
3002 break;
3003 }
3004
3005 hwc_display = nullptr;
3006 map_info->Reset();
3007 }
3008
ValidateDisplayInternal(hwc2_display_t display,uint32_t * out_num_types,uint32_t * out_num_requests)3009 HWC2::Error HWCSession::ValidateDisplayInternal(hwc2_display_t display, uint32_t *out_num_types,
3010 uint32_t *out_num_requests) {
3011 HWCDisplay *hwc_display = hwc_display_[display];
3012
3013 DTRACE_SCOPED();
3014 if (hwc_display->IsInternalValidateState()) {
3015 // Internal Validation has already been done on display, get the Output params.
3016 return hwc_display->GetValidateDisplayOutput(out_num_types, out_num_requests);
3017 }
3018
3019 if (display == HWC_DISPLAY_PRIMARY) {
3020 // TODO(user): This can be moved to HWCDisplayPrimary
3021 if (need_invalidate_) {
3022 Refresh(display);
3023 need_invalidate_ = false;
3024 }
3025
3026 if (color_mgr_) {
3027 color_mgr_->SetColorModeDetailEnhancer(hwc_display_[display]);
3028 }
3029 }
3030
3031 return hwc_display->Validate(out_num_types, out_num_requests);
3032 }
3033
PresentDisplayInternal(hwc2_display_t display,int32_t * out_retire_fence)3034 HWC2::Error HWCSession::PresentDisplayInternal(hwc2_display_t display, int32_t *out_retire_fence) {
3035 HWCDisplay *hwc_display = hwc_display_[display];
3036
3037 DTRACE_SCOPED();
3038 // If display is in Skip-Validate state and Validate cannot be skipped, do Internal
3039 // Validation to optimize for the frames which don't require the Client composition.
3040 if (hwc_display->IsSkipValidateState() && !hwc_display->CanSkipValidate()) {
3041 uint32_t out_num_types = 0, out_num_requests = 0;
3042 hwc_display->SetFastPathComposition(true);
3043 HWC2::Error error = ValidateDisplayInternal(display, &out_num_types, &out_num_requests);
3044 if ((error != HWC2::Error::None) || hwc_display->HWCClientNeedsValidate()) {
3045 hwc_display->SetValidationState(HWCDisplay::kInternalValidate);
3046 hwc_display->SetFastPathComposition(false);
3047 return HWC2::Error::NotValidated;
3048 }
3049 }
3050 return HWC2::Error::None;
3051 }
3052
DisplayPowerReset()3053 void HWCSession::DisplayPowerReset() {
3054 // Acquire lock on all displays.
3055 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3056 display < HWCCallbacks::kNumDisplays; display++) {
3057 locker_[display].Lock();
3058 }
3059
3060 HWC2::Error status = HWC2::Error::None;
3061 HWC2::PowerMode last_power_mode[HWCCallbacks::kNumDisplays] = {};
3062
3063 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3064 display < HWCCallbacks::kNumDisplays; display++) {
3065 if (hwc_display_[display] != NULL) {
3066 last_power_mode[display] = hwc_display_[display]->GetCurrentPowerMode();
3067 DLOGI("Powering off display = %d", display);
3068 status = hwc_display_[display]->SetPowerMode(HWC2::PowerMode::Off,
3069 true /* teardown */);
3070 if (status != HWC2::Error::None) {
3071 DLOGE("Power off for display = %d failed with error = %d", display, status);
3072 }
3073 }
3074 }
3075 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3076 display < HWCCallbacks::kNumDisplays; display++) {
3077 if (hwc_display_[display] != NULL) {
3078 HWC2::PowerMode mode = last_power_mode[display];
3079 DLOGI("Setting display %d to mode = %d", display, mode);
3080 status = hwc_display_[display]->SetPowerMode(mode, false /* teardown */);
3081 if (status != HWC2::Error::None) {
3082 DLOGE("%d mode for display = %d failed with error = %d", mode, display, status);
3083 }
3084 ColorMode color_mode = hwc_display_[display]->GetCurrentColorMode();
3085 status = hwc_display_[display]->SetColorMode(color_mode);
3086 if (status != HWC2::Error::None) {
3087 DLOGE("SetColorMode failed for display = %d error = %d", display, status);
3088 }
3089 }
3090 }
3091
3092 hwc2_display_t vsync_source = callbacks_.GetVsyncSource();
3093 status = hwc_display_[vsync_source]->SetVsyncEnabled(HWC2::Vsync::Enable);
3094 if (status != HWC2::Error::None) {
3095 DLOGE("Enabling vsync failed for disp: %" PRIu64 " with error = %d", vsync_source, status);
3096 }
3097
3098 // Release lock on all displays.
3099 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3100 display < HWCCallbacks::kNumDisplays; display++) {
3101 locker_[display].Unlock();
3102 }
3103
3104 Refresh(vsync_source);
3105 }
3106
HandleSecureSession()3107 void HWCSession::HandleSecureSession() {
3108 std::bitset<kSecureMax> secure_sessions = 0;
3109 {
3110 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
3111 if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
3112 return;
3113 }
3114 Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
3115 hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
3116 }
3117
3118 // If it is called during primary prepare/commit, we need to pause any ongoing commit on
3119 // external/virtual display.
3120 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3121 display < HWCCallbacks::kNumDisplays; display++) {
3122 Locker::ScopeLock lock_d(locker_[display]);
3123 if (hwc_display_[display]) {
3124 hwc_display_[display]->HandleSecureSession(secure_sessions, &power_on_pending_[display]);
3125 }
3126 }
3127 }
3128
HandlePowerOnPending(hwc2_display_t disp_id,int retire_fence)3129 void HWCSession::HandlePowerOnPending(hwc2_display_t disp_id, int retire_fence) {
3130 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
3131 if (disp_id != active_builtin_disp_id) {
3132 return;
3133 }
3134
3135 Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
3136 bool power_on_pending = false;
3137 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3138 display < HWCCallbacks::kNumDisplays; display++) {
3139 if (display != active_builtin_disp_id) {
3140 Locker::ScopeLock lock_d(locker_[display]);
3141 if (power_on_pending_[display]) {
3142 power_on_pending = true;
3143 break;
3144 }
3145 }
3146 }
3147 if (power_on_pending) {
3148 // retire fence is set only after successful primary commit, So check for retire fence to know
3149 // non secure commit went through to notify driver to change the CRTC mode to non secure.
3150 // Otherwise any commit to non-primary display would fail.
3151 if (retire_fence < 0) {
3152 return;
3153 }
3154 int error = sync_wait(retire_fence, 1000);
3155 if (error < 0) {
3156 DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
3157 }
3158 } else {
3159 return;
3160 }
3161
3162 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3163 display < HWCCallbacks::kNumDisplays; display++) {
3164 if (display != active_builtin_disp_id) {
3165 Locker::ScopeLock lock_d(locker_[display]);
3166 if (power_on_pending_[display] && hwc_display_[display]) {
3167 HWC2::Error status =
3168 hwc_display_[display]->SetPowerMode(HWC2::PowerMode::On, false /* teardown */);
3169 if (status == HWC2::Error::None) {
3170 power_on_pending_[display] = false;
3171 }
3172 }
3173 }
3174 }
3175 }
3176
HandleHotplugPending(hwc2_display_t disp_id,int retire_fence)3177 void HWCSession::HandleHotplugPending(hwc2_display_t disp_id, int retire_fence) {
3178 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
3179 if (disp_id != active_builtin_disp_id ||
3180 (kHotPlugNone == hotplug_pending_event_ && !destroy_virtual_disp_pending_)) {
3181 return;
3182 }
3183
3184 std :: bitset < kSecureMax > secure_sessions = 0;
3185 if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
3186 Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
3187 hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
3188 }
3189
3190 if (secure_sessions.any() || active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
3191 return;
3192 }
3193
3194 if (destroy_virtual_disp_pending_ || kHotPlugEvent == hotplug_pending_event_) {
3195 if (retire_fence >= 0) {
3196 int error = sync_wait(retire_fence, 1000);
3197 if (error < 0) {
3198 DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
3199 }
3200 }
3201 // Destroy the pending virtual display if secure session not present.
3202 if (destroy_virtual_disp_pending_) {
3203 for (auto &map_info : map_info_virtual_) {
3204 DestroyDisplay(&map_info);
3205 destroy_virtual_disp_pending_ = false;
3206 }
3207 }
3208 // Handle connect/disconnect hotplugs if secure session is not present.
3209 hwc2_display_t virtual_display_idx = (hwc2_display_t)GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
3210 if (!hwc_display_[virtual_display_idx] && kHotPlugEvent == hotplug_pending_event_) {
3211 // Handle deferred hotplug event.
3212 int32_t err = pluggable_handler_lock_.TryLock();
3213 if (!err) {
3214 // Do hotplug handling in a different thread to avoid blocking PresentDisplay.
3215 std::thread(&HWCSession::HandlePluggableDisplays, this, true).detach();
3216 pluggable_handler_lock_.Unlock();
3217 } else {
3218 // EBUSY means another thread is already handling hotplug. Skip deferred hotplug handling.
3219 if (EBUSY != err) {
3220 DLOGW("Failed to acquire pluggable display handler lock. Error %d '%s'.", err,
3221 strerror(abs(err)));
3222 }
3223 }
3224 }
3225 }
3226 }
3227
GetReadbackBufferAttributes(hwc2_device_t * device,hwc2_display_t display,int32_t * format,int32_t * dataspace)3228 int32_t HWCSession::GetReadbackBufferAttributes(hwc2_device_t *device, hwc2_display_t display,
3229 int32_t *format, int32_t *dataspace) {
3230 if (!device || !format || !dataspace) {
3231 return HWC2_ERROR_BAD_PARAMETER;
3232 }
3233
3234 if (display != HWC_DISPLAY_PRIMARY) {
3235 return HWC2_ERROR_BAD_DISPLAY;
3236 }
3237
3238 HWCSession *hwc_session = static_cast<HWCSession *>(device);
3239 HWCDisplay *hwc_display = hwc_session->hwc_display_[display];
3240
3241 if (hwc_display) {
3242 *format = HAL_PIXEL_FORMAT_RGB_888;
3243 *dataspace = GetDataspaceFromColorMode(hwc_display->GetCurrentColorMode());
3244 return HWC2_ERROR_NONE;
3245 }
3246
3247 return HWC2_ERROR_BAD_DISPLAY;
3248 }
3249
SetReadbackBuffer(hwc2_device_t * device,hwc2_display_t display,const native_handle_t * buffer,int32_t acquire_fence)3250 int32_t HWCSession::SetReadbackBuffer(hwc2_device_t *device, hwc2_display_t display,
3251 const native_handle_t *buffer, int32_t acquire_fence) {
3252 if (!buffer) {
3253 return HWC2_ERROR_BAD_PARAMETER;
3254 }
3255
3256 if (display != HWC_DISPLAY_PRIMARY) {
3257 return HWC2_ERROR_BAD_DISPLAY;
3258 }
3259
3260 HWCSession *hwc_session = static_cast<HWCSession *>(device);
3261
3262 const int external_display_index = hwc_session->GetDisplayIndex(qdutils::DISPLAY_EXTERNAL);
3263 if ((external_display_index >=0) && (hwc_session->hwc_display_[external_display_index])) {
3264 return HWC2_ERROR_UNSUPPORTED;
3265 }
3266
3267 const int virtual_display_index = hwc_session->GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
3268 if ((virtual_display_index >=0) && (hwc_session->hwc_display_[virtual_display_index])) {
3269 return HWC2_ERROR_UNSUPPORTED;
3270 }
3271
3272 return CallDisplayFunction(device, display, &HWCDisplay::SetReadbackBuffer,
3273 buffer, acquire_fence, false);
3274 }
3275
GetReadbackBufferFence(hwc2_device_t * device,hwc2_display_t display,int32_t * release_fence)3276 int32_t HWCSession::GetReadbackBufferFence(hwc2_device_t *device, hwc2_display_t display,
3277 int32_t *release_fence) {
3278 if (!release_fence) {
3279 return HWC2_ERROR_BAD_PARAMETER;
3280 }
3281
3282 if (display != HWC_DISPLAY_PRIMARY) {
3283 return HWC2_ERROR_BAD_DISPLAY;
3284 }
3285
3286 return CallDisplayFunction(device, display, &HWCDisplay::GetReadbackBufferFence, release_fence);
3287 }
3288
GetDisplayIdentificationData(hwc2_device_t * device,hwc2_display_t display,uint8_t * outPort,uint32_t * outDataSize,uint8_t * outData)3289 int32_t HWCSession::GetDisplayIdentificationData(hwc2_device_t *device, hwc2_display_t display,
3290 uint8_t *outPort, uint32_t *outDataSize,
3291 uint8_t *outData) {
3292 if (!outPort || !outDataSize) {
3293 return HWC2_ERROR_BAD_PARAMETER;
3294 }
3295
3296 if (display >= HWCCallbacks::kNumDisplays) {
3297 return HWC2_ERROR_BAD_DISPLAY;
3298 }
3299
3300 return CallDisplayFunction(device, display, &HWCDisplay::GetDisplayIdentificationData, outPort,
3301 outDataSize, outData);
3302 }
3303
SetQSyncMode(const android::Parcel * input_parcel)3304 android::status_t HWCSession::SetQSyncMode(const android::Parcel *input_parcel) {
3305 auto mode = input_parcel->readInt32();
3306 auto device = static_cast<hwc2_device_t *>(this);
3307
3308 QSyncMode qsync_mode = kQSyncModeNone;
3309 switch (mode) {
3310 case qService::IQService::QSYNC_MODE_NONE:
3311 qsync_mode = kQSyncModeNone;
3312 break;
3313 case qService::IQService::QSYNC_MODE_CONTINUOUS:
3314 qsync_mode = kQSyncModeContinuous;
3315 break;
3316 case qService::IQService::QSYNC_MODE_ONESHOT:
3317 qsync_mode = kQsyncModeOneShot;
3318 break;
3319 default:
3320 DLOGE("Qsync mode not supported %d", mode);
3321 return -EINVAL;
3322 }
3323 return CallDisplayFunction(device, HWC_DISPLAY_PRIMARY, &HWCDisplay::SetQSyncMode, qsync_mode);
3324 }
3325
UpdateThrottlingRate()3326 void HWCSession::UpdateThrottlingRate() {
3327 uint32_t new_min = 0;
3328
3329 for (int i=0; i < HWCCallbacks::kNumDisplays; i++) {
3330 auto &display = hwc_display_[i];
3331 if (!display)
3332 continue;
3333 if (display->GetCurrentPowerMode() != HWC2::PowerMode::Off)
3334 new_min = (new_min == 0) ? display->GetMaxRefreshRate() :
3335 std::min(new_min, display->GetMaxRefreshRate());
3336 }
3337
3338 SetNewThrottlingRate(new_min);
3339 }
3340
SetNewThrottlingRate(const uint32_t new_rate)3341 void HWCSession::SetNewThrottlingRate(const uint32_t new_rate) {
3342 if (new_rate !=0 && throttling_refresh_rate_ != new_rate) {
3343 HWCDisplay::SetThrottlingRefreshRate(new_rate);
3344 throttling_refresh_rate_ = new_rate;
3345 }
3346 }
3347
SetIdlePC(const android::Parcel * input_parcel)3348 android::status_t HWCSession::SetIdlePC(const android::Parcel *input_parcel) {
3349 auto enable = input_parcel->readInt32();
3350 auto synchronous = input_parcel->readInt32();
3351
3352 #ifdef DISPLAY_CONFIG_1_3
3353 return static_cast<android::status_t>(controlIdlePowerCollapse(enable, synchronous));
3354 #else
3355 {
3356 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
3357 if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
3358 DLOGE("No active displays");
3359 return -EINVAL;
3360 }
3361 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
3362 if (hwc_display_[active_builtin_disp_id]) {
3363 DLOGE("Primary display is not ready");
3364 return -EINVAL;
3365 }
3366 auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable, synchronous);
3367 if (err != kErrorNone) {
3368 return (err == kErrorNotSupported) ? 0 : -EINVAL;
3369 }
3370 if (!enable) {
3371 Refresh(active_builtin_disp_id);
3372 int32_t error = locker_[active_builtin_disp_id].WaitFinite(kCommitDoneTimeoutMs);
3373 if (error == ETIMEDOUT) {
3374 DLOGE("Timed out!! Next frame commit done event not received!!");
3375 return error;
3376 }
3377 }
3378 DLOGI("Idle PC %s!!", enable ? "enabled" : "disabled");
3379 }
3380 return 0;
3381 #endif
3382 }
3383
GetActiveBuiltinDisplay()3384 hwc2_display_t HWCSession::GetActiveBuiltinDisplay() {
3385 hwc2_display_t disp_id = HWCCallbacks::kNumDisplays;
3386 // Get first active display among primary and built-in displays.
3387 std::vector<DisplayMapInfo> map_info = {map_info_primary_};
3388 std::copy(map_info_builtin_.begin(), map_info_builtin_.end(), std::back_inserter(map_info));
3389
3390 for (auto &info : map_info) {
3391 SCOPE_LOCK(locker_[info.client_id]);
3392 auto &hwc_display = hwc_display_[info.client_id];
3393 if (hwc_display && hwc_display->GetCurrentPowerMode() != HWC2::PowerMode::Off) {
3394 disp_id = info.client_id;
3395 break;
3396 }
3397 }
3398
3399 return disp_id;
3400 }
3401
3402 } // namespace sdm
3403