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