Home | History | Annotate | Download | only in base
      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