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