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