1 /* 2 * Copyright (c) 2014-2018, 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 <core/dump_interface.h> 21 #include <core/buffer_allocator.h> 22 #include <private/color_params.h> 23 #include <utils/constants.h> 24 #include <utils/String16.h> 25 #include <cutils/properties.h> 26 #include <hardware_legacy/uevent.h> 27 #include <sys/resource.h> 28 #include <sys/prctl.h> 29 #include <binder/Parcel.h> 30 #include <QService.h> 31 #include <display_config.h> 32 #include <utils/debug.h> 33 #include <sync/sync.h> 34 #include <profiler.h> 35 #include <algorithm> 36 #include <string> 37 #include <bitset> 38 #include <thread> 39 #include <memory> 40 41 #include "hwc_buffer_allocator.h" 42 #include "hwc_buffer_sync_handler.h" 43 #include "hwc_session.h" 44 #include "hwc_debugger.h" 45 #include "hwc_display_primary.h" 46 #include "hwc_display_virtual.h" 47 48 #define __CLASS__ "HWCSession" 49 50 #define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi" 51 #define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0" 52 53 static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods; 54 55 hwc_module_t HAL_MODULE_INFO_SYM = { 56 .common = { 57 .tag = HARDWARE_MODULE_TAG, 58 .version_major = 3, 59 .version_minor = 0, 60 .id = HWC_HARDWARE_MODULE_ID, 61 .name = "QTI Hardware Composer Module", 62 .author = "CodeAurora Forum", 63 .methods = &g_hwc_module_methods, 64 .dso = 0, 65 .reserved = {0}, 66 } 67 }; 68 69 namespace sdm { 70 71 static HWCUEvent g_hwc_uevent_; 72 Locker HWCSession::locker_; 73 74 void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) { 75 const char *uevent_thread_name = "HWC_UeventThread"; 76 77 prctl(PR_SET_NAME, uevent_thread_name, 0, 0, 0); 78 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); 79 80 int status = uevent_init(); 81 if (!status) { 82 std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_); 83 hwc_uevent->caller_cv_.notify_one(); 84 DLOGE("Failed to init uevent with err %d", status); 85 return; 86 } 87 88 { 89 // Signal caller thread that worker thread is ready to listen to events. 90 std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_); 91 hwc_uevent->init_done_ = true; 92 hwc_uevent->caller_cv_.notify_one(); 93 } 94 95 while (1) { 96 char uevent_data[PAGE_SIZE] = {}; 97 98 // keep last 2 zeroes to ensure double 0 termination 99 int length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2); 100 101 // scope of lock to this block only, so that caller is free to set event handler to nullptr; 102 { 103 std::lock_guard<std::mutex> guard(hwc_uevent->mutex_); 104 if (hwc_uevent->uevent_listener_) { 105 hwc_uevent->uevent_listener_->UEventHandler(uevent_data, length); 106 } else { 107 DLOGW("UEvent dropped. No uevent listener."); 108 } 109 } 110 } 111 } 112 113 HWCUEvent::HWCUEvent() { 114 std::unique_lock<std::mutex> caller_lock(mutex_); 115 std::thread thread(HWCUEvent::UEventThread, this); 116 thread.detach(); 117 caller_cv_.wait(caller_lock); 118 } 119 120 void HWCUEvent::Register(HWCUEventListener *uevent_listener) { 121 DLOGI("Set uevent listener = %p", uevent_listener); 122 123 std::lock_guard<std::mutex> obj(mutex_); 124 uevent_listener_ = uevent_listener; 125 } 126 127 HWCSession::HWCSession(const hw_module_t *module) { 128 hwc2_device_t::common.tag = HARDWARE_DEVICE_TAG; 129 hwc2_device_t::common.version = HWC_DEVICE_API_VERSION_2_0; 130 hwc2_device_t::common.module = const_cast<hw_module_t *>(module); 131 hwc2_device_t::common.close = Close; 132 hwc2_device_t::getCapabilities = GetCapabilities; 133 hwc2_device_t::getFunction = GetFunction; 134 } 135 136 int HWCSession::Init() { 137 int status = -EINVAL; 138 const char *qservice_name = "display.qservice"; 139 140 if (!g_hwc_uevent_.InitDone()) { 141 return status; 142 } 143 144 // Start QService and connect to it. 145 qService::QService::init(); 146 android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>( 147 android::defaultServiceManager()->getService(android::String16(qservice_name))); 148 149 if (iqservice.get()) { 150 iqservice->connect(android::sp<qClient::IQClient>(this)); 151 qservice_ = reinterpret_cast<qService::QService *>(iqservice.get()); 152 } else { 153 DLOGE("Failed to acquire %s", qservice_name); 154 return -EINVAL; 155 } 156 157 StartServices(); 158 159 DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_, 160 &buffer_sync_handler_, &socket_handler_, 161 &core_intf_); 162 if (error != kErrorNone) { 163 DLOGE("Display core initialization failed. Error = %d", error); 164 return -EINVAL; 165 } 166 167 g_hwc_uevent_.Register(this); 168 169 // If HDMI display is primary display, defer display creation until hotplug event is received. 170 HWDisplayInterfaceInfo hw_disp_info = {}; 171 error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info); 172 if (error != kErrorNone) { 173 g_hwc_uevent_.Register(nullptr); 174 CoreInterface::DestroyCore(); 175 DLOGE("Primary display type not recognized. Error = %d", error); 176 return -EINVAL; 177 } 178 179 if (hw_disp_info.type == kHDMI) { 180 status = 0; 181 hdmi_is_primary_ = true; 182 // Create display if it is connected, else wait for hotplug connect event. 183 if (hw_disp_info.is_connected) { 184 status = HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_, qservice_, 185 &hwc_display_[HWC_DISPLAY_PRIMARY]); 186 } 187 } else { 188 // Create and power on primary display 189 status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &callbacks_, qservice_, 190 &hwc_display_[HWC_DISPLAY_PRIMARY]); 191 color_mgr_ = HWCColorManager::CreateColorManager(&buffer_allocator_); 192 if (!color_mgr_) { 193 DLOGW("Failed to load HWCColorManager."); 194 } 195 } 196 197 if (status) { 198 g_hwc_uevent_.Register(nullptr); 199 CoreInterface::DestroyCore(); 200 return status; 201 } 202 203 struct rlimit fd_limit = {}; 204 getrlimit(RLIMIT_NOFILE, &fd_limit); 205 fd_limit.rlim_cur = fd_limit.rlim_cur * 2; 206 if (fd_limit.rlim_cur < fd_limit.rlim_max) { 207 auto err = setrlimit(RLIMIT_NOFILE, &fd_limit); 208 if (err) { 209 DLOGW("Unable to increase fd limit - err:%d, %s", errno, strerror(errno)); 210 } 211 } 212 213 return 0; 214 } 215 216 int HWCSession::Deinit() { 217 HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY]; 218 if (primary_display) { 219 if (hdmi_is_primary_) { 220 HWCDisplayExternal::Destroy(primary_display); 221 } else { 222 HWCDisplayPrimary::Destroy(primary_display); 223 } 224 } 225 hwc_display_[HWC_DISPLAY_PRIMARY] = nullptr; 226 227 if (color_mgr_) { 228 color_mgr_->DestroyColorManager(); 229 } 230 231 g_hwc_uevent_.Register(nullptr); 232 233 DisplayError error = CoreInterface::DestroyCore(); 234 if (error != kErrorNone) { 235 DLOGE("Display core de-initialization failed. Error = %d", error); 236 } 237 238 return 0; 239 } 240 241 int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) { 242 SCOPE_LOCK(locker_); 243 244 if (!module || !name || !device) { 245 DLOGE("Invalid parameters."); 246 return -EINVAL; 247 } 248 249 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { 250 HWCSession *hwc_session = new HWCSession(module); 251 if (!hwc_session) { 252 return -ENOMEM; 253 } 254 255 int status = hwc_session->Init(); 256 if (status != 0) { 257 return status; 258 } 259 260 hwc2_device_t *composer_device = hwc_session; 261 *device = reinterpret_cast<hw_device_t *>(composer_device); 262 } 263 264 return 0; 265 } 266 267 int HWCSession::Close(hw_device_t *device) { 268 SCOPE_LOCK(locker_); 269 270 if (!device) { 271 return -EINVAL; 272 } 273 274 hwc2_device_t *composer_device = reinterpret_cast<hwc2_device_t *>(device); 275 HWCSession *hwc_session = static_cast<HWCSession *>(composer_device); 276 277 hwc_session->Deinit(); 278 279 return 0; 280 } 281 282 void HWCSession::GetCapabilities(struct hwc2_device *device, uint32_t *outCount, 283 int32_t *outCapabilities) { 284 if (!outCount) { 285 return; 286 } 287 288 int value = 0; 289 bool disable_skip_validate = false; 290 if (Debug::Get()->GetProperty("sdm.debug.disable_skip_validate", &value) == kErrorNone) { 291 disable_skip_validate = (value == 1); 292 } 293 uint32_t count = 1 + (disable_skip_validate ? 0 : 1); 294 295 if (outCapabilities != nullptr && (*outCount >= count)) { 296 outCapabilities[0] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM; 297 if (!disable_skip_validate) { 298 outCapabilities[1] = HWC2_CAPABILITY_SKIP_VALIDATE; 299 } 300 } 301 *outCount = count; 302 } 303 304 template <typename PFN, typename T> 305 static hwc2_function_pointer_t AsFP(T function) { 306 static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer"); 307 return reinterpret_cast<hwc2_function_pointer_t>(function); 308 } 309 310 // HWC2 functions returned in GetFunction 311 // Defined in the same order as in the HWC2 header 312 313 int32_t HWCSession::AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display) { 314 315 if (display >= HWC_NUM_DISPLAY_TYPES) { 316 return HWC2_ERROR_BAD_DISPLAY; 317 } 318 SCOPE_LOCK(locker_); 319 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::AcceptDisplayChanges); 320 } 321 322 int32_t HWCSession::CreateLayer(hwc2_device_t *device, hwc2_display_t display, 323 hwc2_layer_t *out_layer_id) { 324 if (!out_layer_id) { 325 return HWC2_ERROR_BAD_PARAMETER; 326 } 327 if (display >= HWC_NUM_DISPLAY_TYPES) { 328 return HWC2_ERROR_BAD_DISPLAY; 329 } 330 SCOPE_LOCK(locker_); 331 return CallDisplayFunction(device, display, &HWCDisplay::CreateLayer, out_layer_id); 332 } 333 334 int32_t HWCSession::CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height, 335 int32_t *format, hwc2_display_t *out_display_id) { 336 // TODO(user): Handle concurrency with HDMI 337 SCOPE_LOCK(locker_); 338 if (!device) { 339 return HWC2_ERROR_BAD_DISPLAY; 340 } 341 342 if (!out_display_id || !width || !height || !format) { 343 return HWC2_ERROR_BAD_PARAMETER; 344 } 345 346 HWCSession *hwc_session = static_cast<HWCSession *>(device); 347 auto status = hwc_session->CreateVirtualDisplayObject(width, height, format); 348 if (status == HWC2::Error::None) { 349 *out_display_id = HWC_DISPLAY_VIRTUAL; 350 DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d", 351 *out_display_id, width, height); 352 } else { 353 DLOGE("Failed to create virtual display: %s", to_string(status).c_str()); 354 } 355 return INT32(status); 356 } 357 358 int32_t HWCSession::DestroyLayer(hwc2_device_t *device, hwc2_display_t display, 359 hwc2_layer_t layer) { 360 if (display >= HWC_NUM_DISPLAY_TYPES) { 361 return HWC2_ERROR_BAD_DISPLAY; 362 } 363 SCOPE_LOCK(locker_); 364 return CallDisplayFunction(device, display, &HWCDisplay::DestroyLayer, layer); 365 } 366 367 int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) { 368 SCOPE_LOCK(locker_); 369 if (!device || display != HWC_DISPLAY_VIRTUAL) { 370 return HWC2_ERROR_BAD_DISPLAY; 371 } 372 373 DLOGI("Destroying virtual display id:%" PRIu64, display); 374 auto *hwc_session = static_cast<HWCSession *>(device); 375 376 if (hwc_session->hwc_display_[display]) { 377 HWCDisplayVirtual::Destroy(hwc_session->hwc_display_[display]); 378 hwc_session->hwc_display_[display] = nullptr; 379 return HWC2_ERROR_NONE; 380 } else { 381 return HWC2_ERROR_BAD_DISPLAY; 382 } 383 } 384 385 void HWCSession::Dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer) { 386 SCOPE_LOCK(locker_); 387 388 if (!device || !out_size) { 389 return; 390 } 391 auto *hwc_session = static_cast<HWCSession *>(device); 392 const size_t max_dump_size = 8192; 393 394 if (out_buffer == nullptr) { 395 *out_size = max_dump_size; 396 } else { 397 char sdm_dump[4096]; 398 DumpInterface::GetDump(sdm_dump, 4096); // TODO(user): Fix this workaround 399 std::string s(""); 400 for (int id = HWC_DISPLAY_PRIMARY; id <= HWC_DISPLAY_VIRTUAL; id++) { 401 if (hwc_session->hwc_display_[id]) { 402 s += hwc_session->hwc_display_[id]->Dump(); 403 } 404 } 405 s += sdm_dump; 406 auto copied = s.copy(out_buffer, std::min(s.size(), max_dump_size), 0); 407 *out_size = UINT32(copied); 408 } 409 } 410 411 static int32_t GetActiveConfig(hwc2_device_t *device, hwc2_display_t display, 412 hwc2_config_t *out_config) { 413 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetActiveConfig, out_config); 414 } 415 416 static int32_t GetChangedCompositionTypes(hwc2_device_t *device, hwc2_display_t display, 417 uint32_t *out_num_elements, hwc2_layer_t *out_layers, 418 int32_t *out_types) { 419 // null_ptr check only for out_num_elements, as out_layers and out_types can be null. 420 if (!out_num_elements) { 421 return HWC2_ERROR_BAD_PARAMETER; 422 } 423 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetChangedCompositionTypes, 424 out_num_elements, out_layers, out_types); 425 } 426 427 static int32_t GetClientTargetSupport(hwc2_device_t *device, hwc2_display_t display, uint32_t width, 428 uint32_t height, int32_t format, int32_t dataspace) { 429 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetClientTargetSupport, 430 width, height, format, dataspace); 431 } 432 433 static int32_t GetColorModes(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_num_modes, 434 int32_t /*android_color_mode_t*/ *int_out_modes) { 435 auto out_modes = reinterpret_cast<android_color_mode_t *>(int_out_modes); 436 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetColorModes, out_num_modes, 437 out_modes); 438 } 439 440 static int32_t GetDisplayAttribute(hwc2_device_t *device, hwc2_display_t display, 441 hwc2_config_t config, int32_t int_attribute, 442 int32_t *out_value) { 443 auto attribute = static_cast<HWC2::Attribute>(int_attribute); 444 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayAttribute, config, 445 attribute, out_value); 446 } 447 448 static int32_t GetDisplayConfigs(hwc2_device_t *device, hwc2_display_t display, 449 uint32_t *out_num_configs, hwc2_config_t *out_configs) { 450 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayConfigs, 451 out_num_configs, out_configs); 452 } 453 454 static int32_t GetDisplayName(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_size, 455 char *out_name) { 456 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayName, out_size, 457 out_name); 458 } 459 460 static int32_t GetDisplayRequests(hwc2_device_t *device, hwc2_display_t display, 461 int32_t *out_display_requests, uint32_t *out_num_elements, 462 hwc2_layer_t *out_layers, int32_t *out_layer_requests) { 463 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayRequests, 464 out_display_requests, out_num_elements, out_layers, 465 out_layer_requests); 466 } 467 468 static int32_t GetDisplayType(hwc2_device_t *device, hwc2_display_t display, int32_t *out_type) { 469 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayType, out_type); 470 } 471 472 static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display, int32_t *out_support) { 473 if (display == HWC_DISPLAY_PRIMARY) { 474 *out_support = 1; 475 } else { 476 // TODO(user): Port over connect_display_ from HWC1 477 // Return no error for connected displays 478 *out_support = 0; 479 return HWC2_ERROR_BAD_DISPLAY; 480 } 481 return HWC2_ERROR_NONE; 482 } 483 484 static int32_t GetHdrCapabilities(hwc2_device_t* device, hwc2_display_t display, 485 uint32_t* out_num_types, int32_t* out_types, 486 float* out_max_luminance, float* out_max_average_luminance, 487 float* out_min_luminance) { 488 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetHdrCapabilities, 489 out_num_types, out_types, out_max_luminance, 490 out_max_average_luminance, out_min_luminance); 491 } 492 493 static uint32_t GetMaxVirtualDisplayCount(hwc2_device_t *device) { 494 char property[PROPERTY_VALUE_MAX]; 495 property_get("debug.sdm.support_writeback", property, "1"); 496 return (uint32_t) atoi(property); 497 } 498 499 static int32_t GetReleaseFences(hwc2_device_t *device, hwc2_display_t display, 500 uint32_t *out_num_elements, hwc2_layer_t *out_layers, 501 int32_t *out_fences) { 502 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetReleaseFences, 503 out_num_elements, out_layers, out_fences); 504 } 505 506 int32_t HWCSession::PresentDisplay(hwc2_device_t *device, hwc2_display_t display, 507 int32_t *out_retire_fence) { 508 HWCSession *hwc_session = static_cast<HWCSession *>(device); 509 DTRACE_SCOPED(); 510 if (!device) { 511 return HWC2_ERROR_BAD_DISPLAY; 512 } 513 514 auto status = HWC2::Error::BadDisplay; 515 // TODO(user): Handle virtual display/HDMI concurrency 516 if (hwc_session->hwc_display_[display]) { 517 status = hwc_session->hwc_display_[display]->Present(out_retire_fence); 518 // This is only indicative of how many times SurfaceFlinger posts 519 // frames to the display. 520 CALC_FPS(); 521 } 522 523 return INT32(status); 524 } 525 526 int32_t HWCSession::RegisterCallback(hwc2_device_t *device, int32_t descriptor, 527 hwc2_callback_data_t callback_data, 528 hwc2_function_pointer_t pointer) { 529 HWCSession *hwc_session = static_cast<HWCSession *>(device); 530 if (!device) { 531 return HWC2_ERROR_BAD_DISPLAY; 532 } 533 SCOPE_LOCK(hwc_session->callbacks_lock_); 534 auto desc = static_cast<HWC2::Callback>(descriptor); 535 auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer); 536 DLOGD("Registering callback: %s", to_string(desc).c_str()); 537 if (descriptor == HWC2_CALLBACK_HOTPLUG) { 538 if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY] && !hwc_session->hdmi_is_primary_) { 539 hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected); 540 } 541 } 542 hwc_session->callbacks_lock_.Broadcast(); 543 return INT32(error); 544 } 545 546 static int32_t SetActiveConfig(hwc2_device_t *device, hwc2_display_t display, 547 hwc2_config_t config) { 548 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetActiveConfig, config); 549 } 550 551 static int32_t SetClientTarget(hwc2_device_t *device, hwc2_display_t display, 552 buffer_handle_t target, int32_t acquire_fence, 553 int32_t dataspace, hwc_region_t damage) { 554 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetClientTarget, target, 555 acquire_fence, dataspace, damage); 556 } 557 558 int32_t HWCSession::SetColorMode(hwc2_device_t *device, hwc2_display_t display, 559 int32_t /*android_color_mode_t*/ int_mode) { 560 auto mode = static_cast<android_color_mode_t>(int_mode); 561 SCOPE_LOCK(locker_); 562 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode); 563 } 564 565 int32_t HWCSession::SetColorTransform(hwc2_device_t *device, hwc2_display_t display, 566 const float *matrix, 567 int32_t /*android_color_transform_t*/ hint) { 568 SCOPE_LOCK(locker_); 569 android_color_transform_t transform_hint = static_cast<android_color_transform_t>(hint); 570 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetColorTransform, matrix, 571 transform_hint); 572 } 573 574 static int32_t SetCursorPosition(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, 575 int32_t x, int32_t y) { 576 auto status = INT32(HWC2::Error::None); 577 status = HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetCursorPosition, 578 layer, x, y); 579 if (status == INT32(HWC2::Error::None)) { 580 // Update cursor position 581 HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetCursorPosition, x, y); 582 } 583 return status; 584 } 585 586 static int32_t SetLayerBlendMode(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, 587 int32_t int_mode) { 588 auto mode = static_cast<HWC2::BlendMode>(int_mode); 589 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBlendMode, mode); 590 } 591 592 static int32_t SetLayerBuffer(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, 593 buffer_handle_t buffer, int32_t acquire_fence) { 594 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerBuffer, buffer, 595 acquire_fence); 596 } 597 598 static int32_t SetLayerColor(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, 599 hwc_color_t color) { 600 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerColor, color); 601 } 602 603 static int32_t SetLayerCompositionType(hwc2_device_t *device, hwc2_display_t display, 604 hwc2_layer_t layer, int32_t int_type) { 605 auto type = static_cast<HWC2::Composition>(int_type); 606 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerCompositionType, 607 type); 608 } 609 610 static int32_t SetLayerDataspace(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, 611 int32_t dataspace) { 612 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDataspace, 613 dataspace); 614 } 615 616 static int32_t SetLayerDisplayFrame(hwc2_device_t *device, hwc2_display_t display, 617 hwc2_layer_t layer, hwc_rect_t frame) { 618 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerDisplayFrame, 619 frame); 620 } 621 622 static int32_t SetLayerPlaneAlpha(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, 623 float alpha) { 624 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerPlaneAlpha, 625 alpha); 626 } 627 628 static int32_t SetLayerSourceCrop(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, 629 hwc_frect_t crop) { 630 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSourceCrop, crop); 631 } 632 633 static int32_t SetLayerSurfaceDamage(hwc2_device_t *device, hwc2_display_t display, 634 hwc2_layer_t layer, hwc_region_t damage) { 635 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerSurfaceDamage, 636 damage); 637 } 638 639 static int32_t SetLayerTransform(hwc2_device_t *device, hwc2_display_t display, hwc2_layer_t layer, 640 int32_t int_transform) { 641 auto transform = static_cast<HWC2::Transform>(int_transform); 642 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerTransform, 643 transform); 644 } 645 646 static int32_t SetLayerVisibleRegion(hwc2_device_t *device, hwc2_display_t display, 647 hwc2_layer_t layer, hwc_region_t visible) { 648 return HWCSession::CallLayerFunction(device, display, layer, &HWCLayer::SetLayerVisibleRegion, 649 visible); 650 } 651 652 int32_t HWCSession::SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display, 653 hwc2_layer_t layer, uint32_t z) { 654 SCOPE_LOCK(locker_); 655 return CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z); 656 } 657 658 int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display, 659 buffer_handle_t buffer, int32_t releaseFence) { 660 if (!device) { 661 return HWC2_ERROR_BAD_DISPLAY; 662 } 663 664 if (display != HWC_DISPLAY_VIRTUAL) { 665 return HWC2_ERROR_UNSUPPORTED; 666 } 667 668 auto *hwc_session = static_cast<HWCSession *>(device); 669 if (hwc_session->hwc_display_[display]) { 670 auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_session->hwc_display_[display]); 671 auto status = vds->SetOutputBuffer(buffer, releaseFence); 672 return INT32(status); 673 } else { 674 return HWC2_ERROR_BAD_DISPLAY; 675 } 676 } 677 678 int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) { 679 auto mode = static_cast<HWC2::PowerMode>(int_mode); 680 SCOPE_LOCK(locker_); 681 return CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode); 682 } 683 684 static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display, int32_t int_enabled) { 685 auto enabled = static_cast<HWC2::Vsync>(int_enabled); 686 return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetVsyncEnabled, enabled); 687 } 688 689 int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display, 690 uint32_t *out_num_types, uint32_t *out_num_requests) { 691 DTRACE_SCOPED(); 692 SCOPE_LOCK(locker_); 693 HWCSession *hwc_session = static_cast<HWCSession *>(device); 694 if (!device) { 695 return HWC2_ERROR_BAD_DISPLAY; 696 } 697 698 // TODO(user): Handle secure session, handle QDCM solid fill 699 // Handle external_pending_connect_ in CreateVirtualDisplay 700 auto status = HWC2::Error::BadDisplay; 701 if (hwc_session->hwc_display_[display]) { 702 if (display == HWC_DISPLAY_PRIMARY) { 703 // TODO(user): This can be moved to HWCDisplayPrimary 704 if (hwc_session->reset_panel_) { 705 DLOGW("panel is in bad state, resetting the panel"); 706 hwc_session->ResetPanel(); 707 } 708 709 if (hwc_session->need_invalidate_) { 710 hwc_session->Refresh(display); 711 } 712 713 if (hwc_session->color_mgr_) { 714 hwc_session->color_mgr_->SetColorModeDetailEnhancer(hwc_session->hwc_display_[display]); 715 } 716 } 717 718 status = hwc_session->hwc_display_[display]->Validate(out_num_types, out_num_requests); 719 } 720 return INT32(status); 721 } 722 723 hwc2_function_pointer_t HWCSession::GetFunction(struct hwc2_device *device, 724 int32_t int_descriptor) { 725 auto descriptor = static_cast<HWC2::FunctionDescriptor>(int_descriptor); 726 727 switch (descriptor) { 728 case HWC2::FunctionDescriptor::AcceptDisplayChanges: 729 return AsFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(HWCSession::AcceptDisplayChanges); 730 case HWC2::FunctionDescriptor::CreateLayer: 731 return AsFP<HWC2_PFN_CREATE_LAYER>(CreateLayer); 732 case HWC2::FunctionDescriptor::CreateVirtualDisplay: 733 return AsFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(HWCSession::CreateVirtualDisplay); 734 case HWC2::FunctionDescriptor::DestroyLayer: 735 return AsFP<HWC2_PFN_DESTROY_LAYER>(DestroyLayer); 736 case HWC2::FunctionDescriptor::DestroyVirtualDisplay: 737 return AsFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(HWCSession::DestroyVirtualDisplay); 738 case HWC2::FunctionDescriptor::Dump: 739 return AsFP<HWC2_PFN_DUMP>(HWCSession::Dump); 740 case HWC2::FunctionDescriptor::GetActiveConfig: 741 return AsFP<HWC2_PFN_GET_ACTIVE_CONFIG>(GetActiveConfig); 742 case HWC2::FunctionDescriptor::GetChangedCompositionTypes: 743 return AsFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(GetChangedCompositionTypes); 744 case HWC2::FunctionDescriptor::GetClientTargetSupport: 745 return AsFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(GetClientTargetSupport); 746 case HWC2::FunctionDescriptor::GetColorModes: 747 return AsFP<HWC2_PFN_GET_COLOR_MODES>(GetColorModes); 748 case HWC2::FunctionDescriptor::GetDisplayAttribute: 749 return AsFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(GetDisplayAttribute); 750 case HWC2::FunctionDescriptor::GetDisplayConfigs: 751 return AsFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(GetDisplayConfigs); 752 case HWC2::FunctionDescriptor::GetDisplayName: 753 return AsFP<HWC2_PFN_GET_DISPLAY_NAME>(GetDisplayName); 754 case HWC2::FunctionDescriptor::GetDisplayRequests: 755 return AsFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(GetDisplayRequests); 756 case HWC2::FunctionDescriptor::GetDisplayType: 757 return AsFP<HWC2_PFN_GET_DISPLAY_TYPE>(GetDisplayType); 758 case HWC2::FunctionDescriptor::GetHdrCapabilities: 759 return AsFP<HWC2_PFN_GET_HDR_CAPABILITIES>(GetHdrCapabilities); 760 case HWC2::FunctionDescriptor::GetDozeSupport: 761 return AsFP<HWC2_PFN_GET_DOZE_SUPPORT>(GetDozeSupport); 762 case HWC2::FunctionDescriptor::GetMaxVirtualDisplayCount: 763 return AsFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(GetMaxVirtualDisplayCount); 764 case HWC2::FunctionDescriptor::GetReleaseFences: 765 return AsFP<HWC2_PFN_GET_RELEASE_FENCES>(GetReleaseFences); 766 case HWC2::FunctionDescriptor::PresentDisplay: 767 return AsFP<HWC2_PFN_PRESENT_DISPLAY>(PresentDisplay); 768 case HWC2::FunctionDescriptor::RegisterCallback: 769 return AsFP<HWC2_PFN_REGISTER_CALLBACK>(RegisterCallback); 770 case HWC2::FunctionDescriptor::SetActiveConfig: 771 return AsFP<HWC2_PFN_SET_ACTIVE_CONFIG>(SetActiveConfig); 772 case HWC2::FunctionDescriptor::SetClientTarget: 773 return AsFP<HWC2_PFN_SET_CLIENT_TARGET>(SetClientTarget); 774 case HWC2::FunctionDescriptor::SetColorMode: 775 return AsFP<HWC2_PFN_SET_COLOR_MODE>(SetColorMode); 776 case HWC2::FunctionDescriptor::SetColorTransform: 777 return AsFP<HWC2_PFN_SET_COLOR_TRANSFORM>(SetColorTransform); 778 case HWC2::FunctionDescriptor::SetCursorPosition: 779 return AsFP<HWC2_PFN_SET_CURSOR_POSITION>(SetCursorPosition); 780 case HWC2::FunctionDescriptor::SetLayerBlendMode: 781 return AsFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(SetLayerBlendMode); 782 case HWC2::FunctionDescriptor::SetLayerBuffer: 783 return AsFP<HWC2_PFN_SET_LAYER_BUFFER>(SetLayerBuffer); 784 case HWC2::FunctionDescriptor::SetLayerColor: 785 return AsFP<HWC2_PFN_SET_LAYER_COLOR>(SetLayerColor); 786 case HWC2::FunctionDescriptor::SetLayerCompositionType: 787 return AsFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(SetLayerCompositionType); 788 case HWC2::FunctionDescriptor::SetLayerDataspace: 789 return AsFP<HWC2_PFN_SET_LAYER_DATASPACE>(SetLayerDataspace); 790 case HWC2::FunctionDescriptor::SetLayerDisplayFrame: 791 return AsFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(SetLayerDisplayFrame); 792 case HWC2::FunctionDescriptor::SetLayerPlaneAlpha: 793 return AsFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(SetLayerPlaneAlpha); 794 // Sideband stream is not supported 795 // case HWC2::FunctionDescriptor::SetLayerSidebandStream: 796 case HWC2::FunctionDescriptor::SetLayerSourceCrop: 797 return AsFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(SetLayerSourceCrop); 798 case HWC2::FunctionDescriptor::SetLayerSurfaceDamage: 799 return AsFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(SetLayerSurfaceDamage); 800 case HWC2::FunctionDescriptor::SetLayerTransform: 801 return AsFP<HWC2_PFN_SET_LAYER_TRANSFORM>(SetLayerTransform); 802 case HWC2::FunctionDescriptor::SetLayerVisibleRegion: 803 return AsFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(SetLayerVisibleRegion); 804 case HWC2::FunctionDescriptor::SetLayerZOrder: 805 return AsFP<HWC2_PFN_SET_LAYER_Z_ORDER>(SetLayerZOrder); 806 case HWC2::FunctionDescriptor::SetOutputBuffer: 807 return AsFP<HWC2_PFN_SET_OUTPUT_BUFFER>(SetOutputBuffer); 808 case HWC2::FunctionDescriptor::SetPowerMode: 809 return AsFP<HWC2_PFN_SET_POWER_MODE>(SetPowerMode); 810 case HWC2::FunctionDescriptor::SetVsyncEnabled: 811 return AsFP<HWC2_PFN_SET_VSYNC_ENABLED>(SetVsyncEnabled); 812 case HWC2::FunctionDescriptor::ValidateDisplay: 813 return AsFP<HWC2_PFN_VALIDATE_DISPLAY>(HWCSession::ValidateDisplay); 814 default: 815 DLOGD("Unknown/Unimplemented function descriptor: %d (%s)", int_descriptor, 816 to_string(descriptor).c_str()); 817 return nullptr; 818 } 819 return nullptr; 820 } 821 822 // TODO(user): handle locking 823 824 HWC2::Error HWCSession::CreateVirtualDisplayObject(uint32_t width, uint32_t height, 825 int32_t *format) { 826 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) { 827 return HWC2::Error::NoResources; 828 } 829 auto status = HWCDisplayVirtual::Create(core_intf_, &buffer_allocator_, &callbacks_, width, 830 height, format, &hwc_display_[HWC_DISPLAY_VIRTUAL]); 831 // TODO(user): validate width and height support 832 if (status) 833 return HWC2::Error::Unsupported; 834 835 return HWC2::Error::None; 836 } 837 838 int32_t HWCSession::ConnectDisplay(int disp) { 839 DLOGI("Display = %d", disp); 840 841 int status = 0; 842 uint32_t primary_width = 0; 843 uint32_t primary_height = 0; 844 845 hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height); 846 847 if (disp == HWC_DISPLAY_EXTERNAL) { 848 status = HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_, primary_width, 849 primary_height, qservice_, false, &hwc_display_[disp]); 850 } else { 851 DLOGE("Invalid display type"); 852 return -1; 853 } 854 855 if (!status) { 856 hwc_display_[disp]->SetSecureDisplay(secure_display_active_); 857 } 858 859 return status; 860 } 861 862 int HWCSession::DisconnectDisplay(int disp) { 863 DLOGI("Display = %d", disp); 864 865 if (disp == HWC_DISPLAY_EXTERNAL) { 866 HWCDisplayExternal::Destroy(hwc_display_[disp]); 867 } else if (disp == HWC_DISPLAY_VIRTUAL) { 868 HWCDisplayVirtual::Destroy(hwc_display_[disp]); 869 } else { 870 DLOGE("Invalid display type"); 871 return -1; 872 } 873 874 hwc_display_[disp] = NULL; 875 876 return 0; 877 } 878 879 // Qclient methods 880 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel, 881 android::Parcel *output_parcel) { 882 android::status_t status = 0; 883 884 switch (command) { 885 case qService::IQService::DYNAMIC_DEBUG: 886 DynamicDebug(input_parcel); 887 break; 888 889 case qService::IQService::SCREEN_REFRESH: 890 refreshScreen(); 891 break; 892 893 case qService::IQService::SET_IDLE_TIMEOUT: 894 setIdleTimeout(UINT32(input_parcel->readInt32())); 895 break; 896 897 case qService::IQService::SET_FRAME_DUMP_CONFIG: 898 SetFrameDumpConfig(input_parcel); 899 break; 900 901 case qService::IQService::SET_MAX_PIPES_PER_MIXER: 902 status = SetMaxMixerStages(input_parcel); 903 break; 904 905 case qService::IQService::SET_DISPLAY_MODE: 906 status = SetDisplayMode(input_parcel); 907 break; 908 909 case qService::IQService::SET_SECONDARY_DISPLAY_STATUS: { 910 int disp_id = INT(input_parcel->readInt32()); 911 HWCDisplay::DisplayStatus disp_status = 912 static_cast<HWCDisplay::DisplayStatus>(input_parcel->readInt32()); 913 status = SetSecondaryDisplayStatus(disp_id, disp_status); 914 output_parcel->writeInt32(status); 915 } 916 break; 917 918 case qService::IQService::CONFIGURE_DYN_REFRESH_RATE: 919 status = ConfigureRefreshRate(input_parcel); 920 break; 921 922 case qService::IQService::SET_VIEW_FRAME: 923 break; 924 925 case qService::IQService::TOGGLE_SCREEN_UPDATES: { 926 int32_t input = input_parcel->readInt32(); 927 status = toggleScreenUpdate(input == 1); 928 output_parcel->writeInt32(status); 929 } 930 break; 931 932 case qService::IQService::QDCM_SVC_CMDS: 933 status = QdcmCMDHandler(input_parcel, output_parcel); 934 break; 935 936 case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED: { 937 int disp_id = input_parcel->readInt32(); 938 uint32_t min_enc_level = UINT32(input_parcel->readInt32()); 939 status = MinHdcpEncryptionLevelChanged(disp_id, min_enc_level); 940 output_parcel->writeInt32(status); 941 } 942 break; 943 944 case qService::IQService::CONTROL_PARTIAL_UPDATE: { 945 int disp_id = input_parcel->readInt32(); 946 uint32_t enable = UINT32(input_parcel->readInt32()); 947 status = ControlPartialUpdate(disp_id, enable == 1); 948 output_parcel->writeInt32(status); 949 } 950 break; 951 952 case qService::IQService::SET_ACTIVE_CONFIG: { 953 uint32_t config = UINT32(input_parcel->readInt32()); 954 int disp_id = input_parcel->readInt32(); 955 status = SetActiveConfigIndex(disp_id, config); 956 } 957 break; 958 959 case qService::IQService::GET_ACTIVE_CONFIG: { 960 int disp_id = input_parcel->readInt32(); 961 uint32_t config = 0; 962 status = GetActiveConfigIndex(disp_id, &config); 963 output_parcel->writeInt32(INT(config)); 964 } 965 break; 966 967 case qService::IQService::GET_CONFIG_COUNT: { 968 int disp_id = input_parcel->readInt32(); 969 uint32_t count = 0; 970 status = GetConfigCount(disp_id, &count); 971 output_parcel->writeInt32(INT(count)); 972 } 973 break; 974 975 case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG: 976 status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel); 977 break; 978 979 case qService::IQService::GET_PANEL_BRIGHTNESS: { 980 int level = 0; 981 status = GetPanelBrightness(&level); 982 output_parcel->writeInt32(level); 983 } 984 break; 985 986 case qService::IQService::SET_PANEL_BRIGHTNESS: { 987 uint32_t level = UINT32(input_parcel->readInt32()); 988 status = setPanelBrightness(level); 989 output_parcel->writeInt32(status); 990 } 991 break; 992 993 case qService::IQService::GET_DISPLAY_VISIBLE_REGION: 994 status = GetVisibleDisplayRect(input_parcel, output_parcel); 995 break; 996 997 case qService::IQService::SET_CAMERA_STATUS: { 998 uint32_t camera_status = UINT32(input_parcel->readInt32()); 999 status = setCameraLaunchStatus(camera_status); 1000 } 1001 break; 1002 1003 case qService::IQService::GET_BW_TRANSACTION_STATUS: { 1004 bool state = true; 1005 status = DisplayBWTransactionPending(&state); 1006 output_parcel->writeInt32(state); 1007 } 1008 break; 1009 1010 case qService::IQService::SET_LAYER_MIXER_RESOLUTION: 1011 status = SetMixerResolution(input_parcel); 1012 break; 1013 1014 case qService::IQService::SET_COLOR_MODE: 1015 status = SetColorModeOverride(input_parcel); 1016 break; 1017 1018 case qService::IQService::SET_STAND_BY_MODE: 1019 status = SetStandByMode(input_parcel); 1020 break; 1021 1022 default: 1023 DLOGW("QService command = %d is not supported", command); 1024 return -EINVAL; 1025 } 1026 1027 return status; 1028 } 1029 1030 android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel 1031 *input_parcel, 1032 android::Parcel *output_parcel) { 1033 SCOPE_LOCK(locker_); 1034 1035 int config = input_parcel->readInt32(); 1036 int dpy = input_parcel->readInt32(); 1037 int error = android::BAD_VALUE; 1038 DisplayConfigVariableInfo display_attributes; 1039 1040 if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES || config < 0) { 1041 return android::BAD_VALUE; 1042 } 1043 1044 if (hwc_display_[dpy]) { 1045 error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes); 1046 if (error == 0) { 1047 output_parcel->writeInt32(INT(display_attributes.vsync_period_ns)); 1048 output_parcel->writeInt32(INT(display_attributes.x_pixels)); 1049 output_parcel->writeInt32(INT(display_attributes.y_pixels)); 1050 output_parcel->writeFloat(display_attributes.x_dpi); 1051 output_parcel->writeFloat(display_attributes.y_dpi); 1052 output_parcel->writeInt32(0); // Panel type, unsupported. 1053 } 1054 } 1055 1056 return error; 1057 } 1058 1059 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) { 1060 SCOPE_LOCK(locker_); 1061 1062 uint32_t operation = UINT32(input_parcel->readInt32()); 1063 HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY]; 1064 1065 switch (operation) { 1066 case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE: 1067 return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false); 1068 1069 case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE: 1070 return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true); 1071 1072 case qdutils::SET_BINDER_DYN_REFRESH_RATE: { 1073 uint32_t refresh_rate = UINT32(input_parcel->readInt32()); 1074 return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refresh_rate); 1075 } 1076 1077 default: 1078 DLOGW("Invalid operation %d", operation); 1079 return -EINVAL; 1080 } 1081 1082 return 0; 1083 } 1084 1085 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) { 1086 SCOPE_LOCK(locker_); 1087 1088 uint32_t mode = UINT32(input_parcel->readInt32()); 1089 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode); 1090 } 1091 1092 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) { 1093 SCOPE_LOCK(locker_); 1094 1095 DisplayError error = kErrorNone; 1096 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32()); 1097 uint32_t max_mixer_stages = UINT32(input_parcel->readInt32()); 1098 1099 if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) { 1100 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 1101 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages); 1102 if (error != kErrorNone) { 1103 return -EINVAL; 1104 } 1105 } 1106 } 1107 1108 if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) { 1109 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { 1110 error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages); 1111 if (error != kErrorNone) { 1112 return -EINVAL; 1113 } 1114 } 1115 } 1116 1117 if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) { 1118 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) { 1119 error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages); 1120 if (error != kErrorNone) { 1121 return -EINVAL; 1122 } 1123 } 1124 } 1125 1126 return 0; 1127 } 1128 1129 void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) { 1130 SCOPE_LOCK(locker_); 1131 1132 uint32_t frame_dump_count = UINT32(input_parcel->readInt32()); 1133 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32()); 1134 uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32()); 1135 1136 if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) { 1137 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 1138 hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type); 1139 } 1140 } 1141 1142 if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) { 1143 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { 1144 hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type); 1145 } 1146 } 1147 1148 if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) { 1149 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) { 1150 hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type); 1151 } 1152 } 1153 } 1154 1155 android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) { 1156 SCOPE_LOCK(locker_); 1157 1158 DisplayError error = kErrorNone; 1159 uint32_t dpy = UINT32(input_parcel->readInt32()); 1160 1161 if (dpy != HWC_DISPLAY_PRIMARY) { 1162 DLOGI("Resoulution change not supported for this display %d", dpy); 1163 return -EINVAL; 1164 } 1165 1166 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) { 1167 DLOGI("Primary display is not initialized"); 1168 return -EINVAL; 1169 } 1170 1171 uint32_t width = UINT32(input_parcel->readInt32()); 1172 uint32_t height = UINT32(input_parcel->readInt32()); 1173 1174 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height); 1175 if (error != kErrorNone) { 1176 return -EINVAL; 1177 } 1178 1179 return 0; 1180 } 1181 1182 android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) { 1183 auto display = static_cast<hwc2_display_t >(input_parcel->readInt32()); 1184 auto mode = static_cast<android_color_mode_t>(input_parcel->readInt32()); 1185 auto device = static_cast<hwc2_device_t *>(this); 1186 1187 if (display >= HWC_NUM_DISPLAY_TYPES) { 1188 return -EINVAL; 1189 } 1190 1191 auto err = CallDisplayFunction(device, display, &HWCDisplay::SetColorMode, mode); 1192 if (err != HWC2_ERROR_NONE) 1193 return -EINVAL; 1194 return 0; 1195 } 1196 1197 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) { 1198 SCOPE_LOCK(locker_); 1199 1200 int type = input_parcel->readInt32(); 1201 bool enable = (input_parcel->readInt32() > 0); 1202 DLOGI("type = %d enable = %d", type, enable); 1203 int verbose_level = input_parcel->readInt32(); 1204 1205 switch (type) { 1206 case qService::IQService::DEBUG_ALL: 1207 HWCDebugHandler::DebugAll(enable, verbose_level); 1208 break; 1209 1210 case qService::IQService::DEBUG_MDPCOMP: 1211 HWCDebugHandler::DebugStrategy(enable, verbose_level); 1212 HWCDebugHandler::DebugCompManager(enable, verbose_level); 1213 break; 1214 1215 case qService::IQService::DEBUG_PIPE_LIFECYCLE: 1216 HWCDebugHandler::DebugResources(enable, verbose_level); 1217 break; 1218 1219 case qService::IQService::DEBUG_DRIVER_CONFIG: 1220 HWCDebugHandler::DebugDriverConfig(enable, verbose_level); 1221 break; 1222 1223 case qService::IQService::DEBUG_ROTATOR: 1224 HWCDebugHandler::DebugResources(enable, verbose_level); 1225 HWCDebugHandler::DebugDriverConfig(enable, verbose_level); 1226 HWCDebugHandler::DebugRotator(enable, verbose_level); 1227 break; 1228 1229 case qService::IQService::DEBUG_QDCM: 1230 HWCDebugHandler::DebugQdcm(enable, verbose_level); 1231 break; 1232 1233 default: 1234 DLOGW("type = %d is not supported", type); 1235 } 1236 } 1237 1238 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel, 1239 android::Parcel *output_parcel) { 1240 int ret = 0; 1241 int32_t *brightness_value = NULL; 1242 uint32_t display_id(0); 1243 PPPendingParams pending_action; 1244 PPDisplayAPIPayload resp_payload, req_payload; 1245 1246 if (!color_mgr_) { 1247 return -1; 1248 } 1249 1250 pending_action.action = kNoAction; 1251 pending_action.params = NULL; 1252 1253 // Read display_id, payload_size and payload from in_parcel. 1254 ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload); 1255 if (!ret) { 1256 if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY]) 1257 ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload, &resp_payload, 1258 &pending_action); 1259 1260 if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL]) 1261 ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload, 1262 &pending_action); 1263 } 1264 1265 if (ret) { 1266 output_parcel->writeInt32(ret); // first field in out parcel indicates return code. 1267 req_payload.DestroyPayload(); 1268 resp_payload.DestroyPayload(); 1269 return ret; 1270 } 1271 1272 switch (pending_action.action) { 1273 case kInvalidating: 1274 Refresh(HWC_DISPLAY_PRIMARY); 1275 break; 1276 case kEnterQDCMMode: 1277 ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]); 1278 break; 1279 case kExitQDCMMode: 1280 ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]); 1281 break; 1282 case kApplySolidFill: 1283 ret = 1284 color_mgr_->SetSolidFill(pending_action.params, true, hwc_display_[HWC_DISPLAY_PRIMARY]); 1285 Refresh(HWC_DISPLAY_PRIMARY); 1286 break; 1287 case kDisableSolidFill: 1288 ret = 1289 color_mgr_->SetSolidFill(pending_action.params, false, hwc_display_[HWC_DISPLAY_PRIMARY]); 1290 Refresh(HWC_DISPLAY_PRIMARY); 1291 break; 1292 case kSetPanelBrightness: 1293 brightness_value = reinterpret_cast<int32_t *>(resp_payload.payload); 1294 if (brightness_value == NULL) { 1295 DLOGE("Brightness value is Null"); 1296 return -EINVAL; 1297 } 1298 if (HWC_DISPLAY_PRIMARY == display_id) 1299 ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value); 1300 break; 1301 case kEnableFrameCapture: 1302 ret = color_mgr_->SetFrameCapture(pending_action.params, true, 1303 hwc_display_[HWC_DISPLAY_PRIMARY]); 1304 Refresh(HWC_DISPLAY_PRIMARY); 1305 break; 1306 case kDisableFrameCapture: 1307 ret = color_mgr_->SetFrameCapture(pending_action.params, false, 1308 hwc_display_[HWC_DISPLAY_PRIMARY]); 1309 break; 1310 case kConfigureDetailedEnhancer: 1311 ret = color_mgr_->SetDetailedEnhancer(pending_action.params, 1312 hwc_display_[HWC_DISPLAY_PRIMARY]); 1313 Refresh(HWC_DISPLAY_PRIMARY); 1314 break; 1315 case kNoAction: 1316 break; 1317 default: 1318 DLOGW("Invalid pending action = %d!", pending_action.action); 1319 break; 1320 } 1321 1322 // for display API getter case, marshall returned params into out_parcel. 1323 output_parcel->writeInt32(ret); 1324 HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel); 1325 req_payload.DestroyPayload(); 1326 resp_payload.DestroyPayload(); 1327 hwc_display_[display_id]->ResetValidation(); 1328 1329 return (ret ? -EINVAL : 0); 1330 } 1331 1332 void HWCSession::UEventHandler(const char *uevent_data, int length) { 1333 if (strcasestr(uevent_data, HWC_UEVENT_SWITCH_HDMI)) { 1334 DLOGI("Uevent HDMI = %s", uevent_data); 1335 int connected = GetEventValue(uevent_data, length, "SWITCH_STATE="); 1336 if (connected >= 0) { 1337 DLOGI("HDMI = %s", connected ? "connected" : "disconnected"); 1338 if (HotPlugHandler(connected) == -1) { 1339 DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected"); 1340 } 1341 } 1342 } else if (strcasestr(uevent_data, HWC_UEVENT_GRAPHICS_FB0)) { 1343 DLOGI("Uevent FB0 = %s", uevent_data); 1344 int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE="); 1345 if (panel_reset == 0) { 1346 Refresh(0); 1347 reset_panel_ = true; 1348 } 1349 } 1350 } 1351 1352 int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) { 1353 const char *iterator_str = uevent_data; 1354 while (((iterator_str - uevent_data) <= length) && (*iterator_str)) { 1355 const char *pstr = strstr(iterator_str, event_info); 1356 if (pstr != NULL) { 1357 return (atoi(iterator_str + strlen(event_info))); 1358 } 1359 iterator_str += strlen(iterator_str) + 1; 1360 } 1361 1362 return -1; 1363 } 1364 1365 void HWCSession::ResetPanel() { 1366 HWC2::Error status; 1367 1368 DLOGI("Powering off primary"); 1369 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC2::PowerMode::Off); 1370 if (status != HWC2::Error::None) { 1371 DLOGE("power-off on primary failed with error = %d", status); 1372 } 1373 1374 DLOGI("Restoring power mode on primary"); 1375 HWC2::PowerMode mode = hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode(); 1376 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode); 1377 if (status != HWC2::Error::None) { 1378 DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status); 1379 } 1380 1381 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetVsyncEnabled(HWC2::Vsync::Enable); 1382 if (status != HWC2::Error::None) { 1383 DLOGE("enabling vsync failed for primary with error = %d", status); 1384 } 1385 1386 reset_panel_ = false; 1387 } 1388 1389 int HWCSession::HotPlugHandler(bool connected) { 1390 int status = 0; 1391 bool notify_hotplug = false; 1392 1393 // To prevent sending events to client while a lock is held, acquire scope locks only within 1394 // below scope so that those get automatically unlocked after the scope ends. 1395 do { 1396 SCOPE_LOCK(locker_); 1397 1398 // If HDMI is primary but not created yet (first time), create it and notify surfaceflinger. 1399 // if it is already created, but got disconnected/connected again, 1400 // just toggle display status and do not notify surfaceflinger. 1401 // If HDMI is not primary, create/destroy external display normally. 1402 if (hdmi_is_primary_) { 1403 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 1404 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetState(connected); 1405 } else { 1406 status = HWCDisplayExternal::Create(core_intf_, &buffer_allocator_, &callbacks_, 1407 qservice_, &hwc_display_[HWC_DISPLAY_PRIMARY]); 1408 notify_hotplug = true; 1409 } 1410 1411 break; 1412 } 1413 1414 // Primary display must be connected for HDMI as secondary cases. 1415 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) { 1416 DLOGE("Primary display is not connected."); 1417 return -1; 1418 } 1419 1420 if (connected) { 1421 // Connect external display if virtual display is not connected. 1422 // Else, defer external display connection and process it when virtual display 1423 // tears down; Do not notify SurfaceFlinger since connection is deferred now. 1424 if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) { 1425 status = ConnectDisplay(HWC_DISPLAY_EXTERNAL); 1426 if (status) { 1427 return status; 1428 } 1429 notify_hotplug = true; 1430 } else { 1431 DLOGI("Virtual display is connected, pending connection"); 1432 external_pending_connect_ = true; 1433 } 1434 } else { 1435 // Do not return error if external display is not in connected status. 1436 // Due to virtual display concurrency, external display connection might be still pending 1437 // but hdmi got disconnected before pending connection could be processed. 1438 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { 1439 status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL); 1440 notify_hotplug = true; 1441 } 1442 external_pending_connect_ = false; 1443 } 1444 } while (0); 1445 1446 if (connected) { 1447 Refresh(0); 1448 1449 if (!hdmi_is_primary_) { 1450 // wait for sufficient time to ensure sufficient resources are available to process new 1451 // new display connection. 1452 uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY)); 1453 usleep(vsync_period * 2 / 1000); 1454 } 1455 } 1456 1457 // notify client 1458 if (notify_hotplug) { 1459 HotPlug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL, 1460 connected ? HWC2::Connection::Connected : HWC2::Connection::Disconnected); 1461 } 1462 1463 qservice_->onHdmiHotplug(INT(connected)); 1464 1465 return 0; 1466 } 1467 1468 int HWCSession::GetVsyncPeriod(int disp) { 1469 SCOPE_LOCK(locker_); 1470 // default value 1471 int32_t vsync_period = 1000000000l / 60; 1472 auto attribute = HWC2::Attribute::VsyncPeriod; 1473 1474 if (hwc_display_[disp]) { 1475 hwc_display_[disp]->GetDisplayAttribute(0, attribute, &vsync_period); 1476 } 1477 1478 return vsync_period; 1479 } 1480 1481 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel, 1482 android::Parcel *output_parcel) { 1483 SCOPE_LOCK(locker_); 1484 1485 int dpy = input_parcel->readInt32(); 1486 if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES) { 1487 return android::BAD_VALUE; 1488 } 1489 1490 if (!hwc_display_[dpy]) { 1491 return android::NO_INIT; 1492 } 1493 1494 hwc_rect_t visible_rect = {0, 0, 0, 0}; 1495 int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect); 1496 if (error < 0) { 1497 return error; 1498 } 1499 1500 output_parcel->writeInt32(visible_rect.left); 1501 output_parcel->writeInt32(visible_rect.top); 1502 output_parcel->writeInt32(visible_rect.right); 1503 output_parcel->writeInt32(visible_rect.bottom); 1504 1505 return android::NO_ERROR; 1506 } 1507 1508 android::status_t HWCSession::SetStandByMode(const android::Parcel *input_parcel) { 1509 SCOPE_LOCK(locker_); 1510 1511 bool enable = (input_parcel->readInt32() > 0); 1512 1513 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) { 1514 DLOGI("Primary display is not initialized"); 1515 return -EINVAL; 1516 } 1517 1518 hwc_display_[HWC_DISPLAY_PRIMARY]->SetStandByMode(enable); 1519 1520 return android::NO_ERROR; 1521 } 1522 1523 void HWCSession::Refresh(hwc2_display_t display) { 1524 SCOPE_LOCK(callbacks_lock_); 1525 HWC2::Error err = callbacks_.Refresh(display); 1526 while (err != HWC2::Error::None) { 1527 callbacks_lock_.Wait(); 1528 err = callbacks_.Refresh(display); 1529 } 1530 } 1531 1532 void HWCSession::HotPlug(hwc2_display_t display, HWC2::Connection state) { 1533 SCOPE_LOCK(callbacks_lock_); 1534 HWC2::Error err = callbacks_.Hotplug(display, state); 1535 while (err != HWC2::Error::None) { 1536 callbacks_lock_.Wait(); 1537 err = callbacks_.Hotplug(display, state); 1538 } 1539 } 1540 1541 } // namespace sdm 1542