OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/display/output_util.h" | 5 #include "base/x11/edid_parser_x11.h" |
6 | 6 |
7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
8 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
9 | 9 |
10 #include <X11/extensions/Xrandr.h> | 10 #include <X11/extensions/Xrandr.h> |
11 | 11 |
12 namespace chromeos { | 12 namespace base { |
13 | 13 |
14 namespace { | 14 namespace { |
15 | 15 |
16 // Returns the number of characters in the string literal but doesn't count its | 16 // Returns the number of characters in the string literal but doesn't count its |
17 // terminator NULL byte. | 17 // terminator NULL byte. |
18 #define charsize(str) (arraysize(str) - 1) | 18 #define charsize(str) (arraysize(str) - 1) |
19 | 19 |
20 // Sample EDID data extracted from real devices. | 20 // Sample EDID data extracted from real devices. |
21 const unsigned char kNormalDisplay[] = | 21 const unsigned char kNormalDisplay[] = |
22 "\x00\xff\xff\xff\xff\xff\xff\x00\x22\xf0\x6c\x28\x01\x01\x01\x01" | 22 "\x00\xff\xff\xff\xff\xff\xff\x00\x22\xf0\x6c\x28\x01\x01\x01\x01" |
(...skipping 26 matching lines...) Expand all Loading... |
49 "\x00\x53\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x01\x1d" | 49 "\x00\x53\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x01\x1d" |
50 "\x02\x03\x1f\xf1\x47\x90\x04\x05\x03\x20\x22\x07\x23\x09\x07\x07" | 50 "\x02\x03\x1f\xf1\x47\x90\x04\x05\x03\x20\x22\x07\x23\x09\x07\x07" |
51 "\x83\x01\x00\x00\xe2\x00\x0f\x67\x03\x0c\x00\x20\x00\xb8\x2d\x01" | 51 "\x83\x01\x00\x00\xe2\x00\x0f\x67\x03\x0c\x00\x20\x00\xb8\x2d\x01" |
52 "\x1d\x80\x18\x71\x1c\x16\x20\x58\x2c\x25\x00\xa0\x5a\x00\x00\x00" | 52 "\x1d\x80\x18\x71\x1c\x16\x20\x58\x2c\x25\x00\xa0\x5a\x00\x00\x00" |
53 "\x9e\x01\x1d\x00\x72\x51\xd0\x1e\x20\x6e\x28\x55\x00\xa0\x5a\x00" | 53 "\x9e\x01\x1d\x00\x72\x51\xd0\x1e\x20\x6e\x28\x55\x00\xa0\x5a\x00" |
54 "\x00\x00\x1e\x8c\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\xa0" | 54 "\x00\x00\x1e\x8c\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\xa0" |
55 "\x5a\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | 55 "\x5a\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" |
56 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | 56 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" |
57 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6"; | 57 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6"; |
58 | 58 |
59 // The EDID info misdetecting overscan once. see crbug.com/226318 | |
60 const unsigned char kMisdetecedDisplay[] = | |
61 "\x00\xff\xff\xff\xff\xff\xff\x00\x10\xac\x64\x40\x4c\x30\x30\x32" | |
62 "\x0c\x15\x01\x03\x80\x40\x28\x78\xea\x8d\x85\xad\x4f\x35\xb1\x25" | |
63 "\x0e\x50\x54\xa5\x4b\x00\x71\x4f\x81\x00\x81\x80\xd1\x00\xa9\x40" | |
64 "\x01\x01\x01\x01\x01\x01\x28\x3c\x80\xa0\x70\xb0\x23\x40\x30\x20" | |
65 "\x36\x00\x81\x91\x21\x00\x00\x1a\x00\x00\x00\xff\x00\x50\x48\x35" | |
66 "\x4e\x59\x31\x33\x4e\x32\x30\x30\x4c\x0a\x00\x00\x00\xfc\x00\x44" | |
67 "\x45\x4c\x4c\x20\x55\x33\x30\x31\x31\x0a\x20\x20\x00\x00\x00\xfd" | |
68 "\x00\x31\x56\x1d\x5e\x12\x00\x0a\x20\x20\x20\x20\x20\x20\x01\x38" | |
69 "\x02\x03\x29\xf1\x50\x90\x05\x04\x03\x02\x07\x16\x01\x06\x11\x12" | |
70 "\x15\x13\x14\x1f\x20\x23\x0d\x7f\x07\x83\x0f\x00\x00\x67\x03\x0c" | |
71 "\x00\x10\x00\x38\x2d\xe3\x05\x03\x01\x02\x3a\x80\x18\x71\x38\x2d" | |
72 "\x40\x58\x2c\x45\x00\x81\x91\x21\x00\x00\x1e\x01\x1d\x80\x18\x71" | |
73 "\x1c\x16\x20\x58\x2c\x25\x00\x81\x91\x21\x00\x00\x9e\x01\x1d\x00" | |
74 "\x72\x51\xd0\x1e\x20\x6e\x28\x55\x00\x81\x91\x21\x00\x00\x1e\x8c" | |
75 "\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\x81\x91\x21\x00\x00" | |
76 "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x94"; | |
77 | |
78 } | |
79 | |
80 const unsigned char kLP2565A[] = | 59 const unsigned char kLP2565A[] = |
81 "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x22\xF0\x76\x26\x01\x01\x01\x01" | 60 "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x22\xF0\x76\x26\x01\x01\x01\x01" |
82 "\x02\x12\x01\x03\x80\x34\x21\x78\xEE\xEF\x95\xA3\x54\x4C\x9B\x26" | 61 "\x02\x12\x01\x03\x80\x34\x21\x78\xEE\xEF\x95\xA3\x54\x4C\x9B\x26" |
83 "\x0F\x50\x54\xA5\x6B\x80\x81\x40\x81\x80\x81\x99\x71\x00\xA9\x00" | 62 "\x0F\x50\x54\xA5\x6B\x80\x81\x40\x81\x80\x81\x99\x71\x00\xA9\x00" |
84 "\xA9\x40\xB3\x00\xD1\x00\x28\x3C\x80\xA0\x70\xB0\x23\x40\x30\x20" | 63 "\xA9\x40\xB3\x00\xD1\x00\x28\x3C\x80\xA0\x70\xB0\x23\x40\x30\x20" |
85 "\x36\x00\x07\x44\x21\x00\x00\x1A\x00\x00\x00\xFD\x00\x30\x55\x1E" | 64 "\x36\x00\x07\x44\x21\x00\x00\x1A\x00\x00\x00\xFD\x00\x30\x55\x1E" |
86 "\x5E\x11\x00\x0A\x20\x20\x20\x20\x20\x20\x00\x00\x00\xFC\x00\x48" | 65 "\x5E\x11\x00\x0A\x20\x20\x20\x20\x20\x20\x00\x00\x00\xFC\x00\x48" |
87 "\x50\x20\x4C\x50\x32\x34\x36\x35\x0A\x20\x20\x20\x00\x00\x00\xFF" | 66 "\x50\x20\x4C\x50\x32\x34\x36\x35\x0A\x20\x20\x20\x00\x00\x00\xFF" |
88 "\x00\x43\x4E\x4B\x38\x30\x32\x30\x34\x48\x4D\x0A\x20\x20\x00\xA4"; | 67 "\x00\x43\x4E\x4B\x38\x30\x32\x30\x34\x48\x4D\x0A\x20\x20\x00\xA4"; |
89 | 68 |
90 const unsigned char kLP2565B[] = | 69 const unsigned char kLP2565B[] = |
91 "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x22\xF0\x75\x26\x01\x01\x01\x01" | 70 "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x22\xF0\x75\x26\x01\x01\x01\x01" |
92 "\x02\x12\x01\x03\x6E\x34\x21\x78\xEE\xEF\x95\xA3\x54\x4C\x9B\x26" | 71 "\x02\x12\x01\x03\x6E\x34\x21\x78\xEE\xEF\x95\xA3\x54\x4C\x9B\x26" |
93 "\x0F\x50\x54\xA5\x6B\x80\x81\x40\x71\x00\xA9\x00\xA9\x40\xA9\x4F" | 72 "\x0F\x50\x54\xA5\x6B\x80\x81\x40\x71\x00\xA9\x00\xA9\x40\xA9\x4F" |
94 "\xB3\x00\xD1\xC0\xD1\x00\x28\x3C\x80\xA0\x70\xB0\x23\x40\x30\x20" | 73 "\xB3\x00\xD1\xC0\xD1\x00\x28\x3C\x80\xA0\x70\xB0\x23\x40\x30\x20" |
95 "\x36\x00\x07\x44\x21\x00\x00\x1A\x00\x00\x00\xFD\x00\x30\x55\x1E" | 74 "\x36\x00\x07\x44\x21\x00\x00\x1A\x00\x00\x00\xFD\x00\x30\x55\x1E" |
96 "\x5E\x15\x00\x0A\x20\x20\x20\x20\x20\x20\x00\x00\x00\xFC\x00\x48" | 75 "\x5E\x15\x00\x0A\x20\x20\x20\x20\x20\x20\x00\x00\x00\xFC\x00\x48" |
97 "\x50\x20\x4C\x50\x32\x34\x36\x35\x0A\x20\x20\x20\x00\x00\x00\xFF" | 76 "\x50\x20\x4C\x50\x32\x34\x36\x35\x0A\x20\x20\x20\x00\x00\x00\xFF" |
98 "\x00\x43\x4E\x4B\x38\x30\x32\x30\x34\x48\x4D\x0A\x20\x20\x00\x45"; | 77 "\x00\x43\x4E\x4B\x38\x30\x32\x30\x34\x48\x4D\x0A\x20\x20\x00\x45"; |
99 | 78 |
100 TEST(OutputUtilTest, ParseEDID) { | 79 } // namespace |
| 80 |
| 81 TEST(EdidParserX11Test, ParseEDID) { |
101 uint16 manufacturer_id = 0; | 82 uint16 manufacturer_id = 0; |
102 std::string human_readable_name; | 83 std::string human_readable_name; |
103 EXPECT_TRUE(ParseOutputDeviceData( | 84 EXPECT_TRUE(ParseOutputDeviceData( |
104 kNormalDisplay, charsize(kNormalDisplay), | 85 kNormalDisplay, charsize(kNormalDisplay), |
105 &manufacturer_id, &human_readable_name)); | 86 &manufacturer_id, &human_readable_name)); |
106 EXPECT_EQ(0x22f0u, manufacturer_id); | 87 EXPECT_EQ(0x22f0u, manufacturer_id); |
107 EXPECT_EQ("HP ZR30w", human_readable_name); | 88 EXPECT_EQ("HP ZR30w", human_readable_name); |
108 | 89 |
109 manufacturer_id = 0; | 90 manufacturer_id = 0; |
110 human_readable_name.clear(); | 91 human_readable_name.clear(); |
(...skipping 11 matching lines...) Expand all Loading... |
122 | 103 |
123 manufacturer_id = 0; | 104 manufacturer_id = 0; |
124 human_readable_name.clear(); | 105 human_readable_name.clear(); |
125 EXPECT_TRUE(ParseOutputDeviceData( | 106 EXPECT_TRUE(ParseOutputDeviceData( |
126 kOverscanDisplay, charsize(kOverscanDisplay), | 107 kOverscanDisplay, charsize(kOverscanDisplay), |
127 &manufacturer_id, &human_readable_name)); | 108 &manufacturer_id, &human_readable_name)); |
128 EXPECT_EQ(0x4c2du, manufacturer_id); | 109 EXPECT_EQ(0x4c2du, manufacturer_id); |
129 EXPECT_EQ("SAMSUNG", human_readable_name); | 110 EXPECT_EQ("SAMSUNG", human_readable_name); |
130 } | 111 } |
131 | 112 |
132 TEST(OutputUtilTest, ParseBrokenEDID) { | 113 TEST(EdidParserX11Test, ParseBrokenEDID) { |
133 uint16 manufacturer_id = 0; | 114 uint16 manufacturer_id = 0; |
134 std::string human_readable_name; | 115 std::string human_readable_name; |
135 | 116 |
136 // length == 0 | 117 // length == 0 |
137 EXPECT_FALSE(ParseOutputDeviceData( | 118 EXPECT_FALSE(ParseOutputDeviceData( |
138 kNormalDisplay, 0, | 119 kNormalDisplay, 0, |
139 &manufacturer_id, &human_readable_name)); | 120 &manufacturer_id, &human_readable_name)); |
140 | 121 |
141 // name is broken. Copying kNormalDisplay and substitute its name data by | 122 // name is broken. Copying kNormalDisplay and substitute its name data by |
142 // some control code. | 123 // some control code. |
(...skipping 10 matching lines...) Expand all Loading... |
153 | 134 |
154 // If |human_readable_name| isn't specified, it skips parsing the name. | 135 // If |human_readable_name| isn't specified, it skips parsing the name. |
155 manufacturer_id = 0; | 136 manufacturer_id = 0; |
156 EXPECT_TRUE(ParseOutputDeviceData( | 137 EXPECT_TRUE(ParseOutputDeviceData( |
157 reinterpret_cast<const unsigned char*>(display_data.data()), | 138 reinterpret_cast<const unsigned char*>(display_data.data()), |
158 display_data.size(), | 139 display_data.size(), |
159 &manufacturer_id, NULL)); | 140 &manufacturer_id, NULL)); |
160 EXPECT_EQ(0x22f0u, manufacturer_id); | 141 EXPECT_EQ(0x22f0u, manufacturer_id); |
161 } | 142 } |
162 | 143 |
163 TEST(OutputUtilTest, ParseOverscanFlag) { | 144 TEST(EdidParserX11Test, GetDisplayId) { |
164 bool flag = false; | |
165 EXPECT_FALSE(ParseOutputOverscanFlag( | |
166 kNormalDisplay, charsize(kNormalDisplay), &flag)); | |
167 | |
168 flag = false; | |
169 EXPECT_FALSE(ParseOutputOverscanFlag( | |
170 kInternalDisplay, charsize(kInternalDisplay), &flag)); | |
171 | |
172 flag = false; | |
173 EXPECT_TRUE(ParseOutputOverscanFlag( | |
174 kOverscanDisplay, charsize(kOverscanDisplay), &flag)); | |
175 EXPECT_TRUE(flag); | |
176 | |
177 flag = false; | |
178 EXPECT_FALSE(ParseOutputOverscanFlag( | |
179 kMisdetecedDisplay, charsize(kMisdetecedDisplay), &flag)); | |
180 | |
181 flag = false; | |
182 // Copy |kOverscanDisplay| and set flags to false in it. The overscan flags | |
183 // are embedded at byte 150 in this specific example. Fix here too when the | |
184 // contents of kOverscanDisplay is altered. | |
185 std::string display_data(reinterpret_cast<const char*>(kOverscanDisplay), | |
186 charsize(kOverscanDisplay)); | |
187 display_data[150] = '\0'; | |
188 EXPECT_TRUE(ParseOutputOverscanFlag( | |
189 reinterpret_cast<const unsigned char*>(display_data.data()), | |
190 display_data.size(), &flag)); | |
191 EXPECT_FALSE(flag); | |
192 } | |
193 | |
194 TEST(OutputUtilTest, ParseBrokenOverscanData) { | |
195 // Do not fill valid data here because it anyway fails to parse the data. | |
196 scoped_ptr<unsigned char[]> data(new unsigned char[126]); | |
197 bool flag = false; | |
198 EXPECT_FALSE(ParseOutputOverscanFlag(data.get(), 0, &flag)); | |
199 EXPECT_FALSE(ParseOutputOverscanFlag(data.get(), 126, &flag)); | |
200 | |
201 // extending data because ParseOutputOverscanFlag() will access the data. | |
202 data.reset(new unsigned char[150]); | |
203 // The number of CEA extensions is stored at byte 126. | |
204 data[126] = '\x01'; | |
205 EXPECT_FALSE(ParseOutputOverscanFlag(data.get(), 128, &flag)); | |
206 EXPECT_FALSE(ParseOutputOverscanFlag(data.get(), 150, &flag)); | |
207 } | |
208 | |
209 TEST(OutputUtilTest, IsInternalOutputName) { | |
210 EXPECT_TRUE(IsInternalOutputName("LVDS")); | |
211 EXPECT_TRUE(IsInternalOutputName("eDP")); | |
212 EXPECT_TRUE(IsInternalOutputName("DSI")); | |
213 EXPECT_TRUE(IsInternalOutputName("LVDSxx")); | |
214 EXPECT_TRUE(IsInternalOutputName("eDPzz")); | |
215 EXPECT_TRUE(IsInternalOutputName("DSIyy")); | |
216 | |
217 EXPECT_FALSE(IsInternalOutputName("xyz")); | |
218 EXPECT_FALSE(IsInternalOutputName("abcLVDS")); | |
219 EXPECT_FALSE(IsInternalOutputName("cdeeDP")); | |
220 EXPECT_FALSE(IsInternalOutputName("abcDSI")); | |
221 EXPECT_FALSE(IsInternalOutputName("LVD")); | |
222 EXPECT_FALSE(IsInternalOutputName("eD")); | |
223 EXPECT_FALSE(IsInternalOutputName("DS")); | |
224 } | |
225 | |
226 TEST(OutputUtilTest, GetDisplayId) { | |
227 // EDID of kLP2565A and B are slightly different but actually the same device. | 145 // EDID of kLP2565A and B are slightly different but actually the same device. |
228 int64 id1 = -1; | 146 int64 id1 = -1; |
229 int64 id2 = -1; | 147 int64 id2 = -1; |
230 EXPECT_TRUE(GetDisplayIdFromEDID(kLP2565A, charsize(kLP2565A), 0, &id1)); | 148 EXPECT_TRUE(GetDisplayIdFromEDID(kLP2565A, charsize(kLP2565A), 0, &id1)); |
231 EXPECT_TRUE(GetDisplayIdFromEDID(kLP2565B, charsize(kLP2565B), 0, &id2)); | 149 EXPECT_TRUE(GetDisplayIdFromEDID(kLP2565B, charsize(kLP2565B), 0, &id2)); |
232 EXPECT_EQ(id1, id2); | 150 EXPECT_EQ(id1, id2); |
233 EXPECT_NE(-1, id1); | 151 EXPECT_NE(-1, id1); |
234 } | 152 } |
235 | 153 |
236 TEST(OutputUtilTest, GetDisplayIdFromInternal) { | 154 TEST(EdidParserX11Test, GetDisplayIdFromInternal) { |
237 int64 id = -1; | 155 int64 id = -1; |
238 EXPECT_TRUE(GetDisplayIdFromEDID( | 156 EXPECT_TRUE(GetDisplayIdFromEDID( |
239 kInternalDisplay, charsize(kInternalDisplay), 0, &id)); | 157 kInternalDisplay, charsize(kInternalDisplay), 0, &id)); |
240 EXPECT_NE(-1, id); | 158 EXPECT_NE(-1, id); |
241 } | 159 } |
242 | 160 |
243 TEST(OutputUtilTest, GetDisplayIdFailure) { | 161 TEST(EdidParserX11Test, GetDisplayIdFailure) { |
244 int64 id = -1; | 162 int64 id = -1; |
245 EXPECT_FALSE(GetDisplayIdFromEDID(NULL, 0, 0, &id)); | 163 EXPECT_FALSE(GetDisplayIdFromEDID(NULL, 0, 0, &id)); |
246 EXPECT_EQ(-1, id); | 164 EXPECT_EQ(-1, id); |
247 } | 165 } |
248 | 166 |
249 } // namespace chromeos | 167 } // namespace base |
OLD | NEW |