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