1 /*
2 // Copyright (c) 2014 Intel Corporation 
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
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 
DisplayAnalyzer()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 
~DisplayAnalyzer()50 DisplayAnalyzer::~DisplayAnalyzer()
51 {
52 }
53 
initialize()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 
deinitialize()77 void DisplayAnalyzer::deinitialize()
78 {
79     mPendingEvents.clear();
80     mVideoStateMap.clear();
81     mInitialized = false;
82 }
83 
analyzeContents(size_t numDisplays,hwc_display_contents_1_t ** displays)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 
handleVideoExtMode()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 
checkVideoExtMode()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 
isVideoExtModeActive()231 bool DisplayAnalyzer::isVideoExtModeActive()
232 {
233     return mVideoExtModeActive;
234 }
235 
isVideoExtModeEnabled()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 
isVideoLayer(hwc_layer_1_t & layer)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 
isVideoFullScreen(int device,hwc_layer_1_t & layer)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 
isOverlayAllowed()300 bool DisplayAnalyzer::isOverlayAllowed()
301 {
302     return mOverlayAllowed;
303 }
304 
getVideoInstances()305 int DisplayAnalyzer::getVideoInstances()
306 {
307     return (int)mVideoStateMap.size();
308 }
309 
postHotplugEvent(bool connected)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 
postVideoEvent(int instanceID,int state)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 
postBlankEvent(bool blank)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 
postInputEvent(bool active)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 
postIdleEntryEvent(void)371 void DisplayAnalyzer::postIdleEntryEvent(void)
372 {
373     Event e;
374     e.type = IDLE_ENTRY_EVENT;
375     e.nValue = 0;
376     postEvent(e);
377 }
378 
postEvent(Event & e)379 void DisplayAnalyzer::postEvent(Event& e)
380 {
381     Mutex::Autolock lock(mEventMutex);
382     mPendingEvents.add(e);
383 }
384 
getEvent(Event & e)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 
handlePendingEvents()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 
handleHotplugEvent(bool connected)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 
handleBlankEvent(bool blank)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 
handleTimingEvent()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 
handleVideoEvent(int instanceID,int state)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 
blankSecondaryDevice()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 
handleInputEvent(bool active)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 
handleDpmsEvent(int delayCount)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 
handleIdleEntryEvent(int count)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 
handleIdleExitEvent()699 void DisplayAnalyzer::handleIdleExitEvent()
700 {
701     DTRACE("handling idle exit event");
702 
703     setCompositionType(0, HWC_FRAMEBUFFER, true);
704 }
705 
handleVideoCheckEvent()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 
enterVideoExtMode()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 
exitVideoExtMode()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 
isPresentationLayer(hwc_layer_1_t & layer)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 
hasProtectedLayer()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 
isProtectedLayer(hwc_layer_1_t & layer)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 
ignoreVideoSkipFlag()860 bool DisplayAnalyzer::ignoreVideoSkipFlag()
861 {
862     return mIgnoreVideoSkipFlag;
863 }
864 
setCompositionType(hwc_display_contents_1_t * display,int type)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 
setCompositionType(int device,int type,bool reset)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 
getFirstVideoInstanceSessionID()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