• Home
  • History
  • Annotate
  • 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  #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