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