Use std::string in DeviceProductInfo and serialize it as Flattenable
Use std::string instead of fixed size char arrays. Serialize
DeviceProductInfo and DisplayInfo as Flattenable instead of using
memcpy().
Bug: 145299597
Test: 1. m
2. adb shell dumpsys display
3. check that DeviceProductInfo is correctly populated
Change-Id: Id21186138b39d7bb167c41ff7ee9387081ac6285
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 04c21a9..e1c112a 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -371,10 +371,8 @@
data.writeStrongBinder(display);
remote()->transact(BnSurfaceComposer::GET_DISPLAY_INFO, data, &reply);
const status_t result = reply.readInt32();
- if (result == NO_ERROR) {
- memcpy(info, reply.readInplace(sizeof(DisplayInfo)), sizeof(DisplayInfo));
- }
- return result;
+ if (result != NO_ERROR) return result;
+ return reply.read(*info);
}
virtual status_t getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayConfig>* configs) {
@@ -1377,10 +1375,8 @@
const sp<IBinder> display = data.readStrongBinder();
const status_t result = getDisplayInfo(display, &info);
reply->writeInt32(result);
- if (result == NO_ERROR) {
- memcpy(reply->writeInplace(sizeof(DisplayInfo)), &info, sizeof(DisplayInfo));
- }
- return NO_ERROR;
+ if (result != NO_ERROR) return result;
+ return reply->write(info);
}
case GET_DISPLAY_CONFIGS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 9f7f36f..3965cf0 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -46,7 +46,7 @@
apex_available: [
"//apex_available:anyapex",
- "//apex_available:platform",
+ "//apex_available:platform",
],
shared_libs: [
"libutils",
@@ -97,6 +97,8 @@
"BufferHubEventFd.cpp",
"BufferHubMetadata.cpp",
"DebugUtils.cpp",
+ "DeviceProductInfo.cpp",
+ "DisplayInfo.cpp",
"Fence.cpp",
"FenceTime.cpp",
"FrameStats.cpp",
diff --git a/libs/ui/DeviceProductInfo.cpp b/libs/ui/DeviceProductInfo.cpp
new file mode 100644
index 0000000..efd61b6
--- /dev/null
+++ b/libs/ui/DeviceProductInfo.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2020 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 <ui/DeviceProductInfo.h>
+
+#include <ui/FlattenableHelpers.h>
+
+namespace android {
+
+size_t DeviceProductInfo::getFlattenedSize() const {
+ return FlattenableHelpers::getFlattenedSize(name) + sizeof(manufacturerPnpId) +
+ FlattenableHelpers::getFlattenedSize(productId) + sizeof(manufactureOrModelDate);
+}
+
+status_t DeviceProductInfo::flatten(void* buffer, size_t size) const {
+ if (size < getFlattenedSize()) {
+ return NO_MEMORY;
+ }
+ FlattenableHelpers::write(buffer, size, name);
+ FlattenableUtils::write(buffer, size, manufacturerPnpId);
+ FlattenableHelpers::write(buffer, size, productId);
+ FlattenableUtils::write(buffer, size, manufactureOrModelDate);
+ return NO_ERROR;
+}
+
+status_t DeviceProductInfo::unflatten(void const* buffer, size_t size) {
+ if (size < getFlattenedSize()) {
+ return NO_MEMORY;
+ }
+ FlattenableHelpers::read(buffer, size, &name);
+ FlattenableUtils::read(buffer, size, manufacturerPnpId);
+ FlattenableHelpers::read(buffer, size, &productId);
+ FlattenableUtils::read(buffer, size, manufactureOrModelDate);
+ return NO_ERROR;
+}
+
+} // namespace android
diff --git a/libs/ui/DisplayInfo.cpp b/libs/ui/DisplayInfo.cpp
new file mode 100644
index 0000000..6ed7e19
--- /dev/null
+++ b/libs/ui/DisplayInfo.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2020 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 <ui/DisplayInfo.h>
+
+#include <cstdint>
+
+#include <ui/FlattenableHelpers.h>
+
+namespace android {
+
+size_t DisplayInfo::getFlattenedSize() const {
+ return sizeof(connectionType) + sizeof(density) + sizeof(secure) +
+ FlattenableHelpers::getFlattenedSize(deviceProductInfo);
+}
+
+status_t DisplayInfo::flatten(void* buffer, size_t size) const {
+ if (size < getFlattenedSize()) {
+ return NO_MEMORY;
+ }
+ FlattenableUtils::write(buffer, size, connectionType);
+ FlattenableUtils::write(buffer, size, density);
+ FlattenableUtils::write(buffer, size, secure);
+ FlattenableHelpers::write(buffer, size, deviceProductInfo);
+
+ return NO_ERROR;
+}
+
+status_t DisplayInfo::unflatten(void const* buffer, size_t size) {
+ if (size < getFlattenedSize()) {
+ return NO_MEMORY;
+ }
+ FlattenableUtils::read(buffer, size, connectionType);
+ FlattenableUtils::read(buffer, size, density);
+ FlattenableUtils::read(buffer, size, secure);
+ FlattenableHelpers::read(buffer, size, &deviceProductInfo);
+
+ return NO_ERROR;
+}
+
+} // namespace android
diff --git a/libs/ui/include/ui/DeviceProductInfo.h b/libs/ui/include/ui/DeviceProductInfo.h
index c396e73..cc5ebe4 100644
--- a/libs/ui/include/ui/DeviceProductInfo.h
+++ b/libs/ui/include/ui/DeviceProductInfo.h
@@ -19,8 +19,12 @@
#include <array>
#include <cstdint>
#include <optional>
+#include <string>
+#include <type_traits>
#include <variant>
+#include <utils/Flattenable.h>
+
namespace android {
// NUL-terminated plug and play ID.
@@ -29,9 +33,7 @@
// Product-specific information about the display or the directly connected device on the
// display chain. For example, if the display is transitively connected, this field may contain
// product information about the intermediate device.
-struct DeviceProductInfo {
- static constexpr size_t TEXT_BUFFER_SIZE = 20;
-
+struct DeviceProductInfo : LightFlattenable<DeviceProductInfo> {
struct ModelYear {
uint32_t year;
};
@@ -44,16 +46,22 @@
};
// Display name.
- std::array<char, TEXT_BUFFER_SIZE> name;
+ std::string name;
// Manufacturer Plug and Play ID.
PnpId manufacturerPnpId;
// Manufacturer product ID.
- std::array<char, TEXT_BUFFER_SIZE> productId;
+ std::string productId;
using ManufactureOrModelDate = std::variant<ModelYear, ManufactureYear, ManufactureWeekAndYear>;
+ static_assert(std::is_trivially_copyable_v<ManufactureOrModelDate>);
ManufactureOrModelDate manufactureOrModelDate;
+
+ bool isFixedSize() const { return false; }
+ size_t getFlattenedSize() const;
+ status_t flatten(void* buffer, size_t size) const;
+ status_t unflatten(void const* buffer, size_t size);
};
} // namespace android
diff --git a/libs/ui/include/ui/DisplayInfo.h b/libs/ui/include/ui/DisplayInfo.h
index 897060c..03e0a38 100644
--- a/libs/ui/include/ui/DisplayInfo.h
+++ b/libs/ui/include/ui/DisplayInfo.h
@@ -20,19 +20,23 @@
#include <type_traits>
#include <ui/DeviceProductInfo.h>
+#include <utils/Flattenable.h>
namespace android {
enum class DisplayConnectionType { Internal, External };
// Immutable information about physical display.
-struct DisplayInfo {
+struct DisplayInfo : LightFlattenable<DisplayInfo> {
DisplayConnectionType connectionType = DisplayConnectionType::Internal;
float density = 0.f;
bool secure = false;
std::optional<DeviceProductInfo> deviceProductInfo;
-};
-static_assert(std::is_trivially_copyable_v<DisplayInfo>);
+ bool isFixedSize() const { return false; }
+ size_t getFlattenedSize() const;
+ status_t flatten(void* buffer, size_t size) const;
+ status_t unflatten(void const* buffer, size_t size);
+};
} // namespace android
diff --git a/libs/ui/include_private/ui/FlattenableHelpers.h b/libs/ui/include_private/ui/FlattenableHelpers.h
new file mode 100644
index 0000000..bdf4804
--- /dev/null
+++ b/libs/ui/include_private/ui/FlattenableHelpers.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#pragma once
+
+#include <optional>
+#include <type_traits>
+
+#include <utils/Flattenable.h>
+
+namespace android {
+
+struct FlattenableHelpers {
+ // Flattenable helpers for reading and writing std::string
+ static size_t getFlattenedSize(const std::string& str) { return str.length() + 1; }
+
+ static void write(void*& buffer, size_t& size, const std::string& str) {
+ strcpy(reinterpret_cast<char*>(buffer), str.c_str());
+ FlattenableUtils::advance(buffer, size, getFlattenedSize(str));
+ }
+
+ static void read(void const*& buffer, size_t& size, std::string* str) {
+ str->assign(reinterpret_cast<const char*>(buffer));
+ FlattenableUtils::advance(buffer, size, getFlattenedSize(*str));
+ }
+
+ // Flattenable utils for reading and writing std::optional
+ template <class T, typename = std::enable_if_t<std::is_base_of_v<LightFlattenable<T>, T>>>
+ static size_t getFlattenedSize(const std::optional<T>& value) {
+ return sizeof(bool) + (value ? value->getFlattenedSize() : 0);
+ }
+
+ template <class T, typename = std::enable_if_t<std::is_base_of_v<LightFlattenable<T>, T>>>
+ static void write(void*& buffer, size_t& size, const std::optional<T>& value) {
+ if (value) {
+ FlattenableUtils::write(buffer, size, true);
+ value->flatten(buffer, size);
+ FlattenableUtils::advance(buffer, size, value->getFlattenedSize());
+ } else {
+ FlattenableUtils::write(buffer, size, false);
+ }
+ }
+
+ template <class T, typename = std::enable_if_t<std::is_base_of_v<LightFlattenable<T>, T>>>
+ static void read(void const*& buffer, size_t& size, std::optional<T>* value) {
+ bool isPresent;
+ FlattenableUtils::read(buffer, size, isPresent);
+ if (isPresent) {
+ *value = T();
+ (*value)->unflatten(buffer, size);
+ FlattenableUtils::advance(buffer, size, (*value)->getFlattenedSize());
+ } else {
+ value->reset();
+ }
+ }
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
index f24f314..63897cc 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
@@ -70,12 +70,8 @@
DeviceProductInfo buildDeviceProductInfo(const Edid& edid) {
DeviceProductInfo info;
- std::copy(edid.displayName.begin(), edid.displayName.end(), info.name.begin());
- info.name[edid.displayName.size()] = '\0';
-
- const auto productId = std::to_string(edid.productId);
- std::copy(productId.begin(), productId.end(), info.productId.begin());
- info.productId[productId.size()] = '\0';
+ info.name.assign(edid.displayName);
+ info.productId = std::to_string(edid.productId);
info.manufacturerPnpId = edid.pnpId;
constexpr uint8_t kModelYearFlag = 0xff;
@@ -181,7 +177,6 @@
constexpr size_t kDescriptorCount = 4;
constexpr size_t kDescriptorLength = 18;
- static_assert(kDescriptorLength - kEdidHeaderLength < DeviceProductInfo::TEXT_BUFFER_SIZE);
for (size_t i = 0; i < kDescriptorCount; i++) {
if (view.size() < kDescriptorLength) {
diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
index c2ddfce..2c7a281 100644
--- a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
@@ -293,9 +293,9 @@
ASSERT_TRUE(displayIdInfo);
ASSERT_TRUE(displayIdInfo->deviceProductInfo);
const auto& info = *displayIdInfo->deviceProductInfo;
- EXPECT_STREQ("", info.name.data());
+ EXPECT_EQ("", info.name);
EXPECT_STREQ("SEC", info.manufacturerPnpId.data());
- EXPECT_STREQ("12610", info.productId.data());
+ EXPECT_EQ("12610", info.productId);
ASSERT_TRUE(std::holds_alternative<ManufactureYear>(info.manufactureOrModelDate));
EXPECT_EQ(2011, std::get<ManufactureYear>(info.manufactureOrModelDate).year);
}
@@ -304,9 +304,9 @@
ASSERT_TRUE(displayIdInfo);
ASSERT_TRUE(displayIdInfo->deviceProductInfo);
const auto& info = *displayIdInfo->deviceProductInfo;
- EXPECT_STREQ("HP ZR30w", info.name.data());
+ EXPECT_EQ("HP ZR30w", info.name);
EXPECT_STREQ("HWP", info.manufacturerPnpId.data());
- EXPECT_STREQ("10348", info.productId.data());
+ EXPECT_EQ("10348", info.productId);
ASSERT_TRUE(std::holds_alternative<ManufactureWeekAndYear>(info.manufactureOrModelDate));
const auto& date = std::get<ManufactureWeekAndYear>(info.manufactureOrModelDate);
EXPECT_EQ(2012, date.year);
@@ -317,9 +317,9 @@
ASSERT_TRUE(displayIdInfo);
ASSERT_TRUE(displayIdInfo->deviceProductInfo);
const auto& info = *displayIdInfo->deviceProductInfo;
- EXPECT_STREQ("SAMSUNG", info.name.data());
+ EXPECT_EQ("SAMSUNG", info.name);
EXPECT_STREQ("SAM", info.manufacturerPnpId.data());
- EXPECT_STREQ("2302", info.productId.data());
+ EXPECT_EQ("2302", info.productId);
ASSERT_TRUE(std::holds_alternative<ManufactureWeekAndYear>(info.manufactureOrModelDate));
const auto& date = std::get<ManufactureWeekAndYear>(info.manufactureOrModelDate);
EXPECT_EQ(2011, date.year);
@@ -330,9 +330,9 @@
ASSERT_TRUE(displayIdInfo);
ASSERT_TRUE(displayIdInfo->deviceProductInfo);
const auto& info = *displayIdInfo->deviceProductInfo;
- EXPECT_STREQ("Panasonic-TV", info.name.data());
+ EXPECT_EQ("Panasonic-TV", info.name);
EXPECT_STREQ("MEI", info.manufacturerPnpId.data());
- EXPECT_STREQ("41622", info.productId.data());
+ EXPECT_EQ("41622", info.productId);
ASSERT_TRUE(std::holds_alternative<ManufactureYear>(info.manufactureOrModelDate));
const auto& date = std::get<ManufactureYear>(info.manufactureOrModelDate);
EXPECT_EQ(2019, date.year);
@@ -342,9 +342,9 @@
ASSERT_TRUE(displayIdInfo);
ASSERT_TRUE(displayIdInfo->deviceProductInfo);
const auto& info = *displayIdInfo->deviceProductInfo;
- EXPECT_STREQ("Hisense", info.name.data());
+ EXPECT_EQ("Hisense", info.name);
EXPECT_STREQ("HEC", info.manufacturerPnpId.data());
- EXPECT_STREQ("0", info.productId.data());
+ EXPECT_EQ("0", info.productId);
ASSERT_TRUE(std::holds_alternative<ManufactureWeekAndYear>(info.manufactureOrModelDate));
const auto& date = std::get<ManufactureWeekAndYear>(info.manufactureOrModelDate);
EXPECT_EQ(2019, date.year);
@@ -355,9 +355,9 @@
ASSERT_TRUE(displayIdInfo);
ASSERT_TRUE(displayIdInfo->deviceProductInfo);
const auto& info = *displayIdInfo->deviceProductInfo;
- EXPECT_STREQ("LP2361", info.name.data());
+ EXPECT_EQ("LP2361", info.name);
EXPECT_STREQ("CTL", info.manufacturerPnpId.data());
- EXPECT_STREQ("9373", info.productId.data());
+ EXPECT_EQ("9373", info.productId);
ASSERT_TRUE(std::holds_alternative<ModelYear>(info.manufactureOrModelDate));
EXPECT_EQ(2013, std::get<ModelYear>(info.manufactureOrModelDate).year);
}