| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2018 The Android Open Source Project | 
|  | 3 | * | 
|  | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | * you may not use this file except in compliance with the License. | 
|  | 6 | * You may obtain a copy of the License at | 
|  | 7 | * | 
|  | 8 | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | * | 
|  | 10 | * Unless required by applicable law or agreed to in writing, software | 
|  | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | * See the License for the specific language governing permissions and | 
|  | 14 | * limitations under the License. | 
|  | 15 | */ | 
|  | 16 |  | 
| Dominik Laskowski | 1733796 | 2020-03-02 15:51:15 -0800 | [diff] [blame] | 17 | #include <functional> | 
|  | 18 | #include <string_view> | 
|  | 19 |  | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 20 | #include <gmock/gmock.h> | 
|  | 21 | #include <gtest/gtest.h> | 
|  | 22 |  | 
|  | 23 | #include "DisplayHardware/DisplayIdentification.h" | 
|  | 24 |  | 
|  | 25 | namespace android { | 
|  | 26 | namespace { | 
|  | 27 |  | 
|  | 28 | const unsigned char kInternalEdid[] = | 
|  | 29 | "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\xa3\x42\x31\x00\x00\x00\x00" | 
|  | 30 | "\x00\x15\x01\x03\x80\x1a\x10\x78\x0a\xd3\xe5\x95\x5c\x60\x90\x27" | 
|  | 31 | "\x19\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" | 
|  | 32 | "\x01\x01\x01\x01\x01\x01\x9e\x1b\x00\xa0\x50\x20\x12\x30\x10\x30" | 
|  | 33 | "\x13\x00\x05\xa3\x10\x00\x00\x19\x00\x00\x00\x0f\x00\x00\x00\x00" | 
|  | 34 | "\x00\x00\x00\x00\x00\x23\x87\x02\x64\x00\x00\x00\x00\xfe\x00\x53" | 
|  | 35 | "\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x00\x00\x00\xfe" | 
|  | 36 | "\x00\x31\x32\x31\x41\x54\x31\x31\x2d\x38\x30\x31\x0a\x20\x00\x45"; | 
|  | 37 |  | 
|  | 38 | const unsigned char kExternalEdid[] = | 
|  | 39 | "\x00\xff\xff\xff\xff\xff\xff\x00\x22\xf0\x6c\x28\x01\x01\x01\x01" | 
|  | 40 | "\x02\x16\x01\x04\xb5\x40\x28\x78\xe2\x8d\x85\xad\x4f\x35\xb1\x25" | 
|  | 41 | "\x0e\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" | 
|  | 42 | "\x01\x01\x01\x01\x01\x01\xe2\x68\x00\xa0\xa0\x40\x2e\x60\x30\x20" | 
|  | 43 | "\x36\x00\x81\x90\x21\x00\x00\x1a\xbc\x1b\x00\xa0\x50\x20\x17\x30" | 
|  | 44 | "\x30\x20\x36\x00\x81\x90\x21\x00\x00\x1a\x00\x00\x00\xfc\x00\x48" | 
|  | 45 | "\x50\x20\x5a\x52\x33\x30\x77\x0a\x20\x20\x20\x20\x00\x00\x00\xff" | 
|  | 46 | "\x00\x43\x4e\x34\x32\x30\x32\x31\x33\x37\x51\x0a\x20\x20\x00\x71"; | 
|  | 47 |  | 
|  | 48 | // Extended EDID with timing extension. | 
|  | 49 | const unsigned char kExternalEedid[] = | 
|  | 50 | "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\x2d\xfe\x08\x00\x00\x00\x00" | 
|  | 51 | "\x29\x15\x01\x03\x80\x10\x09\x78\x0a\xee\x91\xa3\x54\x4c\x99\x26" | 
|  | 52 | "\x0f\x50\x54\xbd\xef\x80\x71\x4f\x81\xc0\x81\x00\x81\x80\x95\x00" | 
|  | 53 | "\xa9\xc0\xb3\x00\x01\x01\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c" | 
|  | 54 | "\x45\x00\xa0\x5a\x00\x00\x00\x1e\x66\x21\x56\xaa\x51\x00\x1e\x30" | 
|  | 55 | "\x46\x8f\x33\x00\xa0\x5a\x00\x00\x00\x1e\x00\x00\x00\xfd\x00\x18" | 
|  | 56 | "\x4b\x0f\x51\x17\x00\x0a\x20\x20\x20\x20\x20\x20\x00\x00\x00\xfc" | 
|  | 57 | "\x00\x53\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x01\x1d" | 
|  | 58 | "\x02\x03\x1f\xf1\x47\x90\x04\x05\x03\x20\x22\x07\x23\x09\x07\x07" | 
|  | 59 | "\x83\x01\x00\x00\xe2\x00\x0f\x67\x03\x0c\x00\x20\x00\xb8\x2d\x01" | 
|  | 60 | "\x1d\x80\x18\x71\x1c\x16\x20\x58\x2c\x25\x00\xa0\x5a\x00\x00\x00" | 
|  | 61 | "\x9e\x01\x1d\x00\x72\x51\xd0\x1e\x20\x6e\x28\x55\x00\xa0\x5a\x00" | 
|  | 62 | "\x00\x00\x1e\x8c\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\xa0" | 
|  | 63 | "\x5a\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | 
|  | 64 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | 
|  | 65 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6"; | 
|  | 66 |  | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 67 | const unsigned char kPanasonicTvEdid[] = | 
|  | 68 | "\x00\xff\xff\xff\xff\xff\xff\x00\x34\xa9\x96\xa2\x01\x01\x01" | 
|  | 69 | "\x01\x00\x1d\x01\x03\x80\x80\x48\x78\x0a\xda\xff\xa3\x58\x4a" | 
|  | 70 | "\xa2\x29\x17\x49\x4b\x20\x08\x00\x31\x40\x61\x40\x01\x01\x01" | 
|  | 71 | "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x08\xe8\x00\x30\xf2\x70" | 
|  | 72 | "\x5a\x80\xb0\x58\x8a\x00\xba\x88\x21\x00\x00\x1e\x02\x3a\x80" | 
|  | 73 | "\x18\x71\x38\x2d\x40\x58\x2c\x45\x00\xba\x88\x21\x00\x00\x1e" | 
|  | 74 | "\x00\x00\x00\xfc\x00\x50\x61\x6e\x61\x73\x6f\x6e\x69\x63\x2d" | 
|  | 75 | "\x54\x56\x0a\x00\x00\x00\xfd\x00\x17\x3d\x0f\x88\x3c\x00\x0a" | 
|  | 76 | "\x20\x20\x20\x20\x20\x20\x01\x1d\x02\x03\x6b\xf0\x57\x61\x60" | 
|  | 77 | "\x10\x1f\x66\x65\x05\x14\x20\x21\x22\x04\x13\x03\x12\x07\x16" | 
|  | 78 | "\x5d\x5e\x5f\x62\x63\x64\x2c\x0d\x07\x01\x15\x07\x50\x57\x07" | 
|  | 79 | "\x01\x67\x04\x03\x83\x0f\x00\x00\x6e\x03\x0c\x00\x20\x00\x38" | 
|  | 80 | "\x3c\x2f\x08\x80\x01\x02\x03\x04\x67\xd8\x5d\xc4\x01\x78\x80" | 
|  | 81 | "\x03\xe2\x00\x4b\xe3\x05\xff\x01\xe2\x0f\x33\xe3\x06\x0f\x01" | 
|  | 82 | "\xe5\x01\x8b\x84\x90\x01\xeb\x01\x46\xd0\x00\x44\x03\x70\x80" | 
|  | 83 | "\x5e\x75\x94\xe6\x11\x46\xd0\x00\x70\x00\x66\x21\x56\xaa\x51" | 
|  | 84 | "\x00\x1e\x30\x46\x8f\x33\x00\xba\x88\x21\x00\x00\x1e\x00\x00" | 
|  | 85 | "\xc8"; | 
|  | 86 |  | 
|  | 87 | const unsigned char kHisenseTvEdid[] = | 
|  | 88 | "\x00\xff\xff\xff\xff\xff\xff\x00\x20\xa3\x00\x00\x00\x00\x00" | 
|  | 89 | "\x00\x12\x1d\x01\x03\x80\x00\x00\x78\x0a\xd7\xa5\xa2\x59\x4a" | 
|  | 90 | "\x96\x24\x14\x50\x54\xa3\x08\x00\xd1\xc0\xb3\x00\x81\x00\x81" | 
|  | 91 | "\x80\x81\x40\x81\xc0\x01\x01\x01\x01\x02\x3a\x80\x18\x71\x38" | 
|  | 92 | "\x2d\x40\x58\x2c\x45\x00\x3f\x43\x21\x00\x00\x1a\x02\x3a\x80" | 
|  | 93 | "\x18\x71\x38\x2d\x40\x58\x2c\x45\x00\x3f\x43\x21\x00\x00\x1a" | 
|  | 94 | "\x00\x00\x00\xfd\x00\x1e\x4c\x1e\x5a\x1e\x00\x0a\x20\x20\x20" | 
|  | 95 | "\x20\x20\x20\x00\x00\x00\xfc\x00\x48\x69\x73\x65\x6e\x73\x65" | 
|  | 96 | "\x0a\x20\x20\x20\x20\x20\x01\x47\x02\x03\x2d\x71\x50\x90\x05" | 
|  | 97 | "\x04\x03\x07\x02\x06\x01\x1f\x14\x13\x12\x16\x11\x15\x20\x2c" | 
|  | 98 | "\x09\x07\x03\x15\x07\x50\x57\x07\x00\x39\x07\xbb\x66\x03\x0c" | 
| Marin Shalamanov | f1274d4 | 2020-03-02 17:49:16 +0100 | [diff] [blame] | 99 | "\x00\x12\x34\x00\x83\x01\x00\x00\x01\x1d\x00\x72\x51\xd0\x1e" | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 100 | "\x20\x6e\x28\x55\x00\xc4\x8e\x21\x00\x00\x1e\x01\x1d\x80\x18" | 
|  | 101 | "\x71\x1c\x16\x20\x58\x2c\x25\x00\xc4\x8e\x21\x00\x00\x9e\x8c" | 
|  | 102 | "\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\x13\x8e\x21\x00" | 
|  | 103 | "\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | 
|  | 104 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | 
|  | 105 | "\x07"; | 
|  | 106 |  | 
|  | 107 | const unsigned char kCtlDisplayEdid[] = | 
|  | 108 | "\x00\xff\xff\xff\xff\xff\xff\x00\x0e\x8c\x9d\x24\x00\x00\x00\x00" | 
|  | 109 | "\xff\x17\x01\x04\xa5\x34\x1d\x78\x3a\xa7\x25\xa4\x57\x51\xa0\x26" | 
|  | 110 | "\x10\x50\x54\xbf\xef\x80\xb3\x00\xa9\x40\x95\x00\x81\x40\x81\x80" | 
|  | 111 | "\x95\x0f\x71\x4f\x90\x40\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c" | 
|  | 112 | "\x45\x00\x09\x25\x21\x00\x00\x1e\x66\x21\x50\xb0\x51\x00\x1b\x30" | 
|  | 113 | "\x40\x70\x36\x00\x09\x25\x21\x00\x00\x1e\x00\x00\x00\xfd\x00\x31" | 
|  | 114 | "\x4c\x1e\x52\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfc" | 
|  | 115 | "\x00\x4c\x50\x32\x33\x36\x31\x0a\x20\x20\x20\x20\x20\x20\x01\x3e" | 
|  | 116 | "\x02\x03\x22\xf2\x4f\x90\x9f\x05\x14\x04\x13\x03\x02\x12\x11\x07" | 
|  | 117 | "\x06\x16\x15\x01\x23\x09\x07\x07\x83\x01\x00\x00\x65\xb9\x14\x00" | 
|  | 118 | "\x04\x00\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c\x45\x00\x09\x25" | 
|  | 119 | "\x21\x00\x00\x1e\x02\x3a\x80\xd0\x72\x38\x2d\x40\x10\x2c\x45\x80" | 
|  | 120 | "\x09\x25\x21\x00\x00\x1e\x01\x1d\x00\x72\x51\xd0\x1e\x20\x6e\x28" | 
|  | 121 | "\x55\x00\x09\x25\x21\x00\x00\x1e\x8c\x0a\xd0\x8a\x20\xe0\x2d\x10" | 
|  | 122 | "\x10\x3e\x96\x00\x09\x25\x21\x00\x00\x18\x00\x00\x00\x00\x00\x00" | 
|  | 123 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf4"; | 
|  | 124 |  | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 125 | template <size_t N> | 
|  | 126 | DisplayIdentificationData asDisplayIdentificationData(const unsigned char (&bytes)[N]) { | 
|  | 127 | return DisplayIdentificationData(bytes, bytes + N - 1); | 
|  | 128 | } | 
|  | 129 |  | 
| Dominik Laskowski | 1733796 | 2020-03-02 15:51:15 -0800 | [diff] [blame] | 130 | uint32_t hash(const char* str) { | 
|  | 131 | return static_cast<uint32_t>(std::hash<std::string_view>()(str)); | 
|  | 132 | } | 
|  | 133 |  | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 134 | } // namespace | 
|  | 135 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 136 | const DisplayIdentificationData& getInternalEdid() { | 
|  | 137 | static const DisplayIdentificationData data = asDisplayIdentificationData(kInternalEdid); | 
|  | 138 | return data; | 
|  | 139 | } | 
|  | 140 |  | 
|  | 141 | const DisplayIdentificationData& getExternalEdid() { | 
|  | 142 | static const DisplayIdentificationData data = asDisplayIdentificationData(kExternalEdid); | 
|  | 143 | return data; | 
|  | 144 | } | 
|  | 145 |  | 
|  | 146 | const DisplayIdentificationData& getExternalEedid() { | 
|  | 147 | static const DisplayIdentificationData data = asDisplayIdentificationData(kExternalEedid); | 
|  | 148 | return data; | 
|  | 149 | } | 
|  | 150 |  | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 151 | const DisplayIdentificationData& getPanasonicTvEdid() { | 
|  | 152 | static const DisplayIdentificationData data = asDisplayIdentificationData(kPanasonicTvEdid); | 
|  | 153 | return data; | 
|  | 154 | } | 
|  | 155 |  | 
|  | 156 | const DisplayIdentificationData& getHisenseTvEdid() { | 
|  | 157 | static const DisplayIdentificationData data = asDisplayIdentificationData(kHisenseTvEdid); | 
|  | 158 | return data; | 
|  | 159 | } | 
|  | 160 |  | 
|  | 161 | const DisplayIdentificationData& getCtlDisplayEdid() { | 
|  | 162 | static const DisplayIdentificationData data = asDisplayIdentificationData(kCtlDisplayEdid); | 
|  | 163 | return data; | 
|  | 164 | } | 
|  | 165 |  | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 166 | TEST(DisplayIdentificationTest, isEdid) { | 
|  | 167 | EXPECT_FALSE(isEdid({})); | 
|  | 168 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 169 | EXPECT_TRUE(isEdid(getInternalEdid())); | 
|  | 170 | EXPECT_TRUE(isEdid(getExternalEdid())); | 
|  | 171 | EXPECT_TRUE(isEdid(getExternalEedid())); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 172 | EXPECT_TRUE(isEdid(getPanasonicTvEdid())); | 
|  | 173 | EXPECT_TRUE(isEdid(getHisenseTvEdid())); | 
|  | 174 | EXPECT_TRUE(isEdid(getCtlDisplayEdid())); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 175 | } | 
|  | 176 |  | 
|  | 177 | TEST(DisplayIdentificationTest, parseEdid) { | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 178 | auto edid = parseEdid(getInternalEdid()); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 179 | ASSERT_TRUE(edid); | 
|  | 180 | EXPECT_EQ(0x4ca3u, edid->manufacturerId); | 
|  | 181 | EXPECT_STREQ("SEC", edid->pnpId.data()); | 
|  | 182 | // ASCII text should be used as fallback if display name and serial number are missing. | 
| Dominik Laskowski | 1733796 | 2020-03-02 15:51:15 -0800 | [diff] [blame] | 183 | EXPECT_EQ(hash("121AT11-801"), edid->modelHash); | 
|  | 184 | EXPECT_TRUE(edid->displayName.empty()); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 185 | EXPECT_EQ(12610, edid->productId); | 
|  | 186 | EXPECT_EQ(21, edid->manufactureOrModelYear); | 
|  | 187 | EXPECT_EQ(0, edid->manufactureWeek); | 
| Marin Shalamanov | f1274d4 | 2020-03-02 17:49:16 +0100 | [diff] [blame] | 188 | EXPECT_FALSE(edid->cea861Block); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 189 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 190 | edid = parseEdid(getExternalEdid()); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 191 | ASSERT_TRUE(edid); | 
|  | 192 | EXPECT_EQ(0x22f0u, edid->manufacturerId); | 
|  | 193 | EXPECT_STREQ("HWP", edid->pnpId.data()); | 
| Dominik Laskowski | 1733796 | 2020-03-02 15:51:15 -0800 | [diff] [blame] | 194 | EXPECT_EQ(hash("HP ZR30w"), edid->modelHash); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 195 | EXPECT_EQ("HP ZR30w", edid->displayName); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 196 | EXPECT_EQ(10348, edid->productId); | 
|  | 197 | EXPECT_EQ(22, edid->manufactureOrModelYear); | 
|  | 198 | EXPECT_EQ(2, edid->manufactureWeek); | 
| Marin Shalamanov | f1274d4 | 2020-03-02 17:49:16 +0100 | [diff] [blame] | 199 | EXPECT_FALSE(edid->cea861Block); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 200 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 201 | edid = parseEdid(getExternalEedid()); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 202 | ASSERT_TRUE(edid); | 
|  | 203 | EXPECT_EQ(0x4c2du, edid->manufacturerId); | 
|  | 204 | EXPECT_STREQ("SAM", edid->pnpId.data()); | 
| Dominik Laskowski | 1733796 | 2020-03-02 15:51:15 -0800 | [diff] [blame] | 205 | EXPECT_EQ(hash("SAMSUNG"), edid->modelHash); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 206 | EXPECT_EQ("SAMSUNG", edid->displayName); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 207 | EXPECT_EQ(2302, edid->productId); | 
|  | 208 | EXPECT_EQ(21, edid->manufactureOrModelYear); | 
|  | 209 | EXPECT_EQ(41, edid->manufactureWeek); | 
| Marin Shalamanov | f1274d4 | 2020-03-02 17:49:16 +0100 | [diff] [blame] | 210 | ASSERT_TRUE(edid->cea861Block); | 
|  | 211 | ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock); | 
| Marin Shalamanov | f1274d4 | 2020-03-02 17:49:16 +0100 | [diff] [blame] | 212 | auto physicalAddress = edid->cea861Block->hdmiVendorDataBlock->physicalAddress; | 
| Marin Shalamanov | dac1acb | 2020-04-06 16:11:25 +0200 | [diff] [blame] | 213 | EXPECT_EQ(2, physicalAddress.a); | 
|  | 214 | EXPECT_EQ(0, physicalAddress.b); | 
|  | 215 | EXPECT_EQ(0, physicalAddress.c); | 
|  | 216 | EXPECT_EQ(0, physicalAddress.d); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 217 |  | 
|  | 218 | edid = parseEdid(getPanasonicTvEdid()); | 
|  | 219 | ASSERT_TRUE(edid); | 
|  | 220 | EXPECT_EQ(13481, edid->manufacturerId); | 
|  | 221 | EXPECT_STREQ("MEI", edid->pnpId.data()); | 
| Dominik Laskowski | 1733796 | 2020-03-02 15:51:15 -0800 | [diff] [blame] | 222 | EXPECT_EQ(hash("Panasonic-TV"), edid->modelHash); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 223 | EXPECT_EQ("Panasonic-TV", edid->displayName); | 
|  | 224 | EXPECT_EQ(41622, edid->productId); | 
|  | 225 | EXPECT_EQ(29, edid->manufactureOrModelYear); | 
|  | 226 | EXPECT_EQ(0, edid->manufactureWeek); | 
| Marin Shalamanov | f1274d4 | 2020-03-02 17:49:16 +0100 | [diff] [blame] | 227 | ASSERT_TRUE(edid->cea861Block); | 
|  | 228 | ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock); | 
| Marin Shalamanov | f1274d4 | 2020-03-02 17:49:16 +0100 | [diff] [blame] | 229 | physicalAddress = edid->cea861Block->hdmiVendorDataBlock->physicalAddress; | 
| Marin Shalamanov | dac1acb | 2020-04-06 16:11:25 +0200 | [diff] [blame] | 230 | EXPECT_EQ(2, physicalAddress.a); | 
|  | 231 | EXPECT_EQ(0, physicalAddress.b); | 
|  | 232 | EXPECT_EQ(0, physicalAddress.c); | 
|  | 233 | EXPECT_EQ(0, physicalAddress.d); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 234 |  | 
|  | 235 | edid = parseEdid(getHisenseTvEdid()); | 
|  | 236 | ASSERT_TRUE(edid); | 
|  | 237 | EXPECT_EQ(8355, edid->manufacturerId); | 
|  | 238 | EXPECT_STREQ("HEC", edid->pnpId.data()); | 
| Dominik Laskowski | 1733796 | 2020-03-02 15:51:15 -0800 | [diff] [blame] | 239 | EXPECT_EQ(hash("Hisense"), edid->modelHash); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 240 | EXPECT_EQ("Hisense", edid->displayName); | 
|  | 241 | EXPECT_EQ(0, edid->productId); | 
|  | 242 | EXPECT_EQ(29, edid->manufactureOrModelYear); | 
|  | 243 | EXPECT_EQ(18, edid->manufactureWeek); | 
| Marin Shalamanov | f1274d4 | 2020-03-02 17:49:16 +0100 | [diff] [blame] | 244 | ASSERT_TRUE(edid->cea861Block); | 
|  | 245 | ASSERT_TRUE(edid->cea861Block->hdmiVendorDataBlock); | 
| Marin Shalamanov | f1274d4 | 2020-03-02 17:49:16 +0100 | [diff] [blame] | 246 | physicalAddress = edid->cea861Block->hdmiVendorDataBlock->physicalAddress; | 
| Marin Shalamanov | dac1acb | 2020-04-06 16:11:25 +0200 | [diff] [blame] | 247 | EXPECT_EQ(1, physicalAddress.a); | 
|  | 248 | EXPECT_EQ(2, physicalAddress.b); | 
|  | 249 | EXPECT_EQ(3, physicalAddress.c); | 
|  | 250 | EXPECT_EQ(4, physicalAddress.d); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 251 |  | 
|  | 252 | edid = parseEdid(getCtlDisplayEdid()); | 
|  | 253 | ASSERT_TRUE(edid); | 
|  | 254 | EXPECT_EQ(3724, edid->manufacturerId); | 
|  | 255 | EXPECT_STREQ("CTL", edid->pnpId.data()); | 
| Dominik Laskowski | 1733796 | 2020-03-02 15:51:15 -0800 | [diff] [blame] | 256 | EXPECT_EQ(hash("LP2361"), edid->modelHash); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 257 | EXPECT_EQ("LP2361", edid->displayName); | 
|  | 258 | EXPECT_EQ(9373, edid->productId); | 
|  | 259 | EXPECT_EQ(23, edid->manufactureOrModelYear); | 
|  | 260 | EXPECT_EQ(0xff, edid->manufactureWeek); | 
| Marin Shalamanov | f1274d4 | 2020-03-02 17:49:16 +0100 | [diff] [blame] | 261 | ASSERT_TRUE(edid->cea861Block); | 
|  | 262 | EXPECT_FALSE(edid->cea861Block->hdmiVendorDataBlock); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 263 | } | 
|  | 264 |  | 
|  | 265 | TEST(DisplayIdentificationTest, parseInvalidEdid) { | 
|  | 266 | EXPECT_FALSE(isEdid({})); | 
|  | 267 | EXPECT_FALSE(parseEdid({})); | 
|  | 268 |  | 
|  | 269 | // Display name must be printable. | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 270 | auto data = getExternalEdid(); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 271 | data[97] = '\x1b'; | 
|  | 272 | auto edid = parseEdid(data); | 
|  | 273 | ASSERT_TRUE(edid); | 
|  | 274 | // Serial number should be used as fallback if display name is invalid. | 
| Dominik Laskowski | 1733796 | 2020-03-02 15:51:15 -0800 | [diff] [blame] | 275 | const auto modelHash = hash("CN4202137Q"); | 
|  | 276 | EXPECT_EQ(modelHash, edid->modelHash); | 
|  | 277 | EXPECT_TRUE(edid->displayName.empty()); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 278 |  | 
|  | 279 | // Parsing should succeed even if EDID is truncated. | 
|  | 280 | data.pop_back(); | 
|  | 281 | edid = parseEdid(data); | 
|  | 282 | ASSERT_TRUE(edid); | 
| Dominik Laskowski | 1733796 | 2020-03-02 15:51:15 -0800 | [diff] [blame] | 283 | EXPECT_EQ(modelHash, edid->modelHash); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 284 | } | 
|  | 285 |  | 
|  | 286 | TEST(DisplayIdentificationTest, getPnpId) { | 
|  | 287 | EXPECT_FALSE(getPnpId(0)); | 
|  | 288 | EXPECT_FALSE(getPnpId(static_cast<uint16_t>(-1))); | 
|  | 289 |  | 
|  | 290 | EXPECT_STREQ("SEC", getPnpId(0x4ca3u).value_or(PnpId{}).data()); | 
|  | 291 | EXPECT_STREQ("HWP", getPnpId(0x22f0u).value_or(PnpId{}).data()); | 
|  | 292 | EXPECT_STREQ("SAM", getPnpId(0x4c2du).value_or(PnpId{}).data()); | 
|  | 293 | } | 
|  | 294 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 295 | TEST(DisplayIdentificationTest, parseDisplayIdentificationData) { | 
|  | 296 | const auto primaryInfo = parseDisplayIdentificationData(0, getInternalEdid()); | 
|  | 297 | ASSERT_TRUE(primaryInfo); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 298 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 299 | const auto secondaryInfo = parseDisplayIdentificationData(1, getExternalEdid()); | 
|  | 300 | ASSERT_TRUE(secondaryInfo); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 301 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 302 | const auto tertiaryInfo = parseDisplayIdentificationData(2, getExternalEedid()); | 
|  | 303 | ASSERT_TRUE(tertiaryInfo); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 304 |  | 
|  | 305 | // Display IDs should be unique. | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 306 | EXPECT_NE(primaryInfo->id, secondaryInfo->id); | 
|  | 307 | EXPECT_NE(primaryInfo->id, tertiaryInfo->id); | 
|  | 308 | EXPECT_NE(secondaryInfo->id, tertiaryInfo->id); | 
|  | 309 | } | 
|  | 310 |  | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 311 | TEST(DisplayIdentificationTest, deviceProductInfo) { | 
|  | 312 | using ManufactureYear = DeviceProductInfo::ManufactureYear; | 
|  | 313 | using ManufactureWeekAndYear = DeviceProductInfo::ManufactureWeekAndYear; | 
|  | 314 | using ModelYear = DeviceProductInfo::ModelYear; | 
| Marin Shalamanov | dac1acb | 2020-04-06 16:11:25 +0200 | [diff] [blame] | 315 | using RelativeAddress = DeviceProductInfo::RelativeAddress; | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 316 |  | 
|  | 317 | { | 
|  | 318 | const auto displayIdInfo = parseDisplayIdentificationData(0, getInternalEdid()); | 
|  | 319 | ASSERT_TRUE(displayIdInfo); | 
|  | 320 | ASSERT_TRUE(displayIdInfo->deviceProductInfo); | 
|  | 321 | const auto& info = *displayIdInfo->deviceProductInfo; | 
| Dominik Laskowski | 1733796 | 2020-03-02 15:51:15 -0800 | [diff] [blame] | 322 | EXPECT_STREQ("", info.name.data()); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 323 | EXPECT_STREQ("SEC", info.manufacturerPnpId.data()); | 
|  | 324 | EXPECT_STREQ("12610", info.productId.data()); | 
|  | 325 | ASSERT_TRUE(std::holds_alternative<ManufactureYear>(info.manufactureOrModelDate)); | 
|  | 326 | EXPECT_EQ(2011, std::get<ManufactureYear>(info.manufactureOrModelDate).year); | 
| Marin Shalamanov | dac1acb | 2020-04-06 16:11:25 +0200 | [diff] [blame] | 327 | EXPECT_EQ(DeviceProductInfo::NO_RELATIVE_ADDRESS, info.relativeAddress); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 328 | } | 
|  | 329 | { | 
|  | 330 | const auto displayIdInfo = parseDisplayIdentificationData(0, getExternalEdid()); | 
|  | 331 | ASSERT_TRUE(displayIdInfo); | 
|  | 332 | ASSERT_TRUE(displayIdInfo->deviceProductInfo); | 
|  | 333 | const auto& info = *displayIdInfo->deviceProductInfo; | 
|  | 334 | EXPECT_STREQ("HP ZR30w", info.name.data()); | 
|  | 335 | EXPECT_STREQ("HWP", info.manufacturerPnpId.data()); | 
|  | 336 | EXPECT_STREQ("10348", info.productId.data()); | 
|  | 337 | ASSERT_TRUE(std::holds_alternative<ManufactureWeekAndYear>(info.manufactureOrModelDate)); | 
|  | 338 | const auto& date = std::get<ManufactureWeekAndYear>(info.manufactureOrModelDate); | 
|  | 339 | EXPECT_EQ(2012, date.year); | 
|  | 340 | EXPECT_EQ(2, date.week); | 
| Marin Shalamanov | dac1acb | 2020-04-06 16:11:25 +0200 | [diff] [blame] | 341 | EXPECT_EQ(DeviceProductInfo::NO_RELATIVE_ADDRESS, info.relativeAddress); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 342 | } | 
|  | 343 | { | 
|  | 344 | const auto displayIdInfo = parseDisplayIdentificationData(0, getExternalEedid()); | 
|  | 345 | ASSERT_TRUE(displayIdInfo); | 
|  | 346 | ASSERT_TRUE(displayIdInfo->deviceProductInfo); | 
|  | 347 | const auto& info = *displayIdInfo->deviceProductInfo; | 
|  | 348 | EXPECT_STREQ("SAMSUNG", info.name.data()); | 
|  | 349 | EXPECT_STREQ("SAM", info.manufacturerPnpId.data()); | 
|  | 350 | EXPECT_STREQ("2302", info.productId.data()); | 
|  | 351 | ASSERT_TRUE(std::holds_alternative<ManufactureWeekAndYear>(info.manufactureOrModelDate)); | 
|  | 352 | const auto& date = std::get<ManufactureWeekAndYear>(info.manufactureOrModelDate); | 
|  | 353 | EXPECT_EQ(2011, date.year); | 
|  | 354 | EXPECT_EQ(41, date.week); | 
| Marin Shalamanov | dac1acb | 2020-04-06 16:11:25 +0200 | [diff] [blame] | 355 | EXPECT_EQ((RelativeAddress{{2, 0, 0, 0}}), info.relativeAddress); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 356 | } | 
|  | 357 | { | 
|  | 358 | const auto displayIdInfo = parseDisplayIdentificationData(0, getPanasonicTvEdid()); | 
|  | 359 | ASSERT_TRUE(displayIdInfo); | 
|  | 360 | ASSERT_TRUE(displayIdInfo->deviceProductInfo); | 
|  | 361 | const auto& info = *displayIdInfo->deviceProductInfo; | 
|  | 362 | EXPECT_STREQ("Panasonic-TV", info.name.data()); | 
|  | 363 | EXPECT_STREQ("MEI", info.manufacturerPnpId.data()); | 
|  | 364 | EXPECT_STREQ("41622", info.productId.data()); | 
|  | 365 | ASSERT_TRUE(std::holds_alternative<ManufactureYear>(info.manufactureOrModelDate)); | 
|  | 366 | const auto& date = std::get<ManufactureYear>(info.manufactureOrModelDate); | 
|  | 367 | EXPECT_EQ(2019, date.year); | 
| Marin Shalamanov | dac1acb | 2020-04-06 16:11:25 +0200 | [diff] [blame] | 368 | EXPECT_EQ((RelativeAddress{{2, 0, 0, 0}}), info.relativeAddress); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 369 | } | 
|  | 370 | { | 
|  | 371 | const auto displayIdInfo = parseDisplayIdentificationData(0, getHisenseTvEdid()); | 
|  | 372 | ASSERT_TRUE(displayIdInfo); | 
|  | 373 | ASSERT_TRUE(displayIdInfo->deviceProductInfo); | 
|  | 374 | const auto& info = *displayIdInfo->deviceProductInfo; | 
|  | 375 | EXPECT_STREQ("Hisense", info.name.data()); | 
|  | 376 | EXPECT_STREQ("HEC", info.manufacturerPnpId.data()); | 
|  | 377 | EXPECT_STREQ("0", info.productId.data()); | 
|  | 378 | ASSERT_TRUE(std::holds_alternative<ManufactureWeekAndYear>(info.manufactureOrModelDate)); | 
|  | 379 | const auto& date = std::get<ManufactureWeekAndYear>(info.manufactureOrModelDate); | 
|  | 380 | EXPECT_EQ(2019, date.year); | 
|  | 381 | EXPECT_EQ(18, date.week); | 
| Marin Shalamanov | dac1acb | 2020-04-06 16:11:25 +0200 | [diff] [blame] | 382 | EXPECT_EQ((RelativeAddress{{1, 2, 3, 4}}), info.relativeAddress); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 383 | } | 
|  | 384 | { | 
|  | 385 | const auto displayIdInfo = parseDisplayIdentificationData(0, getCtlDisplayEdid()); | 
|  | 386 | ASSERT_TRUE(displayIdInfo); | 
|  | 387 | ASSERT_TRUE(displayIdInfo->deviceProductInfo); | 
|  | 388 | const auto& info = *displayIdInfo->deviceProductInfo; | 
|  | 389 | EXPECT_STREQ("LP2361", info.name.data()); | 
|  | 390 | EXPECT_STREQ("CTL", info.manufacturerPnpId.data()); | 
|  | 391 | EXPECT_STREQ("9373", info.productId.data()); | 
|  | 392 | ASSERT_TRUE(std::holds_alternative<ModelYear>(info.manufactureOrModelDate)); | 
|  | 393 | EXPECT_EQ(2013, std::get<ModelYear>(info.manufactureOrModelDate).year); | 
| Marin Shalamanov | dac1acb | 2020-04-06 16:11:25 +0200 | [diff] [blame] | 394 | EXPECT_EQ(DeviceProductInfo::NO_RELATIVE_ADDRESS, info.relativeAddress); | 
| Marin Shalamanov | f5de90d | 2019-10-08 10:57:25 +0200 | [diff] [blame] | 395 | } | 
|  | 396 | } | 
|  | 397 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 398 | TEST(DisplayIdentificationTest, getFallbackDisplayId) { | 
|  | 399 | // Manufacturer ID should be invalid. | 
|  | 400 | ASSERT_FALSE(getPnpId(getFallbackDisplayId(0))); | 
|  | 401 | ASSERT_FALSE(getPnpId(getFallbackDisplayId(0xffu))); | 
|  | 402 | } | 
|  | 403 |  | 
|  | 404 | TEST(DisplayIdentificationTest, getVirtualDisplayId) { | 
|  | 405 | // Manufacturer ID should be invalid. | 
|  | 406 | ASSERT_FALSE(getPnpId(getVirtualDisplayId(0))); | 
|  | 407 | ASSERT_FALSE(getPnpId(getVirtualDisplayId(0xffff'ffffu))); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 408 | } | 
|  | 409 |  | 
|  | 410 | } // namespace android |