Add metadata store to surfaces
This adds a key/value metadata storage mechanism to
surfaces that allows the windowmanager to pass information
to the surfaceflinger frontend.
This then moves the existing metadata (window type and
ownerUID) into this metadata structure.
Bug: 122925737
Test: Phone boots and surfaces fling. Some unittests
Change-Id: I72c574737b7f75be2311a341812b15d385f507ed
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 0e447d8..0ca3759 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -73,14 +73,10 @@
return lbc;
}
-
-status_t Client::createSurface(
- const String8& name,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- const sp<IBinder>& parentHandle, int32_t windowType, int32_t ownerUid,
- sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp)
-{
+status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t flags, const sp<IBinder>& parentHandle,
+ LayerMetadata metadata, sp<IBinder>* handle,
+ sp<IGraphicBufferProducer>* gbp) {
sp<Layer> parent = nullptr;
if (parentHandle != nullptr) {
auto layerHandle = reinterpret_cast<Layer::Handle*>(parentHandle.get());
@@ -91,14 +87,14 @@
}
// We rely on createLayer to check permissions.
- return mFlinger->createLayer(name, this, w, h, format, flags, windowType,
- ownerUid, handle, gbp, &parent);
+ return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
+ &parent);
}
status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
PixelFormat format, uint32_t flags,
const sp<IGraphicBufferProducer>& parent,
- int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
+ LayerMetadata metadata, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp) {
if (mFlinger->authenticateSurfaceTexture(parent) == false) {
return BAD_VALUE;
@@ -111,8 +107,7 @@
sp<IBinder> parentHandle = layer->getHandle();
- return createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, handle,
- gbp);
+ return createSurface(name, w, h, format, flags, parentHandle, std::move(metadata), handle, gbp);
}
status_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const {
diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h
index 0f5ee4c..74e4818 100644
--- a/services/surfaceflinger/Client.h
+++ b/services/surfaceflinger/Client.h
@@ -51,18 +51,16 @@
private:
// ISurfaceComposerClient interface
- virtual status_t createSurface(
- const String8& name,
- uint32_t w, uint32_t h,PixelFormat format, uint32_t flags,
- const sp<IBinder>& parent, int32_t windowType, int32_t ownerUid,
- sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp);
+ virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t flags, const sp<IBinder>& parent,
+ LayerMetadata metadata, sp<IBinder>* handle,
+ sp<IGraphicBufferProducer>* gbp);
virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
PixelFormat format, uint32_t flags,
const sp<IGraphicBufferProducer>& parent,
- int32_t windowType, int32_t ownerUid,
- sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp);
+ LayerMetadata metadata, sp<IBinder>* handle,
+ sp<IGraphicBufferProducer>* gbp);
virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index ef77590..272793a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -94,8 +94,6 @@
mCurrentState.layerStack = 0;
mCurrentState.sequence = 0;
mCurrentState.requested_legacy = mCurrentState.active_legacy;
- mCurrentState.appId = 0;
- mCurrentState.type = 0;
mCurrentState.active.w = UINT32_MAX;
mCurrentState.active.h = UINT32_MAX;
mCurrentState.active.transform.set(0, 0);
@@ -600,14 +598,16 @@
to_string(error).c_str(), static_cast<int32_t>(error));
getBE().compositionInfo.hwc.z = z;
- int type = s.type;
- int appId = s.appId;
+ int type = s.metadata.getInt32(METADATA_WINDOW_TYPE, 0);
+ int appId = s.metadata.getInt32(METADATA_OWNER_UID, 0);
sp<Layer> parent = mDrawingParent.promote();
if (parent.get()) {
auto& parentState = parent->getDrawingState();
- if (parentState.type >= 0 || parentState.appId >= 0) {
- type = parentState.type;
- appId = parentState.appId;
+ const int parentType = parentState.metadata.getInt32(METADATA_WINDOW_TYPE, 0);
+ const int parentAppId = parentState.metadata.getInt32(METADATA_OWNER_UID, 0);
+ if (parentType >= 0 || parentAppId >= 0) {
+ type = parentType;
+ appId = parentAppId;
}
}
@@ -1316,11 +1316,14 @@
return true;
}
-void Layer::setInfo(int32_t type, int32_t appId) {
- mCurrentState.appId = appId;
- mCurrentState.type = type;
+bool Layer::setMetadata(LayerMetadata data) {
+ bool changed = data.mMap != mCurrentState.metadata.mMap;
+ if (!changed) return false;
+ mCurrentState.metadata = std::move(data);
+ mCurrentState.sequence++;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
+ return true;
}
bool Layer::setLayerStack(uint32_t layerStack) {
@@ -2088,8 +2091,6 @@
layerInfo->set_queued_frames(getQueuedFrameCount());
layerInfo->set_refresh_pending(isBufferLatched());
- layerInfo->set_window_type(state.type);
- layerInfo->set_app_id(state.appId);
layerInfo->set_curr_frame(mCurrentFrameNumber);
layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
@@ -2101,6 +2102,11 @@
barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy);
}
}
+
+ auto protoMap = layerInfo->mutable_metadata();
+ for (const auto& entry : state.metadata.mMap) {
+ (*protoMap)[entry.first] = std::string(entry.second.cbegin(), entry.second.cend());
+ }
}
void Layer::writeToProto(LayerProto* layerInfo, DisplayId displayId) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 685f419..b0efb54 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -167,8 +167,7 @@
Region activeTransparentRegion_legacy;
Region requestedTransparentRegion_legacy;
- int32_t appId;
- int32_t type;
+ LayerMetadata metadata;
// If non-null, a Surface this Surface's Z-order is interpreted relative to.
wp<Layer> zOrderRelativeOf;
@@ -284,7 +283,7 @@
uint64_t frameNumber);
virtual void deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber);
virtual bool setOverrideScalingMode(int32_t overrideScalingMode);
- virtual void setInfo(int32_t type, int32_t appId);
+ virtual bool setMetadata(LayerMetadata data);
virtual bool reparentChildren(const sp<IBinder>& layer);
virtual void setChildrenDrawingParent(const sp<Layer>& layer);
virtual bool reparent(const sp<IBinder>& newParentHandle);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 299499d..04c1ba0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3983,6 +3983,9 @@
ALOGE("Attempt to update InputWindowInfo without permission ACCESS_SURFACE_FLINGER");
}
}
+ if (what & layer_state_t::eMetadataChanged) {
+ if (layer->setMetadata(s.metadata)) flags |= eTraversalNeeded;
+ }
std::vector<sp<CallbackHandle>> callbackHandles;
if ((what & layer_state_t::eListenerCallbacksChanged) && (!s.listenerCallbacks.empty())) {
mTransactionCompletedThread.run();
@@ -4011,13 +4014,10 @@
return flags;
}
-status_t SurfaceFlinger::createLayer(
- const String8& name,
- const sp<Client>& client,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)
-{
+status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
+ uint32_t h, PixelFormat format, uint32_t flags,
+ LayerMetadata metadata, sp<IBinder>* handle,
+ sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent) {
if (int32_t(w|h) < 0) {
ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
int(w), int(h));
@@ -4073,12 +4073,15 @@
// window type is WINDOW_TYPE_DONT_SCREENSHOT from SurfaceControl.java
// TODO b/64227542
- if (windowType == 441731) {
- windowType = 2024; // TYPE_NAVIGATION_BAR_PANEL
- layer->setPrimaryDisplayOnly();
+ if (metadata.has(METADATA_WINDOW_TYPE)) {
+ int32_t windowType = metadata.getInt32(METADATA_WINDOW_TYPE, 0);
+ if (windowType == 441731) {
+ metadata.setInt32(METADATA_WINDOW_TYPE, 2024); // TYPE_NAVIGATION_BAR_PANEL
+ layer->setPrimaryDisplayOnly();
+ }
}
- layer->setInfo(windowType, ownerUid);
+ layer->setMetadata(std::move(metadata));
bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();
result = addClientLayer(client, *handle, *gbp, layer, *parent,
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 68a602c..5219e2f 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -141,7 +141,6 @@
ENHANCED = 2,
};
-
class SurfaceFlingerBE
{
public:
@@ -556,10 +555,9 @@
/* ------------------------------------------------------------------------
* Layer management
*/
- status_t createLayer(const String8& name, const sp<Client>& client,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
- int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent);
+ status_t createLayer(const String8& name, const sp<Client>& client, uint32_t w, uint32_t h,
+ PixelFormat format, uint32_t flags, LayerMetadata metadata,
+ sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent);
status_t createBufferQueueLayer(const sp<Client>& client, const String8& name, uint32_t w,
uint32_t h, uint32_t flags, PixelFormat& format,
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
index ac147fe..cb368b0 100644
--- a/services/surfaceflinger/layerproto/Android.bp
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -1,6 +1,5 @@
cc_library_shared {
name: "liblayers_proto",
- vendor_available: true,
export_include_dirs: ["include"],
srcs: [
@@ -11,6 +10,7 @@
shared_libs: [
"android.hardware.graphics.common@1.1",
+ "libgui",
"libui",
"libprotobuf-cpp-lite",
"libbase",
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index d020a39..5c72fea 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -117,11 +117,15 @@
layer.hwcFrame = generateRect(layerProto.hwc_frame());
layer.hwcCrop = generateFloatRect(layerProto.hwc_crop());
layer.hwcTransform = layerProto.hwc_transform();
- layer.windowType = layerProto.window_type();
- layer.appId = layerProto.app_id();
layer.hwcCompositionType = layerProto.hwc_composition_type();
layer.isProtected = layerProto.is_protected();
layer.cornerRadius = layerProto.corner_radius();
+ for (const auto& entry : layerProto.metadata()) {
+ const std::string& dataStr = entry.second;
+ std::vector<uint8_t>& outData = layer.metadata.mMap[entry.first];
+ outData.resize(dataStr.size());
+ memcpy(outData.data(), dataStr.data(), dataStr.size());
+ }
return layer;
}
@@ -310,7 +314,14 @@
StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str());
StringAppendF(&result, " tr=%s", bufferTransform.to_string().c_str());
StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d,", queuedFrames, refreshPending);
- StringAppendF(&result, " windowType=%d, appId=%d", windowType, appId);
+ StringAppendF(&result, " metadata={");
+ bool first = true;
+ for (const auto& entry : metadata.mMap) {
+ if (!first) result.append(", ");
+ first = false;
+ result.append(metadata.itemToString(entry.first, ":"));
+ }
+ result.append("}");
return result;
}
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index a794ca5..d1b2b1f 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -17,6 +17,7 @@
#include <layerproto/LayerProtoHeader.h>
+#include <gui/LayerMetadata.h>
#include <math/vec4.h>
#include <memory>
@@ -110,11 +111,10 @@
LayerProtoParser::Rect hwcFrame;
LayerProtoParser::FloatRect hwcCrop;
int32_t hwcTransform;
- int32_t windowType;
- int32_t appId;
int32_t hwcCompositionType;
bool isProtected;
float cornerRadius;
+ LayerMetadata metadata;
std::string to_string() const;
};
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index b100438..4c756d9 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -74,8 +74,8 @@
optional FloatRectProto hwc_crop = 31;
// The layer's composer backend transform
optional int32 hwc_transform = 32;
- optional int32 window_type = 33;
- optional int32 app_id = 34;
+ optional int32 window_type = 33 [deprecated=true];
+ optional int32 app_id = 34 [deprecated=true];
// The layer's composition type
optional int32 hwc_composition_type = 35;
// If it's a buffer layer, indicate if the content is protected
@@ -89,6 +89,8 @@
optional int32 effective_scaling_mode = 40;
// Layer's corner radius.
optional float corner_radius = 41;
+ // Metadata map. May be empty.
+ map<int32, bytes> metadata = 42;
}
message PositionProto {
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index e34e568..b2bcb45 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -42,6 +42,7 @@
"EventThreadTest.cpp",
"IdleTimerTest.cpp",
"LayerHistoryTest.cpp",
+ "LayerMetadataTest.cpp",
"SchedulerTest.cpp",
"SchedulerUtilsTest.cpp",
"RefreshRateStatsTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp b/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp
new file mode 100644
index 0000000..92c9f92
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LibSurfaceFlingerUnittests"
+
+#include <binder/Parcel.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <gui/LayerMetadata.h>
+#include <log/log.h>
+
+namespace android {
+namespace {
+
+class LayerMetadataTest : public testing::Test {
+public:
+ LayerMetadataTest();
+ ~LayerMetadataTest() override;
+};
+
+LayerMetadataTest::LayerMetadataTest() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+}
+
+LayerMetadataTest::~LayerMetadataTest() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+}
+
+TEST_F(LayerMetadataTest, testLayerMetadata) {
+ LayerMetadata metadata;
+
+ ASSERT_EQ(0, metadata.mMap.size());
+
+ // Test non-set
+ ASSERT_EQ(3, metadata.getInt32(4, 3));
+
+ // Make sure it's still unset
+ ASSERT_EQ(5, metadata.getInt32(4, 5));
+
+ metadata.setInt32(4, 2);
+ ASSERT_EQ(2, metadata.getInt32(4, 0));
+
+ // data is too small
+ metadata.mMap[2] = std::vector<uint8_t>{'a', 'b'};
+ ASSERT_EQ(0, metadata.getInt32(2, 0));
+
+ LayerMetadata second;
+ std::vector<uint8_t> someData{'c', 'd', '\0'};
+ second.mMap[2] = someData;
+ second.setInt32(6, 5);
+ metadata.merge(second);
+
+ ASSERT_EQ(3, metadata.mMap.size());
+ ASSERT_EQ(someData, second.mMap[2]);
+ ASSERT_EQ(5, metadata.getInt32(6, 0));
+ ASSERT_EQ(2, metadata.getInt32(4, 0));
+
+ Parcel p;
+ metadata.writeToParcel(&p);
+ LayerMetadata reconstructed;
+ reconstructed.setInt32(3, 1); // to make sure it gets replaced
+ p.setDataPosition(0);
+ reconstructed.readFromParcel(&p);
+ ASSERT_EQ(metadata.mMap, reconstructed.mMap);
+}
+
+} // namespace
+} // namespace android