Loading libs/ui/DisplayIdentification.cpp +58 −11 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <ftl/hash.h> #include <log/log.h> #include <ui/DisplayIdentification.h> #include <ui/Size.h> namespace android { namespace { Loading @@ -46,6 +47,10 @@ std::optional<uint8_t> getEdidDescriptorType(const byte_view& view) { return view[3]; } bool isDetailedTimingDescriptor(const byte_view& view) { return view[0] != 0 && view[1] != 0; } std::string_view parseEdidText(const byte_view& view) { std::string_view text(reinterpret_cast<const char*>(view.data()), view.size()); text = text.substr(0, text.find('\n')); Loading Loading @@ -219,6 +224,8 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) { std::string_view displayName; std::string_view serialNumber; std::string_view asciiText; ui::Size preferredDTDPixelSize; ui::Size preferredDTDPhysicalSize; constexpr size_t kDescriptorCount = 4; constexpr size_t kDescriptorLength = 18; Loading @@ -243,6 +250,35 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) { serialNumber = parseEdidText(descriptor); break; } } else if (isDetailedTimingDescriptor(view)) { static constexpr size_t kHorizontalPhysicalLsbOffset = 12; static constexpr size_t kHorizontalPhysicalMsbOffset = 14; static constexpr size_t kVerticalPhysicalLsbOffset = 13; static constexpr size_t kVerticalPhysicalMsbOffset = 14; const uint32_t hSize = static_cast<uint32_t>(view[kHorizontalPhysicalLsbOffset] | ((view[kHorizontalPhysicalMsbOffset] >> 4) << 8)); const uint32_t vSize = static_cast<uint32_t>(view[kVerticalPhysicalLsbOffset] | ((view[kVerticalPhysicalMsbOffset] & 0b1111) << 8)); static constexpr size_t kHorizontalPixelLsbOffset = 2; static constexpr size_t kHorizontalPixelMsbOffset = 4; static constexpr size_t kVerticalPixelLsbOffset = 5; static constexpr size_t kVerticalPixelMsbOffset = 7; const uint8_t hLsb = view[kHorizontalPixelLsbOffset]; const uint8_t hMsb = view[kHorizontalPixelMsbOffset]; const int32_t hPixel = hLsb + ((hMsb & 0xF0) << 4); const uint8_t vLsb = view[kVerticalPixelLsbOffset]; const uint8_t vMsb = view[kVerticalPixelMsbOffset]; const int32_t vPixel = vLsb + ((vMsb & 0xF0) << 4); preferredDTDPixelSize.setWidth(hPixel); preferredDTDPixelSize.setHeight(vPixel); preferredDTDPhysicalSize.setWidth(hSize); preferredDTDPhysicalSize.setHeight(vSize); } view = view.subspan(kDescriptorLength); Loading Loading @@ -297,14 +333,22 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) { } } return Edid{.manufacturerId = manufacturerId, DetailedTimingDescriptor preferredDetailedTimingDescriptor{ .pixelSizeCount = preferredDTDPixelSize, .physicalSizeInMm = preferredDTDPhysicalSize, }; return Edid{ .manufacturerId = manufacturerId, .productId = productId, .pnpId = *pnpId, .modelHash = modelHash, .displayName = displayName, .manufactureOrModelYear = manufactureOrModelYear, .manufactureWeek = manufactureWeek, .cea861Block = cea861Block}; .cea861Block = cea861Block, .preferredDetailedTimingDescriptor = preferredDetailedTimingDescriptor, }; } std::optional<PnpId> getPnpId(uint16_t manufacturerId) { Loading Loading @@ -336,9 +380,12 @@ std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData( } const auto displayId = PhysicalDisplayId::fromEdid(port, edid->manufacturerId, edid->modelHash); return DisplayIdentificationInfo{.id = displayId, return DisplayIdentificationInfo{ .id = displayId, .name = std::string(edid->displayName), .deviceProductInfo = buildDeviceProductInfo(*edid)}; .deviceProductInfo = buildDeviceProductInfo(*edid), .preferredDetailedTimingDescriptor = edid->preferredDetailedTimingDescriptor, }; } PhysicalDisplayId getVirtualDisplayId(uint32_t id) { Loading libs/ui/include/ui/DisplayIdentification.h +8 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <ui/DeviceProductInfo.h> #include <ui/DisplayId.h> #include <ui/Size.h> #define LEGACY_DISPLAY_TYPE_PRIMARY 0 #define LEGACY_DISPLAY_TYPE_EXTERNAL 1 Loading @@ -33,10 +34,16 @@ namespace android { using DisplayIdentificationData = std::vector<uint8_t>; struct DetailedTimingDescriptor { ui::Size pixelSizeCount; ui::Size physicalSizeInMm; }; struct DisplayIdentificationInfo { PhysicalDisplayId id; std::string name; std::optional<DeviceProductInfo> deviceProductInfo; std::optional<DetailedTimingDescriptor> preferredDetailedTimingDescriptor; }; struct ExtensionBlock { Loading Loading @@ -68,6 +75,7 @@ struct Edid { uint8_t manufactureOrModelYear; uint8_t manufactureWeek; std::optional<Cea861ExtensionBlock> cea861Block; std::optional<DetailedTimingDescriptor> preferredDetailedTimingDescriptor; }; bool isEdid(const DisplayIdentificationData&); Loading libs/ui/tests/DisplayIdentification_test.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -194,6 +194,10 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(21, edid->manufactureOrModelYear); EXPECT_EQ(0, edid->manufactureWeek); EXPECT_FALSE(edid->cea861Block); EXPECT_EQ(1280, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width); EXPECT_EQ(800, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height); EXPECT_EQ(261, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width); EXPECT_EQ(163, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height); edid = parseEdid(getExternalEdid()); ASSERT_TRUE(edid); Loading @@ -206,6 +210,10 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(22, edid->manufactureOrModelYear); EXPECT_EQ(2, edid->manufactureWeek); EXPECT_FALSE(edid->cea861Block); EXPECT_EQ(1280, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width); EXPECT_EQ(800, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height); EXPECT_EQ(641, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width); EXPECT_EQ(400, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height); edid = parseEdid(getExternalEedid()); ASSERT_TRUE(edid); Loading @@ -224,6 +232,10 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(0, physicalAddress.b); EXPECT_EQ(0, physicalAddress.c); EXPECT_EQ(0, physicalAddress.d); EXPECT_EQ(1366, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width); EXPECT_EQ(768, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height); EXPECT_EQ(160, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width); EXPECT_EQ(90, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height); edid = parseEdid(getPanasonicTvEdid()); ASSERT_TRUE(edid); Loading @@ -242,6 +254,10 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(0, physicalAddress.b); EXPECT_EQ(0, physicalAddress.c); EXPECT_EQ(0, physicalAddress.d); EXPECT_EQ(1920, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width); EXPECT_EQ(1080, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height); EXPECT_EQ(698, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width); EXPECT_EQ(392, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height); edid = parseEdid(getHisenseTvEdid()); ASSERT_TRUE(edid); Loading @@ -260,6 +276,10 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(2, physicalAddress.b); EXPECT_EQ(3, physicalAddress.c); EXPECT_EQ(4, physicalAddress.d); EXPECT_EQ(1920, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width); EXPECT_EQ(1080, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height); EXPECT_EQ(575, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width); EXPECT_EQ(323, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height); edid = parseEdid(getCtlDisplayEdid()); ASSERT_TRUE(edid); Loading @@ -273,6 +293,10 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(0xff, edid->manufactureWeek); ASSERT_TRUE(edid->cea861Block); EXPECT_FALSE(edid->cea861Block->hdmiVendorDataBlock); EXPECT_EQ(1360, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width); EXPECT_EQ(768, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height); EXPECT_EQ(521, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width); EXPECT_EQ(293, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height); } TEST(DisplayIdentificationTest, parseInvalidEdid) { Loading services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +2 −1 Original line number Diff line number Diff line Loading @@ -51,7 +51,8 @@ public: MOCK_CONST_METHOD0(getMaxVirtualDisplayCount, size_t()); MOCK_CONST_METHOD0(getMaxVirtualDisplayDimension, size_t()); MOCK_METHOD3(allocateVirtualDisplay, bool(HalVirtualDisplayId, ui::Size, ui::PixelFormat*)); MOCK_METHOD2(allocatePhysicalDisplay, void(hal::HWDisplayId, PhysicalDisplayId)); MOCK_METHOD3(allocatePhysicalDisplay, void(hal::HWDisplayId, PhysicalDisplayId, std::optional<ui::Size>)); MOCK_METHOD1(createLayer, std::shared_ptr<HWC2::Layer>(HalDisplayId)); MOCK_METHOD(status_t, getDeviceCompositionChanges, Loading services/surfaceflinger/DisplayHardware/HWC2.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -675,6 +675,11 @@ void Display::loadDisplayCapabilities() { } }); } void Display::setPhysicalSizeInMm(std::optional<ui::Size> size) { mPhysicalSize = size; } } // namespace impl // Layer methods Loading Loading
libs/ui/DisplayIdentification.cpp +58 −11 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <ftl/hash.h> #include <log/log.h> #include <ui/DisplayIdentification.h> #include <ui/Size.h> namespace android { namespace { Loading @@ -46,6 +47,10 @@ std::optional<uint8_t> getEdidDescriptorType(const byte_view& view) { return view[3]; } bool isDetailedTimingDescriptor(const byte_view& view) { return view[0] != 0 && view[1] != 0; } std::string_view parseEdidText(const byte_view& view) { std::string_view text(reinterpret_cast<const char*>(view.data()), view.size()); text = text.substr(0, text.find('\n')); Loading Loading @@ -219,6 +224,8 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) { std::string_view displayName; std::string_view serialNumber; std::string_view asciiText; ui::Size preferredDTDPixelSize; ui::Size preferredDTDPhysicalSize; constexpr size_t kDescriptorCount = 4; constexpr size_t kDescriptorLength = 18; Loading @@ -243,6 +250,35 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) { serialNumber = parseEdidText(descriptor); break; } } else if (isDetailedTimingDescriptor(view)) { static constexpr size_t kHorizontalPhysicalLsbOffset = 12; static constexpr size_t kHorizontalPhysicalMsbOffset = 14; static constexpr size_t kVerticalPhysicalLsbOffset = 13; static constexpr size_t kVerticalPhysicalMsbOffset = 14; const uint32_t hSize = static_cast<uint32_t>(view[kHorizontalPhysicalLsbOffset] | ((view[kHorizontalPhysicalMsbOffset] >> 4) << 8)); const uint32_t vSize = static_cast<uint32_t>(view[kVerticalPhysicalLsbOffset] | ((view[kVerticalPhysicalMsbOffset] & 0b1111) << 8)); static constexpr size_t kHorizontalPixelLsbOffset = 2; static constexpr size_t kHorizontalPixelMsbOffset = 4; static constexpr size_t kVerticalPixelLsbOffset = 5; static constexpr size_t kVerticalPixelMsbOffset = 7; const uint8_t hLsb = view[kHorizontalPixelLsbOffset]; const uint8_t hMsb = view[kHorizontalPixelMsbOffset]; const int32_t hPixel = hLsb + ((hMsb & 0xF0) << 4); const uint8_t vLsb = view[kVerticalPixelLsbOffset]; const uint8_t vMsb = view[kVerticalPixelMsbOffset]; const int32_t vPixel = vLsb + ((vMsb & 0xF0) << 4); preferredDTDPixelSize.setWidth(hPixel); preferredDTDPixelSize.setHeight(vPixel); preferredDTDPhysicalSize.setWidth(hSize); preferredDTDPhysicalSize.setHeight(vSize); } view = view.subspan(kDescriptorLength); Loading Loading @@ -297,14 +333,22 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) { } } return Edid{.manufacturerId = manufacturerId, DetailedTimingDescriptor preferredDetailedTimingDescriptor{ .pixelSizeCount = preferredDTDPixelSize, .physicalSizeInMm = preferredDTDPhysicalSize, }; return Edid{ .manufacturerId = manufacturerId, .productId = productId, .pnpId = *pnpId, .modelHash = modelHash, .displayName = displayName, .manufactureOrModelYear = manufactureOrModelYear, .manufactureWeek = manufactureWeek, .cea861Block = cea861Block}; .cea861Block = cea861Block, .preferredDetailedTimingDescriptor = preferredDetailedTimingDescriptor, }; } std::optional<PnpId> getPnpId(uint16_t manufacturerId) { Loading Loading @@ -336,9 +380,12 @@ std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData( } const auto displayId = PhysicalDisplayId::fromEdid(port, edid->manufacturerId, edid->modelHash); return DisplayIdentificationInfo{.id = displayId, return DisplayIdentificationInfo{ .id = displayId, .name = std::string(edid->displayName), .deviceProductInfo = buildDeviceProductInfo(*edid)}; .deviceProductInfo = buildDeviceProductInfo(*edid), .preferredDetailedTimingDescriptor = edid->preferredDetailedTimingDescriptor, }; } PhysicalDisplayId getVirtualDisplayId(uint32_t id) { Loading
libs/ui/include/ui/DisplayIdentification.h +8 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <ui/DeviceProductInfo.h> #include <ui/DisplayId.h> #include <ui/Size.h> #define LEGACY_DISPLAY_TYPE_PRIMARY 0 #define LEGACY_DISPLAY_TYPE_EXTERNAL 1 Loading @@ -33,10 +34,16 @@ namespace android { using DisplayIdentificationData = std::vector<uint8_t>; struct DetailedTimingDescriptor { ui::Size pixelSizeCount; ui::Size physicalSizeInMm; }; struct DisplayIdentificationInfo { PhysicalDisplayId id; std::string name; std::optional<DeviceProductInfo> deviceProductInfo; std::optional<DetailedTimingDescriptor> preferredDetailedTimingDescriptor; }; struct ExtensionBlock { Loading Loading @@ -68,6 +75,7 @@ struct Edid { uint8_t manufactureOrModelYear; uint8_t manufactureWeek; std::optional<Cea861ExtensionBlock> cea861Block; std::optional<DetailedTimingDescriptor> preferredDetailedTimingDescriptor; }; bool isEdid(const DisplayIdentificationData&); Loading
libs/ui/tests/DisplayIdentification_test.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -194,6 +194,10 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(21, edid->manufactureOrModelYear); EXPECT_EQ(0, edid->manufactureWeek); EXPECT_FALSE(edid->cea861Block); EXPECT_EQ(1280, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width); EXPECT_EQ(800, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height); EXPECT_EQ(261, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width); EXPECT_EQ(163, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height); edid = parseEdid(getExternalEdid()); ASSERT_TRUE(edid); Loading @@ -206,6 +210,10 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(22, edid->manufactureOrModelYear); EXPECT_EQ(2, edid->manufactureWeek); EXPECT_FALSE(edid->cea861Block); EXPECT_EQ(1280, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width); EXPECT_EQ(800, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height); EXPECT_EQ(641, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width); EXPECT_EQ(400, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height); edid = parseEdid(getExternalEedid()); ASSERT_TRUE(edid); Loading @@ -224,6 +232,10 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(0, physicalAddress.b); EXPECT_EQ(0, physicalAddress.c); EXPECT_EQ(0, physicalAddress.d); EXPECT_EQ(1366, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width); EXPECT_EQ(768, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height); EXPECT_EQ(160, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width); EXPECT_EQ(90, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height); edid = parseEdid(getPanasonicTvEdid()); ASSERT_TRUE(edid); Loading @@ -242,6 +254,10 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(0, physicalAddress.b); EXPECT_EQ(0, physicalAddress.c); EXPECT_EQ(0, physicalAddress.d); EXPECT_EQ(1920, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width); EXPECT_EQ(1080, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height); EXPECT_EQ(698, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width); EXPECT_EQ(392, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height); edid = parseEdid(getHisenseTvEdid()); ASSERT_TRUE(edid); Loading @@ -260,6 +276,10 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(2, physicalAddress.b); EXPECT_EQ(3, physicalAddress.c); EXPECT_EQ(4, physicalAddress.d); EXPECT_EQ(1920, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width); EXPECT_EQ(1080, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height); EXPECT_EQ(575, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width); EXPECT_EQ(323, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height); edid = parseEdid(getCtlDisplayEdid()); ASSERT_TRUE(edid); Loading @@ -273,6 +293,10 @@ TEST(DisplayIdentificationTest, parseEdid) { EXPECT_EQ(0xff, edid->manufactureWeek); ASSERT_TRUE(edid->cea861Block); EXPECT_FALSE(edid->cea861Block->hdmiVendorDataBlock); EXPECT_EQ(1360, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width); EXPECT_EQ(768, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height); EXPECT_EQ(521, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width); EXPECT_EQ(293, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height); } TEST(DisplayIdentificationTest, parseInvalidEdid) { Loading
services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +2 −1 Original line number Diff line number Diff line Loading @@ -51,7 +51,8 @@ public: MOCK_CONST_METHOD0(getMaxVirtualDisplayCount, size_t()); MOCK_CONST_METHOD0(getMaxVirtualDisplayDimension, size_t()); MOCK_METHOD3(allocateVirtualDisplay, bool(HalVirtualDisplayId, ui::Size, ui::PixelFormat*)); MOCK_METHOD2(allocatePhysicalDisplay, void(hal::HWDisplayId, PhysicalDisplayId)); MOCK_METHOD3(allocatePhysicalDisplay, void(hal::HWDisplayId, PhysicalDisplayId, std::optional<ui::Size>)); MOCK_METHOD1(createLayer, std::shared_ptr<HWC2::Layer>(HalDisplayId)); MOCK_METHOD(status_t, getDeviceCompositionChanges, Loading
services/surfaceflinger/DisplayHardware/HWC2.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -675,6 +675,11 @@ void Display::loadDisplayCapabilities() { } }); } void Display::setPhysicalSizeInMm(std::optional<ui::Size> size) { mPhysicalSize = size; } } // namespace impl // Layer methods Loading