1/* 2* Copyright (c) 2014 - 2018, The Linux Foundation. All rights reserved. 3* 4* Redistribution and use in source and binary forms, with or without 5* modification, are permitted provided that the following conditions are 6* met: 7* * Redistributions of source code must retain the above copyright 8* notice, this list of conditions and the following disclaimer. 9* * Redistributions in binary form must reproduce the above 10* copyright notice, this list of conditions and the following 11* disclaimer in the documentation and/or other materials provided 12* with the distribution. 13* * Neither the name of The Linux Foundation nor the names of its 14* contributors may be used to endorse or promote products derived 15* from this software without specific prior written permission. 16* 17* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*/ 29 30#include <core/dump_interface.h> 31#include <core/buffer_allocator.h> 32#include <private/color_params.h> 33#include <utils/constants.h> 34#include <utils/String16.h> 35#include <cutils/properties.h> 36#include <hardware_legacy/uevent.h> 37#include <sys/resource.h> 38#include <sys/prctl.h> 39#include <binder/Parcel.h> 40#include <QService.h> 41#include <gr.h> 42#include <gralloc_priv.h> 43#include <display_config.h> 44#include <utils/debug.h> 45#include <sync/sync.h> 46#include <profiler.h> 47#include <bitset> 48#include <vector> 49 50#include "hwc_buffer_allocator.h" 51#include "hwc_buffer_sync_handler.h" 52#include "hwc_session.h" 53#include "hwc_debugger.h" 54#include "hwc_display_null.h" 55#include "hwc_display_primary.h" 56#include "hwc_display_virtual.h" 57#include "hwc_display_external_test.h" 58#include "qd_utils.h" 59 60#define __CLASS__ "HWCSession" 61 62#define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi" 63#define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0" 64 65static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods; 66 67hwc_module_t HAL_MODULE_INFO_SYM = { 68 .common = { 69 .tag = HARDWARE_MODULE_TAG, 70 .version_major = 2, 71 .version_minor = 0, 72 .id = HWC_HARDWARE_MODULE_ID, 73 .name = "QTI Hardware Composer Module", 74 .author = "CodeAurora Forum", 75 .methods = &g_hwc_module_methods, 76 .dso = 0, 77 .reserved = {0}, 78 } 79}; 80 81namespace sdm { 82 83Locker HWCSession::locker_; 84 85static void Invalidate(const struct hwc_procs *procs) { 86} 87 88static void VSync(const struct hwc_procs* procs, int disp, int64_t timestamp) { 89} 90 91static void Hotplug(const struct hwc_procs* procs, int disp, int connected) { 92} 93 94HWCSession::HWCSession(const hw_module_t *module) { 95 // By default, drop any events. Calls will be routed to SurfaceFlinger after registerProcs. 96 hwc_procs_default_.invalidate = Invalidate; 97 hwc_procs_default_.vsync = VSync; 98 hwc_procs_default_.hotplug = Hotplug; 99 100 hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG; 101 hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_5; 102 hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module); 103 hwc_composer_device_1_t::common.close = Close; 104 hwc_composer_device_1_t::prepare = Prepare; 105 hwc_composer_device_1_t::set = Set; 106 hwc_composer_device_1_t::eventControl = EventControl; 107 hwc_composer_device_1_t::setPowerMode = SetPowerMode; 108 hwc_composer_device_1_t::query = Query; 109 hwc_composer_device_1_t::registerProcs = RegisterProcs; 110 hwc_composer_device_1_t::dump = Dump; 111 hwc_composer_device_1_t::getDisplayConfigs = GetDisplayConfigs; 112 hwc_composer_device_1_t::getDisplayAttributes = GetDisplayAttributes; 113 hwc_composer_device_1_t::getActiveConfig = GetActiveConfig; 114 hwc_composer_device_1_t::setActiveConfig = SetActiveConfig; 115 hwc_composer_device_1_t::setCursorPositionAsync = SetCursorPositionAsync; 116} 117 118int HWCSession::Init() { 119 int status = -EINVAL; 120 const char *qservice_name = "display.qservice"; 121 122 // Start QService and connect to it. 123 qService::QService::init(); 124 android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>( 125 android::defaultServiceManager()->getService(android::String16(qservice_name))); 126 127 if (iqservice.get()) { 128 iqservice->connect(android::sp<qClient::IQClient>(this)); 129 qservice_ = reinterpret_cast<qService::QService* >(iqservice.get()); 130 } else { 131 DLOGE("Failed to acquire %s", qservice_name); 132 return -EINVAL; 133 } 134 135 DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_, 136 &buffer_sync_handler_, &socket_handler_, 137 &core_intf_); 138 if (error != kErrorNone) { 139 DLOGE("Display core initialization failed. Error = %d", error); 140 return -EINVAL; 141 } 142 143 SCOPE_LOCK(uevent_locker_); 144 145 if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) { 146 DLOGE("Failed to start = %s, error = %s", uevent_thread_name_, strerror(errno)); 147 CoreInterface::DestroyCore(); 148 return -errno; 149 } 150 151 // Wait for uevent_init() to happen and let the uevent thread wait for uevents, so that hdmi 152 // connect/disconnect events won't be missed 153 uevent_locker_.Wait(); 154 155 // Read which display is first, and create it and store it in primary slot 156 HWDisplayInterfaceInfo hw_disp_info; 157 error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info); 158 if (error == kErrorNone) { 159 if (hw_disp_info.type == kHDMI) { 160 // HDMI is primary display. If already connected, then create it and store in 161 // primary display slot. If not connected, create a NULL display for now. 162 HWCDebugHandler::Get()->SetProperty("persist.sys.is_hdmi_primary", "1"); 163 is_hdmi_primary_ = true; 164 if (hw_disp_info.is_connected) { 165 status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, 0, 0, false); 166 is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY); 167 } else { 168 // NullDisplay simply closes all its fences, and advertizes a standard 169 // resolution to SurfaceFlinger 170 status = HWCDisplayNull::Create(core_intf_, &hwc_procs_, 171 &hwc_display_[HWC_DISPLAY_PRIMARY]); 172 } 173 } else { 174 // Create and power on primary display 175 status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &hwc_procs_, qservice_, 176 &hwc_display_[HWC_DISPLAY_PRIMARY]); 177 } 178 } else { 179 // Create and power on primary display 180 status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &hwc_procs_, qservice_, 181 &hwc_display_[HWC_DISPLAY_PRIMARY]); 182 } 183 184 if (status) { 185 CoreInterface::DestroyCore(); 186 uevent_thread_exit_ = true; 187 pthread_join(uevent_thread_, NULL); 188 return status; 189 } 190 191 color_mgr_ = HWCColorManager::CreateColorManager(); 192 if (!color_mgr_) { 193 DLOGW("Failed to load HWCColorManager."); 194 } 195 196 connected_displays_[HWC_DISPLAY_PRIMARY] = 1; 197 struct rlimit fd_limit = {}; 198 getrlimit(RLIMIT_NOFILE, &fd_limit); 199 fd_limit.rlim_cur = fd_limit.rlim_cur * 2; 200 auto err = setrlimit(RLIMIT_NOFILE, &fd_limit); 201 if (err) { 202 DLOGW("Unable to increase fd limit - err: %d, %s", errno, strerror(errno)); 203 } 204 return 0; 205} 206 207int HWCSession::Deinit() { 208 HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]); 209 hwc_display_[HWC_DISPLAY_PRIMARY] = 0; 210 if (color_mgr_) { 211 color_mgr_->DestroyColorManager(); 212 } 213 uevent_thread_exit_ = true; 214 pthread_join(uevent_thread_, NULL); 215 216 DisplayError error = CoreInterface::DestroyCore(); 217 if (error != kErrorNone) { 218 DLOGE("Display core de-initialization failed. Error = %d", error); 219 } 220 221 connected_displays_[HWC_DISPLAY_PRIMARY] = 0; 222 return 0; 223} 224 225int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) { 226 SEQUENCE_WAIT_SCOPE_LOCK(locker_); 227 228 if (!module || !name || !device) { 229 DLOGE("Invalid parameters."); 230 return -EINVAL; 231 } 232 233 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { 234 HWCSession *hwc_session = new HWCSession(module); 235 if (!hwc_session) { 236 return -ENOMEM; 237 } 238 239 int status = hwc_session->Init(); 240 if (status != 0) { 241 delete hwc_session; 242 return status; 243 } 244 245 hwc_composer_device_1_t *composer_device = hwc_session; 246 *device = reinterpret_cast<hw_device_t *>(composer_device); 247 } 248 249 return 0; 250} 251 252int HWCSession::Close(hw_device_t *device) { 253 SEQUENCE_WAIT_SCOPE_LOCK(locker_); 254 255 if (!device) { 256 return -EINVAL; 257 } 258 259 hwc_composer_device_1_t *composer_device = reinterpret_cast<hwc_composer_device_1_t *>(device); 260 HWCSession *hwc_session = static_cast<HWCSession *>(composer_device); 261 262 hwc_session->Deinit(); 263 delete hwc_session; 264 265 return 0; 266} 267 268int HWCSession::Prepare(hwc_composer_device_1 *device, size_t num_displays, 269 hwc_display_contents_1_t **displays) { 270 DTRACE_SCOPED(); 271 272 if (!device || !displays || num_displays > HWC_NUM_DISPLAY_TYPES) { 273 return -EINVAL; 274 } 275 276 HWCSession *hwc_session = static_cast<HWCSession *>(device); 277 hwc_procs_t const *hwc_procs = NULL; 278 bool hotplug_connect = false; 279 280 // Hold mutex only in this scope. 281 { 282 SEQUENCE_ENTRY_SCOPE_LOCK(locker_); 283 284 hwc_procs = hwc_session->hwc_procs_; 285 286 if (hwc_session->reset_panel_) { 287 DLOGW("panel is in bad state, resetting the panel"); 288 hwc_session->ResetPanel(); 289 } 290 291 if (hwc_session->need_invalidate_) { 292 hwc_procs->invalidate(hwc_procs); 293 hwc_session->need_invalidate_ = false; 294 } 295 296 hwc_session->HandleSecureDisplaySession(displays); 297 298 if (hwc_session->color_mgr_) { 299 HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]; 300 if (primary_display && !hwc_session->is_hdmi_primary_) { 301 int ret = hwc_session->color_mgr_->SolidFillLayersPrepare(displays, primary_display); 302 if (ret) 303 return 0; 304 } 305 } 306 307 for (ssize_t dpy = static_cast<ssize_t>(num_displays - 1); dpy >= 0; dpy--) { 308 hwc_display_contents_1_t *content_list = displays[dpy]; 309 // If external display is connected, ignore virtual display content list. 310 // If virtual display content list is valid, connect virtual display if not connected. 311 // If virtual display content list is invalid, disconnect virtual display if connected. 312 // If external display connection is pending, connect external display when virtual 313 // display is destroyed. 314 // If HDMI is primary and the output format is YUV then ignore the virtual display 315 // content list. 316 if (dpy == HWC_DISPLAY_VIRTUAL) { 317 if (hwc_session->hwc_display_[HWC_DISPLAY_EXTERNAL] || 318 (hwc_session->is_hdmi_primary_ && hwc_session->is_hdmi_yuv_)) { 319 continue; 320 } 321 322 bool valid_content = HWCDisplayVirtual::IsValidContentList(content_list); 323 bool connected = (hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL] != NULL); 324 325 if (valid_content && !connected) { 326 hwc_session->ConnectDisplay(HWC_DISPLAY_VIRTUAL, content_list); 327 } else if (!valid_content && connected) { 328 hwc_session->DisconnectDisplay(HWC_DISPLAY_VIRTUAL); 329 330 if (hwc_session->external_pending_connect_) { 331 DLOGI("Process pending external display connection"); 332 hwc_session->ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL); 333 hwc_session->external_pending_connect_ = false; 334 hotplug_connect = true; 335 } 336 } 337 } 338 339 if (hwc_session->hwc_display_[dpy]) { 340 if (!content_list) { 341 DLOGI("Display[%d] connected. content_list is null", dpy); 342 } else if (!content_list->numHwLayers) { 343 DLOGE("Display[%d] connected. numHwLayers is zero", dpy); 344 } else { 345 hwc_session->hwc_display_[dpy]->Prepare(content_list); 346 } 347 } 348 } 349 } 350 351 if (hotplug_connect) { 352 // notify client 353 hwc_procs->hotplug(hwc_procs, HWC_DISPLAY_EXTERNAL, true); 354 } 355 // Return 0, else client will go into bad state 356 return 0; 357} 358 359int HWCSession::GetVsyncPeriod(int disp) { 360 SCOPE_LOCK(locker_); 361 // default value 362 int32_t vsync_period = 1000000000l / 60; 363 const uint32_t attribute = HWC_DISPLAY_VSYNC_PERIOD; 364 365 if (hwc_display_[disp]) { 366 hwc_display_[disp]->GetDisplayAttributes(0, &attribute, &vsync_period); 367 } 368 369 return vsync_period; 370} 371 372int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays, 373 hwc_display_contents_1_t **displays) { 374 DTRACE_SCOPED(); 375 376 SEQUENCE_EXIT_SCOPE_LOCK(locker_); 377 378 if (!device || !displays || num_displays > HWC_NUM_DISPLAY_TYPES) { 379 return -EINVAL; 380 } 381 382 HWCSession *hwc_session = static_cast<HWCSession *>(device); 383 384 if (hwc_session->color_mgr_) { 385 HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]; 386 if (primary_display) { 387 int ret = hwc_session->color_mgr_->SolidFillLayersSet(displays, primary_display); 388 if (ret) 389 return 0; 390 hwc_session->color_mgr_->SetColorModeDetailEnhancer(primary_display); 391 } 392 } 393 394 for (size_t dpy = 0; dpy < num_displays; dpy++) { 395 hwc_display_contents_1_t *content_list = displays[dpy]; 396 397 // Drop virtual display composition if virtual display object could not be created 398 // due to HDMI concurrency. 399 if (dpy == HWC_DISPLAY_VIRTUAL && !hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) { 400 CloseAcquireFds(content_list); 401 if (content_list) { 402 content_list->retireFenceFd = -1; 403 } 404 405 continue; 406 } 407 408 if (hwc_session->hwc_display_[dpy]) { 409 hwc_session->hwc_display_[dpy]->Commit(content_list); 410 } 411 CloseAcquireFds(content_list); 412 } 413 414 if (hwc_session->new_bw_mode_) { 415 hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY]; 416 hwc_session->new_bw_mode_ = false; 417 if (hwc_session->bw_mode_release_fd_ >= 0) { 418 close(hwc_session->bw_mode_release_fd_); 419 } 420 hwc_session->bw_mode_release_fd_ = dup(content_list->retireFenceFd); 421 } 422 423 // This is only indicative of how many times SurfaceFlinger posts 424 // frames to the display. 425 CALC_FPS(); 426 427 // Return 0, else client will go into bad state 428 return 0; 429} 430 431void HWCSession::CloseAcquireFds(hwc_display_contents_1_t *content_list) { 432 if (content_list) { 433 for (size_t i = 0; i < content_list->numHwLayers; i++) { 434 int &acquireFenceFd = content_list->hwLayers[i].acquireFenceFd; 435 if (acquireFenceFd >= 0) { 436 close(acquireFenceFd); 437 acquireFenceFd = -1; 438 } 439 } 440 441 int &outbufAcquireFenceFd = content_list->outbufAcquireFenceFd; 442 if (outbufAcquireFenceFd >= 0) { 443 close(outbufAcquireFenceFd); 444 outbufAcquireFenceFd = -1; 445 } 446 } 447} 448 449bool HWCSession::IsDisplayYUV(int disp) { 450 int error = -EINVAL; 451 bool is_yuv = false; 452 DisplayConfigVariableInfo attributes = {}; 453 454 if (disp < 0 || disp >= HWC_NUM_DISPLAY_TYPES || !hwc_display_[disp]) { 455 DLOGE("Invalid input parameters. Display = %d", disp); 456 return is_yuv; 457 } 458 459 uint32_t active_config = 0; 460 error = hwc_display_[disp]->GetActiveDisplayConfig(&active_config); 461 if (!error) { 462 error = hwc_display_[disp]->GetDisplayAttributesForConfig(INT(active_config), &attributes); 463 if (error == 0) { 464 is_yuv = attributes.is_yuv; 465 } else { 466 DLOGW("Error querying display attributes. Display = %d, Config = %d", disp, active_config); 467 } 468 } 469 470 return is_yuv; 471} 472 473int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) { 474 SCOPE_LOCK(locker_); 475 476 if (!device) { 477 return -EINVAL; 478 } 479 480 HWCSession *hwc_session = static_cast<HWCSession *>(device); 481 int status = -EINVAL; 482 if (hwc_session->hwc_display_[disp]) { 483 status = hwc_session->hwc_display_[disp]->EventControl(event, enable); 484 } 485 486 return status; 487} 488 489int HWCSession::SetPowerMode(hwc_composer_device_1 *device, int disp, int mode) { 490 SEQUENCE_WAIT_SCOPE_LOCK(locker_); 491 492 if (!device) { 493 return -EINVAL; 494 } 495 496 HWCSession *hwc_session = static_cast<HWCSession *>(device); 497 int status = -EINVAL; 498 if (hwc_session->hwc_display_[disp]) { 499 status = hwc_session->hwc_display_[disp]->SetPowerMode(mode); 500 } 501 502 return status; 503} 504 505int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) { 506 SCOPE_LOCK(locker_); 507 508 if (!device || !value) { 509 return -EINVAL; 510 } 511 512 int status = 0; 513 514 switch (param) { 515 case HWC_BACKGROUND_LAYER_SUPPORTED: 516 value[0] = 1; 517 break; 518 519 default: 520 status = -EINVAL; 521 } 522 523 return status; 524} 525 526void HWCSession::RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs) { 527 SCOPE_LOCK(locker_); 528 529 if (!device || !procs) { 530 return; 531 } 532 533 HWCSession *hwc_session = static_cast<HWCSession *>(device); 534 hwc_session->hwc_procs_ = procs; 535} 536 537void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) { 538 SEQUENCE_WAIT_SCOPE_LOCK(locker_); 539 540 if (!device || !buffer || !length) { 541 return; 542 } 543 544 DumpInterface::GetDump(buffer, UINT32(length)); 545} 546 547int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs, 548 size_t *num_configs) { 549 SCOPE_LOCK(locker_); 550 551 if (!device || !configs || !num_configs) { 552 return -EINVAL; 553 } 554 555 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) { 556 return -EINVAL; 557 } 558 559 HWCSession *hwc_session = static_cast<HWCSession *>(device); 560 int status = -EINVAL; 561 if (hwc_session->hwc_display_[disp]) { 562 status = hwc_session->hwc_display_[disp]->GetDisplayConfigs(configs, num_configs); 563 } 564 565 return status; 566} 567 568int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config, 569 const uint32_t *display_attributes, int32_t *values) { 570 SCOPE_LOCK(locker_); 571 572 if (!device || !display_attributes || !values) { 573 return -EINVAL; 574 } 575 576 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) { 577 return -EINVAL; 578 } 579 580 HWCSession *hwc_session = static_cast<HWCSession *>(device); 581 int status = -EINVAL; 582 if (hwc_session->hwc_display_[disp]) { 583 status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, display_attributes, 584 values); 585 } 586 587 return status; 588} 589 590int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) { 591 SCOPE_LOCK(locker_); 592 593 if (!device) { 594 return -EINVAL; 595 } 596 597 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) { 598 return -EINVAL; 599 } 600 601 HWCSession *hwc_session = static_cast<HWCSession *>(device); 602 int active_config = -1; 603 if (hwc_session->hwc_display_[disp]) { 604 active_config = hwc_session->hwc_display_[disp]->GetActiveConfig(); 605 } 606 607 return active_config; 608} 609 610int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) { 611 SEQUENCE_WAIT_SCOPE_LOCK(locker_); 612 613 if (!device) { 614 return -EINVAL; 615 } 616 617 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) { 618 return -EINVAL; 619 } 620 621 HWCSession *hwc_session = static_cast<HWCSession *>(device); 622 int status = -EINVAL; 623 624 if (hwc_session->hwc_display_[disp]) { 625 status = hwc_session->hwc_display_[disp]->SetActiveConfig(index); 626 } 627 628 return status; 629} 630 631int HWCSession::SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y) { 632 DTRACE_SCOPED(); 633 634 SCOPE_LOCK(locker_); 635 636 if (!device || (disp < HWC_DISPLAY_PRIMARY) || (disp > HWC_DISPLAY_VIRTUAL)) { 637 return -EINVAL; 638 } 639 640 int status = -EINVAL; 641 HWCSession *hwc_session = static_cast<HWCSession *>(device); 642 if (hwc_session->hwc_display_[disp]) { 643 status = hwc_session->hwc_display_[disp]->SetCursorPosition(x, y); 644 } 645 646 return status; 647} 648 649int HWCSession::ConnectDisplay(int disp, hwc_display_contents_1_t *content_list) { 650 DLOGI("Display = %d", disp); 651 652 int status = 0; 653 uint32_t primary_width = 0; 654 uint32_t primary_height = 0; 655 656 hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height); 657 658 if (disp == HWC_DISPLAY_EXTERNAL) { 659 status = CreateExternalDisplay(disp, primary_width, primary_height, false); 660 connected_displays_[HWC_DISPLAY_EXTERNAL] = 1; 661 } else if (disp == HWC_DISPLAY_VIRTUAL) { 662 status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width, primary_height, 663 content_list, &hwc_display_[disp]); 664 connected_displays_[HWC_DISPLAY_VIRTUAL] = 1; 665 } else { 666 DLOGE("Invalid display type"); 667 return -1; 668 } 669 670 if (!status) { 671 hwc_display_[disp]->SetSecureDisplay(secure_display_active_, true); 672 } 673 674 return status; 675} 676 677int HWCSession::DisconnectDisplay(int disp) { 678 DLOGI("Display = %d", disp); 679 680 if (disp == HWC_DISPLAY_EXTERNAL) { 681 HWCDisplayExternal::Destroy(hwc_display_[disp]); 682 connected_displays_[HWC_DISPLAY_EXTERNAL] = 0; 683 } else if (disp == HWC_DISPLAY_VIRTUAL) { 684 HWCDisplayVirtual::Destroy(hwc_display_[disp]); 685 connected_displays_[HWC_DISPLAY_VIRTUAL] = 0; 686 } else { 687 DLOGE("Invalid display type"); 688 return -1; 689 } 690 691 hwc_display_[disp] = NULL; 692 693 return 0; 694} 695 696android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel, 697 android::Parcel *output_parcel) { 698 SEQUENCE_WAIT_SCOPE_LOCK(locker_); 699 700 android::status_t status = 0; 701 702 switch (command) { 703 case qService::IQService::DYNAMIC_DEBUG: 704 DynamicDebug(input_parcel); 705 break; 706 707 case qService::IQService::SCREEN_REFRESH: 708 hwc_procs_->invalidate(hwc_procs_); 709 break; 710 711 case qService::IQService::SET_IDLE_TIMEOUT: 712 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 713 uint32_t timeout = UINT32(input_parcel->readInt32()); 714 hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(timeout); 715 } 716 break; 717 718 case qService::IQService::SET_FRAME_DUMP_CONFIG: 719 SetFrameDumpConfig(input_parcel); 720 break; 721 722 case qService::IQService::SET_MAX_PIPES_PER_MIXER: 723 status = SetMaxMixerStages(input_parcel); 724 break; 725 726 case qService::IQService::SET_DISPLAY_MODE: 727 status = SetDisplayMode(input_parcel); 728 break; 729 730 case qService::IQService::SET_SECONDARY_DISPLAY_STATUS: 731 status = SetSecondaryDisplayStatus(input_parcel, output_parcel); 732 break; 733 734 case qService::IQService::CONFIGURE_DYN_REFRESH_RATE: 735 status = ConfigureRefreshRate(input_parcel); 736 break; 737 738 case qService::IQService::SET_VIEW_FRAME: 739 break; 740 741 case qService::IQService::TOGGLE_SCREEN_UPDATES: 742 status = ToggleScreenUpdates(input_parcel, output_parcel); 743 break; 744 745 case qService::IQService::QDCM_SVC_CMDS: 746 status = QdcmCMDHandler(input_parcel, output_parcel); 747 break; 748 749 case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED: 750 status = OnMinHdcpEncryptionLevelChange(input_parcel, output_parcel); 751 break; 752 753 case qService::IQService::CONTROL_PARTIAL_UPDATE: 754 status = ControlPartialUpdate(input_parcel, output_parcel); 755 break; 756 757 case qService::IQService::SET_ACTIVE_CONFIG: 758 status = HandleSetActiveDisplayConfig(input_parcel, output_parcel); 759 break; 760 761 case qService::IQService::GET_ACTIVE_CONFIG: 762 status = HandleGetActiveDisplayConfig(input_parcel, output_parcel); 763 break; 764 765 case qService::IQService::GET_CONFIG_COUNT: 766 status = HandleGetDisplayConfigCount(input_parcel, output_parcel); 767 break; 768 769 case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG: 770 status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel); 771 break; 772 773 case qService::IQService::GET_PANEL_BRIGHTNESS: 774 status = GetPanelBrightness(input_parcel, output_parcel); 775 break; 776 777 case qService::IQService::SET_PANEL_BRIGHTNESS: 778 status = SetPanelBrightness(input_parcel, output_parcel); 779 break; 780 781 case qService::IQService::GET_DISPLAY_VISIBLE_REGION: 782 status = GetVisibleDisplayRect(input_parcel, output_parcel); 783 break; 784 785 case qService::IQService::SET_CAMERA_STATUS: 786 status = SetDynamicBWForCamera(input_parcel, output_parcel); 787 break; 788 789 case qService::IQService::GET_BW_TRANSACTION_STATUS: 790 status = GetBWTransactionStatus(input_parcel, output_parcel); 791 break; 792 793 case qService::IQService::SET_LAYER_MIXER_RESOLUTION: 794 status = SetMixerResolution(input_parcel); 795 break; 796 797 case qService::IQService::GET_HDR_CAPABILITIES: 798 status = GetHdrCapabilities(input_parcel, output_parcel); 799 break; 800 801 default: 802 DLOGW("QService command = %d is not supported", command); 803 return -EINVAL; 804 } 805 806 return status; 807} 808 809android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel, 810 android::Parcel *output_parcel) { 811 int input = input_parcel->readInt32(); 812 int error = android::BAD_VALUE; 813 814 if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) { 815 error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1); 816 if (error != 0) { 817 DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error); 818 } 819 } 820 output_parcel->writeInt32(error); 821 822 return error; 823} 824 825android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel, 826 android::Parcel *output_parcel) { 827 int level = input_parcel->readInt32(); 828 int error = android::BAD_VALUE; 829 830 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 831 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level); 832 if (error != 0) { 833 DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error); 834 } 835 } 836 output_parcel->writeInt32(error); 837 838 return error; 839} 840 841android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel, 842 android::Parcel *output_parcel) { 843 int error = android::BAD_VALUE; 844 int ret = error; 845 846 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 847 error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret); 848 if (error != 0) { 849 ret = error; 850 DLOGE("Failed to get the panel brightness. Error = %d", error); 851 } 852 } 853 output_parcel->writeInt32(ret); 854 855 return error; 856} 857 858android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel, 859 android::Parcel *out) { 860 DisplayError error = kErrorNone; 861 int ret = 0; 862 uint32_t disp_id = UINT32(input_parcel->readInt32()); 863 uint32_t enable = UINT32(input_parcel->readInt32()); 864 865 if (disp_id != HWC_DISPLAY_PRIMARY) { 866 DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id); 867 ret = -EINVAL; 868 out->writeInt32(ret); 869 return ret; 870 } 871 872 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) { 873 DLOGE("primary display object is not instantiated"); 874 ret = -EINVAL; 875 out->writeInt32(ret); 876 return ret; 877 } 878 879 uint32_t pending = 0; 880 error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending); 881 882 if (error == kErrorNone) { 883 if (!pending) { 884 out->writeInt32(ret); 885 return ret; 886 } 887 } else if (error == kErrorNotSupported) { 888 out->writeInt32(ret); 889 return ret; 890 } else { 891 ret = -EINVAL; 892 out->writeInt32(ret); 893 return ret; 894 } 895 896 // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future. 897 hwc_procs_->invalidate(hwc_procs_); 898 899 // Wait until partial update control is complete 900 ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs); 901 902 out->writeInt32(ret); 903 904 return ret; 905} 906 907android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel, 908 android::Parcel *output_parcel) { 909 int config = input_parcel->readInt32(); 910 int dpy = input_parcel->readInt32(); 911 int error = android::BAD_VALUE; 912 913 if (dpy > HWC_DISPLAY_VIRTUAL) { 914 return android::BAD_VALUE; 915 } 916 917 if (hwc_display_[dpy]) { 918 error = hwc_display_[dpy]->SetActiveDisplayConfig(config); 919 if (error == 0) { 920 hwc_procs_->invalidate(hwc_procs_); 921 } 922 } 923 924 return error; 925} 926 927android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel, 928 android::Parcel *output_parcel) { 929 int dpy = input_parcel->readInt32(); 930 int error = android::BAD_VALUE; 931 932 if (dpy > HWC_DISPLAY_VIRTUAL) { 933 return android::BAD_VALUE; 934 } 935 936 if (hwc_display_[dpy]) { 937 uint32_t config = 0; 938 error = hwc_display_[dpy]->GetActiveDisplayConfig(&config); 939 if (error == 0) { 940 output_parcel->writeInt32(INT(config)); 941 } 942 } 943 944 return error; 945} 946 947android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel, 948 android::Parcel *output_parcel) { 949 int dpy = input_parcel->readInt32(); 950 int error = android::BAD_VALUE; 951 952 if (dpy > HWC_DISPLAY_VIRTUAL) { 953 return android::BAD_VALUE; 954 } 955 956 uint32_t count = 0; 957 if (hwc_display_[dpy]) { 958 error = hwc_display_[dpy]->GetDisplayConfigCount(&count); 959 if (error == 0) { 960 output_parcel->writeInt32(INT(count)); 961 } 962 } 963 964 return error; 965} 966 967android::status_t HWCSession::SetDisplayPort(DisplayPort sdm_disp_port, int *hwc_disp_port) { 968 if (!hwc_disp_port) { 969 return -EINVAL; 970 } 971 972 switch (sdm_disp_port) { 973 case kPortDSI: 974 *hwc_disp_port = qdutils::DISPLAY_PORT_DSI; 975 break; 976 case kPortDTV: 977 *hwc_disp_port = qdutils::DISPLAY_PORT_DTV; 978 break; 979 case kPortLVDS: 980 *hwc_disp_port = qdutils::DISPLAY_PORT_LVDS; 981 break; 982 case kPortEDP: 983 *hwc_disp_port = qdutils::DISPLAY_PORT_EDP; 984 break; 985 case kPortWriteBack: 986 *hwc_disp_port = qdutils::DISPLAY_PORT_WRITEBACK; 987 break; 988 case kPortDP: 989 *hwc_disp_port = qdutils::DISPLAY_PORT_DP; 990 break; 991 case kPortDefault: 992 *hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT; 993 break; 994 default: 995 DLOGE("Invalid sdm display port %d", sdm_disp_port); 996 return -EINVAL; 997 } 998 999 return 0; 1000} 1001 1002android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel 1003 *input_parcel, 1004 android::Parcel *output_parcel) { 1005 int config = input_parcel->readInt32(); 1006 int dpy = input_parcel->readInt32(); 1007 int error = android::BAD_VALUE; 1008 DisplayConfigVariableInfo display_attributes; 1009 DisplayPort sdm_disp_port = kPortDefault; 1010 int hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT; 1011 1012 if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES || config < 0) { 1013 return android::BAD_VALUE; 1014 } 1015 1016 if (hwc_display_[dpy]) { 1017 error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes); 1018 if (error == 0) { 1019 hwc_display_[dpy]->GetDisplayPort(&sdm_disp_port); 1020 1021 SetDisplayPort(sdm_disp_port, &hwc_disp_port); 1022 1023 output_parcel->writeInt32(INT(display_attributes.vsync_period_ns)); 1024 output_parcel->writeInt32(INT(display_attributes.x_pixels)); 1025 output_parcel->writeInt32(INT(display_attributes.y_pixels)); 1026 output_parcel->writeFloat(display_attributes.x_dpi); 1027 output_parcel->writeFloat(display_attributes.y_dpi); 1028 output_parcel->writeInt32(hwc_disp_port); 1029 output_parcel->writeInt32(display_attributes.is_yuv); 1030 } 1031 } 1032 1033 return error; 1034} 1035 1036android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel, 1037 android::Parcel *output_parcel) { 1038 int ret = -EINVAL; 1039 1040 uint32_t display_id = UINT32(input_parcel->readInt32()); 1041 uint32_t display_status = UINT32(input_parcel->readInt32()); 1042 1043 DLOGI("Display = %d, Status = %d", display_id, display_status); 1044 1045 if (display_id >= HWC_NUM_DISPLAY_TYPES) { 1046 DLOGE("Invalid display_id"); 1047 } else if (display_id == HWC_DISPLAY_PRIMARY) { 1048 DLOGE("Not supported for this display"); 1049 } else if (!hwc_display_[display_id]) { 1050 DLOGW("Display is not connected"); 1051 } else { 1052 ret = hwc_display_[display_id]->SetDisplayStatus(display_status); 1053 } 1054 1055 output_parcel->writeInt32(ret); 1056 1057 return ret; 1058} 1059 1060android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) { 1061 uint32_t operation = UINT32(input_parcel->readInt32()); 1062 switch (operation) { 1063 case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE: 1064 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform( 1065 HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false); 1066 case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE: 1067 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform( 1068 HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true); 1069 case qdutils::SET_BINDER_DYN_REFRESH_RATE: 1070 { 1071 uint32_t refresh_rate = UINT32(input_parcel->readInt32()); 1072 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform( 1073 HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, 1074 refresh_rate); 1075 } 1076 default: 1077 DLOGW("Invalid operation %d", operation); 1078 return -EINVAL; 1079 } 1080 1081 return 0; 1082} 1083 1084android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) { 1085 uint32_t mode = UINT32(input_parcel->readInt32()); 1086 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode); 1087} 1088 1089android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) { 1090 DisplayError error = kErrorNone; 1091 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32()); 1092 uint32_t max_mixer_stages = UINT32(input_parcel->readInt32()); 1093 1094 if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) { 1095 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 1096 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages); 1097 if (error != kErrorNone) { 1098 return -EINVAL; 1099 } 1100 } 1101 } 1102 1103 if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) { 1104 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { 1105 error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages); 1106 if (error != kErrorNone) { 1107 return -EINVAL; 1108 } 1109 } 1110 } 1111 1112 if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) { 1113 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) { 1114 error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages); 1115 if (error != kErrorNone) { 1116 return -EINVAL; 1117 } 1118 } 1119 } 1120 1121 return 0; 1122} 1123 1124android::status_t HWCSession::SetDynamicBWForCamera(const android::Parcel *input_parcel, 1125 android::Parcel *output_parcel) { 1126 DisplayError error = kErrorNone; 1127 uint32_t camera_status = UINT32(input_parcel->readInt32()); 1128 HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault; 1129 1130 // trigger invalidate to apply new bw caps. 1131 hwc_procs_->invalidate(hwc_procs_); 1132 1133 error = core_intf_->SetMaxBandwidthMode(mode); 1134 if (error != kErrorNone) { 1135 return -EINVAL; 1136 } 1137 1138 new_bw_mode_ = true; 1139 need_invalidate_ = true; 1140 1141 return 0; 1142} 1143 1144android::status_t HWCSession::GetBWTransactionStatus(const android::Parcel *input_parcel, 1145 android::Parcel *output_parcel) { 1146 bool state = true; 1147 1148 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 1149 if (sync_wait(bw_mode_release_fd_, 0) < 0) { 1150 DLOGI("bw_transaction_release_fd is not yet signalled: err= %s", strerror(errno)); 1151 state = false; 1152 } 1153 output_parcel->writeInt32(state); 1154 } 1155 1156 return 0; 1157} 1158 1159void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) { 1160 uint32_t frame_dump_count = UINT32(input_parcel->readInt32()); 1161 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32()); 1162 uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32()); 1163 1164 if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) { 1165 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 1166 hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type); 1167 } 1168 } 1169 1170 if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) { 1171 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { 1172 hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type); 1173 } 1174 } 1175 1176 if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) { 1177 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) { 1178 hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type); 1179 } 1180 } 1181} 1182 1183android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) { 1184 DisplayError error = kErrorNone; 1185 uint32_t dpy = UINT32(input_parcel->readInt32()); 1186 1187 if (dpy != HWC_DISPLAY_PRIMARY) { 1188 DLOGI("Resoulution change not supported for this display %d", dpy); 1189 return -EINVAL; 1190 } 1191 1192 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) { 1193 DLOGI("Primary display is not initialized"); 1194 return -EINVAL; 1195 } 1196 1197 uint32_t width = UINT32(input_parcel->readInt32()); 1198 uint32_t height = UINT32(input_parcel->readInt32()); 1199 1200 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height); 1201 if (error != kErrorNone) { 1202 return -EINVAL; 1203 } 1204 1205 return 0; 1206} 1207 1208android::status_t HWCSession::GetHdrCapabilities(const android::Parcel *input_parcel, 1209 android::Parcel *output_parcel) { 1210 uint32_t display_id = UINT32(input_parcel->readInt32()); 1211 if (display_id >= HWC_NUM_DISPLAY_TYPES) { 1212 DLOGE("Invalid display id = %d", display_id); 1213 return -EINVAL; 1214 } 1215 1216 if (hwc_display_[display_id] == NULL) { 1217 DLOGW("Display = %d not initialized", display_id); 1218 return -EINVAL; 1219 } 1220 1221 DisplayConfigFixedInfo fixed_info = {}; 1222 int ret = hwc_display_[display_id]->GetDisplayFixedConfig(&fixed_info); 1223 if (ret) { 1224 DLOGE("Failed"); 1225 return ret; 1226 } 1227 1228 if (!fixed_info.hdr_supported) { 1229 DLOGI("HDR is not supported"); 1230 return 0; 1231 } 1232 1233 std::vector<int32_t> supported_hdr_types; 1234 // Only HDR10 supported now, in future add other supported HDR formats(HLG, DolbyVision) 1235 supported_hdr_types.push_back(HAL_HDR_HDR10); 1236 1237 static const float kLuminanceFactor = 10000.0; 1238 // luminance is expressed in the unit of 0.0001 cd/m2, convert it to 1cd/m2. 1239 float max_luminance = FLOAT(fixed_info.max_luminance)/kLuminanceFactor; 1240 float max_average_luminance = FLOAT(fixed_info.average_luminance)/kLuminanceFactor; 1241 float min_luminance = FLOAT(fixed_info.min_luminance)/kLuminanceFactor; 1242 1243 if (output_parcel != nullptr) { 1244 output_parcel->writeInt32Vector(supported_hdr_types); 1245 output_parcel->writeFloat(max_luminance); 1246 output_parcel->writeFloat(max_average_luminance); 1247 output_parcel->writeFloat(min_luminance); 1248 } 1249 1250 return 0; 1251} 1252 1253void HWCSession::DynamicDebug(const android::Parcel *input_parcel) { 1254 int type = input_parcel->readInt32(); 1255 bool enable = (input_parcel->readInt32() > 0); 1256 DLOGI("type = %d enable = %d", type, enable); 1257 int verbose_level = input_parcel->readInt32(); 1258 1259 switch (type) { 1260 case qService::IQService::DEBUG_ALL: 1261 HWCDebugHandler::DebugAll(enable, verbose_level); 1262 break; 1263 1264 case qService::IQService::DEBUG_MDPCOMP: 1265 HWCDebugHandler::DebugStrategy(enable, verbose_level); 1266 HWCDebugHandler::DebugCompManager(enable, verbose_level); 1267 break; 1268 1269 case qService::IQService::DEBUG_PIPE_LIFECYCLE: 1270 HWCDebugHandler::DebugResources(enable, verbose_level); 1271 break; 1272 1273 case qService::IQService::DEBUG_DRIVER_CONFIG: 1274 HWCDebugHandler::DebugDriverConfig(enable, verbose_level); 1275 break; 1276 1277 case qService::IQService::DEBUG_ROTATOR: 1278 HWCDebugHandler::DebugResources(enable, verbose_level); 1279 HWCDebugHandler::DebugDriverConfig(enable, verbose_level); 1280 HWCDebugHandler::DebugRotator(enable, verbose_level); 1281 break; 1282 1283 case qService::IQService::DEBUG_QDCM: 1284 HWCDebugHandler::DebugQdcm(enable, verbose_level); 1285 break; 1286 1287 default: 1288 DLOGW("type = %d is not supported", type); 1289 } 1290} 1291 1292android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel, 1293 android::Parcel *output_parcel) { 1294 int ret = 0; 1295 int32_t *brightness_value = NULL; 1296 uint32_t display_id(0); 1297 PPPendingParams pending_action; 1298 PPDisplayAPIPayload resp_payload, req_payload; 1299 1300 if (!color_mgr_) { 1301 return -1; 1302 } 1303 1304 pending_action.action = kNoAction; 1305 pending_action.params = NULL; 1306 1307 // Read display_id, payload_size and payload from in_parcel. 1308 ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload); 1309 if (!ret) { 1310 if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY]) 1311 ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload, 1312 &resp_payload, &pending_action); 1313 1314 if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL]) 1315 ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload, 1316 &pending_action); 1317 } 1318 1319 if (ret) { 1320 output_parcel->writeInt32(ret); // first field in out parcel indicates return code. 1321 req_payload.DestroyPayload(); 1322 resp_payload.DestroyPayload(); 1323 return ret; 1324 } 1325 1326 switch (pending_action.action) { 1327 case kInvalidating: 1328 hwc_procs_->invalidate(hwc_procs_); 1329 break; 1330 case kEnterQDCMMode: 1331 ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]); 1332 break; 1333 case kExitQDCMMode: 1334 ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]); 1335 break; 1336 case kApplySolidFill: 1337 ret = color_mgr_->SetSolidFill(pending_action.params, 1338 true, hwc_display_[HWC_DISPLAY_PRIMARY]); 1339 hwc_procs_->invalidate(hwc_procs_); 1340 break; 1341 case kDisableSolidFill: 1342 ret = color_mgr_->SetSolidFill(pending_action.params, 1343 false, hwc_display_[HWC_DISPLAY_PRIMARY]); 1344 hwc_procs_->invalidate(hwc_procs_); 1345 break; 1346 case kSetPanelBrightness: 1347 brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload); 1348 if (brightness_value == NULL) { 1349 DLOGE("Brightness value is Null"); 1350 return -EINVAL; 1351 } 1352 if (HWC_DISPLAY_PRIMARY == display_id) 1353 ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value); 1354 break; 1355 case kEnableFrameCapture: 1356 ret = color_mgr_->SetFrameCapture(pending_action.params, 1357 true, hwc_display_[HWC_DISPLAY_PRIMARY]); 1358 hwc_procs_->invalidate(hwc_procs_); 1359 break; 1360 case kDisableFrameCapture: 1361 ret = color_mgr_->SetFrameCapture(pending_action.params, 1362 false, hwc_display_[HWC_DISPLAY_PRIMARY]); 1363 break; 1364 case kConfigureDetailedEnhancer: 1365 ret = color_mgr_->SetDetailedEnhancer(pending_action.params, 1366 hwc_display_[HWC_DISPLAY_PRIMARY]); 1367 hwc_procs_->invalidate(hwc_procs_); 1368 break; 1369 case kInvalidatingAndkSetPanelBrightness: 1370 brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload); 1371 if (brightness_value == NULL) { 1372 DLOGE("Brightness value is Null"); 1373 return -EINVAL; 1374 } 1375 if (HWC_DISPLAY_PRIMARY == display_id) 1376 ret = hwc_display_[HWC_DISPLAY_PRIMARY]->CachePanelBrightness(*brightness_value); 1377 hwc_procs_->invalidate(hwc_procs_); 1378 break; 1379 case kNoAction: 1380 break; 1381 default: 1382 DLOGW("Invalid pending action = %d!", pending_action.action); 1383 break; 1384 } 1385 1386 // for display API getter case, marshall returned params into out_parcel. 1387 output_parcel->writeInt32(ret); 1388 HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel); 1389 req_payload.DestroyPayload(); 1390 resp_payload.DestroyPayload(); 1391 1392 return (ret? -EINVAL : 0); 1393} 1394 1395android::status_t HWCSession::OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel, 1396 android::Parcel *output_parcel) { 1397 int ret = -EINVAL; 1398 uint32_t display_id = UINT32(input_parcel->readInt32()); 1399 uint32_t min_enc_level = UINT32(input_parcel->readInt32()); 1400 1401 DLOGI("Display %d", display_id); 1402 1403 if (display_id >= HWC_NUM_DISPLAY_TYPES) { 1404 DLOGE("Invalid display_id"); 1405 } else if (display_id != HWC_DISPLAY_EXTERNAL) { 1406 DLOGE("Not supported for display"); 1407 } else if (!hwc_display_[display_id]) { 1408 DLOGW("Display is not connected"); 1409 } else { 1410 ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange(min_enc_level); 1411 } 1412 1413 output_parcel->writeInt32(ret); 1414 1415 return ret; 1416} 1417 1418void* HWCSession::HWCUeventThread(void *context) { 1419 if (context) { 1420 return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler(); 1421 } 1422 1423 return NULL; 1424} 1425 1426void* HWCSession::HWCUeventThreadHandler() { 1427 static char uevent_data[PAGE_SIZE]; 1428 int length = 0; 1429 1430 uevent_locker_.Lock(); 1431 prctl(PR_SET_NAME, uevent_thread_name_, 0, 0, 0); 1432 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); 1433 if (!uevent_init()) { 1434 DLOGE("Failed to init uevent"); 1435 pthread_exit(0); 1436 uevent_locker_.Signal(); 1437 uevent_locker_.Unlock(); 1438 return NULL; 1439 } 1440 1441 uevent_locker_.Signal(); 1442 uevent_locker_.Unlock(); 1443 1444 while (!uevent_thread_exit_) { 1445 // keep last 2 zeroes to ensure double 0 termination 1446 length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2); 1447 1448 if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) { 1449 DLOGI("Uevent HDMI = %s", uevent_data); 1450 int connected = GetEventValue(uevent_data, length, "SWITCH_STATE="); 1451 if (connected >= 0) { 1452 DLOGI("HDMI = %s", connected ? "connected" : "disconnected"); 1453 if (HotPlugHandler(connected) == -1) { 1454 DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected"); 1455 } 1456 } 1457 } else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) { 1458 DLOGI("Uevent FB0 = %s", uevent_data); 1459 int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE="); 1460 if (panel_reset == 0) { 1461 if (hwc_procs_) { 1462 reset_panel_ = true; 1463 hwc_procs_->invalidate(hwc_procs_); 1464 } else { 1465 DLOGW("Ignore resetpanel - hwc_proc not registered"); 1466 } 1467 } 1468 } 1469 } 1470 pthread_exit(0); 1471 1472 return NULL; 1473} 1474 1475int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) { 1476 const char *iterator_str = uevent_data; 1477 while (((iterator_str - uevent_data) <= length) && (*iterator_str)) { 1478 const char *pstr = strstr(iterator_str, event_info); 1479 if (pstr != NULL) { 1480 return (atoi(iterator_str + strlen(event_info))); 1481 } 1482 iterator_str += strlen(iterator_str) + 1; 1483 } 1484 1485 return -1; 1486} 1487 1488void HWCSession::ResetPanel() { 1489 int status = -EINVAL; 1490 1491 DLOGI("Powering off primary"); 1492 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_OFF); 1493 if (status) { 1494 DLOGE("power-off on primary failed with error = %d", status); 1495 } 1496 1497 DLOGI("Restoring power mode on primary"); 1498 int32_t mode = INT(hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode()); 1499 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode); 1500 if (status) { 1501 DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status); 1502 } 1503 1504 status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, 1); 1505 if (status) { 1506 DLOGE("enabling vsync failed for primary with error = %d", status); 1507 } 1508 1509 reset_panel_ = false; 1510} 1511 1512int HWCSession::HotPlugHandler(bool connected) { 1513 int status = 0; 1514 bool notify_hotplug = false; 1515 bool refresh_screen = false; 1516 1517 // To prevent sending events to client while a lock is held, acquire scope locks only within 1518 // below scope so that those get automatically unlocked after the scope ends. 1519 { 1520 SEQUENCE_WAIT_SCOPE_LOCK(locker_); 1521 1522 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) { 1523 DLOGE("Primay display is not connected."); 1524 return -1; 1525 } 1526 1527 1528 HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY]; 1529 HWCDisplay *external_display = NULL; 1530 HWCDisplay *null_display = NULL; 1531 1532 if (primary_display->GetDisplayClass() == DISPLAY_CLASS_EXTERNAL) { 1533 external_display = static_cast<HWCDisplayExternal *>(hwc_display_[HWC_DISPLAY_PRIMARY]); 1534 } else if (primary_display->GetDisplayClass() == DISPLAY_CLASS_NULL) { 1535 null_display = static_cast<HWCDisplayNull *>(hwc_display_[HWC_DISPLAY_PRIMARY]); 1536 } 1537 1538 // If primary display connected is a NULL display, then replace it with the external display 1539 if (connected) { 1540 // If we are in HDMI as primary and the primary display just got plugged in 1541 if (is_hdmi_primary_ && null_display) { 1542 uint32_t primary_width, primary_height; 1543 int status = 0; 1544 null_display->GetFrameBufferResolution(&primary_width, &primary_height); 1545 delete null_display; 1546 hwc_display_[HWC_DISPLAY_PRIMARY] = NULL; 1547 1548 // Create external display with a forced framebuffer resolution to that of what the NULL 1549 // display had. This is necessary because SurfaceFlinger does not dynamically update 1550 // framebuffer resolution once it reads it at bootup. So we always have to have the NULL 1551 // display/external display both at the bootup resolution. 1552 status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, primary_width, primary_height, true); 1553 if (status) { 1554 DLOGE("Could not create external display"); 1555 return -1; 1556 } 1557 1558 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_NORMAL); 1559 if (status) { 1560 DLOGE("power-on on primary failed with error = %d", status); 1561 } 1562 1563 is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY); 1564 1565 // Next, go ahead and enable vsync on external display. This is expliclity required 1566 // because in HDMI as primary case, SurfaceFlinger may not be aware of underlying 1567 // changing display. and thus may not explicitly enable vsync 1568 1569 status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, true); 1570 if (status) { 1571 DLOGE("Error enabling vsync for HDMI as primary case"); 1572 } 1573 // Don't do hotplug notification for HDMI as primary case for now 1574 notify_hotplug = false; 1575 refresh_screen = true; 1576 } else { 1577 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { 1578 DLOGE("HDMI is already connected"); 1579 return -1; 1580 } 1581 1582 // Connect external display if virtual display is not connected. 1583 // Else, defer external display connection and process it when virtual display 1584 // tears down; Do not notify SurfaceFlinger since connection is deferred now. 1585 if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) { 1586 status = ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL); 1587 if (status) { 1588 return status; 1589 } 1590 notify_hotplug = true; 1591 } else { 1592 DLOGI("Virtual display is connected, pending connection"); 1593 external_pending_connect_ = true; 1594 } 1595 } 1596 } else { 1597 // Do not return error if external display is not in connected status. 1598 // Due to virtual display concurrency, external display connection might be still pending 1599 // but hdmi got disconnected before pending connection could be processed. 1600 1601 if (is_hdmi_primary_ && external_display) { 1602 uint32_t x_res, y_res; 1603 external_display->GetFrameBufferResolution(&x_res, &y_res); 1604 // Need to manually disable VSYNC as SF is not aware of connect/disconnect cases 1605 // for HDMI as primary 1606 external_display->EventControl(HWC_EVENT_VSYNC, false); 1607 HWCDisplayExternal::Destroy(external_display); 1608 1609 HWCDisplayNull *null_display; 1610 1611 int status = HWCDisplayNull::Create(core_intf_, &hwc_procs_, 1612 reinterpret_cast<HWCDisplay **>(&null_display)); 1613 1614 if (status) { 1615 DLOGE("Could not create Null display when primary got disconnected"); 1616 return -1; 1617 } 1618 1619 null_display->SetResolution(x_res, y_res); 1620 hwc_display_[HWC_DISPLAY_PRIMARY] = null_display; 1621 1622 // Don't do hotplug notification for HDMI as primary case for now 1623 notify_hotplug = false; 1624 } else { 1625 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { 1626 status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL); 1627 notify_hotplug = true; 1628 } 1629 external_pending_connect_ = false; 1630 } 1631 } 1632 } 1633 1634 if (connected && (notify_hotplug || refresh_screen)) { 1635 // trigger screen refresh to ensure sufficient resources are available to process new 1636 // new display connection. 1637 hwc_procs_->invalidate(hwc_procs_); 1638 uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY)); 1639 usleep(vsync_period * 2 / 1000); 1640 } 1641 // notify client 1642 if (notify_hotplug) { 1643 hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected); 1644 } 1645 1646 qservice_->onHdmiHotplug(INT(connected)); 1647 1648 return 0; 1649} 1650 1651void HWCSession::HandleSecureDisplaySession(hwc_display_contents_1_t **displays) { 1652 secure_display_active_ = false; 1653 if (!*displays) { 1654 DLOGW("Invalid display contents"); 1655 return; 1656 } 1657 1658 hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY]; 1659 if (!content_list) { 1660 DLOGW("Invalid primary content list"); 1661 return; 1662 } 1663 size_t num_hw_layers = content_list->numHwLayers; 1664 1665 for (size_t i = 0; i < num_hw_layers - 1; i++) { 1666 hwc_layer_1_t &hwc_layer = content_list->hwLayers[i]; 1667 const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle); 1668 if (pvt_handle && pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) { 1669 secure_display_active_ = true; 1670 } 1671 } 1672 1673 // Force flush on primary during transitions(secure<->non secure) 1674 // when external displays are connected. 1675 bool force_flush = false; 1676 if ((connected_displays_[HWC_DISPLAY_PRIMARY] == 1) && 1677 ((connected_displays_[HWC_DISPLAY_EXTERNAL] == 1) || 1678 (connected_displays_[HWC_DISPLAY_VIRTUAL] == 1))) { 1679 force_flush = true; 1680 } 1681 1682 for (ssize_t dpy = static_cast<ssize_t>(HWC_NUM_DISPLAY_TYPES - 1); dpy >= 0; dpy--) { 1683 if (hwc_display_[dpy]) { 1684 hwc_display_[dpy]->SetSecureDisplay(secure_display_active_, force_flush); 1685 } 1686 } 1687} 1688 1689android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel, 1690 android::Parcel *output_parcel) { 1691 int dpy = input_parcel->readInt32(); 1692 1693 if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES) { 1694 return android::BAD_VALUE;; 1695 } 1696 1697 if (!hwc_display_[dpy]) { 1698 return android::NO_INIT; 1699 } 1700 1701 hwc_rect_t visible_rect = {0, 0, 0, 0}; 1702 int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect); 1703 if (error < 0) { 1704 return error; 1705 } 1706 1707 output_parcel->writeInt32(visible_rect.left); 1708 output_parcel->writeInt32(visible_rect.top); 1709 output_parcel->writeInt32(visible_rect.right); 1710 output_parcel->writeInt32(visible_rect.bottom); 1711 1712 return android::NO_ERROR; 1713} 1714 1715int HWCSession::CreateExternalDisplay(int disp, uint32_t primary_width, uint32_t primary_height, 1716 bool use_primary_res) { 1717 uint32_t panel_bpp = 0; 1718 uint32_t pattern_type = 0; 1719 1720 if (qdutils::isDPConnected()) { 1721 qdutils::getDPTestConfig(&panel_bpp, &pattern_type); 1722 } 1723 1724 if (panel_bpp && pattern_type) { 1725 return HWCDisplayExternalTest::Create(core_intf_, &hwc_procs_, qservice_, panel_bpp, 1726 pattern_type, &hwc_display_[disp]); 1727 } 1728 1729 return HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width, primary_height, 1730 qservice_, use_primary_res, &hwc_display_[disp]); 1731} 1732 1733} // namespace sdm 1734 1735