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