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