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