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