diff options
40 files changed, 902 insertions, 313 deletions
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp index aad9939bc5..25e5247c68 100644 --- a/cmds/installd/dexopt.cpp +++ b/cmds/installd/dexopt.cpp @@ -313,9 +313,14 @@ class RunDex2Oat : public ExecVHelper { bool skip_compilation = vold_decrypt == "trigger_restart_min_framework" || vold_decrypt == "1"; - const std::string resolve_startup_string_arg = + const std::string resolve_startup_string_arg = MapPropertyToArg("dalvik.vm.dex2oat-resolve-startup-strings", "--resolve-startup-const-strings=%s"); + + const std::string image_block_size_arg = + MapPropertyToArg("dalvik.vm.dex2oat-max-image-block-size", + "--max-image-block-size=%s"); + const bool generate_debug_info = GetBoolProperty("debug.generate-debug-info", false); std::string image_format_arg; @@ -430,6 +435,7 @@ class RunDex2Oat : public ExecVHelper { AddRuntimeArg(dex2oat_Xmx_arg); AddArg(resolve_startup_string_arg); + AddArg(image_block_size_arg); AddArg(dex2oat_compiler_filter_arg); AddArg(dex2oat_threads_arg); AddArg(dex2oat_swap_fd); diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml index 561f5ba9a6..13b960adfe 100644 --- a/data/etc/car_core_hardware.xml +++ b/data/etc/car_core_hardware.xml @@ -36,7 +36,6 @@ <feature name="android.hardware.type.automotive" /> <!-- basic system services --> - <feature name="android.software.app_widgets" /> <feature name="android.software.connectionservice" /> <feature name="android.software.voice_recognizers" notLowRam="true" /> <feature name="android.software.backup" /> diff --git a/libs/graphicsenv/Android.bp b/libs/graphicsenv/Android.bp index bab87acb05..280c14a3ea 100644 --- a/libs/graphicsenv/Android.bp +++ b/libs/graphicsenv/Android.bp @@ -22,8 +22,9 @@ cc_library_shared { cflags: ["-Wall", "-Werror"], shared_libs: [ - "liblog", + "libbase", "libcutils", + "liblog", ], export_include_dirs: ["include"], diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp index afa32b6d63..c2a6764338 100644 --- a/libs/graphicsenv/GraphicsEnv.cpp +++ b/libs/graphicsenv/GraphicsEnv.cpp @@ -18,32 +18,99 @@ #define LOG_TAG "GraphicsEnv" #include <graphicsenv/GraphicsEnv.h> -#include <sys/prctl.h> - -#include <mutex> +#include <dlfcn.h> +#include <android-base/file.h> +#include <android-base/properties.h> +#include <android-base/strings.h> #include <android/dlext.h> #include <cutils/properties.h> #include <log/log.h> +#include <sys/prctl.h> + +#include <mutex> // TODO(b/37049319) Get this from a header once one exists extern "C" { - android_namespace_t* android_get_exported_namespace(const char*); - android_namespace_t* android_create_namespace(const char* name, - const char* ld_library_path, - const char* default_library_path, - uint64_t type, - const char* permitted_when_isolated_path, - android_namespace_t* parent); +android_namespace_t* android_get_exported_namespace(const char*); +android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path, + const char* default_library_path, uint64_t type, + const char* permitted_when_isolated_path, + android_namespace_t* parent); +bool android_link_namespaces(android_namespace_t* from, android_namespace_t* to, + const char* shared_libs_sonames); - enum { - ANDROID_NAMESPACE_TYPE_ISOLATED = 1, - ANDROID_NAMESPACE_TYPE_SHARED = 2, - }; +enum { + ANDROID_NAMESPACE_TYPE_ISOLATED = 1, + ANDROID_NAMESPACE_TYPE_SHARED = 2, +}; } namespace android { +enum NativeLibrary { + LLNDK = 0, + VNDKSP = 1, +}; + +static constexpr const char* kNativeLibrariesSystemConfigPath[] = {"/etc/llndk.libraries.txt", + "/etc/vndksp.libraries.txt"}; + +static std::string vndkVersionStr() { +#ifdef __BIONIC__ + std::string version = android::base::GetProperty("ro.vndk.version", ""); + if (version != "" && version != "current") { + return "." + version; + } +#endif + return ""; +} + +static void insertVndkVersionStr(std::string* fileName) { + LOG_ALWAYS_FATAL_IF(!fileName, "fileName should never be nullptr"); + size_t insertPos = fileName->find_last_of("."); + if (insertPos == std::string::npos) { + insertPos = fileName->length(); + } + fileName->insert(insertPos, vndkVersionStr()); +} + +static bool readConfig(const std::string& configFile, std::vector<std::string>* soNames) { + // Read list of public native libraries from the config file. + std::string fileContent; + if (!base::ReadFileToString(configFile, &fileContent)) { + return false; + } + + std::vector<std::string> lines = base::Split(fileContent, "\n"); + + for (auto& line : lines) { + auto trimmedLine = base::Trim(line); + if (!trimmedLine.empty()) { + soNames->push_back(trimmedLine); + } + } + + return true; +} + +static const std::string getSystemNativeLibraries(NativeLibrary type) { + static const char* androidRootEnv = getenv("ANDROID_ROOT"); + static const std::string rootDir = androidRootEnv != nullptr ? androidRootEnv : "/system"; + + std::string nativeLibrariesSystemConfig = rootDir + kNativeLibrariesSystemConfigPath[type]; + + insertVndkVersionStr(&nativeLibrariesSystemConfig); + + std::vector<std::string> soNames; + if (!readConfig(nativeLibrariesSystemConfig, &soNames)) { + ALOGE("Failed to retrieve library names from %s", nativeLibrariesSystemConfig.c_str()); + return ""; + } + + return base::Join(soNames, ':'); +} + /*static*/ GraphicsEnv& GraphicsEnv::getInstance() { static GraphicsEnv env; return env; @@ -59,8 +126,8 @@ int GraphicsEnv::getCanLoadSystemLibraries() { void GraphicsEnv::setDriverPath(const std::string path) { if (!mDriverPath.empty()) { - ALOGV("ignoring attempt to change driver path from '%s' to '%s'", - mDriverPath.c_str(), path.c_str()); + ALOGV("ignoring attempt to change driver path from '%s' to '%s'", mDriverPath.c_str(), + path.c_str()); return; } ALOGV("setting driver path to '%s'", path.c_str()); @@ -102,7 +169,7 @@ void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace, const std:: mAppNamespace = appNamespace; } else { ALOGV("Vulkan layer search path already set, not clobbering with '%s' for namespace %p'", - layerPaths.c_str(), appNamespace); + layerPaths.c_str(), appNamespace); } } @@ -154,20 +221,41 @@ void GraphicsEnv::setDebugLayersGLES(const std::string layers) { android_namespace_t* GraphicsEnv::getDriverNamespace() { static std::once_flag once; std::call_once(once, [this]() { - if (mDriverPath.empty()) - return; - // If the sphal namespace isn't configured for a device, don't support updatable drivers. - // We need a parent namespace to inherit the default search path from. - auto sphalNamespace = android_get_exported_namespace("sphal"); - if (!sphalNamespace) return; + 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_SHARED | - ANDROID_NAMESPACE_TYPE_ISOLATED, + ANDROID_NAMESPACE_TYPE_ISOLATED, nullptr, // permitted_when_isolated_path - sphalNamespace); + 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; + } + + 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; + } }); + return mDriverNamespace; } diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 69e5379047..80d435f67b 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -599,6 +599,43 @@ public: } return err; } + + virtual status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display, + ui::PixelFormat* outFormat, + ui::Dataspace* outDataspace, + uint8_t* outComponentMask) const { + if (!outFormat || !outDataspace || !outComponentMask) return BAD_VALUE; + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + data.writeStrongBinder(display); + + status_t error = + remote()->transact(BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES, + data, &reply); + if (error != NO_ERROR) { + return error; + } + + uint32_t value = 0; + error = reply.readUint32(&value); + if (error != NO_ERROR) { + return error; + } + *outFormat = static_cast<ui::PixelFormat>(value); + + error = reply.readUint32(&value); + if (error != NO_ERROR) { + return error; + } + *outDataspace = static_cast<ui::Dataspace>(value); + + error = reply.readUint32(&value); + if (error != NO_ERROR) { + return error; + } + *outComponentMask = static_cast<uint8_t>(value); + return error; + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -951,6 +988,22 @@ status_t BnSurfaceComposer::onTransact( } return result; } + case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + + sp<IBinder> display = data.readStrongBinder(); + ui::PixelFormat format; + ui::Dataspace dataspace; + uint8_t component = 0; + auto result = + getDisplayedContentSamplingAttributes(display, &format, &dataspace, &component); + if (result == NO_ERROR) { + reply->writeUint32(static_cast<uint32_t>(format)); + reply->writeUint32(static_cast<uint32_t>(dataspace)); + reply->writeUint32(static_cast<uint32_t>(component)); + } + return result; + } default: { return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 87c6f27c57..41e5abbd0e 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1077,6 +1077,15 @@ status_t SurfaceComposerClient::getHdrCapabilities(const sp<IBinder>& display, outCapabilities); } +status_t SurfaceComposerClient::getDisplayedContentSamplingAttributes(const sp<IBinder>& display, + ui::PixelFormat* outFormat, + ui::Dataspace* outDataspace, + uint8_t* outComponentMask) { + return ComposerService::getComposerService() + ->getDisplayedContentSamplingAttributes(display, outFormat, outDataspace, + outComponentMask); +} + // ---------------------------------------------------------------------------- status_t ScreenshotClient::capture(const sp<IBinder>& display, const ui::Dataspace reqDataSpace, diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 761f31a04b..3b6c6e44b1 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -293,6 +293,13 @@ public: ui::PixelFormat* defaultPixelFormat, ui::Dataspace* wideColorGamutDataspace, ui::PixelFormat* wideColorGamutPixelFormat) const = 0; + /* + * Requires the ACCESS_SURFACE_FLINGER permission. + */ + virtual status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display, + ui::PixelFormat* outFormat, + ui::Dataspace* outDataspace, + uint8_t* outComponentMask) const = 0; }; // ---------------------------------------------------------------------------- @@ -332,6 +339,7 @@ public: CREATE_SCOPED_CONNECTION, GET_COMPOSITION_PREFERENCE, GET_COLOR_MANAGEMENT, + GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES, }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 10c27b1a33..cf55b6b33d 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -381,6 +381,11 @@ public: inline sp<ISurfaceComposerClient> getClient() { return mClient; } + static status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display, + ui::PixelFormat* outFormat, + ui::Dataspace* outDataspace, + uint8_t* outComponentMask); + private: virtual void onFirstRef(); diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp index a6295e0387..6de641d0e0 100644 --- a/libs/gui/tests/Android.bp +++ b/libs/gui/tests/Android.bp @@ -17,6 +17,7 @@ cc_test { "BufferQueue_test.cpp", "CpuConsumer_test.cpp", "EndToEndNativeInputTest.cpp", + "DisplayedContentSampling_test.cpp", "FillBuffer.cpp", "GLTest.cpp", "IGraphicBufferProducer_test.cpp", diff --git a/libs/gui/tests/DisplayedContentSampling_test.cpp b/libs/gui/tests/DisplayedContentSampling_test.cpp new file mode 100644 index 0000000000..f2c0e0ca7f --- /dev/null +++ b/libs/gui/tests/DisplayedContentSampling_test.cpp @@ -0,0 +1,68 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include <binder/ProcessState.h> +#include <gui/ISurfaceComposer.h> +#include <gui/Surface.h> +#include <gui/SurfaceComposerClient.h> +#include <inttypes.h> + +namespace android { + +using Transaction = SurfaceComposerClient::Transaction; + +static constexpr uint32_t INVALID_MASK = 0x10; +class DisplayedContentSamplingTest : public ::testing::Test { +protected: + void SetUp() { + mComposerClient = new SurfaceComposerClient; + ASSERT_EQ(OK, mComposerClient->initCheck()); + mDisplayToken = mComposerClient->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain); + ASSERT_TRUE(mDisplayToken); + } + + bool shouldSkipTest(status_t status) { + if (status == PERMISSION_DENIED) { + SUCCEED() << "permissions denial, skipping test"; + return true; + } + if (status == INVALID_OPERATION) { + SUCCEED() << "optional function not supported, skipping test"; + return true; + } + return false; + } + + sp<SurfaceComposerClient> mComposerClient; + sp<IBinder> mDisplayToken; +}; + +TEST_F(DisplayedContentSamplingTest, GetDisplayedContentSamplingAttributesAreSane) { + ui::PixelFormat format; + ui::Dataspace dataspace; + uint8_t componentMask = 0; + status_t status = + mComposerClient->getDisplayedContentSamplingAttributes(mDisplayToken, &format, + &dataspace, &componentMask); + if (shouldSkipTest(status)) { + return; + } + EXPECT_EQ(OK, status); + EXPECT_LE(componentMask, INVALID_MASK); +} +} // namespace android diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 2871302927..86e9c23a7e 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -59,9 +59,8 @@ static const int LAYER_BASE = INT32_MAX - 10; class InputSurface { public: InputSurface(const sp<SurfaceComposerClient>& scc, int width, int height) { - mSurfaceControl = scc->createSurface(String8("Test Surface"), - width, height, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor); + mSurfaceControl = scc->createSurface(String8("Test Surface"), 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor); InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel); mServerChannel->setToken(new BBinder()); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 4ba7da3560..3950bb6258 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -641,6 +641,12 @@ public: ui::PixelFormat* /*outWideColorGamutPixelFormat*/) const override { return NO_ERROR; } + status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& /*display*/, + ui::PixelFormat* /*outFormat*/, + ui::Dataspace* /*outDataspace*/, + uint8_t* /*outComponentMask*/) const override { + return NO_ERROR; + } virtual status_t getColorManagement(bool* /*outGetColorManagement*/) const { return NO_ERROR; } diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index 0a0c8ca014..f7709754c8 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -109,6 +109,7 @@ cc_library_shared { // bufferhub is not used when building libgui for vendors target: { vendor: { + cflags: ["-DLIBUI_IN_VNDK"], exclude_srcs: [ "BufferHubBuffer.cpp", "BufferHubMetadata.cpp", @@ -116,6 +117,7 @@ cc_library_shared { exclude_header_libs: [ "libbufferhub_headers", "libdvr_headers", + "libnativewindow_headers", ], exclude_shared_libs: [ "libpdx_default_transport", @@ -128,6 +130,7 @@ cc_library_shared { "libbufferhub_headers", "libdvr_headers", "libnativebase_headers", + "libnativewindow_headers", "libhardware_headers", "libui_headers", "libpdx_headers", @@ -155,6 +158,7 @@ cc_library_headers { vendor_available: true, target: { vendor: { + cflags: ["-DLIBUI_IN_VNDK"], override_export_include_dirs: ["include_vndk"], }, }, diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp index 8cc1a4e3b4..e747ee11be 100644 --- a/libs/ui/BufferHubBuffer.cpp +++ b/libs/ui/BufferHubBuffer.cpp @@ -36,10 +36,12 @@ #include <private/dvr/bufferhub_rpc.h> #pragma clang diagnostic pop -#include <ui/BufferHubBuffer.h> - #include <poll.h> +#include <android-base/unique_fd.h> +#include <ui/BufferHubBuffer.h> + +using android::base::unique_fd; using android::dvr::BufferTraits; using android::dvr::DetachedBufferRPC; using android::dvr::NativeHandleWrapper; @@ -132,7 +134,9 @@ int BufferHubBuffer::ImportGraphicBuffer() { const int bufferId = bufferTraits.id(); // Import the metadata. - mMetadata = BufferHubMetadata::Import(bufferTraits.take_metadata_handle()); + LocalHandle metadataHandle = bufferTraits.take_metadata_handle(); + unique_fd metadataFd(metadataHandle.Release()); + mMetadata = BufferHubMetadata::Import(std::move(metadataFd)); if (!mMetadata.IsValid()) { ALOGE("BufferHubBuffer::ImportGraphicBuffer: invalid metadata."); @@ -156,6 +160,16 @@ int BufferHubBuffer::ImportGraphicBuffer() { // GraphicBuffer instance can be created in future. mBufferHandle = bufferTraits.take_buffer_handle(); + // Populate buffer desc based on buffer traits. + mBufferDesc.width = bufferTraits.width(); + mBufferDesc.height = bufferTraits.height(); + mBufferDesc.layers = bufferTraits.layer_count(); + mBufferDesc.format = bufferTraits.format(); + mBufferDesc.usage = bufferTraits.usage(); + mBufferDesc.stride = bufferTraits.stride(); + mBufferDesc.rfu0 = 0U; + mBufferDesc.rfu1 = 0U; + // If all imports succeed, replace the previous buffer and id. mId = bufferId; mClientStateMask = bufferTraits.client_state_mask(); diff --git a/libs/ui/BufferHubMetadata.cpp b/libs/ui/BufferHubMetadata.cpp index 1e08ed1388..18d9a2c963 100644 --- a/libs/ui/BufferHubMetadata.cpp +++ b/libs/ui/BufferHubMetadata.cpp @@ -48,47 +48,47 @@ BufferHubMetadata BufferHubMetadata::Create(size_t userMetadataSize) { return {}; } - // Hand over the ownership of the fd to a pdx::LocalHandle immediately after the successful - // return of ashmem_create_region. The ashmemHandle is going to own the fd and to prevent fd + // Hand over the ownership of the fd to a unique_fd immediately after the successful + // return of ashmem_create_region. The ashmemFd is going to own the fd and to prevent fd // leaks during error handling. - pdx::LocalHandle ashmemHandle{fd}; + unique_fd ashmemFd{fd}; - if (ashmem_set_prot_region(ashmemHandle.Get(), kAshmemProt) != 0) { + if (ashmem_set_prot_region(ashmemFd.get(), kAshmemProt) != 0) { ALOGE("BufferHubMetadata::Create: failed to set protect region."); return {}; } - return BufferHubMetadata::Import(std::move(ashmemHandle)); + return BufferHubMetadata::Import(std::move(ashmemFd)); } /* static */ -BufferHubMetadata BufferHubMetadata::Import(pdx::LocalHandle ashmemHandle) { - if (!ashmem_valid(ashmemHandle.Get())) { +BufferHubMetadata BufferHubMetadata::Import(unique_fd ashmemFd) { + if (!ashmem_valid(ashmemFd.get())) { ALOGE("BufferHubMetadata::Import: invalid ashmem fd."); return {}; } - size_t metadataSize = static_cast<size_t>(ashmem_get_size_region(ashmemHandle.Get())); + size_t metadataSize = static_cast<size_t>(ashmem_get_size_region(ashmemFd.get())); size_t userMetadataSize = metadataSize - kMetadataHeaderSize; // Note that here the buffer state is mapped from shared memory as an atomic object. The // std::atomic's constructor will not be called so that the original value stored in the memory // region can be preserved. auto metadataHeader = static_cast<MetadataHeader*>(mmap(nullptr, metadataSize, kAshmemProt, - MAP_SHARED, ashmemHandle.Get(), + MAP_SHARED, ashmemFd.get(), /*offset=*/0)); if (metadataHeader == nullptr) { ALOGE("BufferHubMetadata::Import: failed to map region."); return {}; } - return BufferHubMetadata(userMetadataSize, std::move(ashmemHandle), metadataHeader); + return BufferHubMetadata(userMetadataSize, std::move(ashmemFd), metadataHeader); } -BufferHubMetadata::BufferHubMetadata(size_t userMetadataSize, pdx::LocalHandle ashmemHandle, +BufferHubMetadata::BufferHubMetadata(size_t userMetadataSize, unique_fd ashmemFd, MetadataHeader* metadataHeader) : mUserMetadataSize(userMetadataSize), - mAshmemHandle(std::move(ashmemHandle)), + mAshmemFd(std::move(ashmemFd)), mMetadataHeader(metadataHeader) {} BufferHubMetadata::~BufferHubMetadata() { diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 29deb010e8..e606e26f8b 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -22,6 +22,10 @@ #include <grallocusage/GrallocUsageConversion.h> +#ifndef LIBUI_IN_VNDK +#include <ui/BufferHubBuffer.h> +#endif // LIBUI_IN_VNDK + #include <ui/Gralloc2.h> #include <ui/GraphicBufferAllocator.h> #include <ui/GraphicBufferMapper.h> @@ -89,6 +93,21 @@ GraphicBuffer::GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod m inUsage, inStride); } +#ifndef LIBUI_IN_VNDK +GraphicBuffer::GraphicBuffer(std::unique_ptr<BufferHubBuffer> buffer) : GraphicBuffer() { + if (buffer == nullptr) { + mInitCheck = BAD_VALUE; + return; + } + + mInitCheck = initWithHandle(buffer->DuplicateHandle(), /*method=*/TAKE_UNREGISTERED_HANDLE, + buffer->desc().width, buffer->desc().height, + static_cast<PixelFormat>(buffer->desc().format), + buffer->desc().layers, buffer->desc().usage, buffer->desc().stride); + mBufferHubBuffer = std::move(buffer); +} +#endif // LIBUI_IN_VNDK + GraphicBuffer::~GraphicBuffer() { if (handle) { @@ -483,6 +502,12 @@ status_t GraphicBuffer::unflatten( return NO_ERROR; } +#ifndef LIBUI_IN_VNDK +bool GraphicBuffer::isBufferHubBuffer() const { + return mBufferHubBuffer != nullptr; +} +#endif // LIBUI_IN_VNDK + // --------------------------------------------------------------------------- }; // namespace android diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h index daf61928a4..6850b43f8a 100644 --- a/libs/ui/include/ui/BufferHubBuffer.h +++ b/libs/ui/include/ui/BufferHubBuffer.h @@ -38,6 +38,7 @@ #include <private/dvr/native_handle_wrapper.h> #pragma clang diagnostic pop +#include <android/hardware_buffer.h> #include <ui/BufferHubMetadata.h> namespace android { @@ -62,9 +63,9 @@ public: // Allocates a standalone BufferHubBuffer not associated with any producer consumer set. static std::unique_ptr<BufferHubBuffer> Create(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format, - uint64_t usage, size_t mUserMetadataSize) { + uint64_t usage, size_t userMetadataSize) { return std::unique_ptr<BufferHubBuffer>( - new BufferHubBuffer(width, height, layerCount, format, usage, mUserMetadataSize)); + new BufferHubBuffer(width, height, layerCount, format, usage, userMetadataSize)); } // Imports the given channel handle to a BufferHubBuffer, taking ownership. @@ -79,6 +80,9 @@ public: // bufferhubd share the same buffer id. int id() const { return mId; } + // Returns the buffer description, which is guaranteed to be faithful values from bufferhubd. + const AHardwareBuffer_Desc& desc() const { return mBufferDesc; } + const native_handle_t* DuplicateHandle() { return mBufferHandle.DuplicateHandle(); } // Returns the current value of MetadataHeader::buffer_state. @@ -118,7 +122,7 @@ public: private: BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format, - uint64_t usage, size_t mUserMetadataSize); + uint64_t usage, size_t userMetadataSize); BufferHubBuffer(pdx::LocalChannelHandle mChannelHandle); @@ -128,6 +132,9 @@ private: int mId = -1; uint64_t mClientStateMask = 0; + // Stores ground truth of the buffer. + AHardwareBuffer_Desc mBufferDesc; + // Wrapps the gralloc buffer handle of this buffer. dvr::NativeHandleWrapper<pdx::LocalHandle> mBufferHandle; diff --git a/libs/ui/include/ui/BufferHubMetadata.h b/libs/ui/include/ui/BufferHubMetadata.h index 94a9000a32..4261971f55 100644 --- a/libs/ui/include/ui/BufferHubMetadata.h +++ b/libs/ui/include/ui/BufferHubMetadata.h @@ -33,12 +33,17 @@ #pragma clang diagnostic ignored "-Wundefined-func-template" #pragma clang diagnostic ignored "-Wunused-template" #pragma clang diagnostic ignored "-Wweak-vtables" -#include <pdx/file_handle.h> #include <private/dvr/buffer_hub_defs.h> #pragma clang diagnostic pop +#include <android-base/unique_fd.h> + namespace android { +namespace { +using base::unique_fd; +} // namespace + class BufferHubMetadata { public: // Creates a new BufferHubMetadata backed by an ashmem region. @@ -50,11 +55,8 @@ public: // Imports an existing BufferHubMetadata from an ashmem FD. // - // TODO(b/112338294): Refactor BufferHub to use Binder as its internal IPC backend instead of - // UDS. - // - // @param ashmemHandle Ashmem file handle representing an ashmem region. - static BufferHubMetadata Import(pdx::LocalHandle ashmemHandle); + // @param ashmemFd Ashmem file descriptor representing an ashmem region. + static BufferHubMetadata Import(unique_fd ashmemFd); BufferHubMetadata() = default; @@ -67,7 +69,7 @@ public: mUserMetadataSize = other.mUserMetadataSize; other.mUserMetadataSize = 0; - mAshmemHandle = std::move(other.mAshmemHandle); + mAshmemFd = std::move(other.mAshmemFd); // The old raw mMetadataHeader pointer must be cleared, otherwise the destructor will // automatically mummap() the shared memory. @@ -79,25 +81,25 @@ public: // Returns true if the metadata is valid, i.e. the metadata has a valid ashmem fd and the ashmem // has been mapped into virtual address space. - bool IsValid() const { return mAshmemHandle.IsValid() && mMetadataHeader != nullptr; } + bool IsValid() const { return mAshmemFd.get() != -1 && mMetadataHeader != nullptr; } size_t user_metadata_size() const { return mUserMetadataSize; } size_t metadata_size() const { return mUserMetadataSize + dvr::BufferHubDefs::kMetadataHeaderSize; } - const pdx::LocalHandle& ashmem_handle() const { return mAshmemHandle; } + const unique_fd& ashmem_fd() const { return mAshmemFd; } dvr::BufferHubDefs::MetadataHeader* metadata_header() { return mMetadataHeader; } private: - BufferHubMetadata(size_t userMetadataSize, pdx::LocalHandle ashmemHandle, + BufferHubMetadata(size_t userMetadataSize, unique_fd ashmemFd, dvr::BufferHubDefs::MetadataHeader* metadataHeader); BufferHubMetadata(const BufferHubMetadata&) = delete; void operator=(const BufferHubMetadata&) = delete; size_t mUserMetadataSize = 0; - pdx::LocalHandle mAshmemHandle; + unique_fd mAshmemFd; dvr::BufferHubDefs::MetadataHeader* mMetadataHeader = nullptr; }; diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h index fe6229ab48..81f6cd9061 100644 --- a/libs/ui/include/ui/GraphicBuffer.h +++ b/libs/ui/include/ui/GraphicBuffer.h @@ -34,6 +34,10 @@ namespace android { +#ifndef LIBUI_IN_VNDK +class BufferHubBuffer; +#endif // LIBUI_IN_VNDK + class GraphicBufferMapper; // =========================================================================== @@ -133,6 +137,11 @@ public: GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat, uint32_t inUsage, std::string requestorName = "<Unknown>"); +#ifndef LIBUI_IN_VNDK + // Create a GraphicBuffer from an existing BufferHubBuffer. + GraphicBuffer(std::unique_ptr<BufferHubBuffer> buffer); +#endif // LIBUI_IN_VNDK + // return status status_t initCheck() const; @@ -188,6 +197,11 @@ public: status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const; status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count); +#ifndef LIBUI_IN_VNDK + // Returns whether this GraphicBuffer is backed by BufferHubBuffer. + bool isBufferHubBuffer() const; +#endif // LIBUI_IN_VNDK + private: ~GraphicBuffer(); @@ -237,6 +251,11 @@ private: // match the BufferQueue's internal generation number (set through // IGBP::setGenerationNumber), attempts to attach the buffer will fail. uint32_t mGenerationNumber; + +#ifndef LIBUI_IN_VNDK + // Stores a BufferHubBuffer that handles buffer signaling, identification. + std::unique_ptr<BufferHubBuffer> mBufferHubBuffer; +#endif // LIBUI_IN_VNDK }; }; // namespace android diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp index 4c9c1768e0..b7ad4e5a80 100644 --- a/libs/ui/tests/Android.bp +++ b/libs/ui/tests/Android.bp @@ -29,6 +29,22 @@ cc_test { } cc_test { + name: "GraphicBuffer_test", + header_libs: [ + "libbufferhub_headers", + "libdvr_headers", + "libnativewindow_headers", + ], + shared_libs: [ + "libpdx_default_transport", + "libui", + "libutils", + ], + srcs: ["GraphicBuffer_test.cpp"], + cflags: ["-Wall", "-Werror"], +} + +cc_test { name: "BufferHubBuffer_test", header_libs: [ "libbufferhub_headers", diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp index 6af8033e76..d30636f8cc 100644 --- a/libs/ui/tests/BufferHubBuffer_test.cpp +++ b/libs/ui/tests/BufferHubBuffer_test.cpp @@ -156,20 +156,25 @@ TEST_F(BufferHubBufferTest, DuplicateBuffer) { memcpy(&desc, &aDesc, sizeof(HardwareBufferDescription)); sp<IBufferClient> client; + BufferHubStatus ret; IBufferHub::allocateBuffer_cb alloc_cb = [&](const auto& outClient, const auto& status) { - ASSERT_EQ(status, BufferHubStatus::NO_ERROR); - ASSERT_NE(nullptr, outClient.get()); client = outClient; + ret = status; }; ASSERT_TRUE(bufferhub->allocateBuffer(desc, kUserMetadataSize, alloc_cb).isOk()); + EXPECT_EQ(ret, BufferHubStatus::NO_ERROR); + ASSERT_NE(nullptr, client.get()); - IBufferClient::duplicate_cb dup_cb = [](const auto& token, const auto& status) { - ASSERT_EQ(status, BufferHubStatus::NO_ERROR); - ASSERT_NE(token.getNativeHandle(), nullptr); - EXPECT_EQ(token->numInts, 1); - EXPECT_EQ(token->numFds, 0); + hidl_handle token; + IBufferClient::duplicate_cb dup_cb = [&](const auto& outToken, const auto& status) { + token = outToken; + ret = status; }; EXPECT_TRUE(client->duplicate(dup_cb).isOk()); + EXPECT_EQ(ret, BufferHubStatus::NO_ERROR); + ASSERT_NE(token.getNativeHandle(), nullptr); + EXPECT_EQ(token->numInts, 1); + EXPECT_EQ(token->numFds, 0); } } // namespace diff --git a/libs/ui/tests/BufferHubMetadata_test.cpp b/libs/ui/tests/BufferHubMetadata_test.cpp index 4209392afa..70f86b3ef2 100644 --- a/libs/ui/tests/BufferHubMetadata_test.cpp +++ b/libs/ui/tests/BufferHubMetadata_test.cpp @@ -43,11 +43,11 @@ TEST_F(BufferHubMetadataTest, Import_Success) { EXPECT_TRUE(m1.IsValid()); EXPECT_NE(m1.metadata_header(), nullptr); - pdx::LocalHandle h2 = m1.ashmem_handle().Duplicate(); - EXPECT_TRUE(h2.IsValid()); + unique_fd h2 = unique_fd(dup(m1.ashmem_fd().get())); + EXPECT_NE(h2.get(), -1); BufferHubMetadata m2 = BufferHubMetadata::Import(std::move(h2)); - EXPECT_FALSE(h2.IsValid()); + EXPECT_EQ(h2.get(), -1); EXPECT_TRUE(m1.IsValid()); BufferHubDefs::MetadataHeader* mh1 = m1.metadata_header(); EXPECT_NE(mh1, nullptr); @@ -71,31 +71,29 @@ TEST_F(BufferHubMetadataTest, MoveMetadataInvalidatesOldOne) { BufferHubMetadata m1 = BufferHubMetadata::Create(sizeof(int)); EXPECT_TRUE(m1.IsValid()); EXPECT_NE(m1.metadata_header(), nullptr); - EXPECT_TRUE(m1.ashmem_handle().IsValid()); + EXPECT_NE(m1.ashmem_fd().get(), -1); EXPECT_EQ(m1.user_metadata_size(), sizeof(int)); BufferHubMetadata m2 = std::move(m1); - // After the move, the metadata header (a raw pointer) should be reset in the - // older buffer. + // After the move, the metadata header (a raw pointer) should be reset in the older buffer. EXPECT_EQ(m1.metadata_header(), nullptr); EXPECT_NE(m2.metadata_header(), nullptr); - EXPECT_FALSE(m1.ashmem_handle().IsValid()); - EXPECT_TRUE(m2.ashmem_handle().IsValid()); + EXPECT_EQ(m1.ashmem_fd().get(), -1); + EXPECT_NE(m2.ashmem_fd().get(), -1); EXPECT_EQ(m1.user_metadata_size(), 0U); EXPECT_EQ(m2.user_metadata_size(), sizeof(int)); BufferHubMetadata m3{std::move(m2)}; - // After the move, the metadata header (a raw pointer) should be reset in the - // older buffer. + // After the move, the metadata header (a raw pointer) should be reset in the older buffer. EXPECT_EQ(m2.metadata_header(), nullptr); EXPECT_NE(m3.metadata_header(), nullptr); - EXPECT_FALSE(m2.ashmem_handle().IsValid()); - EXPECT_TRUE(m3.ashmem_handle().IsValid()); + EXPECT_EQ(m2.ashmem_fd().get(), -1); + EXPECT_NE(m3.ashmem_fd().get(), -1); EXPECT_EQ(m2.user_metadata_size(), 0U); EXPECT_EQ(m3.user_metadata_size(), sizeof(int)); diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp new file mode 100644 index 0000000000..95ca2c16b3 --- /dev/null +++ b/libs/ui/tests/GraphicBuffer_test.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "GraphicBufferTest" + +#include <ui/BufferHubBuffer.h> +#include <ui/GraphicBuffer.h> + +#include <gtest/gtest.h> + +namespace android { + +namespace { + +constexpr uint32_t kTestWidth = 1024; +constexpr uint32_t kTestHeight = 1; +constexpr uint32_t kTestFormat = HAL_PIXEL_FORMAT_BLOB; +constexpr uint32_t kTestLayerCount = 1; +constexpr uint64_t kTestUsage = GraphicBuffer::USAGE_SW_WRITE_OFTEN; + +} // namespace + +class GraphicBufferTest : public testing::Test {}; + +TEST_F(GraphicBufferTest, CreateFromBufferHubBuffer) { + std::unique_ptr<BufferHubBuffer> b1 = + BufferHubBuffer::Create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat, + kTestUsage, /*userMetadataSize=*/0); + EXPECT_TRUE(b1->IsValid()); + + sp<GraphicBuffer> gb(new GraphicBuffer(std::move(b1))); + EXPECT_TRUE(gb->isBufferHubBuffer()); + + EXPECT_EQ(gb->getWidth(), kTestWidth); + EXPECT_EQ(gb->getHeight(), kTestHeight); + EXPECT_EQ(static_cast<uint32_t>(gb->getPixelFormat()), kTestFormat); + EXPECT_EQ(gb->getUsage(), kTestUsage); + EXPECT_EQ(gb->getLayerCount(), kTestLayerCount); +} + +} // namespace android diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp index e27f23310e..6edadcd6ed 100644 --- a/opengl/libs/EGL/Loader.cpp +++ b/opengl/libs/EGL/Loader.cpp @@ -41,13 +41,27 @@ extern "C" { android_namespace_t* android_get_exported_namespace(const char*); - // TODO(ianelliott@): Get this from an ANGLE header: + // TODO(ianelliott@): Get the following from an ANGLE header: + // Version-1 API: typedef bool (*fpANGLEGetUtilityAPI)(unsigned int* versionToUse); - - // TODO(ianelliott@): Get this from an ANGLE header: typedef bool (*fpAndroidUseANGLEForApplication)(int fd, long offset, long length, const char* appName, const char* deviceMfr, const char* deviceModel); + // Version-2 API: + typedef bool (*fpANGLEGetFeatureSupportUtilAPIVersion)(unsigned int* versionToUse); + typedef bool (*fpANGLEAndroidParseRulesString)(const char *rulesString, + void** rulesHandle, int* rulesVersion); + typedef bool (*fpANGLEGetSystemInfo)(void** handle); + typedef bool (*fpANGLEAddDeviceInfoToSystemInfo)(const char* deviceMfr, + const char* deviceModel, + void* handle); + typedef bool (*fpANGLEShouldBeUsedForApplication)(void* rules_handle, + int rules_version, + void* system_info_handle, + const char *appName); + typedef bool (*fpANGLEFreeRulesHandle)(void* handle); + typedef bool (*fpANGLEFreeSystemInfoHandle)(void* handle); + } // ---------------------------------------------------------------------------- @@ -523,19 +537,21 @@ static bool check_angle_rules(void* so, const char* app_name) { property_get("ro.product.manufacturer", manufacturer, "UNSET"); property_get("ro.product.model", model, "UNSET"); + // TODO: Replace this with the new function name once the version-1 API is removed: fpANGLEGetUtilityAPI ANGLEGetUtilityAPI = (fpANGLEGetUtilityAPI)dlsym(so, "ANGLEGetUtilityAPI"); if (ANGLEGetUtilityAPI) { // Negotiate the interface version by requesting most recent known to the platform - unsigned int versionToUse = 1; + unsigned int versionToUse = 2; + // TODO: Replace this with the new function name once the version-1 API is removed: if ((ANGLEGetUtilityAPI)(&versionToUse)) { // Add and remove versions below as needed switch(versionToUse) { case 1: { - ALOGV("Using version 1 of ANGLE opt-in/out logic interface"); + ALOGV("Using version 1 of ANGLE feature-support library"); fpAndroidUseANGLEForApplication AndroidUseANGLEForApplication = (fpAndroidUseANGLEForApplication)dlsym(so, "AndroidUseANGLEForApplication"); @@ -548,6 +564,65 @@ static bool check_angle_rules(void* so, const char* app_name) { } } break; + case 2: { + ALOGV("Using version 2 of ANGLE feature-support library"); + void* rules_handle = nullptr; + int rules_version = 0; + void* system_info_handle = nullptr; + + // Get the symbols for the feature-support-utility library: +#define GET_SYMBOL(symbol) \ + fp##symbol symbol = (fp##symbol)dlsym(so, #symbol); \ + if (!symbol) { \ + ALOGW("Cannot find "#symbol" in ANGLE feature-support library"); \ + break; \ + } + GET_SYMBOL(ANGLEAndroidParseRulesString); + GET_SYMBOL(ANGLEGetSystemInfo); + GET_SYMBOL(ANGLEAddDeviceInfoToSystemInfo); + GET_SYMBOL(ANGLEShouldBeUsedForApplication); + GET_SYMBOL(ANGLEFreeRulesHandle); + GET_SYMBOL(ANGLEFreeSystemInfoHandle); + + // Read the contents of the file into a string: + off_t fileSize = rules_length; + off_t startOfContent = rules_offset; + lseek(rules_fd, startOfContent, SEEK_SET); + char *buffer = new char[fileSize + 1]; + ssize_t numBytesRead = read(rules_fd, buffer, fileSize); + if (numBytesRead < 0) { + ALOGW("Cannot read rules file"); + break; + } + if (numBytesRead == 0) { + ALOGW("Empty rules file"); + break; + } + buffer[numBytesRead] = '\0'; + std::string rule_file_contents = std::string(buffer); + delete[] buffer; + + // Parse the rules, obtain the SystemInfo, and evaluate the + // application against the rules: + if (!(ANGLEAndroidParseRulesString)(rule_file_contents.c_str(), + &rules_handle, &rules_version)) { + ALOGW("ANGLE feature-support library cannot parse rules file"); + break; + } + if (!(ANGLEGetSystemInfo)(&system_info_handle)) { + ALOGW("ANGLE feature-support library cannot obtain SystemInfo"); + break; + } + if (!(ANGLEAddDeviceInfoToSystemInfo)(manufacturer, model, system_info_handle)) { + ALOGW("ANGLE feature-support library cannot add device info to SystemInfo"); + break; + } + use_angle = (ANGLEShouldBeUsedForApplication)(rules_handle, rules_version, + system_info_handle, app_name_str.c_str()); + (ANGLEFreeRulesHandle)(rules_handle); + (ANGLEFreeSystemInfoHandle)(system_info_handle); + } + break; default: ALOGW("Cannot find supported version of ANGLE feature-support library, found version %u", versionToUse); } diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp index 0fb4ac6c11..8dc80cce18 100644 --- a/services/sensorservice/SensorEventConnection.cpp +++ b/services/sensorservice/SensorEventConnection.cpp @@ -315,32 +315,7 @@ status_t SensorService::SensorEventConnection::sendEvents( if (mCacheSize != 0) { // There are some events in the cache which need to be sent first. Copy this buffer to // the end of cache. - if (mCacheSize + count <= mMaxCacheSize) { - memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t)); - mCacheSize += count; - } else { - // Check if any new sensors have registered on this connection which may have increased - // the max cache size that is desired. - if (mCacheSize + count < computeMaxCacheSizeLocked()) { - reAllocateCacheLocked(scratch, count); - return status_t(NO_ERROR); - } - // Some events need to be dropped. - int remaningCacheSize = mMaxCacheSize - mCacheSize; - if (remaningCacheSize != 0) { - memcpy(&mEventCache[mCacheSize], scratch, - remaningCacheSize * sizeof(sensors_event_t)); - } - int numEventsDropped = count - remaningCacheSize; - countFlushCompleteEventsLocked(mEventCache, numEventsDropped); - // Drop the first "numEventsDropped" in the cache. - memmove(mEventCache, &mEventCache[numEventsDropped], - (mCacheSize - numEventsDropped) * sizeof(sensors_event_t)); - - // Copy the remainingEvents in scratch buffer to the end of cache. - memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch + remaningCacheSize, - numEventsDropped * sizeof(sensors_event_t)); - } + appendEventsToCacheLocked(scratch, count); return status_t(NO_ERROR); } @@ -376,8 +351,8 @@ status_t SensorService::SensorEventConnection::sendEvents( mEventCache = new sensors_event_t[mMaxCacheSize]; mCacheSize = 0; } - memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t)); - mCacheSize += count; + // Save the events so that they can be written later + appendEventsToCacheLocked(scratch, count); // Add this file descriptor to the looper to get a callback when this fd is available for // writing. @@ -417,6 +392,51 @@ void SensorService::SensorEventConnection::reAllocateCacheLocked(sensors_event_t mMaxCacheSize = new_cache_size; } +void SensorService::SensorEventConnection::appendEventsToCacheLocked(sensors_event_t const* events, + int count) { + if (count <= 0) { + return; + } else if (mCacheSize + count <= mMaxCacheSize) { + // The events fit within the current cache: add them + memcpy(&mEventCache[mCacheSize], events, count * sizeof(sensors_event_t)); + mCacheSize += count; + } else if (mCacheSize + count <= computeMaxCacheSizeLocked()) { + // The events fit within a resized cache: resize the cache and add the events + reAllocateCacheLocked(events, count); + } else { + // The events do not fit within the cache: drop the oldest events. + ALOGW("Dropping events from cache (%d / %d) to save %d newer events", mCacheSize, + mMaxCacheSize, count); + + int freeSpace = mMaxCacheSize - mCacheSize; + + // Drop up to the currently cached number of events to make room for new events + int cachedEventsToDrop = std::min(mCacheSize, count - freeSpace); + + // New events need to be dropped if there are more new events than the size of the cache + int newEventsToDrop = std::max(0, count - mMaxCacheSize); + + // Determine the number of new events to copy into the cache + int eventsToCopy = std::min(mMaxCacheSize, count); + + // Check for any flush complete events in the events that will be dropped + countFlushCompleteEventsLocked(mEventCache, cachedEventsToDrop); + countFlushCompleteEventsLocked(events, newEventsToDrop); + + // Only shift the events if they will not all be overwritten + if (eventsToCopy != mMaxCacheSize) { + memmove(mEventCache, &mEventCache[cachedEventsToDrop], + (mCacheSize - cachedEventsToDrop) * sizeof(sensors_event_t)); + } + mCacheSize -= cachedEventsToDrop; + + // Copy the events into the cache + memcpy(&mEventCache[mCacheSize], &events[newEventsToDrop], + eventsToCopy * sizeof(sensors_event_t)); + mCacheSize += eventsToCopy; + } +} + void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() { ASensorEvent flushCompleteEvent; memset(&flushCompleteEvent, 0, sizeof(flushCompleteEvent)); diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h index 40c21ff585..eefd81a258 100644 --- a/services/sensorservice/SensorEventConnection.h +++ b/services/sensorservice/SensorEventConnection.h @@ -108,6 +108,10 @@ private: // size, reallocate memory and copy over events from the older cache. void reAllocateCacheLocked(sensors_event_t const* scratch, int count); + // Add the events to the cache. If the cache would be exceeded, drop events at the beginning of + // the cache. + void appendEventsToCacheLocked(sensors_event_t const* events, int count); + // LooperCallback method. If there is data to read on this fd, it is an ack from the app that it // has read events from a wake up sensor, decrement mWakeLockRefCount. If this fd is available // for writing send the data from the cache. diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index ade62bf68f..b862278e35 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -68,7 +68,7 @@ BufferLayer::~BufferLayer() { ALOGE("Found stale hardware composer layers when destroying " "surface flinger layer %s", mName.string()); - destroyAllHwcLayers(); + destroyAllHwcLayersPlusChildren(); } mTimeStats.onDestroy(getSequence()); @@ -501,7 +501,7 @@ Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime // FIXME: postedRegion should be dirty & bounds // transform the dirty region to window-manager space - return getTransform().transform(Region(Rect(getActiveWidth(s), getActiveHeight(s)))); + return getTransform().transform(Region(getBufferSize(s))); } // transaction @@ -624,11 +624,13 @@ void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityT ui::Transform t = getTransform(); Rect win = bounds; + const int bufferWidth = getBufferSize(s).getWidth(); + const int bufferHeight = getBufferSize(s).getHeight(); - float left = float(win.left) / float(getActiveWidth(s)); - float top = float(win.top) / float(getActiveHeight(s)); - float right = float(win.right) / float(getActiveWidth(s)); - float bottom = float(win.bottom) / float(getActiveHeight(s)); + const float left = float(win.left) / float(bufferWidth); + const float top = float(win.top) / float(bufferHeight); + const float right = float(win.right) / float(bufferWidth); + const float bottom = float(win.bottom) / float(bufferHeight); // TODO: we probably want to generate the texture coords with the mesh // here we assume that we only have 4 vertices diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index f0bccaabf1..b919da73e2 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -1023,6 +1023,33 @@ Error Composer::setLayerColorTransform(Display display, Layer layer, const float return Error::NONE; } +Error Composer::getDisplayedContentSamplingAttributes(Display display, PixelFormat* outFormat, + Dataspace* outDataspace, + uint8_t* outComponentMask) { + if (!outFormat || !outDataspace || !outComponentMask) { + return Error::BAD_PARAMETER; + } + if (!mClient_2_3) { + return Error::UNSUPPORTED; + } + Error error = kDefaultError; + mClient_2_3->getDisplayedContentSamplingAttributes(display, + [&](const auto tmpError, + const auto& tmpFormat, + const auto& tmpDataspace, + const auto& tmpComponentMask) { + error = tmpError; + if (error == Error::NONE) { + *outFormat = tmpFormat; + *outDataspace = tmpDataspace; + *outComponentMask = + static_cast<uint8_t>( + tmpComponentMask); + } + }); + return error; +} + CommandReader::~CommandReader() { resetData(); diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 4188352a76..c39171efa1 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -193,6 +193,9 @@ public: std::vector<uint8_t>* outData) = 0; virtual Error setLayerColorTransform(Display display, Layer layer, const float* matrix) = 0; + virtual Error getDisplayedContentSamplingAttributes(Display display, PixelFormat* outFormat, + Dataspace* outDataspace, + uint8_t* outComponentMask) = 0; }; namespace impl { @@ -392,6 +395,9 @@ public: Error getDisplayIdentificationData(Display display, uint8_t* outPort, std::vector<uint8_t>* outData) override; Error setLayerColorTransform(Display display, Layer layer, const float* matrix) override; + Error getDisplayedContentSamplingAttributes(Display display, PixelFormat* outFormat, + Dataspace* outDataspace, + uint8_t* outComponentMask) override; private: class CommandWriter : public CommandWriterBase { diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 393041d681..b4ac506c6b 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -538,6 +538,14 @@ Error Display::getHdrCapabilities(HdrCapabilities* outCapabilities) const return Error::None; } +Error Display::getDisplayedContentSamplingAttributes(PixelFormat* outFormat, + Dataspace* outDataspace, + uint8_t* outComponentMask) const { + auto intError = mComposer.getDisplayedContentSamplingAttributes(mId, outFormat, outDataspace, + outComponentMask); + return static_cast<Error>(intError); +} + Error Display::getReleaseFences( std::unordered_map<Layer*, sp<Fence>>* outFences) const { diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index d274631f9d..607d9ef718 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -237,6 +237,9 @@ public: [[clang::warn_unused_result]] Error supportsDoze(bool* outSupport) const; [[clang::warn_unused_result]] Error getHdrCapabilities( android::HdrCapabilities* outCapabilities) const; + [[clang::warn_unused_result]] Error getDisplayedContentSamplingAttributes( + android::ui::PixelFormat* outFormat, android::ui::Dataspace* outDataspace, + uint8_t* outComponentMask) const; [[clang::warn_unused_result]] Error getReleaseFences( std::unordered_map<Layer*, android::sp<android::Fence>>* outFences) const; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 9bbc37fe87..c93b4d6acd 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -733,6 +733,20 @@ mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace return matrix; } +status_t HWComposer::getDisplayedContentSamplingAttributes(DisplayId displayId, + ui::PixelFormat* outFormat, + ui::Dataspace* outDataspace, + uint8_t* outComponentMask) { + RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); + const auto error = + mDisplayData[displayId] + .hwcDisplay->getDisplayedContentSamplingAttributes(outFormat, outDataspace, + outComponentMask); + if (error == HWC2::Error::Unsupported) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); + RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); + return NO_ERROR; +} + bool HWComposer::isUsingVrComposer() const { return getComposer()->isUsingVrComposer(); } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 2f579077cc..1e5f971f83 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -125,6 +125,11 @@ public: mat4 getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace); + // Returns the attributes of the color sampling engine. + status_t getDisplayedContentSamplingAttributes(DisplayId displayId, ui::PixelFormat* outFormat, + ui::Dataspace* outDataspace, + uint8_t* outComponentMask); + // Events handling --------------------------------------------------------- // Returns stable display ID (and display name on connection of new or previously disconnected diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 6ac09016bb..81456dfea9 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -123,7 +123,7 @@ Layer::~Layer() { mFrameTracker.logAndResetStats(mName); - destroyAllHwcLayers(); + destroyAllHwcLayersPlusChildren(); mFlinger->onLayerDestroyed(); } @@ -175,6 +175,14 @@ void Layer::onRemovedFromCurrentState() { } } +void Layer::addToCurrentState() { + mRemovedFromCurrentState = false; + + for (const auto& child : mCurrentChildren) { + child->addToCurrentState(); + } +} + // --------------------------------------------------------------------------- // set-up // --------------------------------------------------------------------------- @@ -226,17 +234,21 @@ bool Layer::destroyHwcLayer(DisplayId displayId) { return true; } -void Layer::destroyAllHwcLayers() { +void Layer::destroyHwcLayersForAllDisplays() { size_t numLayers = getBE().mHwcLayers.size(); for (size_t i = 0; i < numLayers; ++i) { LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.empty(), "destroyAllHwcLayers failed"); destroyHwcLayer(getBE().mHwcLayers.begin()->first); } +} + +void Layer::destroyAllHwcLayersPlusChildren() { + destroyHwcLayersForAllDisplays(); LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(), "All hardware composer layers should have been destroyed"); for (const sp<Layer>& child : mDrawingChildren) { - child->destroyAllHwcLayers(); + child->destroyAllHwcLayersPlusChildren(); } } @@ -367,27 +379,24 @@ Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& display) const { // layerstack space, and convert-back to layer space. // if there are no window scaling involved, this operation will map to full // pixels in the buffer. - // FIXME: the 3 lines below can produce slightly incorrect clipping when we have - // a viewport clipping and a window transform. we should use floating point to fix this. - - Rect activeCrop(getActiveWidth(s), getActiveHeight(s)); - Rect crop = getCrop(s); - if (!crop.isEmpty()) { - activeCrop.intersect(crop, &activeCrop); - } + FloatRect activeCropFloat = computeBounds(); ui::Transform t = getTransform(); - activeCrop = t.transform(activeCrop); - if (!activeCrop.intersect(display->getViewport(), &activeCrop)) { + // Transform to screen space. + activeCropFloat = t.transform(activeCropFloat); + activeCropFloat = activeCropFloat.intersect(display->getViewport().toFloatRect()); + // Back to layer space to work with the content crop. + activeCropFloat = t.inverse().transform(activeCropFloat); + // This needs to be here as transform.transform(Rect) computes the + // transformed rect and then takes the bounding box of the result before + // returning. This means + // transform.inverse().transform(transform.transform(Rect)) != Rect + // in which case we need to make sure the final rect is clipped to the + // display bounds. + Rect activeCrop{activeCropFloat}; + if (!activeCrop.intersect(getBufferSize(s), &activeCrop)) { activeCrop.clear(); } - - const auto& p = mDrawingParent.promote(); - if (p != nullptr) { - auto parentCrop = p->computeInitialCrop(display); - activeCrop.intersect(parentCrop, &activeCrop); - } - return activeCrop; } @@ -399,24 +408,8 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& display) const { // In addition there is a WM-specified crop we pull from our drawing state. const State& s(getDrawingState()); - // Screen space to make reduction to parent crop clearer. Rect activeCrop = computeInitialCrop(display); - ui::Transform t = getTransform(); - // Back to layer space to work with the content crop. - activeCrop = t.inverse().transform(activeCrop); - - // This needs to be here as transform.transform(Rect) computes the - // transformed rect and then takes the bounding box of the result before - // returning. This means - // transform.inverse().transform(transform.transform(Rect)) != Rect - // in which case we need to make sure the final rect is clipped to the - // display bounds. - if (!activeCrop.intersect(Rect(getActiveWidth(s), getActiveHeight(s)), &activeCrop)) { - activeCrop.clear(); - } - - // subtract the transparent region and snap to the bounds - activeCrop = reduce(activeCrop, getActiveTransparentRegion(s)); + Rect bufferSize = getBufferSize(s); // Transform the window crop to match the buffer coordinate system, // which means using the inverse of the current transform set on the @@ -437,8 +430,8 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& display) const { ui::Transform(invTransform)).getOrientation(); } - int winWidth = getActiveWidth(s); - int winHeight = getActiveHeight(s); + int winWidth = bufferSize.getWidth(); + int winHeight = bufferSize.getHeight(); if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { // If the activeCrop has been rotate the ends are rotated but not // the space itself so when transforming ends back we can't rely on @@ -450,10 +443,10 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& display) const { if (is_h_flipped == is_v_flipped) { invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H; } - winWidth = getActiveHeight(s); - winHeight = getActiveWidth(s); + std::swap(winWidth, winHeight); } - const Rect winCrop = activeCrop.transform(invTransform, getActiveWidth(s), getActiveHeight(s)); + const Rect winCrop = + activeCrop.transform(invTransform, bufferSize.getWidth(), bufferSize.getHeight()); // below, crop is intersected with winCrop expressed in crop's coordinate space float xScale = crop.getWidth() / float(winWidth); @@ -489,6 +482,8 @@ void Layer::setGeometry(const sp<const DisplayDevice>& display, uint32_t z) { // this gives us only the "orientation" component of the transform const State& s(getDrawingState()); + const int bufferWidth = getBufferSize(s).getWidth(); + const int bufferHeight = getBufferSize(s).getHeight(); auto blendMode = HWC2::BlendMode::None; if (!isOpaque(s) || getAlpha() != 1.0f) { blendMode = @@ -519,16 +514,15 @@ void Layer::setGeometry(const sp<const DisplayDevice>& display, uint32_t z) { // transform.inverse().transform(transform.transform(Rect)) != Rect // in which case we need to make sure the final rect is clipped to the // display bounds. - if (!activeCrop.intersect(Rect(getActiveWidth(s), getActiveHeight(s)), &activeCrop)) { + if (!activeCrop.intersect(Rect(bufferWidth, bufferHeight), &activeCrop)) { activeCrop.clear(); } // mark regions outside the crop as transparent - activeTransparentRegion.orSelf(Rect(0, 0, getActiveWidth(s), activeCrop.top)); - activeTransparentRegion.orSelf( - Rect(0, activeCrop.bottom, getActiveWidth(s), getActiveHeight(s))); + activeTransparentRegion.orSelf(Rect(0, 0, bufferWidth, activeCrop.top)); + activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, bufferWidth, bufferHeight)); activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom)); activeTransparentRegion.orSelf( - Rect(activeCrop.right, activeCrop.top, getActiveWidth(s), activeCrop.bottom)); + Rect(activeCrop.right, activeCrop.top, bufferWidth, activeCrop.bottom)); } // computeBounds returns a FloatRect to provide more accuracy during the @@ -664,11 +658,7 @@ void Layer::updateCursorPosition(const sp<const DisplayDevice>& display) { // Apply the layer's transform, followed by the display's global transform // Here we're guaranteed that the layer's transform preserves rects - Rect win(getActiveWidth(s), getActiveHeight(s)); - Rect crop = getCrop(s); - if (!crop.isEmpty()) { - win.intersect(crop, &win); - } + Rect win = getCroppedBufferSize(s); // Subtract the transparent region and snap to the bounds Rect bounds = reduce(win, getActiveTransparentRegion(s)); Rect frame(getTransform().transform(bounds)); @@ -1602,6 +1592,10 @@ bool Layer::reparent(const sp<IBinder>& newParentHandle) { } newParent->addChild(this); + if (!newParent->isRemovedFromCurrentState()) { + addToCurrentState(); + } + sp<Client> client(mClientRef.promote()); sp<Client> newParentClient(newParent->mClientRef.promote()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index fe8d5a95c9..a4f9c9345b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -491,6 +491,11 @@ public: */ void onRemovedFromCurrentState(); + /* + * Called when the layer is added back to the current state list. + */ + void addToCurrentState(); + // Updates the transform hint in our SurfaceFlingerConsumer to match // the current orientation of the display device. void updateTransformHint(const sp<const DisplayDevice>& display) const; @@ -512,7 +517,8 @@ public: bool createHwcLayer(HWComposer* hwc, DisplayId displayId); bool destroyHwcLayer(DisplayId displayId); - void destroyAllHwcLayers(); + void destroyHwcLayersForAllDisplays(); + void destroyAllHwcLayersPlusChildren(); bool hasHwcLayer(DisplayId displayId) const { return getBE().mHwcLayers.count(displayId) > 0; } @@ -596,6 +602,12 @@ public: int32_t getZ() const; virtual void pushPendingState(); + /** + * Returns active buffer size in the correct orientation. Buffer size is determined by undoing + * any buffer transformations. If the layer has no buffer then return INVALID_RECT. + */ + virtual Rect getBufferSize(const Layer::State&) const { return Rect::INVALID_RECT; } + protected: // constant sp<SurfaceFlinger> mFlinger; @@ -819,12 +831,6 @@ private: * bounds are constrained by its parent bounds. */ Rect getCroppedBufferSize(const Layer::State& s) const; - - /** - * Returns active buffer size in the correct orientation. Buffer size is determined by undoing - * any buffer transformations. If the layer has no buffer then return INVALID_RECT. - */ - virtual Rect getBufferSize(const Layer::State&) const { return Rect::INVALID_RECT; } }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1db87915bc..adc46ccab9 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1114,6 +1114,23 @@ status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& displayToken, return NO_ERROR; } +status_t SurfaceFlinger::getDisplayedContentSamplingAttributes(const sp<IBinder>& displayToken, + ui::PixelFormat* outFormat, + ui::Dataspace* outDataspace, + uint8_t* outComponentMask) const { + if (!outFormat || !outDataspace || !outComponentMask) { + return BAD_VALUE; + } + Mutex::Autolock _l(mStateLock); + const auto display = getDisplayDeviceLocked(displayToken); + if (!display || !display->getId()) { + ALOGE("getDisplayedContentSamplingAttributes: Bad display token: %p", display.get()); + return BAD_VALUE; + } + return getHwComposer().getDisplayedContentSamplingAttributes(*display->getId(), outFormat, + outDataspace, outComponentMask); +} + status_t SurfaceFlinger::enableVSyncInjections(bool enable) { postMessageSync(new LambdaMessage([&] { Mutex::Autolock _l(mStateLock); @@ -2737,6 +2754,17 @@ void SurfaceFlinger::updateCursorAsync() } } +void SurfaceFlinger::latchAndReleaseBuffer(const sp<Layer>& layer) { + if (layer->hasReadyFrame()) { + const nsecs_t expectedPresentTime = mPrimaryDispSync->expectedPresentTime(); + if (layer->shouldPresentNow(expectedPresentTime)) { + bool ignored = false; + layer->latchBuffer(ignored, systemTime(), Fence::NO_FENCE); + } + } + layer->releasePendingBuffer(systemTime()); +} + void SurfaceFlinger::commitTransaction() { if (!mLayersPendingRemoval.isEmpty()) { @@ -2750,11 +2778,9 @@ void SurfaceFlinger::commitTransaction() // showing at its last configured state until we eventually // abandon the buffer queue. if (l->isRemovedFromCurrentState()) { - l->destroyAllHwcLayers(); - // destroyAllHwcLayers traverses to children, but releasePendingBuffer - // doesn't in other scenarios. So we have to traverse explicitly here. l->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* child) { - child->releasePendingBuffer(systemTime()); + child->destroyHwcLayersForAllDisplays(); + latchAndReleaseBuffer(child); }); } } @@ -3207,7 +3233,7 @@ status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, } else { if (parent->isRemovedFromCurrentState()) { ALOGE("addClientLayer called with a removed parent"); - return NAME_NOT_FOUND; + lbc->onRemovedFromCurrentState(); } parent->addChild(lbc); } @@ -3707,11 +3733,24 @@ status_t SurfaceFlinger::createLayer( result = createBufferStateLayer(client, uniqueName, w, h, flags, handle, &layer); break; case ISurfaceComposerClient::eFXSurfaceColor: + // check if buffer size is set for color layer. + if (w > 0 || h > 0) { + ALOGE("createLayer() failed, w or h cannot be set for color layer (w=%d, h=%d)", + int(w), int(h)); + return BAD_VALUE; + } + result = createColorLayer(client, uniqueName, w, h, flags, handle, &layer); break; case ISurfaceComposerClient::eFXSurfaceContainer: + // check if buffer size is set for container layer. + if (w > 0 || h > 0) { + ALOGE("createLayer() failed, w or h cannot be set for container layer (w=%d, h=%d)", + int(w), int(h)); + return BAD_VALUE; + } result = createContainerLayer(client, uniqueName, w, h, flags, handle, &layer); @@ -4725,7 +4764,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case SET_ACTIVE_CONFIG: case SET_ACTIVE_COLOR_MODE: case INJECT_VSYNC: - case SET_POWER_MODE: { + case SET_POWER_MODE: + case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: { if (!callingThreadHasUnscopedSurfaceFlingerAccess()) { IPCThreadState* ipc = IPCThreadState::self(); ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d", @@ -5161,12 +5201,14 @@ status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder, const ui::Transform& getTransform() const override { return mTransform; } Rect getBounds() const override { const Layer::State& layerState(mLayer->getDrawingState()); - return Rect(mLayer->getActiveWidth(layerState), mLayer->getActiveHeight(layerState)); + return mLayer->getBufferSize(layerState); } int getHeight() const override { - return mLayer->getActiveHeight(mLayer->getDrawingState()); + return mLayer->getBufferSize(mLayer->getDrawingState()).getHeight(); + } + int getWidth() const override { + return mLayer->getBufferSize(mLayer->getDrawingState()).getWidth(); } - int getWidth() const override { return mLayer->getActiveWidth(mLayer->getDrawingState()); } bool isSecure() const override { return false; } bool needsFiltering() const override { return mNeedsFiltering; } Rect getSourceCrop() const override { @@ -5240,12 +5282,12 @@ status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder, Rect crop(sourceCrop); if (sourceCrop.width() <= 0) { crop.left = 0; - crop.right = parent->getActiveWidth(parent->getCurrentState()); + crop.right = parent->getBufferSize(parent->getCurrentState()).getWidth(); } if (sourceCrop.height() <= 0) { crop.top = 0; - crop.bottom = parent->getActiveHeight(parent->getCurrentState()); + crop.bottom = parent->getBufferSize(parent->getCurrentState()).getHeight(); } int32_t reqWidth = crop.width() * frameScale; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 4a14de7f73..eff5fca95f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -480,6 +480,9 @@ private: status_t getCompositionPreference(ui::Dataspace* outDataspace, ui::PixelFormat* outPixelFormat, ui::Dataspace* outWideColorGamutDataspace, ui::PixelFormat* outWideColorGamutPixelFormat) const override; + virtual status_t getDisplayedContentSamplingAttributes( + const sp<IBinder>& display, ui::PixelFormat* outFormat, ui::Dataspace* outDataspace, + uint8_t* outComponentMask) const override; /* ------------------------------------------------------------------------ * DeathRecipient interface @@ -549,6 +552,7 @@ private: // Can only be called from the main thread or with mStateLock held uint32_t setTransactionFlags(uint32_t flags); uint32_t setTransactionFlags(uint32_t flags, Scheduler::TransactionStart transactionStart); + void latchAndReleaseBuffer(const sp<Layer>& layer); void commitTransaction(); bool containsAnyInvalidClientState(const Vector<ComposerState>& states); uint32_t setClientStateLocked(const ComposerState& composerState); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index a600a0a5af..7e95d99512 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -334,16 +334,10 @@ protected: virtual sp<SurfaceControl> createLayer(const sp<SurfaceComposerClient>& client, const char* name, uint32_t width, uint32_t height, uint32_t flags = 0) { - auto layer = - client->createSurface(String8(name), width, height, PIXEL_FORMAT_RGBA_8888, flags); - EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl"; + auto layer = createSurface(client, name, width, height, PIXEL_FORMAT_RGBA_8888, flags); Transaction t; t.setLayerStack(layer, mDisplayLayerStack).setLayer(layer, mLayerZBase); - // If we are creating a color layer, set its crop since its size will be ignored. - if (flags == ISurfaceComposerClient::eFXSurfaceColor) { - t.setCrop_legacy(layer, Rect(0, 0, width, height)); - } status_t error = t.apply(); if (error != NO_ERROR) { @@ -354,6 +348,15 @@ protected: return layer; } + virtual sp<SurfaceControl> createSurface(const sp<SurfaceComposerClient>& client, + const char* name, uint32_t width, uint32_t height, + PixelFormat format, uint32_t flags, + SurfaceControl* parent = nullptr) { + auto layer = client->createSurface(String8(name), width, height, format, flags, parent); + EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl"; + return layer; + } + virtual sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height, uint32_t flags = 0) { return createLayer(mClient, name, width, height, flags); @@ -509,9 +512,9 @@ private: mDisplayLayerStack = 0; - mBlackBgSurface = mClient->createSurface(String8("BaseSurface"), mDisplayWidth, - mDisplayHeight, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor); + mBlackBgSurface = + createSurface(mClient, "BaseSurface", 0 /* buffer width */, 0 /* buffer height */, + PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor); // set layer stack (b/68888219) Transaction t; @@ -834,8 +837,9 @@ TEST_P(LayerTypeTransactionTest, SetZBasic) { TEST_P(LayerTypeTransactionTest, SetZNegative) { sp<SurfaceControl> parent = - LayerTransactionTest::createLayer("Parent", mDisplayWidth, mDisplayHeight, + LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */, ISurfaceComposerClient::eFXSurfaceContainer); + Transaction().setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)).apply(); sp<SurfaceControl> layerR; sp<SurfaceControl> layerG; ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); @@ -892,8 +896,9 @@ TEST_P(LayerTypeTransactionTest, SetRelativeZBasic) { TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) { sp<SurfaceControl> parent = - LayerTransactionTest::createLayer("Parent", mDisplayWidth, mDisplayHeight, + LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */, ISurfaceComposerClient::eFXSurfaceContainer); + Transaction().setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)).apply(); sp<SurfaceControl> layerR; sp<SurfaceControl> layerG; sp<SurfaceControl> layerB; @@ -1225,10 +1230,15 @@ TEST_F(LayerTransactionTest, SetColorBasic) { sp<SurfaceControl> colorLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE( - colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); + ASSERT_NO_FATAL_FAILURE(colorLayer = + createLayer("test", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor)); + + Transaction() + .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)) + .setLayer(colorLayer, mLayerZBase + 1) + .apply(); - Transaction().setLayer(colorLayer, mLayerZBase + 1).apply(); { SCOPED_TRACE("default color"); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); @@ -1248,10 +1258,14 @@ TEST_F(LayerTransactionTest, SetColorBasic) { TEST_F(LayerTransactionTest, SetColorClamped) { sp<SurfaceControl> colorLayer; - ASSERT_NO_FATAL_FAILURE( - colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); + ASSERT_NO_FATAL_FAILURE(colorLayer = + createLayer("test", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor)); + Transaction() + .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)) + .setColor(colorLayer, half3(2.0f, -1.0f, 0.0f)) + .apply(); - Transaction().setColor(colorLayer, half3(2.0f, -1.0f, 0.0f)).apply(); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } @@ -1260,8 +1274,10 @@ TEST_F(LayerTransactionTest, SetColorWithAlpha) { sp<SurfaceControl> colorLayer; ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE( - colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); + ASSERT_NO_FATAL_FAILURE(colorLayer = + createLayer("test", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor)); + Transaction().setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)).apply(); const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f); const float alpha = 0.25f; @@ -1285,9 +1301,10 @@ TEST_F(LayerTransactionTest, SetColorWithParentAlpha_Bug74220420) { ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parentWithAlpha", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE(colorLayer = createLayer( - "childWithColor", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); - + ASSERT_NO_FATAL_FAILURE(colorLayer = createLayer("childWithColor", 0 /* buffer width */, + 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor)); + Transaction().setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)).apply(); const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f); const float alpha = 0.25f; const ubyte3 expected((vec3(color) * alpha + vec3(1.0f, 0.0f, 0.0f) * (1.0f - alpha)) * 255.0f); @@ -2129,10 +2146,13 @@ public: TEST_F(LayerTransactionTest, SetColorTransformBasic) { sp<SurfaceControl> colorLayer; - ASSERT_NO_FATAL_FAILURE( - colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor)); - - Transaction().setLayer(colorLayer, mLayerZBase + 1).apply(); + ASSERT_NO_FATAL_FAILURE(colorLayer = + createLayer("test", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor)); + Transaction() + .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)) + .setLayer(colorLayer, mLayerZBase + 1) + .apply(); { SCOPED_TRACE("default color"); screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); @@ -3024,11 +3044,10 @@ TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) { std::unique_ptr<ScreenCapture> sc; sp<SurfaceControl> childNoBuffer = - mClient->createSurface(String8("Bufferless child"), 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - sp<SurfaceControl> childBuffer = - mClient->createSurface(String8("Buffered child"), 20, 20, - PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get()); + createSurface(mClient, "Bufferless child", 0 /* buffer width */, 0 /* buffer height */, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + sp<SurfaceControl> childBuffer = createSurface(mClient, "Buffered child", 20, 20, + PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get()); fillSurfaceRGBA8(childBuffer, 200, 200, 200); SurfaceComposerClient::Transaction{} .setCrop_legacy(childNoBuffer, Rect(0, 0, 10, 10)) @@ -3078,8 +3097,8 @@ class ChildLayerTest : public LayerUpdateTest { protected: void SetUp() override { LayerUpdateTest::SetUp(); - mChild = mClient->createSurface(String8("Child surface"), 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, + mFGSurfaceControl.get()); fillSurfaceRGBA8(mChild, 200, 200, 200); { @@ -3254,8 +3273,7 @@ TEST_F(ChildLayerTest, ReparentChildren) { TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) { sp<SurfaceControl> mGrandChild = - mClient->createSurface(String8("Grand Child"), 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); + createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); fillSurfaceRGBA8(mGrandChild, 111, 111, 111); { @@ -3318,10 +3336,9 @@ TEST_F(ChildLayerTest, DetachChildrenSameClient) { TEST_F(ChildLayerTest, DetachChildrenDifferentClient) { sp<SurfaceComposerClient> mNewComposerClient = new SurfaceComposerClient; sp<SurfaceControl> mChildNewClient = - mNewComposerClient->createSurface(String8("New Child Test Surface"), 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + createSurface(mNewComposerClient, "New Child Test Surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - ASSERT_TRUE(mChildNewClient != nullptr); ASSERT_TRUE(mChildNewClient->isValid()); fillSurfaceRGBA8(mChildNewClient, 200, 200, 200); @@ -3482,9 +3499,8 @@ TEST_F(ChildLayerTest, Bug36858924) { mChild.clear(); // Now recreate it as hidden - mChild = mClient->createSurface(String8("Child surface"), 10, 10, - PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eHidden, - mFGSurfaceControl.get()); + mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eHidden, mFGSurfaceControl.get()); // Show the child layer in a deferred transaction asTransaction([&](Transaction& t) { @@ -3600,9 +3616,8 @@ TEST_F(ChildLayerTest, ReparentFromNoParent) { } TEST_F(ChildLayerTest, NestedChildren) { - sp<SurfaceControl> grandchild = - mClient->createSurface(String8("Grandchild surface"), 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); + sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); fillSurfaceRGBA8(grandchild, 50, 50, 50); { @@ -3640,9 +3655,8 @@ protected: // Verify setting a size on a buffer layer has no effect. TEST_F(BoundlessLayerTest, BufferLayerIgnoresSize) { sp<SurfaceControl> bufferLayer = - mClient->createSurface(String8("BufferLayer"), 45, 45, PIXEL_FORMAT_RGBA_8888, 0, - mFGSurfaceControl.get()); - ASSERT_TRUE(bufferLayer != nullptr); + createSurface(mClient, "BufferLayer", 45, 45, PIXEL_FORMAT_RGBA_8888, 0, + mFGSurfaceControl.get()); ASSERT_TRUE(bufferLayer->isValid()); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::BLACK, 30, 30)); asTransaction([&](Transaction& t) { t.show(bufferLayer); }); @@ -3661,10 +3675,8 @@ TEST_F(BoundlessLayerTest, BufferLayerIgnoresSize) { // which will crop the color layer. TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentBufferBounds) { sp<SurfaceControl> colorLayer = - mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor, - mFGSurfaceControl.get()); - ASSERT_TRUE(colorLayer != nullptr); + createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, mFGSurfaceControl.get()); ASSERT_TRUE(colorLayer->isValid()); asTransaction([&](Transaction& t) { t.setColor(colorLayer, half3{0, 0, 0}); @@ -3684,15 +3696,12 @@ TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentBufferBounds) { // Verify a boundless color layer will fill its parent bounds. The parent has no buffer but has // a crop which will be used to crop the color layer. TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentCropBounds) { - sp<SurfaceControl> cropLayer = - mClient->createSurface(String8("CropLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, - 0 /* flags */, mFGSurfaceControl.get()); - ASSERT_TRUE(cropLayer != nullptr); + sp<SurfaceControl> cropLayer = createSurface(mClient, "CropLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, + 0 /* flags */, mFGSurfaceControl.get()); ASSERT_TRUE(cropLayer->isValid()); sp<SurfaceControl> colorLayer = - mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor, cropLayer.get()); - ASSERT_TRUE(colorLayer != nullptr); + createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, cropLayer.get()); ASSERT_TRUE(colorLayer->isValid()); asTransaction([&](Transaction& t) { t.setCrop_legacy(cropLayer, Rect(5, 5, 10, 10)); @@ -3716,10 +3725,8 @@ TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentCropBounds) { // Verify for boundless layer with no children, their transforms have no effect. TEST_F(BoundlessLayerTest, BoundlessColorLayerTransformHasNoEffect) { sp<SurfaceControl> colorLayer = - mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor, - mFGSurfaceControl.get()); - ASSERT_TRUE(colorLayer != nullptr); + createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, mFGSurfaceControl.get()); ASSERT_TRUE(colorLayer->isValid()); asTransaction([&](Transaction& t) { t.setPosition(colorLayer, 320, 320); @@ -3741,20 +3748,16 @@ TEST_F(BoundlessLayerTest, BoundlessColorLayerTransformHasNoEffect) { // Verify for boundless layer with children, their transforms have an effect. TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerCanSetTransform) { sp<SurfaceControl> boundlessLayerRightShift = - mClient->createSurface(String8("BoundlessLayerRightShift"), 0, 0, - PIXEL_FORMAT_RGBA_8888, 0 /* flags */, mFGSurfaceControl.get()); - ASSERT_TRUE(boundlessLayerRightShift != nullptr); + createSurface(mClient, "BoundlessLayerRightShift", 0, 0, PIXEL_FORMAT_RGBA_8888, + 0 /* flags */, mFGSurfaceControl.get()); ASSERT_TRUE(boundlessLayerRightShift->isValid()); sp<SurfaceControl> boundlessLayerDownShift = - mClient->createSurface(String8("BoundlessLayerLeftShift"), 0, 0, PIXEL_FORMAT_RGBA_8888, - 0 /* flags */, boundlessLayerRightShift.get()); - ASSERT_TRUE(boundlessLayerDownShift != nullptr); + createSurface(mClient, "BoundlessLayerLeftShift", 0, 0, PIXEL_FORMAT_RGBA_8888, + 0 /* flags */, boundlessLayerRightShift.get()); ASSERT_TRUE(boundlessLayerDownShift->isValid()); sp<SurfaceControl> colorLayer = - mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor, - boundlessLayerDownShift.get()); - ASSERT_TRUE(colorLayer != nullptr); + createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, boundlessLayerDownShift.get()); ASSERT_TRUE(colorLayer->isValid()); asTransaction([&](Transaction& t) { t.setPosition(boundlessLayerRightShift, 32, 0); @@ -3815,16 +3818,13 @@ TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerDoNotCrop) { // Verify for boundless root layers with children, their transforms have an effect. TEST_F(BoundlessLayerTest, RootBoundlessLayerCanSetTransform) { - sp<SurfaceControl> rootBoundlessLayer = - mClient->createSurface(String8("RootBoundlessLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, - 0 /* flags */); - ASSERT_TRUE(rootBoundlessLayer != nullptr); + sp<SurfaceControl> rootBoundlessLayer = createSurface(mClient, "RootBoundlessLayer", 0, 0, + PIXEL_FORMAT_RGBA_8888, 0 /* flags */); ASSERT_TRUE(rootBoundlessLayer->isValid()); sp<SurfaceControl> colorLayer = - mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor, - rootBoundlessLayer.get()); - ASSERT_TRUE(colorLayer != nullptr); + createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, rootBoundlessLayer.get()); + ASSERT_TRUE(colorLayer->isValid()); asTransaction([&](Transaction& t) { t.setLayer(rootBoundlessLayer, INT32_MAX - 1); @@ -3864,9 +3864,8 @@ TEST_F(ScreenCaptureTest, CaptureSingleLayer) { TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { auto fgHandle = mFGSurfaceControl->getHandle(); - sp<SurfaceControl> child = - mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, - 0, mFGSurfaceControl.get()); + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); SurfaceComposerClient::Transaction().show(child).apply(true); @@ -3880,9 +3879,8 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) { auto fgHandle = mFGSurfaceControl->getHandle(); - sp<SurfaceControl> child = - mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, - 0, mFGSurfaceControl.get()); + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); SurfaceComposerClient::Transaction().show(child).apply(true); @@ -3894,9 +3892,8 @@ TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) { } TEST_F(ScreenCaptureTest, CaptureTransparent) { - sp<SurfaceControl> child = - mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, - 0, mFGSurfaceControl.get()); + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); @@ -3914,9 +3911,9 @@ TEST_F(ScreenCaptureTest, CaptureTransparent) { TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) { auto fgHandle = mFGSurfaceControl->getHandle(); - sp<SurfaceControl> child = - mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, - 0, mFGSurfaceControl.get()); + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + ASSERT_NE(nullptr, child.get()) << "failed to create surface"; sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 10, 10, 0); fillSurfaceRGBA8(child, 200, 200, 200); fillSurfaceRGBA8(relative, 100, 100, 100); @@ -3937,12 +3934,10 @@ TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) { TEST_F(ScreenCaptureTest, CaptureRelativeInTree) { auto fgHandle = mFGSurfaceControl->getHandle(); - sp<SurfaceControl> child = - mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, - 0, mFGSurfaceControl.get()); - sp<SurfaceControl> relative = - mClient->createSurface(String8("Relative surface"), 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + sp<SurfaceControl> relative = createSurface(mClient, "Relative surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); fillSurfaceRGBA8(relative, 100, 100, 100); @@ -3971,9 +3966,8 @@ public: void SetUp() override { LayerUpdateTest::SetUp(); - mChild = - mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, - 0, mFGSurfaceControl.get()); + mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, + mFGSurfaceControl.get()); fillSurfaceRGBA8(mChild, 200, 200, 200); SurfaceComposerClient::Transaction().show(mChild).apply(true); @@ -4029,14 +4023,12 @@ TEST_F(ScreenCaptureChildOnlyTest, RegressionTest76099859) { TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { auto fgHandle = mFGSurfaceControl->getHandle(); - sp<SurfaceControl> child = - mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, - 0, mFGSurfaceControl.get()); + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); - sp<SurfaceControl> grandchild = - mClient->createSurface(String8("Grandchild surface"), 5, 5, - PIXEL_FORMAT_RGBA_8888, 0, child.get()); + sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5, + PIXEL_FORMAT_RGBA_8888, 0, child.get()); fillSurfaceRGBA8(grandchild, 50, 50, 50); SurfaceComposerClient::Transaction() @@ -4053,9 +4045,8 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { } TEST_F(ScreenCaptureTest, CaptureChildOnly) { - sp<SurfaceControl> child = - mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, - 0, mFGSurfaceControl.get()); + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); auto childHandle = child->getHandle(); @@ -4068,15 +4059,13 @@ TEST_F(ScreenCaptureTest, CaptureChildOnly) { } TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { - sp<SurfaceControl> child = - mClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, - 0, mFGSurfaceControl.get()); + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); fillSurfaceRGBA8(child, 200, 200, 200); auto childHandle = child->getHandle(); - sp<SurfaceControl> grandchild = - mClient->createSurface(String8("Grandchild surface"), 5, 5, - PIXEL_FORMAT_RGBA_8888, 0, child.get()); + sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5, + PIXEL_FORMAT_RGBA_8888, 0, child.get()); fillSurfaceRGBA8(grandchild, 50, 50, 50); SurfaceComposerClient::Transaction() @@ -4095,9 +4084,8 @@ TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { TEST_F(ScreenCaptureTest, CaptureCrop) { sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0); - sp<SurfaceControl> blueLayer = - mClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, - 0, redLayer.get()); + sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30, + PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30)); @@ -4128,9 +4116,8 @@ TEST_F(ScreenCaptureTest, CaptureCrop) { TEST_F(ScreenCaptureTest, CaptureSize) { sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0); - sp<SurfaceControl> blueLayer = - mClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888, - 0, redLayer.get()); + sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30, + PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30)); diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h index c0395c01ce..03ef2f830e 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h @@ -113,6 +113,8 @@ public: MOCK_METHOD4(setLayerInfo, Error(Display, Layer, uint32_t, uint32_t)); MOCK_METHOD3(getRenderIntents, Error(Display, ColorMode, std::vector<RenderIntent>*)); MOCK_METHOD3(setLayerColorTransform, Error(Display, Layer, const float*)); + MOCK_METHOD4(getDisplayedContentSamplingAttributes, + Error(Display, PixelFormat*, Dataspace*, uint8_t*)); }; } // namespace mock diff --git a/services/vr/bufferhubd/buffer_channel.cpp b/services/vr/bufferhubd/buffer_channel.cpp index 589b31a285..6c64bcd279 100644 --- a/services/vr/bufferhubd/buffer_channel.cpp +++ b/services/vr/bufferhubd/buffer_channel.cpp @@ -83,10 +83,13 @@ Status<BufferTraits<BorrowedHandle>> BufferChannel::OnImport( ATRACE_NAME("BufferChannel::OnImport"); ALOGD_IF(TRACE, "BufferChannel::OnImport: buffer=%d.", buffer_id()); + BorrowedHandle ashmem_handle = + BorrowedHandle(buffer_node_->metadata().ashmem_fd().get()); + // TODO(b/112057680) Move away from the GraphicBuffer-based IonBuffer. return BufferTraits<BorrowedHandle>{ /*buffer_handle=*/buffer_node_->buffer_handle(), - /*metadata_handle=*/buffer_node_->metadata().ashmem_handle().Borrow(), + /*metadata_handle=*/ashmem_handle, /*id=*/buffer_id(), /*client_state_mask=*/client_state_mask_, /*metadata_size=*/buffer_node_->metadata().metadata_size(), |