Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31ddf291 authored by Sean Paul's avatar Sean Paul
Browse files

SF: Use PNP ID + Product ID for modelString fallback

Use PNP ID and Product ID as the fallback to Display Name for modelString. The PNP ID is in block zero of the EDID and is validated earlier in the function. This guarantees EDIDs without a Monitor Name Descriptor Block will have a valid modelString.

Bug: 419618180
Flag: EXEMPT bugfix
Test: DisplayIdentificationTest.parseEdid
Test: Tested on device without Monitor Name Descriptor Block, ensured parseEdid now succeeds

Change-Id: Ibf0377dce80ff03c648fcd3411e676a74796a073
parent 37aa10a5
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -318,24 +318,29 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) {
        view = view.subspan(kDescriptorLength);
    }

    // Prefer display name instead of using product code or (integer) serial number, since the
    // latter have been observed to change on some displays with multiple inputs. As fields are
    // discovered to be empty, fall back to less reliable fields.
    std::string_view modelString = displayName;

    if (modelString.empty()) {
        ALOGW("Invalid EDID: falling back to serial number due to missing display name.");
        ALOGW("EDID: falling back to serial number due to missing display name.");
        modelString = descriptorBlockSerialNumber;
    }
    if (modelString.empty()) {
        ALOGW("Invalid EDID: falling back to ASCII text due to missing serial number.");
        ALOGW("EDID: falling back to ASCII text due to missing serial number.");
        modelString = asciiText;
    }

    std::string productString;
    if (modelString.empty()) {
        ALOGE("Invalid EDID: display name and fallback descriptors are missing.");
        return {};
        ALOGW("EDID: falling back to PNP + ProductID due to missing unspecified text.");
        productString = std::string(pnpId->data()) + std::to_string(productId);
        modelString = productString;
    }

    // Hash model string instead of using product code or (integer) serial number, since the latter
    // have been observed to change on some displays with multiple inputs. Use a stable hash instead
    // of std::hash which is only required to be same within a single execution of a program.
    // Use a stable hash instead of std::hash which is only required to be same within a single
    // execution of a program.
    const uint32_t modelHash = static_cast<uint32_t>(*ftl::stable_hash(modelString));

    // Parse extension blocks.
+37 −0
Original line number Diff line number Diff line
@@ -130,6 +130,16 @@ const unsigned char kCtlDisplayEdid[] =
        "\x10\x3e\x96\x00\x09\x25\x21\x00\x00\x18\x00\x00\x00\x00\x00\x00"
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf4";

const unsigned char kEdidWithMissingDescriptors[] =
        "\x00\xff\xff\xff\xff\xff\xff\x00\x09\xe5\x76\x0a\x00\x00\x00\x00"
        "\x19\x1f\x01\x04\xa5\x1c\x13\x78\x03\xee\x95\xa3\x54\x4c\x99\x26"
        "\x0f\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
        "\x01\x01\x01\x01\x01\x01\x12\x5c\xd0\x18\x81\xe0\x2d\x50\x30\x20"
        "\x36\x00\x1d\xbe\x10\x00\x00\x1a\x62\x3d\xd0\x18\x81\xe0\x2d\x50"
        "\x30\x20\x36\x00\x1d\xbe\x10\x00\x00\x1a\x00\x00\x00\x00\x00\x00"
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"
        "\x00\x0d\x28\xff\x0a\x3c\xc8\x0f\x0b\x23\xc8\x00\x00\x00\x00\xcc";

template <size_t N>
DisplayIdentificationData asDisplayIdentificationData(const unsigned char (&bytes)[N]) {
    return DisplayIdentificationData(bytes, bytes + N - 1);
@@ -171,6 +181,12 @@ const DisplayIdentificationData& getCtlDisplayEdid() {
    return data;
}

const DisplayIdentificationData& getEdidWithMissingDescriptors() {
    static const DisplayIdentificationData data =
            asDisplayIdentificationData(kEdidWithMissingDescriptors);
    return data;
}

TEST(DisplayIdentificationTest, isEdid) {
    EXPECT_FALSE(isEdid({}));

@@ -328,6 +344,27 @@ TEST(DisplayIdentificationTest, parseEdid) {
    EXPECT_EQ(768, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height);
    EXPECT_EQ(521, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width);
    EXPECT_EQ(293, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height);

    edid = parseEdid(getEdidWithMissingDescriptors());
    ASSERT_TRUE(edid);
    EXPECT_EQ("", edid->displayName);
    EXPECT_TRUE(!edid->hashedBlockZeroSerialNumberOpt.has_value());
    EXPECT_FALSE(edid->hashedDescriptorBlockSerialNumberOpt.has_value());
    EXPECT_EQ(2533, edid->manufacturerId);
    EXPECT_STREQ("BOE", edid->pnpId.data());
    EXPECT_EQ(2678, edid->productId);
    // modelHash derived from PNP ID and Product ID since descriptors are missing.
    EXPECT_EQ(hash("BOE2678"), edid->modelHash);
    EXPECT_EQ(hash("BOE2678"), 565221063);
    EXPECT_EQ(31, edid->manufactureOrModelYear);
    EXPECT_EQ(25, edid->manufactureWeek);
    EXPECT_EQ(28, edid->physicalSizeInCm.width);
    EXPECT_EQ(19, edid->physicalSizeInCm.height);
    ASSERT_TRUE(!edid->cea861Block);
    EXPECT_EQ(2256, edid->preferredDetailedTimingDescriptor->pixelSizeCount.width);
    EXPECT_EQ(1504, edid->preferredDetailedTimingDescriptor->pixelSizeCount.height);
    EXPECT_EQ(285, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.width);
    EXPECT_EQ(190, edid->preferredDetailedTimingDescriptor->physicalSizeInMm.height);
}

TEST(DisplayIdentificationTest, parseInvalidEdid) {