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