summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp')
-rw-r--r--services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp376
1 files changed, 376 insertions, 0 deletions
diff --git a/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp b/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp
new file mode 100644
index 0000000..96d4b1d
--- /dev/null
+++ b/services/surfaceflinger/ExSurfaceFlinger/ExSurfaceFlinger.cpp
@@ -0,0 +1,376 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ExSurfaceFlinger.h"
+#include "ExLayer.h"
+#include <fstream>
+#include <cutils/properties.h>
+#ifdef QTI_BSP
+#include <hardware/display_defs.h>
+#endif
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+namespace android {
+
+bool ExSurfaceFlinger::sExtendedMode = false;
+
+ExSurfaceFlinger::ExSurfaceFlinger() {
+ char property[PROPERTY_VALUE_MAX] = {0};
+
+ mDebugLogs = false;
+ if((property_get("persist.debug.qdframework.logs", property, NULL) > 0) &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+ (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ mDebugLogs = true;
+ }
+
+ ALOGD_IF(isDebug(),"Creating custom SurfaceFlinger %s",__FUNCTION__);
+
+ mDisableExtAnimation = false;
+ if((property_get("sys.disable_ext_animation", property, "0") > 0) &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+ (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ mDisableExtAnimation = true;
+ }
+
+ ALOGD_IF(isDebug(),"Animation on external is %s in %s",
+ mDisableExtAnimation ? "disabled" : "not disabled", __FUNCTION__);
+}
+
+ExSurfaceFlinger::~ExSurfaceFlinger() { }
+
+void ExSurfaceFlinger::updateExtendedMode() {
+ char prop[PROPERTY_VALUE_MAX];
+ property_get("sys.extended_mode", prop, "0");
+ sExtendedMode = atoi(prop) ? true : false;
+}
+
+void ExSurfaceFlinger::getIndexLOI(size_t dpy,
+ const LayerVector& currentLayers,
+ bool& bIgnoreLayers,
+ int& indexLOI ) {
+ size_t i = currentLayers.size();
+ while(i--) {
+ const sp<Layer>& layer = currentLayers[i];
+ /* iterate through the layer list to find ext_only layers and store
+ * the index
+ */
+ if (layer->isSecureDisplay()) {
+ bIgnoreLayers = true;
+ indexLOI = -1;
+ if(!dpy)
+ indexLOI = i;
+ break;
+ }
+ /* iterate through the layer list to find ext_only layers or yuv
+ * layer(extended_mode) and store the index
+ */
+ if ((dpy && (layer->isExtOnly() ||
+ (isExtendedMode() && layer->isYuvLayer())))) {
+ bIgnoreLayers= true;
+ indexLOI = i;
+ }
+ }
+ return;
+}
+
+bool ExSurfaceFlinger::updateLayerVisibleNonTransparentRegion(
+ const int& dpy, const sp<Layer>& layer,
+ bool& bIgnoreLayers, int& indexLOI,
+ uint32_t layerStack, const int& i) {
+
+ const Layer::State& s(layer->getDrawingState());
+
+ /* Only add the layer marked as "external_only" or yuvLayer
+ * (extended_mode) to external list and
+ * only remove the layer marked as "external_only" or yuvLayer in
+ * extended_mode from primary list
+ * and do not add the layer marked as "internal_only" to external list
+ * Add secure UI layers to primary and remove other layers from internal
+ * and external list
+ */
+ if(((bIgnoreLayers && indexLOI != (int)i) ||
+ (!dpy && layer->isExtOnly()) ||
+ (!dpy && isExtendedMode() && layer->isYuvLayer()))||
+ (dpy && layer->isIntOnly())) {
+ /* Ignore all other layers except the layers marked as ext_only
+ * by setting visible non transparent region empty
+ */
+ Region visibleNonTransRegion;
+ visibleNonTransRegion.set(Rect(0,0));
+ layer->setVisibleNonTransparentRegion(visibleNonTransRegion);
+ return true;
+ }
+ /* only consider the layers on the given later stack
+ * Override layers created using presentation class by the layers having
+ * ext_only flag enabled
+ */
+ if(s.layerStack != layerStack && !bIgnoreLayers) {
+ /* set the visible region as empty since we have removed the
+ * layerstack check in rebuildLayerStack() function
+ */
+ Region visibleNonTransRegion;
+ visibleNonTransRegion.set(Rect(0,0));
+ layer->setVisibleNonTransparentRegion(visibleNonTransRegion);
+ return true;
+ }
+
+ if (mDisableExtAnimation) {
+ /* Remove screenShotSurface from secondary displays when ext animation disabled */
+ const int screenShotLen = strlen("ScreenshotSurface");
+ if (dpy && !strncmp(layer->getName(), "ScreenshotSurface", screenShotLen) ) {
+ Region visibleNonTransRegion;
+ visibleNonTransRegion.set(Rect(0, 0));
+ layer->setVisibleNonTransparentRegion(visibleNonTransRegion);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void ExSurfaceFlinger::delayDPTransactionIfNeeded(
+ const Vector<DisplayState>& displays) {
+ /* Delay the display projection transaction by 50ms only when the disable
+ * external rotation animation feature is enabled
+ */
+ if(mDisableExtAnimation) {
+ size_t count = displays.size();
+ for (size_t i=0 ; i<count ; i++) {
+ const DisplayState& s(displays[i]);
+ if((mDisplays.indexOfKey(s.token) >= 0) && (s.token !=
+ mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])) {
+ const uint32_t what = s.what;
+ /* Invalidate and Delay the binder thread by 50 ms on
+ * eDisplayProjectionChanged to trigger a draw cycle so that
+ * it can fix one incorrect frame on the External, when we
+ * disable external animation
+ */
+ if (what & DisplayState::eDisplayProjectionChanged) {
+ invalidateHwcGeometry();
+ repaintEverything();
+ usleep(50000);
+ }
+ }
+ }
+ }
+}
+
+bool ExSurfaceFlinger::canDrawLayerinScreenShot(
+ const sp<const DisplayDevice>& hw,
+ const sp<Layer>& layer) {
+ int dispType = hw->getDisplayType();
+ /* a) Don't draw SecureDisplayLayer or ProtectedLayer.
+ * b) Don't let ext_only and extended_mode to be captured
+ * If not, we would see incorrect image during rotation
+ * on primary.
+ */
+ if(!layer->isSecureDisplay()
+ && !layer->isProtected()
+ && !(!dispType && (layer->isExtOnly() ||
+ (isExtendedMode() && layer->isYuvLayer())))
+ && !(layer->isIntOnly() && dispType)
+ && layer->isVisible()){
+ return true;
+ }
+ return false;
+}
+
+void ExSurfaceFlinger::isfreezeSurfacePresent(bool& freezeSurfacePresent,
+ const sp<const DisplayDevice>& hw,
+ const int32_t& id) {
+ freezeSurfacePresent = false;
+ /* Get the layers in the current drawing state */
+ const LayerVector& layers(mDrawingState.layersSortedByZ);
+ const size_t layerCount = layers.size();
+ /* Look for ScreenShotSurface in external layer list, only when
+ * disable external rotation animation feature is enabled
+ */
+ if(mDisableExtAnimation && (id != HWC_DISPLAY_PRIMARY)) {
+ for (size_t i = 0 ; i < layerCount ; ++i) {
+ static int screenShotLen = strlen("ScreenshotSurface");
+ const sp<Layer>& layer(layers[i]);
+ const Layer::State& s(layer->getDrawingState());
+ /* check the layers associated with external display */
+ if(s.layerStack == hw->getLayerStack()) {
+ if(!strncmp(layer->getName(), "ScreenshotSurface",
+ screenShotLen)) {
+ /* Screenshot layer is present, and animation in
+ * progress
+ */
+ freezeSurfacePresent = true;
+ break;
+ }
+ }
+ }
+ }
+}
+
+void ExSurfaceFlinger::setOrientationEventControl(bool& freezeSurfacePresent,
+ const int32_t& id) {
+ HWComposer& hwc(getHwComposer());
+ HWComposer::LayerListIterator cur = hwc.begin(id);
+
+ if(freezeSurfacePresent) {
+ /* If freezeSurfacePresent, set ANIMATING flag
+ * which is used to support disable animation on external
+ */
+ cur->setAnimating(true);
+ }
+}
+
+void ExSurfaceFlinger::updateVisibleRegionsDirty() {
+ /* If extended_mode is set, and set mVisibleRegionsDirty
+ * as we need to rebuildLayerStack
+ */
+ if(isExtendedMode()) {
+ mVisibleRegionsDirty = true;
+ }
+}
+
+void ExSurfaceFlinger::drawWormHoleIfRequired(HWComposer::LayerListIterator& cur,
+ const HWComposer::LayerListIterator& end,
+ const sp<const DisplayDevice>& hw,
+ const Region& region) {
+ if (cur != end) {
+#ifdef QTI_BSP
+ if (cur->getCompositionType() != HWC_BLIT)
+ drawWormhole(hw, region);
+#endif
+ } else {
+ drawWormhole(hw, region);
+ }
+}
+
+#ifdef DEBUG_CONT_DUMPSYS
+status_t ExSurfaceFlinger::dump(int fd, const Vector<String16>& args) {
+ // Format: adb shell dumpsys SurfaceFlinger --file --no-limit
+ size_t numArgs = args.size();
+ status_t err = NO_ERROR;
+
+ if (!numArgs || (args[0] != String16("--file"))) {
+ return SurfaceFlinger::dump(fd, args);
+ }
+
+ Mutex::Autolock _l(mFileDump.lock);
+
+ // Same command is used to start and end dump.
+ mFileDump.running = !mFileDump.running;
+
+ if (mFileDump.running) {
+ // Create an empty file or erase existing file.
+ std::fstream fs;
+ fs.open(mFileDump.name, std::ios::out);
+ if (!fs) {
+ mFileDump.running = false;
+ err = UNKNOWN_ERROR;
+ } else {
+ mFileDump.position = 0;
+ if (numArgs >= 2 && (args[1] == String16("--nolimit"))) {
+ mFileDump.noLimit = true;
+ } else {
+ mFileDump.noLimit = false;
+ }
+ }
+ }
+
+ String8 result;
+ result += mFileDump.running ? "Start" : "End";
+ result += mFileDump.noLimit ? " unlimited" : " fixed limit";
+ result += " dumpsys to file : ";
+ result += mFileDump.name;
+ result += "\n";
+
+ write(fd, result.string(), result.size());
+
+ return NO_ERROR;
+}
+
+void ExSurfaceFlinger::dumpDrawCycle(bool prePrepare) {
+ Mutex::Autolock _l(mFileDump.lock);
+
+ // User might stop dump collection in middle of prepare & commit.
+ // Collect dumpsys again after commit and replace.
+ if (!mFileDump.running && !mFileDump.replaceAfterCommit) {
+ return;
+ }
+
+ Vector<String16> args;
+ size_t index = 0;
+ String8 dumpsys;
+
+ dumpAllLocked(args, index, dumpsys);
+
+ char timeStamp[32];
+ char dataSize[32];
+ char hms[32];
+ long millis;
+ struct timeval tv;
+ struct tm *ptm;
+
+ gettimeofday(&tv, NULL);
+ ptm = localtime(&tv.tv_sec);
+ strftime (hms, sizeof (hms), "%H:%M:%S", ptm);
+ millis = tv.tv_usec / 1000;
+ snprintf(timeStamp, sizeof(timeStamp), "Timestamp: %s.%03ld", hms, millis);
+ snprintf(dataSize, sizeof(dataSize), "Size: %8zu", dumpsys.size());
+
+ std::fstream fs;
+ fs.open(mFileDump.name, std::ios::in | std::ios::out);
+ if (!fs) {
+ ALOGE("Failed to open %s file for dumpsys", mFileDump.name);
+ return;
+ }
+
+ // Format:
+ // | start code | after commit? | time stamp | dump size | dump data |
+ fs.seekp(mFileDump.position, std::ios::beg);
+
+ fs << "#@#@-- DUMPSYS START --@#@#" << std::endl;
+ fs << "PostCommit: " << ( prePrepare ? "false" : "true" ) << std::endl;
+ fs << timeStamp << std::endl;
+ fs << dataSize << std::endl;
+ fs << dumpsys << std::endl;
+
+ if (prePrepare) {
+ mFileDump.replaceAfterCommit = true;
+ } else {
+ mFileDump.replaceAfterCommit = false;
+ // Reposition only after commit.
+ // Keem file size to appx 20 MB limit by default, wrap around if exceeds.
+ mFileDump.position = fs.tellp();
+ if (!mFileDump.noLimit && (mFileDump.position > (20 * 1024 * 1024))) {
+ mFileDump.position = 0;
+ }
+ }
+
+ fs.close();
+}
+#endif
+
+}; // namespace android