DisplayAnalyzer.cpp revision 0594c42af26255fd8d3d7d39c0cb0e2da5b8841b
1/* 2 * Copyright © 2012 Intel Corporation 3 * All rights reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 * 24 * Authors: 25 * Jackie Li <yaodong.li@intel.com> 26 * 27 */ 28 29#include <common/utils/HwcTrace.h> 30#include <IDisplayDevice.h> 31#include <DisplayQuery.h> 32#include <BufferManager.h> 33#include <DisplayPlaneManager.h> 34#include <Hwcomposer.h> 35#include <common/base/DisplayAnalyzer.h> 36#include <cutils/properties.h> 37#include <GraphicBuffer.h> 38#include <ExternalDevice.h> 39 40namespace android { 41namespace intel { 42 43DisplayAnalyzer::DisplayAnalyzer() 44 : mInitialized(false), 45 mVideoExtModeEnabled(true), 46 mVideoExtModeEligible(false), 47 mVideoExtModeActive(false), 48 mBlankDevice(false), 49 mOverlayAllowed(true), 50 mActiveInputState(true), 51 mIgnoreVideoSkipFlag(false), 52 mProtectedVideoSession(false), 53 mCachedNumDisplays(0), 54 mCachedDisplays(0), 55 mPendingEvents(), 56 mEventMutex(), 57 mEventHandledCondition() 58{ 59} 60 61DisplayAnalyzer::~DisplayAnalyzer() 62{ 63} 64 65bool DisplayAnalyzer::initialize() 66{ 67 // by default video extended mode is enabled 68 char prop[PROPERTY_VALUE_MAX]; 69 if (property_get("hwc.video.extmode.enable", prop, "1") > 0) { 70 mVideoExtModeEnabled = atoi(prop) ? true : false; 71 } 72 mVideoExtModeEligible = false; 73 mVideoExtModeActive = false; 74 mBlankDevice = false; 75 mOverlayAllowed = true; 76 mActiveInputState = true; 77 mIgnoreVideoSkipFlag = false; 78 mProtectedVideoSession = false; 79 mCachedNumDisplays = 0; 80 mCachedDisplays = 0; 81 mPendingEvents.clear(); 82 mVideoStateMap.clear(); 83 mInitialized = true; 84 85 return true; 86} 87 88void DisplayAnalyzer::deinitialize() 89{ 90 mPendingEvents.clear(); 91 mVideoStateMap.clear(); 92 mInitialized = false; 93} 94 95void DisplayAnalyzer::analyzeContents( 96 size_t numDisplays, hwc_display_contents_1_t** displays) 97{ 98 // cache and use them only in this context during analysis 99 mCachedNumDisplays = numDisplays; 100 mCachedDisplays = displays; 101 102 handlePendingEvents(); 103 104 // FIXME: WA for ASUS Face unlock screen flicker issue 105 // If layer count exceeds plane max number, force GLES 106 hwc_display_contents_1_t *content = NULL; 107 for (int i = 0; i < (int)mCachedNumDisplays; i++) { 108 content = mCachedDisplays[i]; 109 if (content == NULL) { 110 continue; 111 } 112 113 if ((content->flags & HWC_GEOMETRY_CHANGED) && 114 (content->numHwLayers > 5) && 115 !hasVideoLayer(i)) 116 setCompositionType(i, HWC_FORCE_FRAMEBUFFER, true); 117 } 118 119 if (mVideoExtModeEnabled) { 120 handleVideoExtMode(); 121 } 122 123 if (mBlankDevice) { 124 // this will make sure device is blanked after geometry changes. 125 // blank event is only processed once 126 blankSecondaryDevice(); 127 } 128} 129 130void DisplayAnalyzer::handleVideoExtMode() 131{ 132 bool eligible = mVideoExtModeEligible; 133 checkVideoExtMode(); 134 if (eligible == mVideoExtModeEligible) { 135 if (mVideoExtModeActive) { 136 // need to mark all layers 137 setCompositionType(0, HWC_OVERLAY, false); 138 } 139 return; 140 } 141 142 if (mVideoExtModeEligible) { 143 if (mActiveInputState) { 144 VTRACE("input is active"); 145 } else { 146 enterVideoExtMode(); 147 } 148 } else { 149 exitVideoExtMode(); 150 } 151} 152 153void DisplayAnalyzer::checkVideoExtMode() 154{ 155 if (mVideoStateMap.size() != 1) { 156 mVideoExtModeEligible = false; 157 return; 158 } 159 160 bool geometryChanged = false; 161 int activeDisplays = 0; 162 163 hwc_display_contents_1_t *content = NULL; 164 for (int i = 0; i < (int)mCachedNumDisplays; i++) { 165 content = mCachedDisplays[i]; 166 if (content == NULL) { 167 continue; 168 } 169 activeDisplays++; 170 if (content->flags & HWC_GEOMETRY_CHANGED) { 171 geometryChanged = true; 172 } 173 } 174 175 if (activeDisplays <= 1) { 176 mVideoExtModeEligible = false; 177 return; 178 } 179 180 // video state update event may come later than geometry change event. 181 // in that case, video extended mode is not detected properly. 182#if 0 183 if (geometryChanged == false) { 184 // use previous analysis result 185 return; 186 } 187#endif 188 // reset eligibility of video extended mode 189 mVideoExtModeEligible = false; 190 191 // check if there is video layer in the primary device 192 content = mCachedDisplays[0]; 193 if (content == NULL) { 194 return; 195 } 196 197 uint32_t videoHandle = 0; 198 bool videoLayerExist = false; 199 bool videoFullScreenOnPrimary = false; 200 bool isVideoLayerSkipped = false; 201 202 // exclude the frame buffer target layer 203 for (int j = 0; j < (int)content->numHwLayers - 1; j++) { 204 videoLayerExist = isVideoLayer(content->hwLayers[j]); 205 if (videoLayerExist) { 206 if ((content->hwLayers[j].flags & HWC_SKIP_LAYER)) { 207 isVideoLayerSkipped = true; 208 } 209 videoHandle = (uint32_t)content->hwLayers[j].handle; 210 videoFullScreenOnPrimary = isVideoFullScreen(0, content->hwLayers[j]); 211 break; 212 } 213 } 214 215 if (videoLayerExist == false) { 216 // no video layer is found in the primary layer 217 return; 218 } 219 220 // check whether video layer exists in external device or virtual device 221 // TODO: video may exist in virtual device but no in external device or vice versa 222 // TODO: multiple video layers are not addressed here 223 for (int i = 1; i < (int)mCachedNumDisplays; i++) { 224 content = mCachedDisplays[i]; 225 if (content == NULL) { 226 continue; 227 } 228 229 // exclude the frame buffer target layer 230 for (int j = 0; j < (int)content->numHwLayers - 1; j++) { 231 if ((uint32_t)content->hwLayers[j].handle == videoHandle) { 232 isVideoLayerSkipped |= (content->hwLayers[j].flags & HWC_SKIP_LAYER); 233 VTRACE("video layer exists in device %d", i); 234 if (isVideoLayerSkipped || videoFullScreenOnPrimary){ 235 VTRACE("Video ext mode eligible, %d, %d", 236 isVideoLayerSkipped, videoFullScreenOnPrimary); 237 mVideoExtModeEligible = true; 238 } else { 239 mVideoExtModeEligible = isVideoFullScreen(i, content->hwLayers[j]); 240 } 241 return; 242 } 243 } 244 } 245} 246 247bool DisplayAnalyzer::isVideoExtModeActive() 248{ 249 return mVideoExtModeActive; 250} 251 252bool DisplayAnalyzer::isVideoExtModeEnabled() 253{ 254#if 1 255 // enable it for run-time debugging purpose. 256 char prop[PROPERTY_VALUE_MAX]; 257 if (property_get("hwc.video.extmode.enable", prop, "1") > 0) { 258 mVideoExtModeEnabled = atoi(prop) ? true : false; 259 } 260 ITRACE("video extended mode enabled: %d", mVideoExtModeEnabled); 261#endif 262 263 return mVideoExtModeEnabled; 264} 265 266bool DisplayAnalyzer::isVideoLayer(hwc_layer_1_t &layer) 267{ 268 bool ret = false; 269 BufferManager *bm = Hwcomposer::getInstance().getBufferManager(); 270 if (!layer.handle) { 271 return false; 272 } 273 DataBuffer *buffer = bm->lockDataBuffer((uint32_t)layer.handle); 274 if (!buffer) { 275 ETRACE("failed to get buffer"); 276 } else { 277 ret = DisplayQuery::isVideoFormat(buffer->getFormat()); 278 bm->unlockDataBuffer(buffer); 279 } 280 return ret; 281} 282 283bool DisplayAnalyzer::isVideoFullScreen(int device, hwc_layer_1_t &layer) 284{ 285 IDisplayDevice *displayDevice = Hwcomposer::getInstance().getDisplayDevice(device); 286 if (!displayDevice) { 287 return false; 288 } 289 int width = 0, height = 0; 290 if (!displayDevice->getDisplaySize(&width, &height)) { 291 return false; 292 } 293 294 VTRACE("video left %d, right %d, top %d, bottom %d, device width %d, height %d", 295 layer.displayFrame.left, layer.displayFrame.right, 296 layer.displayFrame.top, layer.displayFrame.bottom, 297 width, height); 298 299 // full-screen defintion: 300 // width of target display frame == width of target device, with 1 pixel of tolerance, or 301 // Height of target display frame == height of target device, with 1 pixel of tolerance, or 302 // width * height of display frame > 90% of width * height of display device, or 303 // any of above condition is met on either primary display or secondary display 304 int dstW = layer.displayFrame.right - layer.displayFrame.left; 305 int dstH = layer.displayFrame.bottom - layer.displayFrame.top; 306 307 if (abs(dstW - width) <= 1 && 308 abs(dstH - height) <= 1 && 309 dstW * dstH * 10 < width * height * 9) { 310 VTRACE("video is not full-screen"); 311 return false; 312 } 313 return true; 314} 315 316bool DisplayAnalyzer::isOverlayAllowed() 317{ 318 return mOverlayAllowed; 319} 320 321int DisplayAnalyzer::getVideoInstances() 322{ 323 return (int)mVideoStateMap.size(); 324} 325 326void DisplayAnalyzer::postHotplugEvent(bool connected) 327{ 328 if (!connected) { 329 // enable vsync on the primary device immediately 330 Hwcomposer::getInstance().getVsyncManager()->enableDynamicVsync(true); 331 } 332 333 // handle hotplug event (vsync switch) asynchronously 334 Event e; 335 e.type = HOTPLUG_EVENT; 336 e.bValue = connected; 337 postEvent(e); 338 Hwcomposer::getInstance().invalidate(); 339} 340 341void DisplayAnalyzer::postVideoEvent(int instanceID, int state) 342{ 343 Event e; 344 e.type = VIDEO_EVENT; 345 e.videoEvent.instanceID = instanceID; 346 e.videoEvent.state = state; 347 postEvent(e); 348 349 if ((state == VIDEO_PLAYBACK_STARTING) || 350 (state == VIDEO_PLAYBACK_STOPPING && mProtectedVideoSession)) { 351 Hwcomposer::getInstance().invalidate(); 352 // wait for up to 100ms until overlay is disabled. 353 int loop = 0; 354 while (loop++ < 6) { 355 if (Hwcomposer::getInstance().getPlaneManager()->isOverlayPlanesDisabled()) 356 break; 357 usleep(16700); 358 } 359 if (loop == 6) { 360 WTRACE("timeout disabling overlay "); 361 } 362 } 363} 364 365void DisplayAnalyzer::postBlankEvent(bool blank) 366{ 367 Event e; 368 e.type = BLANK_EVENT; 369 e.bValue = blank; 370 postEvent(e); 371 Hwcomposer::getInstance().invalidate(); 372} 373 374void DisplayAnalyzer::postInputEvent(bool active) 375{ 376 Event e; 377 e.type = INPUT_EVENT; 378 e.bValue = active; 379 postEvent(e); 380 Hwcomposer::getInstance().invalidate(); 381} 382 383void DisplayAnalyzer::postIdleEntryEvent(void) 384{ 385 Event e; 386 e.type = IDLE_ENTRY_EVENT; 387 e.nValue = 0; 388 postEvent(e); 389} 390 391void DisplayAnalyzer::postEvent(Event& e) 392{ 393 Mutex::Autolock lock(mEventMutex); 394 mPendingEvents.add(e); 395} 396 397bool DisplayAnalyzer::getEvent(Event& e) 398{ 399 Mutex::Autolock lock(mEventMutex); 400 if (mPendingEvents.size() == 0) { 401 return false; 402 } 403 e = mPendingEvents[0]; 404 mPendingEvents.removeAt(0); 405 return true; 406} 407 408void DisplayAnalyzer::handlePendingEvents() 409{ 410 // handle one event per analysis to avoid blocking surface flinger 411 // some event may take lengthy time to process 412 Event e; 413 if (!getEvent(e)) { 414 return; 415 } 416 417 switch (e.type) { 418 case HOTPLUG_EVENT: 419 handleHotplugEvent(e.bValue); 420 break; 421 case BLANK_EVENT: 422 handleBlankEvent(e.bValue); 423 break; 424 case VIDEO_EVENT: 425 handleVideoEvent(e.videoEvent.instanceID, e.videoEvent.state); 426 break; 427 case TIMING_EVENT: 428 handleTimingEvent(); 429 break; 430 case INPUT_EVENT: 431 handleInputEvent(e.bValue); 432 break; 433 case DPMS_EVENT: 434 handleDpmsEvent(e.nValue); 435 break; 436 case IDLE_ENTRY_EVENT: 437 handleIdleEntryEvent(e.nValue); 438 break; 439 case IDLE_EXIT_EVENT: 440 handleIdleExitEvent(); 441 break; 442 case VIDEO_CHECK_EVENT: 443 handleVideoCheckEvent(); 444 break; 445 } 446} 447 448void DisplayAnalyzer::handleHotplugEvent(bool connected) 449{ 450 if (connected) { 451 Hwcomposer::getInstance().getPowerManager()->disableIdleControl(); 452 } else { 453 if (mVideoStateMap.size() == 0) { 454 Hwcomposer::getInstance().getPowerManager()->enableIdleControl(); 455 } else if (mVideoStateMap.size() == 1) { 456 // Reset input state if HDMI is plug out to 457 // avoid entering extended mode immediately after HDMI is plug in 458 mActiveInputState = true; 459 } 460 } 461} 462 463void DisplayAnalyzer::handleBlankEvent(bool blank) 464{ 465 mBlankDevice = blank; 466 // force geometry changed in the secondary device to reset layer composition type 467 for (int i = 0; i < (int)mCachedNumDisplays; i++) { 468 if (i == IDisplayDevice::DEVICE_PRIMARY) { 469 continue; 470 } 471 if (mCachedDisplays[i]) { 472 mCachedDisplays[i]->flags |= HWC_GEOMETRY_CHANGED; 473 } 474 } 475 blankSecondaryDevice(); 476} 477 478void DisplayAnalyzer::handleTimingEvent() 479{ 480 // check whether external device is connected, reset refresh rate to match video frame rate 481 // if video is in playing state or reset refresh rate to default preferred one if video is not 482 // at playing state 483 Hwcomposer *hwc = &Hwcomposer::getInstance(); 484 ExternalDevice *dev = NULL; 485 dev = (ExternalDevice *)hwc->getDisplayDevice(IDisplayDevice::DEVICE_EXTERNAL); 486 if (!dev) { 487 return; 488 } 489 490 if (!dev->isConnected()) { 491 return; 492 } 493 494 if (hwc->getMultiDisplayObserver()->isExternalDeviceTimingFixed()) { 495 VTRACE("Timing of external device is fixed."); 496 return; 497 } 498 499 int hz = 0; 500 if (mVideoStateMap.size() == 1) { 501 VideoSourceInfo info; 502 int instanceID = mVideoStateMap.keyAt(0); 503 status_t err = hwc->getMultiDisplayObserver()->getVideoSourceInfo( 504 instanceID, &info); 505 if (err == NO_ERROR) { 506 hz = info.frameRate; 507 } 508 } 509 510 dev->setRefreshRate(hz); 511} 512 513void DisplayAnalyzer::handleVideoEvent(int instanceID, int state) 514{ 515 mVideoStateMap.removeItem(instanceID); 516 if (state != VIDEO_PLAYBACK_STOPPED) { 517 mVideoStateMap.add(instanceID, state); 518 } 519 520 Hwcomposer *hwc = &Hwcomposer::getInstance(); 521 522 // sanity check 523 if (hwc->getMultiDisplayObserver()->getVideoSessionNumber() != 524 (int)mVideoStateMap.size()) { 525 WTRACE("session number does not match!!"); 526 mVideoStateMap.clear(); 527 if (state != VIDEO_PLAYBACK_STOPPED) { 528 mVideoStateMap.add(instanceID, state); 529 } 530 } 531 532 // check if composition type needs to be reset 533 bool reset = false; 534 if ((state == VIDEO_PLAYBACK_STARTING) || 535 (state == VIDEO_PLAYBACK_STOPPING && mProtectedVideoSession)) { 536 // if video is in starting or stopping stage, overlay use is temporarily not allowed to 537 // avoid scrambed RGB overlay if video is protected. 538 mOverlayAllowed = false; 539 reset = true; 540 } else { 541 reset = !mOverlayAllowed; 542 mOverlayAllowed = true; 543 } 544 545 if (reset) { 546 hwc_display_contents_1_t *content = NULL; 547 for (int i = 0; i < (int)mCachedNumDisplays; i++) { 548 setCompositionType(i, HWC_FRAMEBUFFER, true); 549 } 550 } 551 552 if (mVideoStateMap.size() == 0) { 553 // reset active input state after video playback stops. 554 // MDS should update input state in 5 seconds after video playback starts 555 mActiveInputState = true; 556 } 557 558 if (mVideoStateMap.size() > 0) { 559 hwc->getPowerManager()->disableIdleControl(); 560 } else if (!hwc->getDrm()->isConnected(IDisplayDevice::DEVICE_EXTERNAL)) { 561 hwc->getPowerManager()->enableIdleControl(); 562 } 563 564 mProtectedVideoSession = false; 565 if (state == VIDEO_PLAYBACK_STARTED) { 566 VideoSourceInfo info; 567 hwc->getMultiDisplayObserver()->getVideoSourceInfo( 568 getFirstVideoInstanceSessionID(), &info); 569 mProtectedVideoSession = info.isProtected; 570 } 571 572 // Setting timing immediately, 573 // Don't posthone to next circle 574 handleTimingEvent(); 575 576 handleVideoCheckEvent(); 577} 578 579void DisplayAnalyzer::blankSecondaryDevice() 580{ 581 hwc_display_contents_1_t *content = NULL; 582 hwc_layer_1 *layer = NULL; 583 for (int i = 0; i < (int)mCachedNumDisplays; i++) { 584 if (i == IDisplayDevice::DEVICE_PRIMARY) { 585 continue; 586 } 587 content = mCachedDisplays[i]; 588 if (content == NULL) { 589 continue; 590 } 591 592 for (int j = 0; j < (int)content->numHwLayers - 1; j++) { 593 layer = &content->hwLayers[j]; 594 if (!layer) { 595 continue; 596 } 597 if (mBlankDevice) { 598 layer->hints |= HWC_HINT_CLEAR_FB; 599 layer->flags &= ~HWC_SKIP_LAYER; 600 layer->compositionType = HWC_OVERLAY; 601 } else { 602 layer->hints &= ~HWC_HINT_CLEAR_FB; 603 layer->compositionType = HWC_FRAMEBUFFER; 604 } 605 } 606 } 607} 608 609void DisplayAnalyzer::handleInputEvent(bool active) 610{ 611 if (active == mActiveInputState) { 612 WTRACE("same input state: %d", active); 613 } 614 mActiveInputState = active; 615 if (!mVideoExtModeEligible) { 616 ITRACE("not eligible for video extended mode"); 617 return; 618 } 619 620 if (active) { 621 exitVideoExtMode(); 622 } else { 623 enterVideoExtMode(); 624 } 625} 626 627void DisplayAnalyzer::handleDpmsEvent(int delayCount) 628{ 629 if (mActiveInputState || !mVideoExtModeEligible) { 630 ITRACE("aborting display power off in video extended mode"); 631 return; 632 } 633 634 if (delayCount < DELAY_BEFORE_DPMS_OFF) { 635 Event e; 636 e.type = DPMS_EVENT; 637 e.nValue = delayCount + 1; 638 postEvent(e); 639 Hwcomposer::getInstance().invalidate(); 640 return; 641 } 642 643 if (Hwcomposer::getInstance().getVsyncManager()->getVsyncSource() == 644 IDisplayDevice::DEVICE_PRIMARY) { 645 Hwcomposer::getInstance().getDrm()->setDpmsMode( 646 IDisplayDevice::DEVICE_PRIMARY, 647 IDisplayDevice::DEVICE_DISPLAY_STANDBY); 648 ETRACE("primary display is source of vsync, we only dim backlight"); 649 return; 650 } 651 652 // panel can't be powered off as touch panel shares the power supply with LCD. 653 DTRACE("primary display coupled with touch on Saltbay, only dim backlight"); 654 Hwcomposer::getInstance().getDrm()->setDpmsMode( 655 IDisplayDevice::DEVICE_PRIMARY, 656 IDisplayDevice::DEVICE_DISPLAY_STANDBY); 657 //IDisplayDevice::DEVICE_DISPLAY_OFF); 658 return; 659} 660 661 662void DisplayAnalyzer::handleIdleEntryEvent(int count) 663{ 664 DTRACE("handling idle entry event, count %d", count); 665 if (hasProtectedLayer()) { 666 ITRACE("Ignoring idle entry as protected layer exists."); 667 setCompositionType(0, HWC_FRAMEBUFFER, true); 668 return; 669 } 670 671 // stop idle entry if external device is connected 672 if (mCachedDisplays && mCachedDisplays[IDisplayDevice::DEVICE_EXTERNAL]) { 673 ITRACE("Ignoring idle entry as external device is connected."); 674 setCompositionType(0, HWC_FRAMEBUFFER, true); 675 return; 676 } 677 678 // stop idle entry if video playback is active 679 // TODO: remove this check for Annidale 680 if (mVideoStateMap.size() > 0) { 681 ITRACE("Ignoring idle entry as video session is active."); 682 setCompositionType(0, HWC_FRAMEBUFFER, true); 683 return; 684 } 685 686 setCompositionType(0, HWC_FORCE_FRAMEBUFFER, true); 687 688 IPowerManager *pm = Hwcomposer::getInstance().getPowerManager(); 689 if (count == 0) { 690 // ready to enter idel mode 691 pm->setIdleReady(); 692 } 693 694 if (count >= DELAY_BEFORE_IDLE_ENTRY) { 695 pm->enterIdleState(); 696 // next prepare/set will exit idle state. 697 Event e; 698 e.type = IDLE_EXIT_EVENT; 699 postEvent(e); 700 } else { 701 // invalidate surface flinger again 702 Event e; 703 e.type = IDLE_ENTRY_EVENT; 704 e.nValue = count + 1; 705 postEvent(e); 706 Hwcomposer::getInstance().invalidate(); 707 } 708} 709 710void DisplayAnalyzer::handleIdleExitEvent() 711{ 712 DTRACE("handling idle exit event"); 713 714 IPowerManager *pm = Hwcomposer::getInstance().getPowerManager(); 715 pm->exitIdleState(); 716 setCompositionType(0, HWC_FRAMEBUFFER, true); 717} 718 719void DisplayAnalyzer::handleVideoCheckEvent() 720{ 721 // check if the first seen video layer on secondary device (HDMI/WFD) is marked as skipped 722 // it is assumed video is always skipped if the first seen video layer is skipped 723 // this is to workaround secure video layer transmitted over non secure output 724 // and HWC_SKIP_LAYER set during rotation animation. 725 mIgnoreVideoSkipFlag = false; 726 727 if (mVideoStateMap.size() != 1 || 728 mCachedNumDisplays <= 1) { 729 return; 730 } 731 732 uint32_t videoHandles[mCachedNumDisplays]; 733 for (int i = 0; i < (int)mCachedNumDisplays; i++) { 734 videoHandles[i] = 0; 735 hwc_display_contents_1_t *content = mCachedDisplays[i]; 736 if (content == NULL) { 737 continue; 738 } 739 for (int j = 0; j < (int)content->numHwLayers - 1; j++) { 740 if (isVideoLayer(content->hwLayers[j])) { 741 videoHandles[i] = (uint32_t)content->hwLayers[j].handle; 742 if (i > 0) { 743 if (videoHandles[i] == videoHandles[0]) { 744 mIgnoreVideoSkipFlag = !(content->hwLayers[j].flags & HWC_SKIP_LAYER); 745 ITRACE("Ignoring video HWC_SKIP_LAYER: %d on output %d", mIgnoreVideoSkipFlag, i); 746 } 747 return; 748 } 749 break; 750 } 751 } 752 } 753 754 if (videoHandles[0]) { 755 WTRACE("Video is on the primary panel only"); 756 return; 757 } 758 759 // video state map indicates video session is active and there is secondary 760 // display, need to continue checking as video is not found in the buffers yet 761 Event e; 762 e.type = VIDEO_CHECK_EVENT; 763 postEvent(e); 764} 765 766void DisplayAnalyzer::enterVideoExtMode() 767{ 768 if (mVideoExtModeActive) { 769 WTRACE("already in video extended mode."); 770 return; 771 } 772 773 ITRACE("entering video extended mode..."); 774 mVideoExtModeActive = true; 775 Hwcomposer::getInstance().getVsyncManager()->resetVsyncSource(); 776 777 setCompositionType(0, HWC_OVERLAY, true); 778 779 // Do not power off primary display immediately as flip is asynchronous 780 Event e; 781 e.type = DPMS_EVENT; 782 e.nValue = 0; 783 postEvent(e); 784 Hwcomposer::getInstance().invalidate(); 785} 786 787void DisplayAnalyzer::exitVideoExtMode() 788{ 789 if (!mVideoExtModeActive) { 790 WTRACE("Not in video extended mode"); 791 return; 792 } 793 794 ITRACE("exiting video extended mode..."); 795 796 mVideoExtModeActive = false; 797 798 Hwcomposer::getInstance().getDrm()->setDpmsMode( 799 IDisplayDevice::DEVICE_PRIMARY, 800 IDisplayDevice::DEVICE_DISPLAY_ON); 801 802 Hwcomposer::getInstance().getVsyncManager()->resetVsyncSource(); 803 804 setCompositionType(0, HWC_FRAMEBUFFER, true); 805} 806 807bool DisplayAnalyzer::isPresentationLayer(hwc_layer_1_t &layer) 808{ 809 if (layer.handle == NULL) { 810 return false; 811 } 812 if (mCachedDisplays == NULL) { 813 return false; 814 } 815 // check if the given layer exists in the primary device 816 hwc_display_contents_1_t *content = mCachedDisplays[0]; 817 if (content == NULL) { 818 return false; 819 } 820 for (size_t i = 0; i < content->numHwLayers - 1; i++) { 821 if ((uint32_t)content->hwLayers[i].handle == (uint32_t)layer.handle) { 822 VTRACE("Layer exists for Primary device"); 823 return false; 824 } 825 } 826 return true; 827} 828 829bool DisplayAnalyzer::hasVideoLayer(int device) 830{ 831 DataBuffer * buffer = NULL; 832 hwc_display_contents_1_t *content = NULL; 833 834 if (mCachedDisplays == NULL) { 835 return false; 836 } 837 838 content = mCachedDisplays[device]; 839 if (content == NULL) { 840 return false; 841 } 842 843 for (size_t i = 0; i < content->numHwLayers - 1; i++) { 844 if (isVideoLayer(content->hwLayers[i])) 845 return true; 846 } 847 848 return false; 849} 850 851bool DisplayAnalyzer::hasProtectedLayer() 852{ 853 DataBuffer * buffer = NULL; 854 hwc_display_contents_1_t *content = NULL; 855 BufferManager *bm = Hwcomposer::getInstance().getBufferManager(); 856 857 if (bm == NULL){ 858 return false; 859 } 860 861 if (mCachedDisplays == NULL) { 862 return false; 863 } 864 // check if the given layer exists in the primary device 865 for (int index = 0; index < (int)mCachedNumDisplays; index++) { 866 content = mCachedDisplays[index]; 867 if (content == NULL) { 868 continue; 869 } 870 871 for (size_t i = 0; i < content->numHwLayers - 1; i++) { 872 if (isProtectedLayer(content->hwLayers[i])) 873 return true; 874 } 875 } 876 877 return false; 878} 879 880bool DisplayAnalyzer::isProtectedLayer(hwc_layer_1_t &layer) 881{ 882 if (!layer.handle) { 883 return false; 884 } 885 bool ret = false; 886 BufferManager *bm = Hwcomposer::getInstance().getBufferManager(); 887 DataBuffer *buffer = bm->lockDataBuffer((uint32_t)layer.handle); 888 if (!buffer) { 889 ETRACE("failed to get buffer"); 890 } else { 891 ret = GraphicBuffer::isProtectedBuffer((GraphicBuffer*)buffer); 892 bm->unlockDataBuffer(buffer); 893 } 894 return ret; 895} 896 897bool DisplayAnalyzer::ignoreVideoSkipFlag() 898{ 899 return mIgnoreVideoSkipFlag; 900} 901 902void DisplayAnalyzer::setCompositionType(hwc_display_contents_1_t *display, int type) 903{ 904 for (size_t i = 0; i < display->numHwLayers - 1; i++) { 905 hwc_layer_1_t *layer = &display->hwLayers[i]; 906 if (layer) layer->compositionType = type; 907 } 908} 909 910void DisplayAnalyzer::setCompositionType(int device, int type, bool reset) 911{ 912 hwc_display_contents_1_t *content = mCachedDisplays[device]; 913 if (content == NULL) { 914 ETRACE("Invalid device %d", device); 915 return; 916 } 917 918 // don't need to set geometry changed if layers are just needed to be marked 919 if (reset) { 920 content->flags |= HWC_GEOMETRY_CHANGED; 921 } 922 923 setCompositionType(content, type); 924} 925 926int DisplayAnalyzer::getFirstVideoInstanceSessionID() { 927 if (mVideoStateMap.size() >= 1) { 928 return mVideoStateMap.keyAt(0); 929 } 930 return -1; 931} 932 933} // namespace intel 934} // namespace android 935 936