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) { 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 if (disp == HWC_DISPLAY_PRIMARY && hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) { 480 // Set the power mode for virtual display while setting power mode for primary, as SF 481 // does not invoke SetPowerMode() for virtual display. 482 status = hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]->SetPowerMode(mode); 483 } 484 485 return status; 486 } 487 488 int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) { 489 SCOPE_LOCK(locker_); 490 491 if (!device || !value) { 492 return -EINVAL; 493 } 494 495 int status = 0; 496 497 switch (param) { 498 case HWC_BACKGROUND_LAYER_SUPPORTED: 499 value[0] = 1; 500 break; 501 502 default: 503 status = -EINVAL; 504 } 505 506 return status; 507 } 508 509 void HWCSession::RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs) { 510 SCOPE_LOCK(locker_); 511 512 if (!device || !procs) { 513 return; 514 } 515 516 HWCSession *hwc_session = static_cast<HWCSession *>(device); 517 hwc_session->hwc_procs_ = procs; 518 } 519 520 void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) { 521 SEQUENCE_WAIT_SCOPE_LOCK(locker_); 522 523 if (!device || !buffer || !length) { 524 return; 525 } 526 527 DumpInterface::GetDump(buffer, UINT32(length)); 528 } 529 530 int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs, 531 size_t *num_configs) { 532 SCOPE_LOCK(locker_); 533 534 if (!device || !configs || !num_configs) { 535 return -EINVAL; 536 } 537 538 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) { 539 return -EINVAL; 540 } 541 542 HWCSession *hwc_session = static_cast<HWCSession *>(device); 543 int status = -EINVAL; 544 if (hwc_session->hwc_display_[disp]) { 545 status = hwc_session->hwc_display_[disp]->GetDisplayConfigs(configs, num_configs); 546 } 547 548 return status; 549 } 550 551 int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config, 552 const uint32_t *display_attributes, int32_t *values) { 553 SCOPE_LOCK(locker_); 554 555 if (!device || !display_attributes || !values) { 556 return -EINVAL; 557 } 558 559 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) { 560 return -EINVAL; 561 } 562 563 HWCSession *hwc_session = static_cast<HWCSession *>(device); 564 int status = -EINVAL; 565 if (hwc_session->hwc_display_[disp]) { 566 status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, display_attributes, 567 values); 568 } 569 570 return status; 571 } 572 573 int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) { 574 SCOPE_LOCK(locker_); 575 576 if (!device) { 577 return -EINVAL; 578 } 579 580 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) { 581 return -EINVAL; 582 } 583 584 HWCSession *hwc_session = static_cast<HWCSession *>(device); 585 int active_config = -1; 586 if (hwc_session->hwc_display_[disp]) { 587 active_config = hwc_session->hwc_display_[disp]->GetActiveConfig(); 588 } 589 590 return active_config; 591 } 592 593 int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) { 594 SEQUENCE_WAIT_SCOPE_LOCK(locker_); 595 596 if (!device) { 597 return -EINVAL; 598 } 599 600 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) { 601 return -EINVAL; 602 } 603 604 HWCSession *hwc_session = static_cast<HWCSession *>(device); 605 int status = -EINVAL; 606 607 if (hwc_session->hwc_display_[disp]) { 608 status = hwc_session->hwc_display_[disp]->SetActiveConfig(index); 609 } 610 611 return status; 612 } 613 614 int HWCSession::SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y) { 615 DTRACE_SCOPED(); 616 617 SCOPE_LOCK(locker_); 618 619 if (!device || (disp < HWC_DISPLAY_PRIMARY) || (disp > HWC_DISPLAY_VIRTUAL)) { 620 return -EINVAL; 621 } 622 623 int status = -EINVAL; 624 HWCSession *hwc_session = static_cast<HWCSession *>(device); 625 if (hwc_session->hwc_display_[disp]) { 626 status = hwc_session->hwc_display_[disp]->SetCursorPosition(x, y); 627 } 628 629 return status; 630 } 631 632 int HWCSession::ConnectDisplay(int disp, hwc_display_contents_1_t *content_list) { 633 DLOGI("Display = %d", disp); 634 635 int status = 0; 636 uint32_t primary_width = 0; 637 uint32_t primary_height = 0; 638 639 hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height); 640 641 if (disp == HWC_DISPLAY_EXTERNAL) { 642 status = HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width, primary_height, 643 qservice_, false, &hwc_display_[disp]); 644 } else if (disp == HWC_DISPLAY_VIRTUAL) { 645 status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width, primary_height, 646 content_list, &hwc_display_[disp]); 647 } else { 648 DLOGE("Invalid display type"); 649 return -1; 650 } 651 652 if (!status) { 653 hwc_display_[disp]->SetSecureDisplay(secure_display_active_); 654 } 655 656 return status; 657 } 658 659 int HWCSession::DisconnectDisplay(int disp) { 660 DLOGI("Display = %d", disp); 661 662 if (disp == HWC_DISPLAY_EXTERNAL) { 663 HWCDisplayExternal::Destroy(hwc_display_[disp]); 664 } else if (disp == HWC_DISPLAY_VIRTUAL) { 665 HWCDisplayVirtual::Destroy(hwc_display_[disp]); 666 } else { 667 DLOGE("Invalid display type"); 668 return -1; 669 } 670 671 hwc_display_[disp] = NULL; 672 673 return 0; 674 } 675 676 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel, 677 android::Parcel *output_parcel) { 678 SEQUENCE_WAIT_SCOPE_LOCK(locker_); 679 680 android::status_t status = 0; 681 682 switch (command) { 683 case qService::IQService::DYNAMIC_DEBUG: 684 DynamicDebug(input_parcel); 685 break; 686 687 case qService::IQService::SCREEN_REFRESH: 688 hwc_procs_->invalidate(hwc_procs_); 689 break; 690 691 case qService::IQService::SET_IDLE_TIMEOUT: 692 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 693 uint32_t timeout = UINT32(input_parcel->readInt32()); 694 hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(timeout); 695 } 696 break; 697 698 case qService::IQService::SET_FRAME_DUMP_CONFIG: 699 SetFrameDumpConfig(input_parcel); 700 break; 701 702 case qService::IQService::SET_MAX_PIPES_PER_MIXER: 703 status = SetMaxMixerStages(input_parcel); 704 break; 705 706 case qService::IQService::SET_DISPLAY_MODE: 707 status = SetDisplayMode(input_parcel); 708 break; 709 710 case qService::IQService::SET_SECONDARY_DISPLAY_STATUS: 711 status = SetSecondaryDisplayStatus(input_parcel, output_parcel); 712 break; 713 714 case qService::IQService::CONFIGURE_DYN_REFRESH_RATE: 715 status = ConfigureRefreshRate(input_parcel); 716 break; 717 718 case qService::IQService::SET_VIEW_FRAME: 719 break; 720 721 case qService::IQService::TOGGLE_SCREEN_UPDATES: 722 status = ToggleScreenUpdates(input_parcel, output_parcel); 723 break; 724 725 case qService::IQService::QDCM_SVC_CMDS: 726 status = QdcmCMDHandler(input_parcel, output_parcel); 727 break; 728 729 case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED: 730 status = OnMinHdcpEncryptionLevelChange(input_parcel, output_parcel); 731 break; 732 733 case qService::IQService::CONTROL_PARTIAL_UPDATE: 734 status = ControlPartialUpdate(input_parcel, output_parcel); 735 break; 736 737 case qService::IQService::SET_ACTIVE_CONFIG: 738 status = HandleSetActiveDisplayConfig(input_parcel, output_parcel); 739 break; 740 741 case qService::IQService::GET_ACTIVE_CONFIG: 742 status = HandleGetActiveDisplayConfig(input_parcel, output_parcel); 743 break; 744 745 case qService::IQService::GET_CONFIG_COUNT: 746 status = HandleGetDisplayConfigCount(input_parcel, output_parcel); 747 break; 748 749 case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG: 750 status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel); 751 break; 752 753 case qService::IQService::GET_PANEL_BRIGHTNESS: 754 status = GetPanelBrightness(input_parcel, output_parcel); 755 break; 756 757 case qService::IQService::SET_PANEL_BRIGHTNESS: 758 status = SetPanelBrightness(input_parcel, output_parcel); 759 break; 760 761 case qService::IQService::GET_DISPLAY_VISIBLE_REGION: 762 status = GetVisibleDisplayRect(input_parcel, output_parcel); 763 break; 764 765 case qService::IQService::SET_CAMERA_STATUS: 766 status = SetDynamicBWForCamera(input_parcel, output_parcel); 767 break; 768 769 case qService::IQService::GET_BW_TRANSACTION_STATUS: 770 status = GetBWTransactionStatus(input_parcel, output_parcel); 771 break; 772 773 case qService::IQService::SET_LAYER_MIXER_RESOLUTION: 774 status = SetMixerResolution(input_parcel); 775 break; 776 777 default: 778 DLOGW("QService command = %d is not supported", command); 779 return -EINVAL; 780 } 781 782 return status; 783 } 784 785 android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel, 786 android::Parcel *output_parcel) { 787 int input = input_parcel->readInt32(); 788 int error = android::BAD_VALUE; 789 790 if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) { 791 error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1); 792 if (error != 0) { 793 DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error); 794 } 795 } 796 output_parcel->writeInt32(error); 797 798 return error; 799 } 800 801 android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel, 802 android::Parcel *output_parcel) { 803 int level = input_parcel->readInt32(); 804 int error = android::BAD_VALUE; 805 806 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 807 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level); 808 if (error != 0) { 809 DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error); 810 } 811 } 812 output_parcel->writeInt32(error); 813 814 return error; 815 } 816 817 android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel, 818 android::Parcel *output_parcel) { 819 int error = android::BAD_VALUE; 820 int ret = error; 821 822 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 823 error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret); 824 if (error != 0) { 825 ret = error; 826 DLOGE("Failed to get the panel brightness. Error = %d", error); 827 } 828 } 829 output_parcel->writeInt32(ret); 830 831 return error; 832 } 833 834 android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel, 835 android::Parcel *out) { 836 DisplayError error = kErrorNone; 837 int ret = 0; 838 uint32_t disp_id = UINT32(input_parcel->readInt32()); 839 uint32_t enable = UINT32(input_parcel->readInt32()); 840 841 if (disp_id != HWC_DISPLAY_PRIMARY) { 842 DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id); 843 ret = -EINVAL; 844 out->writeInt32(ret); 845 return ret; 846 } 847 848 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) { 849 DLOGE("primary display object is not instantiated"); 850 ret = -EINVAL; 851 out->writeInt32(ret); 852 return ret; 853 } 854 855 uint32_t pending = 0; 856 error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending); 857 858 if (error == kErrorNone) { 859 if (!pending) { 860 out->writeInt32(ret); 861 return ret; 862 } 863 } else if (error == kErrorNotSupported) { 864 out->writeInt32(ret); 865 return ret; 866 } else { 867 ret = -EINVAL; 868 out->writeInt32(ret); 869 return ret; 870 } 871 872 // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future. 873 hwc_procs_->invalidate(hwc_procs_); 874 875 // Wait until partial update control is complete 876 ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs); 877 878 out->writeInt32(ret); 879 880 return ret; 881 } 882 883 android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel, 884 android::Parcel *output_parcel) { 885 int config = input_parcel->readInt32(); 886 int dpy = input_parcel->readInt32(); 887 int error = android::BAD_VALUE; 888 889 if (dpy > HWC_DISPLAY_VIRTUAL) { 890 return android::BAD_VALUE; 891 } 892 893 if (hwc_display_[dpy]) { 894 error = hwc_display_[dpy]->SetActiveDisplayConfig(config); 895 if (error == 0) { 896 hwc_procs_->invalidate(hwc_procs_); 897 } 898 } 899 900 return error; 901 } 902 903 android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel, 904 android::Parcel *output_parcel) { 905 int dpy = input_parcel->readInt32(); 906 int error = android::BAD_VALUE; 907 908 if (dpy > HWC_DISPLAY_VIRTUAL) { 909 return android::BAD_VALUE; 910 } 911 912 if (hwc_display_[dpy]) { 913 uint32_t config = 0; 914 error = hwc_display_[dpy]->GetActiveDisplayConfig(&config); 915 if (error == 0) { 916 output_parcel->writeInt32(INT(config)); 917 } 918 } 919 920 return error; 921 } 922 923 android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel, 924 android::Parcel *output_parcel) { 925 int dpy = input_parcel->readInt32(); 926 int error = android::BAD_VALUE; 927 928 if (dpy > HWC_DISPLAY_VIRTUAL) { 929 return android::BAD_VALUE; 930 } 931 932 uint32_t count = 0; 933 if (hwc_display_[dpy]) { 934 error = hwc_display_[dpy]->GetDisplayConfigCount(&count); 935 if (error == 0) { 936 output_parcel->writeInt32(INT(count)); 937 } 938 } 939 940 return error; 941 } 942 943 android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel 944 *input_parcel, 945 android::Parcel *output_parcel) { 946 int config = input_parcel->readInt32(); 947 int dpy = input_parcel->readInt32(); 948 int error = android::BAD_VALUE; 949 DisplayConfigVariableInfo display_attributes; 950 951 if (dpy > HWC_DISPLAY_VIRTUAL) { 952 return android::BAD_VALUE; 953 } 954 955 if (hwc_display_[dpy]) { 956 error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes); 957 if (error == 0) { 958 output_parcel->writeInt32(INT(display_attributes.vsync_period_ns)); 959 output_parcel->writeInt32(INT(display_attributes.x_pixels)); 960 output_parcel->writeInt32(INT(display_attributes.y_pixels)); 961 output_parcel->writeFloat(display_attributes.x_dpi); 962 output_parcel->writeFloat(display_attributes.y_dpi); 963 output_parcel->writeInt32(0); // Panel type, unsupported. 964 output_parcel->writeInt32(display_attributes.is_yuv); 965 } 966 } 967 968 return error; 969 } 970 971 android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel, 972 android::Parcel *output_parcel) { 973 int ret = -EINVAL; 974 975 uint32_t display_id = UINT32(input_parcel->readInt32()); 976 uint32_t display_status = UINT32(input_parcel->readInt32()); 977 978 DLOGI("Display = %d, Status = %d", display_id, display_status); 979 980 if (display_id >= HWC_NUM_DISPLAY_TYPES) { 981 DLOGE("Invalid display_id"); 982 } else if (display_id == HWC_DISPLAY_PRIMARY) { 983 DLOGE("Not supported for this display"); 984 } else if (!hwc_display_[display_id]) { 985 DLOGW("Display is not connected"); 986 } else { 987 ret = hwc_display_[display_id]->SetDisplayStatus(display_status); 988 } 989 990 output_parcel->writeInt32(ret); 991 992 return ret; 993 } 994 995 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) { 996 uint32_t operation = UINT32(input_parcel->readInt32()); 997 switch (operation) { 998 case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE: 999 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform( 1000 HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false); 1001 case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE: 1002 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform( 1003 HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true); 1004 case qdutils::SET_BINDER_DYN_REFRESH_RATE: 1005 { 1006 uint32_t refresh_rate = UINT32(input_parcel->readInt32()); 1007 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform( 1008 HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, 1009 refresh_rate); 1010 } 1011 default: 1012 DLOGW("Invalid operation %d", operation); 1013 return -EINVAL; 1014 } 1015 1016 return 0; 1017 } 1018 1019 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) { 1020 uint32_t mode = UINT32(input_parcel->readInt32()); 1021 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode); 1022 } 1023 1024 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) { 1025 DisplayError error = kErrorNone; 1026 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32()); 1027 uint32_t max_mixer_stages = UINT32(input_parcel->readInt32()); 1028 1029 if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) { 1030 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 1031 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages); 1032 if (error != kErrorNone) { 1033 return -EINVAL; 1034 } 1035 } 1036 } 1037 1038 if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) { 1039 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { 1040 error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages); 1041 if (error != kErrorNone) { 1042 return -EINVAL; 1043 } 1044 } 1045 } 1046 1047 if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) { 1048 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) { 1049 error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages); 1050 if (error != kErrorNone) { 1051 return -EINVAL; 1052 } 1053 } 1054 } 1055 1056 return 0; 1057 } 1058 1059 android::status_t HWCSession::SetDynamicBWForCamera(const android::Parcel *input_parcel, 1060 android::Parcel *output_parcel) { 1061 DisplayError error = kErrorNone; 1062 uint32_t camera_status = UINT32(input_parcel->readInt32()); 1063 HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault; 1064 1065 // trigger invalidate to apply new bw caps. 1066 hwc_procs_->invalidate(hwc_procs_); 1067 1068 error = core_intf_->SetMaxBandwidthMode(mode); 1069 if (error != kErrorNone) { 1070 return -EINVAL; 1071 } 1072 1073 new_bw_mode_ = true; 1074 need_invalidate_ = true; 1075 1076 return 0; 1077 } 1078 1079 android::status_t HWCSession::GetBWTransactionStatus(const android::Parcel *input_parcel, 1080 android::Parcel *output_parcel) { 1081 bool state = true; 1082 1083 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 1084 if (sync_wait(bw_mode_release_fd_, 0) < 0) { 1085 DLOGI("bw_transaction_release_fd is not yet signalled: err= %s", strerror(errno)); 1086 state = false; 1087 } 1088 output_parcel->writeInt32(state); 1089 } 1090 1091 return 0; 1092 } 1093 1094 void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) { 1095 uint32_t frame_dump_count = UINT32(input_parcel->readInt32()); 1096 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32()); 1097 uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32()); 1098 1099 if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) { 1100 if (hwc_display_[HWC_DISPLAY_PRIMARY]) { 1101 hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type); 1102 } 1103 } 1104 1105 if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) { 1106 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { 1107 hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type); 1108 } 1109 } 1110 1111 if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) { 1112 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) { 1113 hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type); 1114 } 1115 } 1116 } 1117 1118 android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) { 1119 DisplayError error = kErrorNone; 1120 uint32_t dpy = UINT32(input_parcel->readInt32()); 1121 1122 if (dpy != HWC_DISPLAY_PRIMARY) { 1123 DLOGI("Resoulution change not supported for this display %d", dpy); 1124 return -EINVAL; 1125 } 1126 1127 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) { 1128 DLOGI("Primary display is not initialized"); 1129 return -EINVAL; 1130 } 1131 1132 uint32_t width = UINT32(input_parcel->readInt32()); 1133 uint32_t height = UINT32(input_parcel->readInt32()); 1134 1135 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height); 1136 if (error != kErrorNone) { 1137 return -EINVAL; 1138 } 1139 1140 return 0; 1141 } 1142 1143 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) { 1144 int type = input_parcel->readInt32(); 1145 bool enable = (input_parcel->readInt32() > 0); 1146 DLOGI("type = %d enable = %d", type, enable); 1147 int verbose_level = input_parcel->readInt32(); 1148 1149 switch (type) { 1150 case qService::IQService::DEBUG_ALL: 1151 HWCDebugHandler::DebugAll(enable, verbose_level); 1152 break; 1153 1154 case qService::IQService::DEBUG_MDPCOMP: 1155 HWCDebugHandler::DebugStrategy(enable, verbose_level); 1156 HWCDebugHandler::DebugCompManager(enable, verbose_level); 1157 break; 1158 1159 case qService::IQService::DEBUG_PIPE_LIFECYCLE: 1160 HWCDebugHandler::DebugResources(enable, verbose_level); 1161 break; 1162 1163 case qService::IQService::DEBUG_DRIVER_CONFIG: 1164 HWCDebugHandler::DebugDriverConfig(enable, verbose_level); 1165 break; 1166 1167 case qService::IQService::DEBUG_ROTATOR: 1168 HWCDebugHandler::DebugResources(enable, verbose_level); 1169 HWCDebugHandler::DebugDriverConfig(enable, verbose_level); 1170 HWCDebugHandler::DebugRotator(enable, verbose_level); 1171 break; 1172 1173 case qService::IQService::DEBUG_QDCM: 1174 HWCDebugHandler::DebugQdcm(enable, verbose_level); 1175 break; 1176 1177 default: 1178 DLOGW("type = %d is not supported", type); 1179 } 1180 } 1181 1182 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel, 1183 android::Parcel *output_parcel) { 1184 int ret = 0; 1185 int32_t *brightness_value = NULL; 1186 uint32_t display_id(0); 1187 PPPendingParams pending_action; 1188 PPDisplayAPIPayload resp_payload, req_payload; 1189 1190 if (!color_mgr_) { 1191 return -1; 1192 } 1193 1194 pending_action.action = kNoAction; 1195 pending_action.params = NULL; 1196 1197 // Read display_id, payload_size and payload from in_parcel. 1198 ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload); 1199 if (!ret) { 1200 if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY]) 1201 ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload, 1202 &resp_payload, &pending_action); 1203 1204 if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL]) 1205 ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload, 1206 &pending_action); 1207 } 1208 1209 if (ret) { 1210 output_parcel->writeInt32(ret); // first field in out parcel indicates return code. 1211 req_payload.DestroyPayload(); 1212 resp_payload.DestroyPayload(); 1213 return ret; 1214 } 1215 1216 switch (pending_action.action) { 1217 case kInvalidating: 1218 hwc_procs_->invalidate(hwc_procs_); 1219 break; 1220 case kEnterQDCMMode: 1221 ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]); 1222 break; 1223 case kExitQDCMMode: 1224 ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]); 1225 break; 1226 case kApplySolidFill: 1227 ret = color_mgr_->SetSolidFill(pending_action.params, 1228 true, hwc_display_[HWC_DISPLAY_PRIMARY]); 1229 hwc_procs_->invalidate(hwc_procs_); 1230 break; 1231 case kDisableSolidFill: 1232 ret = color_mgr_->SetSolidFill(pending_action.params, 1233 false, hwc_display_[HWC_DISPLAY_PRIMARY]); 1234 hwc_procs_->invalidate(hwc_procs_); 1235 break; 1236 case kSetPanelBrightness: 1237 brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload); 1238 if (brightness_value == NULL) { 1239 DLOGE("Brightness value is Null"); 1240 return -EINVAL; 1241 } 1242 if (HWC_DISPLAY_PRIMARY == display_id) 1243 ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value); 1244 break; 1245 case kEnableFrameCapture: 1246 ret = color_mgr_->SetFrameCapture(pending_action.params, 1247 true, hwc_display_[HWC_DISPLAY_PRIMARY]); 1248 hwc_procs_->invalidate(hwc_procs_); 1249 break; 1250 case kDisableFrameCapture: 1251 ret = color_mgr_->SetFrameCapture(pending_action.params, 1252 false, hwc_display_[HWC_DISPLAY_PRIMARY]); 1253 break; 1254 case kNoAction: 1255 break; 1256 default: 1257 DLOGW("Invalid pending action = %d!", pending_action.action); 1258 break; 1259 } 1260 1261 // for display API getter case, marshall returned params into out_parcel. 1262 output_parcel->writeInt32(ret); 1263 HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel); 1264 req_payload.DestroyPayload(); 1265 resp_payload.DestroyPayload(); 1266 1267 return (ret? -EINVAL : 0); 1268 } 1269 1270 android::status_t HWCSession::OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel, 1271 android::Parcel *output_parcel) { 1272 int ret = -EINVAL; 1273 uint32_t display_id = UINT32(input_parcel->readInt32()); 1274 uint32_t min_enc_level = UINT32(input_parcel->readInt32()); 1275 1276 DLOGI("Display %d", display_id); 1277 1278 if (display_id >= HWC_NUM_DISPLAY_TYPES) { 1279 DLOGE("Invalid display_id"); 1280 } else if (display_id != HWC_DISPLAY_EXTERNAL) { 1281 DLOGE("Not supported for display"); 1282 } else if (!hwc_display_[display_id]) { 1283 DLOGW("Display is not connected"); 1284 } else { 1285 ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange(min_enc_level); 1286 } 1287 1288 output_parcel->writeInt32(ret); 1289 1290 return ret; 1291 } 1292 1293 void* HWCSession::HWCUeventThread(void *context) { 1294 if (context) { 1295 return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler(); 1296 } 1297 1298 return NULL; 1299 } 1300 1301 void* HWCSession::HWCUeventThreadHandler() { 1302 static char uevent_data[PAGE_SIZE]; 1303 int length = 0; 1304 prctl(PR_SET_NAME, uevent_thread_name_, 0, 0, 0); 1305 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); 1306 if (!uevent_init()) { 1307 DLOGE("Failed to init uevent"); 1308 pthread_exit(0); 1309 return NULL; 1310 } 1311 1312 while (!uevent_thread_exit_) { 1313 // keep last 2 zeroes to ensure double 0 termination 1314 length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2); 1315 1316 if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) { 1317 DLOGI("Uevent HDMI = %s", uevent_data); 1318 int connected = GetEventValue(uevent_data, length, "SWITCH_STATE="); 1319 if (connected >= 0) { 1320 DLOGI("HDMI = %s", connected ? "connected" : "disconnected"); 1321 if (HotPlugHandler(connected) == -1) { 1322 DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected"); 1323 } 1324 } 1325 } else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) { 1326 DLOGI("Uevent FB0 = %s", uevent_data); 1327 int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE="); 1328 if (panel_reset == 0) { 1329 if (hwc_procs_) { 1330 reset_panel_ = true; 1331 hwc_procs_->invalidate(hwc_procs_); 1332 } else { 1333 DLOGW("Ignore resetpanel - hwc_proc not registered"); 1334 } 1335 } 1336 } 1337 } 1338 pthread_exit(0); 1339 1340 return NULL; 1341 } 1342 1343 int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) { 1344 const char *iterator_str = uevent_data; 1345 while (((iterator_str - uevent_data) <= length) && (*iterator_str)) { 1346 char *pstr = strstr(iterator_str, event_info); 1347 if (pstr != NULL) { 1348 return (atoi(iterator_str + strlen(event_info))); 1349 } 1350 iterator_str += strlen(iterator_str) + 1; 1351 } 1352 1353 return -1; 1354 } 1355 1356 void HWCSession::ResetPanel() { 1357 int status = -EINVAL; 1358 1359 DLOGI("Powering off primary"); 1360 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_OFF); 1361 if (status) { 1362 DLOGE("power-off on primary failed with error = %d", status); 1363 } 1364 1365 DLOGI("Restoring power mode on primary"); 1366 int32_t mode = INT(hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode()); 1367 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode); 1368 if (status) { 1369 DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status); 1370 } 1371 1372 status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, 1); 1373 if (status) { 1374 DLOGE("enabling vsync failed for primary with error = %d", status); 1375 } 1376 1377 reset_panel_ = false; 1378 } 1379 1380 int HWCSession::HotPlugHandler(bool connected) { 1381 int status = 0; 1382 bool notify_hotplug = false; 1383 1384 // To prevent sending events to client while a lock is held, acquire scope locks only within 1385 // below scope so that those get automatically unlocked after the scope ends. 1386 { 1387 SEQUENCE_WAIT_SCOPE_LOCK(locker_); 1388 1389 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) { 1390 DLOGE("Primay display is not connected."); 1391 return -1; 1392 } 1393 1394 1395 HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY]; 1396 HWCDisplay *external_display = NULL; 1397 HWCDisplay *null_display = NULL; 1398 1399 if (primary_display->GetDisplayClass() == DISPLAY_CLASS_EXTERNAL) { 1400 external_display = static_cast<HWCDisplayExternal *>(hwc_display_[HWC_DISPLAY_PRIMARY]); 1401 } else if (primary_display->GetDisplayClass() == DISPLAY_CLASS_NULL) { 1402 null_display = static_cast<HWCDisplayNull *>(hwc_display_[HWC_DISPLAY_PRIMARY]); 1403 } 1404 1405 // If primary display connected is a NULL display, then replace it with the external display 1406 if (connected) { 1407 // If we are in HDMI as primary and the primary display just got plugged in 1408 if (is_hdmi_primary_ && null_display) { 1409 uint32_t primary_width, primary_height; 1410 null_display->GetFrameBufferResolution(&primary_width, &primary_height); 1411 delete null_display; 1412 hwc_display_[HWC_DISPLAY_PRIMARY] = NULL; 1413 1414 // Create external display with a forced framebuffer resolution to that of what the NULL 1415 // display had. This is necessary because SurfaceFlinger does not dynamically update 1416 // framebuffer resolution once it reads it at bootup. So we always have to have the NULL 1417 // display/external display both at the bootup resolution. 1418 int status = HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width, 1419 primary_height, qservice_, true, 1420 &hwc_display_[HWC_DISPLAY_PRIMARY]); 1421 if (status) { 1422 DLOGE("Could not create external display"); 1423 return -1; 1424 } 1425 1426 is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY); 1427 1428 // Next, go ahead and enable vsync on external display. This is expliclity required 1429 // because in HDMI as primary case, SurfaceFlinger may not be aware of underlying 1430 // changing display. and thus may not explicitly enable vsync 1431 1432 status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, true); 1433 if (status) { 1434 DLOGE("Error enabling vsync for HDMI as primary case"); 1435 } 1436 // Don't do hotplug notification for HDMI as primary case for now 1437 notify_hotplug = false; 1438 } else { 1439 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { 1440 DLOGE("HDMI is already connected"); 1441 return -1; 1442 } 1443 1444 // Connect external display if virtual display is not connected. 1445 // Else, defer external display connection and process it when virtual display 1446 // tears down; Do not notify SurfaceFlinger since connection is deferred now. 1447 if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) { 1448 status = ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL); 1449 if (status) { 1450 return status; 1451 } 1452 notify_hotplug = true; 1453 } else { 1454 DLOGI("Virtual display is connected, pending connection"); 1455 external_pending_connect_ = true; 1456 } 1457 } 1458 } else { 1459 // Do not return error if external display is not in connected status. 1460 // Due to virtual display concurrency, external display connection might be still pending 1461 // but hdmi got disconnected before pending connection could be processed. 1462 1463 if (is_hdmi_primary_ && external_display) { 1464 uint32_t x_res, y_res; 1465 external_display->GetFrameBufferResolution(&x_res, &y_res); 1466 // Need to manually disable VSYNC as SF is not aware of connect/disconnect cases 1467 // for HDMI as primary 1468 external_display->EventControl(HWC_EVENT_VSYNC, false); 1469 HWCDisplayExternal::Destroy(external_display); 1470 1471 HWCDisplayNull *null_display; 1472 1473 int status = HWCDisplayNull::Create(core_intf_, &hwc_procs_, 1474 reinterpret_cast<HWCDisplay **>(&null_display)); 1475 1476 if (status) { 1477 DLOGE("Could not create Null display when primary got disconnected"); 1478 return -1; 1479 } 1480 1481 null_display->SetResolution(x_res, y_res); 1482 hwc_display_[HWC_DISPLAY_PRIMARY] = null_display; 1483 1484 // Don't do hotplug notification for HDMI as primary case for now 1485 notify_hotplug = false; 1486 } else { 1487 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) { 1488 status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL); 1489 notify_hotplug = true; 1490 } 1491 external_pending_connect_ = false; 1492 } 1493 } 1494 } 1495 1496 if (connected && notify_hotplug) { 1497 // trigger screen refresh to ensure sufficient resources are available to process new 1498 // new display connection. 1499 hwc_procs_->invalidate(hwc_procs_); 1500 uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY)); 1501 usleep(vsync_period * 2 / 1000); 1502 } 1503 // notify client 1504 if (notify_hotplug) { 1505 hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected); 1506 } 1507 1508 qservice_->onHdmiHotplug(INT(connected)); 1509 1510 return 0; 1511 } 1512 1513 void HWCSession::HandleSecureDisplaySession(hwc_display_contents_1_t **displays) { 1514 secure_display_active_ = false; 1515 if (!*displays) { 1516 DLOGW("Invalid display contents"); 1517 return; 1518 } 1519 1520 hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY]; 1521 if (!content_list) { 1522 DLOGW("Invalid primary content list"); 1523 return; 1524 } 1525 size_t num_hw_layers = content_list->numHwLayers; 1526 1527 for (size_t i = 0; i < num_hw_layers - 1; i++) { 1528 hwc_layer_1_t &hwc_layer = content_list->hwLayers[i]; 1529 const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle); 1530 if (pvt_handle && pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) { 1531 secure_display_active_ = true; 1532 } 1533 } 1534 1535 for (ssize_t dpy = static_cast<ssize_t>(HWC_NUM_DISPLAY_TYPES - 1); dpy >= 0; dpy--) { 1536 if (hwc_display_[dpy]) { 1537 hwc_display_[dpy]->SetSecureDisplay(secure_display_active_); 1538 } 1539 } 1540 } 1541 1542 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel, 1543 android::Parcel *output_parcel) { 1544 int dpy = input_parcel->readInt32(); 1545 1546 if (dpy < HWC_DISPLAY_PRIMARY || dpy > HWC_DISPLAY_VIRTUAL) { 1547 return android::BAD_VALUE;; 1548 } 1549 1550 if (!hwc_display_[dpy]) { 1551 return android::NO_INIT; 1552 } 1553 1554 hwc_rect_t visible_rect = {0, 0, 0, 0}; 1555 int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect); 1556 if (error < 0) { 1557 return error; 1558 } 1559 1560 output_parcel->writeInt32(visible_rect.left); 1561 output_parcel->writeInt32(visible_rect.top); 1562 output_parcel->writeInt32(visible_rect.right); 1563 output_parcel->writeInt32(visible_rect.bottom); 1564 1565 return android::NO_ERROR; 1566 } 1567 1568 } // namespace sdm 1569 1570