diff options
| -rw-r--r-- | libs/binder/Parcel.cpp | 4 | ||||
| -rw-r--r-- | libs/binder/Status.cpp | 31 | ||||
| -rw-r--r-- | libs/graphicsenv/GraphicsEnv.cpp | 111 | ||||
| -rw-r--r-- | libs/graphicsenv/include/graphicsenv/GraphicsEnv.h | 1 | ||||
| -rw-r--r-- | opengl/libs/Android.bp | 4 | ||||
| -rw-r--r-- | opengl/libs/EGL/Loader.cpp | 88 | ||||
| -rw-r--r-- | opengl/libs/EGL/Loader.h | 1 | ||||
| -rw-r--r-- | opengl/libs/EGL/egl.cpp | 10 | ||||
| -rw-r--r-- | opengl/libs/EGL/egl_display.cpp | 2 | ||||
| -rw-r--r-- | opengl/libs/EGL/egldefs.h | 7 | ||||
| -rw-r--r-- | services/surfaceflinger/BufferLayer.cpp | 6 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.cpp | 59 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.h | 23 | ||||
| -rw-r--r-- | services/surfaceflinger/RegionSamplingThread.cpp | 4 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/SurfaceFlinger_test.filter | 2 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/Transaction_test.cpp | 176 |
16 files changed, 444 insertions, 85 deletions
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index d5cdf07444..afa3d33349 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -2086,8 +2086,8 @@ status_t Parcel::readUtf8FromUtf16(std::unique_ptr<std::string>* str) const { const char* Parcel::readCString() const { - const size_t avail = mDataSize-mDataPos; - if (avail > 0) { + if (mDataPos < mDataSize) { + const size_t avail = mDataSize-mDataPos; const char* str = reinterpret_cast<const char*>(mData+mDataPos); // is the string's trailing NUL within the parcel's valid bounds? const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail)); diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp index 8b33a56484..0ad99cee3f 100644 --- a/libs/binder/Status.cpp +++ b/libs/binder/Status.cpp @@ -102,13 +102,23 @@ status_t Status::readFromParcel(const Parcel& parcel) { // Skip over fat response headers. Not used (or propagated) in native code. if (mException == EX_HAS_REPLY_HEADER) { // Note that the header size includes the 4 byte size field. - const int32_t header_start = parcel.dataPosition(); + const size_t header_start = parcel.dataPosition(); + // Get available size before reading more + const size_t header_avail = parcel.dataAvail(); + int32_t header_size; status = parcel.readInt32(&header_size); if (status != OK) { setFromStatusT(status); return status; } + + if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) { + android_errorWriteLog(0x534e4554, "132650049"); + setFromStatusT(UNKNOWN_ERROR); + return UNKNOWN_ERROR; + } + parcel.setDataPosition(header_start + header_size); // And fat response headers are currently only used when there are no // exceptions, so act like there was no error. @@ -135,19 +145,36 @@ status_t Status::readFromParcel(const Parcel& parcel) { setFromStatusT(status); return status; } + if (remote_stack_trace_header_size < 0 || + static_cast<size_t>(remote_stack_trace_header_size) > parcel.dataAvail()) { + + android_errorWriteLog(0x534e4554, "132650049"); + setFromStatusT(UNKNOWN_ERROR); + return UNKNOWN_ERROR; + } parcel.setDataPosition(parcel.dataPosition() + remote_stack_trace_header_size); if (mException == EX_SERVICE_SPECIFIC) { status = parcel.readInt32(&mErrorCode); } else if (mException == EX_PARCELABLE) { // Skip over the blob of Parcelable data - const int32_t header_start = parcel.dataPosition(); + const size_t header_start = parcel.dataPosition(); + // Get available size before reading more + const size_t header_avail = parcel.dataAvail(); + int32_t header_size; status = parcel.readInt32(&header_size); if (status != OK) { setFromStatusT(status); return status; } + + if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) { + android_errorWriteLog(0x534e4554, "132650049"); + setFromStatusT(UNKNOWN_ERROR); + return UNKNOWN_ERROR; + } + parcel.setDataPosition(header_start + header_size); } if (status != OK) { diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp index 407f77d88b..1c5fa52855 100644 --- a/libs/graphicsenv/GraphicsEnv.cpp +++ b/libs/graphicsenv/GraphicsEnv.cpp @@ -534,60 +534,73 @@ void GraphicsEnv::setDebugLayersGLES(const std::string layers) { mDebugLayersGLES = layers; } +// Return true if all the required libraries from vndk and sphal namespace are +// linked to the Game Driver namespace correctly. +bool GraphicsEnv::linkDriverNamespaceLocked(android_namespace_t* vndkNamespace) { + const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK); + if (llndkLibraries.empty()) { + return false; + } + if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) { + ALOGE("Failed to link default namespace[%s]", dlerror()); + return false; + } + + const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP); + if (vndkspLibraries.empty()) { + return false; + } + if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) { + ALOGE("Failed to link vndk namespace[%s]", dlerror()); + return false; + } + + if (mSphalLibraries.empty()) { + return true; + } + + // Make additional libraries in sphal to be accessible + auto sphalNamespace = android_get_exported_namespace("sphal"); + if (!sphalNamespace) { + ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace", + mSphalLibraries.c_str()); + return false; + } + + if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) { + ALOGE("Failed to link sphal namespace[%s]", dlerror()); + return false; + } + + return true; +} + android_namespace_t* GraphicsEnv::getDriverNamespace() { - static std::once_flag once; - std::call_once(once, [this]() { - if (mDriverPath.empty()) return; - - auto vndkNamespace = android_get_exported_namespace("vndk"); - if (!vndkNamespace) return; - - mDriverNamespace = android_create_namespace("gfx driver", - mDriverPath.c_str(), // ld_library_path - mDriverPath.c_str(), // default_library_path - ANDROID_NAMESPACE_TYPE_ISOLATED, - nullptr, // permitted_when_isolated_path - nullptr); - - const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK); - if (llndkLibraries.empty()) { - mDriverNamespace = nullptr; - return; - } - if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) { - ALOGE("Failed to link default namespace[%s]", dlerror()); - mDriverNamespace = nullptr; - return; - } + std::lock_guard<std::mutex> lock(mNamespaceMutex); - const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP); - if (vndkspLibraries.empty()) { - mDriverNamespace = nullptr; - return; - } - if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) { - ALOGE("Failed to link vndk namespace[%s]", dlerror()); - mDriverNamespace = nullptr; - return; - } + if (mDriverNamespace) { + return mDriverNamespace; + } - if (mSphalLibraries.empty()) return; + if (mDriverPath.empty()) { + return nullptr; + } - // Make additional libraries in sphal to be accessible - auto sphalNamespace = android_get_exported_namespace("sphal"); - if (!sphalNamespace) { - ALOGE("Depend on these libraries[%s] in sphal, but failed to get sphal namespace", - mSphalLibraries.c_str()); - mDriverNamespace = nullptr; - return; - } + auto vndkNamespace = android_get_exported_namespace("vndk"); + if (!vndkNamespace) { + return nullptr; + } - if (!android_link_namespaces(mDriverNamespace, sphalNamespace, mSphalLibraries.c_str())) { - ALOGE("Failed to link sphal namespace[%s]", dlerror()); - mDriverNamespace = nullptr; - return; - } - }); + mDriverNamespace = android_create_namespace("gfx driver", + mDriverPath.c_str(), // ld_library_path + mDriverPath.c_str(), // default_library_path + ANDROID_NAMESPACE_TYPE_ISOLATED, + nullptr, // permitted_when_isolated_path + nullptr); + + if (!linkDriverNamespaceLocked(vndkNamespace)) { + mDriverNamespace = nullptr; + } return mDriverNamespace; } diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h index 7d627500fd..f5d19db493 100644 --- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h +++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h @@ -129,6 +129,7 @@ private: void* loadLibrary(std::string name); bool checkAngleRules(void* so); void updateUseAngle(); + bool linkDriverNamespaceLocked(android_namespace_t* vndkNamespace); GraphicsEnv() = default; std::string mDriverPath; diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp index c0bace8486..abc7a72716 100644 --- a/opengl/libs/Android.bp +++ b/opengl/libs/Android.bp @@ -208,6 +208,10 @@ cc_library_shared { defaults: ["gles_libs_defaults"], srcs: ["GLES2/gl2.cpp"], cflags: ["-DLOG_TAG=\"libGLESv2\""], + + // Bug: http://b/133874658 Disable native_coverage as we investigate a + // crash in surfaceflinger on coverage-enabled cuttlefish builds. + native_coverage: false, } //############################################################################## diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp index d5c46c6683..038a432337 100644 --- a/opengl/libs/EGL/Loader.cpp +++ b/opengl/libs/EGL/Loader.cpp @@ -84,6 +84,11 @@ static void* do_android_load_sphal_library(const char* path, int mode) { return android_load_sphal_library(path, mode); } +static int do_android_unload_sphal_library(void* dso) { + ATRACE_CALL(); + return android_unload_sphal_library(dso); +} + Loader::driver_t::driver_t(void* gles) { dso[0] = gles; @@ -180,11 +185,81 @@ static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = { "ro.board.platform", }; +static bool should_unload_system_driver(egl_connection_t* cnx) { + // Return false if the system driver has been unloaded once. + if (cnx->systemDriverUnloaded) { + return false; + } + + // Return true if Angle namespace is set. + android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace(); + if (ns) { + return true; + } + +#ifndef __ANDROID_VNDK__ + // Return true if updated driver namespace is set. + ns = android::GraphicsEnv::getInstance().getDriverNamespace(); + if (ns) { + return true; + } +#endif + + return false; +} + +static void uninit_api(char const* const* api, __eglMustCastToProperFunctionPointerType* curr) { + while (*api) { + *curr++ = nullptr; + api++; + } +} + +void Loader::unload_system_driver(egl_connection_t* cnx) { + ATRACE_CALL(); + + uninit_api(gl_names, + (__eglMustCastToProperFunctionPointerType*)&cnx + ->hooks[egl_connection_t::GLESv2_INDEX] + ->gl); + uninit_api(gl_names, + (__eglMustCastToProperFunctionPointerType*)&cnx + ->hooks[egl_connection_t::GLESv1_INDEX] + ->gl); + uninit_api(egl_names, (__eglMustCastToProperFunctionPointerType*)&cnx->egl); + + if (cnx->dso) { + ALOGD("Unload system gl driver."); + driver_t* hnd = (driver_t*)cnx->dso; + if (hnd->dso[2]) { + do_android_unload_sphal_library(hnd->dso[2]); + } + if (hnd->dso[1]) { + do_android_unload_sphal_library(hnd->dso[1]); + } + if (hnd->dso[0]) { + do_android_unload_sphal_library(hnd->dso[0]); + } + cnx->dso = nullptr; + } + + cnx->systemDriverUnloaded = true; +} + void* Loader::open(egl_connection_t* cnx) { ATRACE_CALL(); const nsecs_t openTime = systemTime(); + if (should_unload_system_driver(cnx)) { + unload_system_driver(cnx); + } + + // If a driver has been loaded, return the driver directly. + if (cnx->dso) { + return cnx->dso; + } + setEmulatorGlesValue(); // Check if we should use ANGLE early, so loading each driver doesn't require repeated queries. @@ -244,9 +319,15 @@ void* Loader::open(egl_connection_t* cnx) "couldn't find an OpenGL ES implementation, make sure you set %s or %s", HAL_SUBNAME_KEY_PROPERTIES[0], HAL_SUBNAME_KEY_PROPERTIES[1]); - cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so"); - cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so"); - cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so"); + if (!cnx->libEgl) { + cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so"); + } + if (!cnx->libGles1) { + cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so"); + } + if (!cnx->libGles2) { + cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so"); + } if (!cnx->libEgl || !cnx->libGles2 || !cnx->libGles1) { android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL, @@ -584,6 +665,7 @@ Loader::driver_t* Loader::attempt_to_load_updated_driver(egl_connection_t* cnx) return nullptr; } + ALOGD("Load updated gl driver."); android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL_UPDATED); driver_t* hnd = nullptr; void* dso = load_updated_driver("GLES", ns); diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h index 0292d02e1d..6f31ab4741 100644 --- a/opengl/libs/EGL/Loader.h +++ b/opengl/libs/EGL/Loader.h @@ -58,6 +58,7 @@ private: driver_t* attempt_to_load_angle(egl_connection_t* cnx); driver_t* attempt_to_load_updated_driver(egl_connection_t* cnx); driver_t* attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix, const bool exact); + void unload_system_driver(egl_connection_t* cnx); void initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask); static __attribute__((noinline)) diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp index 8870d5f571..25b1009ba2 100644 --- a/opengl/libs/EGL/egl.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -187,13 +187,9 @@ static EGLBoolean egl_init_drivers_locked() { // dynamically load our EGL implementation egl_connection_t* cnx = &gEGLImpl; - if (cnx->dso == nullptr) { - cnx->hooks[egl_connection_t::GLESv1_INDEX] = - &gHooks[egl_connection_t::GLESv1_INDEX]; - cnx->hooks[egl_connection_t::GLESv2_INDEX] = - &gHooks[egl_connection_t::GLESv2_INDEX]; - cnx->dso = loader.open(cnx); - } + cnx->hooks[egl_connection_t::GLESv1_INDEX] = &gHooks[egl_connection_t::GLESv1_INDEX]; + cnx->hooks[egl_connection_t::GLESv2_INDEX] = &gHooks[egl_connection_t::GLESv2_INDEX]; + cnx->dso = loader.open(cnx); // Check to see if any layers are enabled and route functions through them if (cnx->dso) { diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp index 8841a3b02c..67d69b4d06 100644 --- a/opengl/libs/EGL/egl_display.cpp +++ b/opengl/libs/EGL/egl_display.cpp @@ -217,7 +217,7 @@ EGLDisplay egl_display_t::getPlatformDisplay(EGLNativeDisplayType display, Loader& loader(Loader::getInstance()); egl_connection_t* const cnx = &gEGLImpl; - if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) { + if (cnx->dso) { EGLDisplay dpy = EGL_NO_DISPLAY; if (cnx->useAngle) { diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h index 9e112cc034..7bb9b59ea4 100644 --- a/opengl/libs/EGL/egldefs.h +++ b/opengl/libs/EGL/egldefs.h @@ -44,7 +44,11 @@ struct egl_connection_t { GLESv2_INDEX = 1 }; - inline egl_connection_t() : dso(nullptr) { + inline egl_connection_t() : dso(nullptr), + libEgl(nullptr), + libGles1(nullptr), + libGles2(nullptr), + systemDriverUnloaded(false) { char const* const* entries = platform_names; EGLFuncPointer* curr = reinterpret_cast<EGLFuncPointer*>(&platform); @@ -76,6 +80,7 @@ struct egl_connection_t { void* libGles1; void* libGles2; + bool systemDriverUnloaded; bool shouldUseAngle; // Should we attempt to load ANGLE bool angleDecided; // Have we tried to load ANGLE bool useAngle; // Was ANGLE successfully loaded diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index a2b6ab6b4d..9d723998c4 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -545,6 +545,12 @@ void BufferLayer::notifyAvailableFrames() { if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled && presentTimeIsCurrent) { point->setFrameAvailable(); + sp<Layer> requestedSyncLayer = point->getRequestedSyncLayer(); + if (requestedSyncLayer) { + // Need to update the transaction flag to ensure the layer's pending transaction + // gets applied. + requestedSyncLayer->setTransactionFlags(eTransactionNeeded); + } } } } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 379b004f9e..898f3bc992 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -144,28 +144,47 @@ Layer::~Layer() { */ void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {} -void Layer::onRemovedFromCurrentState() { - mRemovedFromCurrentState = true; +void Layer::removeRemoteSyncPoints() { + for (auto& point : mRemoteSyncPoints) { + point->setTransactionApplied(); + } + mRemoteSyncPoints.clear(); - // the layer is removed from SF mCurrentState to mLayersPendingRemoval - if (mCurrentState.zOrderRelativeOf != nullptr) { - sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote(); - if (strongRelative != nullptr) { - strongRelative->removeZOrderRelative(this); - mFlinger->setTransactionFlags(eTraversalNeeded); + { + Mutex::Autolock pendingStateLock(mPendingStateMutex); + for (State pendingState : mPendingStates) { + pendingState.barrierLayer_legacy = nullptr; } + } +} + +void Layer::removeRelativeZ(const std::vector<Layer*>& layersInTree) { + if (mCurrentState.zOrderRelativeOf == nullptr) { + return; + } + + sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote(); + if (strongRelative == nullptr) { setZOrderRelativeOf(nullptr); + return; } + if (!std::binary_search(layersInTree.begin(), layersInTree.end(), strongRelative.get())) { + strongRelative->removeZOrderRelative(this); + mFlinger->setTransactionFlags(eTraversalNeeded); + setZOrderRelativeOf(nullptr); + } +} + +void Layer::removeFromCurrentState() { + mRemovedFromCurrentState = true; + // Since we are no longer reachable from CurrentState SurfaceFlinger // will no longer invoke doTransaction for us, and so we will // never finish applying transactions. We signal the sync point // now so that another layer will not become indefinitely // blocked. - for (auto& point: mRemoteSyncPoints) { - point->setTransactionApplied(); - } - mRemoteSyncPoints.clear(); + removeRemoteSyncPoints(); { Mutex::Autolock syncLock(mLocalSyncPointMutex); @@ -175,13 +194,18 @@ void Layer::onRemovedFromCurrentState() { mLocalSyncPoints.clear(); } - for (const auto& child : mCurrentChildren) { - child->onRemovedFromCurrentState(); - } - mFlinger->markLayerPendingRemovalLocked(this); } +void Layer::onRemovedFromCurrentState() { + auto layersInTree = getLayersInTree(LayerVector::StateSet::Current); + std::sort(layersInTree.begin(), layersInTree.end()); + for (const auto& layer : layersInTree) { + layer->removeFromCurrentState(); + layer->removeRelativeZ(layersInTree); + } +} + void Layer::addToCurrentState() { mRemovedFromCurrentState = false; @@ -667,7 +691,7 @@ void Layer::pushPendingState() { // to be applied as per normal (no synchronization). mCurrentState.barrierLayer_legacy = nullptr; } else { - auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy); + auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy, this); if (barrierLayer->addSyncPoint(syncPoint)) { mRemoteSyncPoints.push_back(std::move(syncPoint)); } else { @@ -1510,6 +1534,7 @@ bool Layer::detachChildren() { if (client != nullptr && parentClient != client) { child->mLayerDetached = true; child->detachChildren(); + child->removeRemoteSyncPoints(); } } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 3712b2aff9..5c55111b40 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -571,6 +571,17 @@ public: virtual bool isBufferLatched() const { return false; } /* + * Remove relative z for the layer if its relative parent is not part of the + * provided layer tree. + */ + void removeRelativeZ(const std::vector<Layer*>& layersInTree); + + /* + * Remove from current state and mark for removal. + */ + void removeFromCurrentState(); + + /* * called with the state lock from a binder thread when the layer is * removed from the current list to the pending removal list */ @@ -733,8 +744,11 @@ protected: class SyncPoint { public: - explicit SyncPoint(uint64_t frameNumber) - : mFrameNumber(frameNumber), mFrameIsAvailable(false), mTransactionIsApplied(false) {} + explicit SyncPoint(uint64_t frameNumber, wp<Layer> requestedSyncLayer) + : mFrameNumber(frameNumber), + mFrameIsAvailable(false), + mTransactionIsApplied(false), + mRequestedSyncLayer(requestedSyncLayer) {} uint64_t getFrameNumber() const { return mFrameNumber; } @@ -746,10 +760,13 @@ protected: void setTransactionApplied() { mTransactionIsApplied = true; } + sp<Layer> getRequestedSyncLayer() { return mRequestedSyncLayer.promote(); } + private: const uint64_t mFrameNumber; std::atomic<bool> mFrameIsAvailable; std::atomic<bool> mTransactionIsApplied; + wp<Layer> mRequestedSyncLayer; }; // SyncPoints which will be signaled when the correct frame is at the head @@ -928,6 +945,8 @@ private: void setZOrderRelativeOf(const wp<Layer>& relativeOf); bool mGetHandleCalled = false; + + void removeRemoteSyncPoints(); }; } // namespace android diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 7fa33f597c..66906e950c 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -280,6 +280,10 @@ float sampleArea(const uint32_t* data, int32_t width, int32_t height, int32_t st area.top = height - area.top; area.bottom = height - area.bottom; std::swap(area.top, area.bottom); + + area.left = width - area.left; + area.right = width - area.right; + std::swap(area.left, area.right); } std::array<int32_t, 256> brightnessBuckets = {}; diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter index 5ebae1e522..6b4634ae76 100644 --- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter +++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter @@ -1,5 +1,5 @@ { "presubmit": { - "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*:InvalidHandleTest.*:VirtualDisplayTest.*" + "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*:InvalidHandleTest.*:VirtualDisplayTest.*:RelativeZTest.*" } } diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index ec1ac4b229..f83b3eafe6 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -385,6 +385,18 @@ protected: return createLayer(mClient, name, width, height, flags, parent); } + sp<SurfaceControl> createColorLayer(const char* name, const Color& color, + SurfaceControl* parent = nullptr) { + auto colorLayer = createSurface(mClient, name, 0 /* buffer width */, 0 /* buffer height */, + PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, parent); + asTransaction([&](Transaction& t) { + t.setColor(colorLayer, half3{color.r / 255.0f, color.g / 255.0f, color.b / 255.0f}); + t.setAlpha(colorLayer, color.a / 255.0f); + }); + return colorLayer; + } + ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) { // wait for previous transactions (such as setSize) to complete Transaction().apply(true); @@ -4725,6 +4737,48 @@ TEST_F(ChildLayerTest, DetachChildrenThenAttach) { mCapture->expectColor(Rect(20, 20, 52, 52), Color::RED); } } +TEST_F(ChildLayerTest, DetachChildrenWithDeferredTransaction) { + sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient; + sp<SurfaceControl> childNewClient = + newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + + ASSERT_TRUE(childNewClient != nullptr); + ASSERT_TRUE(childNewClient->isValid()); + + fillSurfaceRGBA8(childNewClient, 200, 200, 200); + + Transaction() + .hide(mChild) + .show(childNewClient) + .setPosition(childNewClient, 10, 10) + .setPosition(mFGSurfaceControl, 64, 64) + .apply(); + + { + mCapture = screenshot(); + Rect rect = Rect(74, 74, 84, 84); + mCapture->expectBorder(rect, Color{195, 63, 63, 255}); + mCapture->expectColor(rect, Color{200, 200, 200, 255}); + } + + Transaction() + .deferTransactionUntil_legacy(childNewClient, mFGSurfaceControl->getHandle(), + mFGSurfaceControl->getSurface()->getNextFrameNumber()) + .apply(); + Transaction().detachChildren(mFGSurfaceControl).apply(); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mFGSurfaceControl, Color::RED, 32, 32)); + + // BufferLayer can still dequeue buffers even though there's a detached layer with a + // deferred transaction. + { + SCOPED_TRACE("new buffer"); + mCapture = screenshot(); + Rect rect = Rect(74, 74, 84, 84); + mCapture->expectBorder(rect, Color::RED); + mCapture->expectColor(rect, Color{200, 200, 200, 255}); + } +} TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) { asTransaction([&](Transaction& t) { @@ -5833,4 +5887,126 @@ TEST_F(DisplayActiveConfigTest, changeAllowedConfig) { allowedConfigs.end()); } +class RelativeZTest : public LayerTransactionTest { +protected: + virtual void SetUp() { + LayerTransactionTest::SetUp(); + ASSERT_EQ(NO_ERROR, mClient->initCheck()); + + const auto display = SurfaceComposerClient::getInternalDisplayToken(); + ASSERT_FALSE(display == nullptr); + + // Back layer + mBackgroundLayer = createColorLayer("Background layer", Color::RED); + + // Front layer + mForegroundLayer = createColorLayer("Foreground layer", Color::GREEN); + + asTransaction([&](Transaction& t) { + t.setDisplayLayerStack(display, 0); + t.setLayer(mBackgroundLayer, INT32_MAX - 2).show(mBackgroundLayer); + t.setLayer(mForegroundLayer, INT32_MAX - 1).show(mForegroundLayer); + }); + } + + virtual void TearDown() { + LayerTransactionTest::TearDown(); + mBackgroundLayer = 0; + mForegroundLayer = 0; + } + + sp<SurfaceControl> mBackgroundLayer; + sp<SurfaceControl> mForegroundLayer; +}; + +// When a layer is reparented offscreen, remove relative z order if the relative parent +// is still onscreen so that the layer is not drawn. +TEST_F(RelativeZTest, LayerRemoved) { + std::unique_ptr<ScreenCapture> sc; + + // Background layer (RED) + // Child layer (WHITE) (relative to foregroud layer) + // Foregroud layer (GREEN) + sp<SurfaceControl> childLayer = + createColorLayer("Child layer", Color::BLUE, mBackgroundLayer.get()); + + Transaction{} + .setRelativeLayer(childLayer, mForegroundLayer->getHandle(), 1) + .show(childLayer) + .apply(); + + { + // The childLayer should be in front of the FG control. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b); + } + + // Background layer (RED) + // Foregroud layer (GREEN) + Transaction{}.reparent(childLayer, nullptr).apply(); + + // Background layer (RED) + // Child layer (WHITE) + // Foregroud layer (GREEN) + Transaction{}.reparent(childLayer, mBackgroundLayer->getHandle()).apply(); + + { + // The relative z info for child layer should be reset, leaving FG control on top. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); + } +} + +// When a layer is reparented offscreen, preseve relative z order if the relative parent +// is also offscreen. Regression test b/132613412 +TEST_F(RelativeZTest, LayerRemovedOffscreenRelativeParent) { + std::unique_ptr<ScreenCapture> sc; + + // Background layer (RED) + // Foregroud layer (GREEN) + // child level 1 (WHITE) + // child level 2a (BLUE) + // child level 3 (GREEN) (relative to child level 2b) + // child level 2b (BLACK) + sp<SurfaceControl> childLevel1 = + createColorLayer("child level 1", Color::WHITE, mForegroundLayer.get()); + sp<SurfaceControl> childLevel2a = + createColorLayer("child level 2a", Color::BLUE, childLevel1.get()); + sp<SurfaceControl> childLevel2b = + createColorLayer("child level 2b", Color::BLACK, childLevel1.get()); + sp<SurfaceControl> childLevel3 = + createColorLayer("child level 3", Color::GREEN, childLevel2a.get()); + + Transaction{} + .setRelativeLayer(childLevel3, childLevel2b->getHandle(), 1) + .show(childLevel2a) + .show(childLevel2b) + .show(childLevel3) + .apply(); + + { + // The childLevel3 should be in front of childLevel2b. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); + } + + // Background layer (RED) + // Foregroud layer (GREEN) + Transaction{}.reparent(childLevel1, nullptr).apply(); + + // Background layer (RED) + // Foregroud layer (GREEN) + // child level 1 (WHITE) + // child level 2 back (BLUE) + // child level 3 (GREEN) (relative to child level 2b) + // child level 2 front (BLACK) + Transaction{}.reparent(childLevel1, mForegroundLayer->getHandle()).apply(); + + { + // Nothing should change at this point since relative z info was preserved. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); + } +} + } // namespace android |