summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/installd/dexopt.cpp8
-rw-r--r--data/etc/car_core_hardware.xml1
-rw-r--r--libs/graphicsenv/Android.bp3
-rw-r--r--libs/graphicsenv/GraphicsEnv.cpp140
-rw-r--r--libs/gui/ISurfaceComposer.cpp53
-rw-r--r--libs/gui/SurfaceComposerClient.cpp9
-rw-r--r--libs/gui/include/gui/ISurfaceComposer.h8
-rw-r--r--libs/gui/include/gui/SurfaceComposerClient.h5
-rw-r--r--libs/gui/tests/Android.bp1
-rw-r--r--libs/gui/tests/DisplayedContentSampling_test.cpp68
-rw-r--r--libs/gui/tests/EndToEndNativeInputTest.cpp5
-rw-r--r--libs/gui/tests/Surface_test.cpp6
-rw-r--r--libs/ui/Android.bp4
-rw-r--r--libs/ui/BufferHubBuffer.cpp20
-rw-r--r--libs/ui/BufferHubMetadata.cpp24
-rw-r--r--libs/ui/GraphicBuffer.cpp25
-rw-r--r--libs/ui/include/ui/BufferHubBuffer.h13
-rw-r--r--libs/ui/include/ui/BufferHubMetadata.h24
-rw-r--r--libs/ui/include/ui/GraphicBuffer.h19
-rw-r--r--libs/ui/tests/Android.bp16
-rw-r--r--libs/ui/tests/BufferHubBuffer_test.cpp19
-rw-r--r--libs/ui/tests/BufferHubMetadata_test.cpp22
-rw-r--r--libs/ui/tests/GraphicBuffer_test.cpp54
-rw-r--r--opengl/libs/EGL/Loader.cpp85
-rw-r--r--services/sensorservice/SensorEventConnection.cpp76
-rw-r--r--services/sensorservice/SensorEventConnection.h4
-rw-r--r--services/surfaceflinger/BufferLayer.cpp14
-rw-r--r--services/surfaceflinger/DisplayHardware/ComposerHal.cpp27
-rw-r--r--services/surfaceflinger/DisplayHardware/ComposerHal.h6
-rw-r--r--services/surfaceflinger/DisplayHardware/HWC2.cpp8
-rw-r--r--services/surfaceflinger/DisplayHardware/HWC2.h3
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp14
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h5
-rw-r--r--services/surfaceflinger/Layer.cpp98
-rw-r--r--services/surfaceflinger/Layer.h20
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp64
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h4
-rw-r--r--services/surfaceflinger/tests/Transaction_test.cpp233
-rw-r--r--services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h2
-rw-r--r--services/vr/bufferhubd/buffer_channel.cpp5
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(),