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