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 #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