[SurfaceFlinger] add getDisplayedContentSamplingAttributes i/f
Add interface to ISurfaceComposer that can query the
graphics.composer for querying the displayed content sampling
engine's supported attributes.
Bug: 116028618
Test: Boot
Test: ran test client against prototype, see attributes reported
Test: Ran new test './libgui_test --gtest_filter="DisplayedContentSamp*"'
Test: on hwc with and without new function hook.
Change-Id: Ie4bebd98d134e63a9f3e21f79ae519a1fe8055b0
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 69e5379..80d435f 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -599,6 +599,43 @@
}
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 @@
}
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 87c6f27..41e5abb 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1077,6 +1077,15 @@
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 761f31a..3b6c6e4 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -293,6 +293,13 @@
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 @@
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 10c27b1..cf55b6b 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -381,6 +381,11 @@
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 a6295e0..6de641d 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -17,6 +17,7 @@
"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 0000000..f2c0e0c
--- /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/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 4ba7da3..3950bb6 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -641,6 +641,12 @@
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/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index f0bccaa..b919da7 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -1023,6 +1023,33 @@
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 4188352..c39171e 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -193,6 +193,9 @@
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 @@
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 393041d..b4ac506 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -538,6 +538,14 @@
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 d274631..607d9ef 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -237,6 +237,9 @@
[[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 9bbc37f..c93b4d6 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -733,6 +733,20 @@
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 2f57907..1e5f971 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -125,6 +125,11 @@
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/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1db8791..6bd43aa 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1114,6 +1114,23 @@
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);
@@ -4725,7 +4742,8 @@
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",
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4a14de7..18accee 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -480,6 +480,9 @@
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
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index c0395c0..03ef2f8 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -113,6 +113,8 @@
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