| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ash/display/display_change_observer_chromeos.h" | |
| 6 | |
| 7 #include "base/memory/ptr_util.h" | |
| 8 #include "testing/gtest/include/gtest/gtest.h" | |
| 9 #include "ui/display/fake_display_snapshot.h" | |
| 10 #include "ui/display/manager/chromeos/display_configurator.h" | |
| 11 #include "ui/display/manager/managed_display_info.h" | |
| 12 #include "ui/display/types/display_mode.h" | |
| 13 | |
| 14 using ui::DisplayConfigurator; | |
| 15 | |
| 16 namespace ash { | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 float ComputeDeviceScaleFactor(float diagonal_inch, | |
| 21 const gfx::Rect& resolution) { | |
| 22 // We assume that displays have square pixel. | |
| 23 float diagonal_pixel = std::sqrt(std::pow(resolution.width(), 2) + | |
| 24 std::pow(resolution.height(), 2)); | |
| 25 float dpi = diagonal_pixel / diagonal_inch; | |
| 26 return DisplayChangeObserver::FindDeviceScaleFactor(dpi); | |
| 27 } | |
| 28 | |
| 29 std::unique_ptr<ui::DisplayMode> MakeDisplayMode(int width, | |
| 30 int height, | |
| 31 bool is_interlaced, | |
| 32 float refresh_rate) { | |
| 33 return base::MakeUnique<ui::DisplayMode>(gfx::Size(width, height), | |
| 34 is_interlaced, refresh_rate); | |
| 35 } | |
| 36 | |
| 37 } // namespace | |
| 38 | |
| 39 TEST(DisplayChangeObserverTest, GetExternalManagedDisplayModeList) { | |
| 40 std::unique_ptr<ui::DisplaySnapshot> display_snapshot = | |
| 41 display::FakeDisplaySnapshot::Builder() | |
| 42 .SetId(123) | |
| 43 .SetNativeMode(MakeDisplayMode(1920, 1200, false, 60)) | |
| 44 // All non-interlaced (as would be seen with different refresh rates). | |
| 45 .AddMode(MakeDisplayMode(1920, 1080, false, 80)) | |
| 46 .AddMode(MakeDisplayMode(1920, 1080, false, 70)) | |
| 47 .AddMode(MakeDisplayMode(1920, 1080, false, 60)) | |
| 48 // Interlaced vs non-interlaced. | |
| 49 .AddMode(MakeDisplayMode(1280, 720, true, 60)) | |
| 50 .AddMode(MakeDisplayMode(1280, 720, false, 60)) | |
| 51 // Interlaced only. | |
| 52 .AddMode(MakeDisplayMode(1024, 768, true, 70)) | |
| 53 .AddMode(MakeDisplayMode(1024, 768, true, 60)) | |
| 54 // Mixed. | |
| 55 .AddMode(MakeDisplayMode(1024, 600, true, 60)) | |
| 56 .AddMode(MakeDisplayMode(1024, 600, false, 70)) | |
| 57 .AddMode(MakeDisplayMode(1024, 600, false, 60)) | |
| 58 // Just one interlaced mode. | |
| 59 .AddMode(MakeDisplayMode(640, 480, true, 60)) | |
| 60 .Build(); | |
| 61 | |
| 62 display::ManagedDisplayInfo::ManagedDisplayModeList display_modes = | |
| 63 DisplayChangeObserver::GetExternalManagedDisplayModeList( | |
| 64 *display_snapshot); | |
| 65 ASSERT_EQ(6u, display_modes.size()); | |
| 66 EXPECT_EQ("640x480", display_modes[0]->size().ToString()); | |
| 67 EXPECT_TRUE(display_modes[0]->is_interlaced()); | |
| 68 EXPECT_EQ(display_modes[0]->refresh_rate(), 60); | |
| 69 | |
| 70 EXPECT_EQ("1024x600", display_modes[1]->size().ToString()); | |
| 71 EXPECT_FALSE(display_modes[1]->is_interlaced()); | |
| 72 EXPECT_EQ(display_modes[1]->refresh_rate(), 70); | |
| 73 | |
| 74 EXPECT_EQ("1024x768", display_modes[2]->size().ToString()); | |
| 75 EXPECT_TRUE(display_modes[2]->is_interlaced()); | |
| 76 EXPECT_EQ(display_modes[2]->refresh_rate(), 70); | |
| 77 | |
| 78 EXPECT_EQ("1280x720", display_modes[3]->size().ToString()); | |
| 79 EXPECT_FALSE(display_modes[3]->is_interlaced()); | |
| 80 EXPECT_EQ(display_modes[3]->refresh_rate(), 60); | |
| 81 | |
| 82 EXPECT_EQ("1920x1080", display_modes[4]->size().ToString()); | |
| 83 EXPECT_FALSE(display_modes[4]->is_interlaced()); | |
| 84 EXPECT_EQ(display_modes[4]->refresh_rate(), 80); | |
| 85 | |
| 86 EXPECT_EQ("1920x1200", display_modes[5]->size().ToString()); | |
| 87 EXPECT_FALSE(display_modes[5]->is_interlaced()); | |
| 88 EXPECT_EQ(display_modes[5]->refresh_rate(), 60); | |
| 89 } | |
| 90 | |
| 91 TEST(DisplayChangeObserverTest, GetEmptyExternalManagedDisplayModeList) { | |
| 92 display::FakeDisplaySnapshot display_snapshot( | |
| 93 123, gfx::Point(), gfx::Size(), ui::DISPLAY_CONNECTION_TYPE_UNKNOWN, | |
| 94 false, false, false, std::string(), 0, | |
| 95 std::vector<std::unique_ptr<const ui::DisplayMode>>(), nullptr, nullptr); | |
| 96 | |
| 97 display::ManagedDisplayInfo::ManagedDisplayModeList display_modes = | |
| 98 DisplayChangeObserver::GetExternalManagedDisplayModeList( | |
| 99 display_snapshot); | |
| 100 EXPECT_EQ(0u, display_modes.size()); | |
| 101 } | |
| 102 | |
| 103 TEST(DisplayChangeObserverTest, GetInternalManagedDisplayModeList) { | |
| 104 std::unique_ptr<ui::DisplaySnapshot> display_snapshot = | |
| 105 display::FakeDisplaySnapshot::Builder() | |
| 106 .SetId(123) | |
| 107 .SetNativeMode(MakeDisplayMode(1366, 768, false, 60)) | |
| 108 .AddMode(MakeDisplayMode(1024, 768, false, 60)) | |
| 109 .AddMode(MakeDisplayMode(800, 600, false, 60)) | |
| 110 .AddMode(MakeDisplayMode(600, 600, false, 56.2)) | |
| 111 .AddMode(MakeDisplayMode(640, 480, false, 59.9)) | |
| 112 .Build(); | |
| 113 | |
| 114 display::ManagedDisplayInfo info(1, "", false); | |
| 115 info.SetBounds(gfx::Rect(0, 0, 1366, 768)); | |
| 116 | |
| 117 display::ManagedDisplayInfo::ManagedDisplayModeList display_modes = | |
| 118 DisplayChangeObserver::GetInternalManagedDisplayModeList( | |
| 119 info, *display_snapshot); | |
| 120 ASSERT_EQ(5u, display_modes.size()); | |
| 121 EXPECT_EQ("1366x768", display_modes[0]->size().ToString()); | |
| 122 EXPECT_FALSE(display_modes[0]->native()); | |
| 123 EXPECT_NEAR(display_modes[0]->ui_scale(), 0.5, 0.01); | |
| 124 EXPECT_EQ(display_modes[0]->refresh_rate(), 60); | |
| 125 | |
| 126 EXPECT_EQ("1366x768", display_modes[1]->size().ToString()); | |
| 127 EXPECT_FALSE(display_modes[1]->native()); | |
| 128 EXPECT_NEAR(display_modes[1]->ui_scale(), 0.6, 0.01); | |
| 129 EXPECT_EQ(display_modes[1]->refresh_rate(), 60); | |
| 130 | |
| 131 EXPECT_EQ("1366x768", display_modes[2]->size().ToString()); | |
| 132 EXPECT_FALSE(display_modes[2]->native()); | |
| 133 EXPECT_NEAR(display_modes[2]->ui_scale(), 0.75, 0.01); | |
| 134 EXPECT_EQ(display_modes[2]->refresh_rate(), 60); | |
| 135 | |
| 136 EXPECT_EQ("1366x768", display_modes[3]->size().ToString()); | |
| 137 EXPECT_TRUE(display_modes[3]->native()); | |
| 138 EXPECT_NEAR(display_modes[3]->ui_scale(), 1.0, 0.01); | |
| 139 EXPECT_EQ(display_modes[3]->refresh_rate(), 60); | |
| 140 | |
| 141 EXPECT_EQ("1366x768", display_modes[4]->size().ToString()); | |
| 142 EXPECT_FALSE(display_modes[4]->native()); | |
| 143 EXPECT_NEAR(display_modes[4]->ui_scale(), 1.125, 0.01); | |
| 144 EXPECT_EQ(display_modes[4]->refresh_rate(), 60); | |
| 145 } | |
| 146 | |
| 147 TEST(DisplayChangeObserverTest, GetInternalHiDPIManagedDisplayModeList) { | |
| 148 // Data picked from peppy. | |
| 149 std::unique_ptr<ui::DisplaySnapshot> display_snapshot = | |
| 150 display::FakeDisplaySnapshot::Builder() | |
| 151 .SetId(123) | |
| 152 .SetNativeMode(MakeDisplayMode(2560, 1700, false, 60)) | |
| 153 .AddMode(MakeDisplayMode(2048, 1536, false, 60)) | |
| 154 .AddMode(MakeDisplayMode(1920, 1440, false, 60)) | |
| 155 .Build(); | |
| 156 | |
| 157 display::ManagedDisplayInfo info(1, "", false); | |
| 158 info.SetBounds(gfx::Rect(0, 0, 2560, 1700)); | |
| 159 info.set_device_scale_factor(2.0f); | |
| 160 | |
| 161 display::ManagedDisplayInfo::ManagedDisplayModeList display_modes = | |
| 162 DisplayChangeObserver::GetInternalManagedDisplayModeList( | |
| 163 info, *display_snapshot); | |
| 164 ASSERT_EQ(8u, display_modes.size()); | |
| 165 EXPECT_EQ("2560x1700", display_modes[0]->size().ToString()); | |
| 166 EXPECT_FALSE(display_modes[0]->native()); | |
| 167 EXPECT_NEAR(display_modes[0]->ui_scale(), 0.5, 0.01); | |
| 168 EXPECT_EQ(display_modes[0]->refresh_rate(), 60); | |
| 169 | |
| 170 EXPECT_EQ("2560x1700", display_modes[1]->size().ToString()); | |
| 171 EXPECT_FALSE(display_modes[1]->native()); | |
| 172 EXPECT_NEAR(display_modes[1]->ui_scale(), 0.625, 0.01); | |
| 173 EXPECT_EQ(display_modes[1]->refresh_rate(), 60); | |
| 174 | |
| 175 EXPECT_EQ("2560x1700", display_modes[2]->size().ToString()); | |
| 176 EXPECT_FALSE(display_modes[2]->native()); | |
| 177 EXPECT_NEAR(display_modes[2]->ui_scale(), 0.8, 0.01); | |
| 178 EXPECT_EQ(display_modes[2]->refresh_rate(), 60); | |
| 179 | |
| 180 EXPECT_EQ("2560x1700", display_modes[3]->size().ToString()); | |
| 181 EXPECT_FALSE(display_modes[3]->native()); | |
| 182 EXPECT_NEAR(display_modes[3]->ui_scale(), 1.0, 0.01); | |
| 183 EXPECT_EQ(display_modes[3]->refresh_rate(), 60); | |
| 184 | |
| 185 EXPECT_EQ("2560x1700", display_modes[4]->size().ToString()); | |
| 186 EXPECT_FALSE(display_modes[4]->native()); | |
| 187 EXPECT_NEAR(display_modes[4]->ui_scale(), 1.125, 0.01); | |
| 188 EXPECT_EQ(display_modes[4]->refresh_rate(), 60); | |
| 189 | |
| 190 EXPECT_EQ("2560x1700", display_modes[5]->size().ToString()); | |
| 191 EXPECT_FALSE(display_modes[5]->native()); | |
| 192 EXPECT_NEAR(display_modes[5]->ui_scale(), 1.25, 0.01); | |
| 193 EXPECT_EQ(display_modes[5]->refresh_rate(), 60); | |
| 194 | |
| 195 EXPECT_EQ("2560x1700", display_modes[6]->size().ToString()); | |
| 196 EXPECT_FALSE(display_modes[6]->native()); | |
| 197 EXPECT_NEAR(display_modes[6]->ui_scale(), 1.5, 0.01); | |
| 198 EXPECT_EQ(display_modes[6]->refresh_rate(), 60); | |
| 199 | |
| 200 EXPECT_EQ("2560x1700", display_modes[7]->size().ToString()); | |
| 201 EXPECT_TRUE(display_modes[7]->native()); | |
| 202 EXPECT_NEAR(display_modes[7]->ui_scale(), 2.0, 0.01); | |
| 203 EXPECT_EQ(display_modes[7]->refresh_rate(), 60); | |
| 204 } | |
| 205 | |
| 206 TEST(DisplayChangeObserverTest, GetInternalManagedDisplayModeList1_25) { | |
| 207 // Data picked from peppy. | |
| 208 std::unique_ptr<ui::DisplaySnapshot> display_snapshot = | |
| 209 display::FakeDisplaySnapshot::Builder() | |
| 210 .SetId(123) | |
| 211 .SetNativeMode(MakeDisplayMode(1920, 1080, false, 60)) | |
| 212 .Build(); | |
| 213 | |
| 214 display::ManagedDisplayInfo info(1, "", false); | |
| 215 info.SetBounds(gfx::Rect(0, 0, 1920, 1080)); | |
| 216 info.set_device_scale_factor(1.25); | |
| 217 | |
| 218 display::ManagedDisplayInfo::ManagedDisplayModeList display_modes = | |
| 219 DisplayChangeObserver::GetInternalManagedDisplayModeList( | |
| 220 info, *display_snapshot); | |
| 221 ASSERT_EQ(5u, display_modes.size()); | |
| 222 EXPECT_EQ("1920x1080", display_modes[0]->size().ToString()); | |
| 223 EXPECT_FALSE(display_modes[0]->native()); | |
| 224 EXPECT_NEAR(display_modes[0]->ui_scale(), 0.5, 0.01); | |
| 225 EXPECT_EQ(display_modes[0]->refresh_rate(), 60); | |
| 226 | |
| 227 EXPECT_EQ("1920x1080", display_modes[1]->size().ToString()); | |
| 228 EXPECT_FALSE(display_modes[1]->native()); | |
| 229 EXPECT_NEAR(display_modes[1]->ui_scale(), 0.625, 0.01); | |
| 230 EXPECT_EQ(display_modes[1]->refresh_rate(), 60); | |
| 231 | |
| 232 EXPECT_EQ("1920x1080", display_modes[2]->size().ToString()); | |
| 233 EXPECT_FALSE(display_modes[2]->native()); | |
| 234 EXPECT_NEAR(display_modes[2]->ui_scale(), 0.8, 0.01); | |
| 235 EXPECT_EQ(display_modes[2]->refresh_rate(), 60); | |
| 236 | |
| 237 EXPECT_EQ("1920x1080", display_modes[3]->size().ToString()); | |
| 238 EXPECT_TRUE(display_modes[3]->native()); | |
| 239 EXPECT_NEAR(display_modes[3]->ui_scale(), 1.0, 0.01); | |
| 240 EXPECT_EQ(display_modes[3]->refresh_rate(), 60); | |
| 241 | |
| 242 EXPECT_EQ("1920x1080", display_modes[4]->size().ToString()); | |
| 243 EXPECT_FALSE(display_modes[4]->native()); | |
| 244 EXPECT_NEAR(display_modes[4]->ui_scale(), 1.25, 0.01); | |
| 245 EXPECT_EQ(display_modes[4]->refresh_rate(), 60); | |
| 246 } | |
| 247 | |
| 248 TEST(DisplayChangeObserverTest, GetExternalManagedDisplayModeList4K) { | |
| 249 std::unique_ptr<ui::DisplaySnapshot> display_snapshot = | |
| 250 display::FakeDisplaySnapshot::Builder() | |
| 251 .SetId(123) | |
| 252 .SetNativeMode(MakeDisplayMode(3840, 2160, false, 30)) | |
| 253 .AddMode(MakeDisplayMode(1920, 1200, false, 60)) | |
| 254 // All non-interlaced (as would be seen with different refresh rates). | |
| 255 .AddMode(MakeDisplayMode(1920, 1080, false, 80)) | |
| 256 .AddMode(MakeDisplayMode(1920, 1080, false, 70)) | |
| 257 .AddMode(MakeDisplayMode(1920, 1080, false, 60)) | |
| 258 // Interlaced vs non-interlaced. | |
| 259 .AddMode(MakeDisplayMode(1280, 720, true, 60)) | |
| 260 .AddMode(MakeDisplayMode(1280, 720, false, 60)) | |
| 261 // Interlaced only. | |
| 262 .AddMode(MakeDisplayMode(1024, 768, true, 70)) | |
| 263 .AddMode(MakeDisplayMode(1024, 768, true, 60)) | |
| 264 // Mixed. | |
| 265 .AddMode(MakeDisplayMode(1024, 600, true, 60)) | |
| 266 .AddMode(MakeDisplayMode(1024, 600, false, 70)) | |
| 267 .AddMode(MakeDisplayMode(1024, 600, false, 60)) | |
| 268 // Just one interlaced mode. | |
| 269 .AddMode(MakeDisplayMode(640, 480, true, 60)) | |
| 270 .Build(); | |
| 271 | |
| 272 display::ManagedDisplayInfo::ManagedDisplayModeList display_modes = | |
| 273 DisplayChangeObserver::GetExternalManagedDisplayModeList( | |
| 274 *display_snapshot); | |
| 275 display::ManagedDisplayInfo info(1, "", false); | |
| 276 info.SetManagedDisplayModes(display_modes); // Sort as external display. | |
| 277 display_modes = info.display_modes(); | |
| 278 | |
| 279 ASSERT_EQ(9u, display_modes.size()); | |
| 280 EXPECT_EQ("640x480", display_modes[0]->size().ToString()); | |
| 281 EXPECT_TRUE(display_modes[0]->is_interlaced()); | |
| 282 EXPECT_EQ(display_modes[0]->refresh_rate(), 60); | |
| 283 | |
| 284 EXPECT_EQ("1024x600", display_modes[1]->size().ToString()); | |
| 285 EXPECT_FALSE(display_modes[1]->is_interlaced()); | |
| 286 EXPECT_EQ(display_modes[1]->refresh_rate(), 70); | |
| 287 | |
| 288 EXPECT_EQ("1024x768", display_modes[2]->size().ToString()); | |
| 289 EXPECT_TRUE(display_modes[2]->is_interlaced()); | |
| 290 EXPECT_EQ(display_modes[2]->refresh_rate(), 70); | |
| 291 | |
| 292 EXPECT_EQ("1280x720", display_modes[3]->size().ToString()); | |
| 293 EXPECT_FALSE(display_modes[3]->is_interlaced()); | |
| 294 EXPECT_EQ(display_modes[3]->refresh_rate(), 60); | |
| 295 | |
| 296 EXPECT_EQ("1920x1080", display_modes[4]->size().ToString()); | |
| 297 EXPECT_FALSE(display_modes[4]->is_interlaced()); | |
| 298 EXPECT_EQ(display_modes[4]->refresh_rate(), 80); | |
| 299 | |
| 300 EXPECT_EQ("3840x2160", display_modes[5]->size().ToString()); | |
| 301 EXPECT_FALSE(display_modes[5]->is_interlaced()); | |
| 302 EXPECT_FALSE(display_modes[5]->native()); | |
| 303 EXPECT_EQ(display_modes[5]->refresh_rate(), 30); | |
| 304 EXPECT_EQ(display_modes[5]->device_scale_factor(), 2.0); | |
| 305 | |
| 306 EXPECT_EQ("1920x1200", display_modes[6]->size().ToString()); | |
| 307 EXPECT_FALSE(display_modes[6]->is_interlaced()); | |
| 308 EXPECT_EQ(display_modes[6]->refresh_rate(), 60); | |
| 309 | |
| 310 EXPECT_EQ("3840x2160", display_modes[7]->size().ToString()); | |
| 311 EXPECT_FALSE(display_modes[7]->is_interlaced()); | |
| 312 EXPECT_FALSE(display_modes[7]->native()); | |
| 313 EXPECT_EQ(display_modes[7]->refresh_rate(), 30); | |
| 314 EXPECT_EQ(display_modes[7]->device_scale_factor(), 1.25); | |
| 315 | |
| 316 EXPECT_EQ("3840x2160", display_modes[8]->size().ToString()); | |
| 317 EXPECT_FALSE(display_modes[8]->is_interlaced()); | |
| 318 EXPECT_TRUE(display_modes[8]->native()); | |
| 319 EXPECT_EQ(display_modes[8]->refresh_rate(), 30); | |
| 320 } | |
| 321 | |
| 322 TEST(DisplayChangeObserverTest, FindDeviceScaleFactor) { | |
| 323 EXPECT_EQ(1.0f, ComputeDeviceScaleFactor(19.5f, gfx::Rect(1600, 900))); | |
| 324 | |
| 325 // 21.5" 1920x1080 | |
| 326 EXPECT_EQ(1.0f, ComputeDeviceScaleFactor(21.5f, gfx::Rect(1920, 1080))); | |
| 327 | |
| 328 // 12.1" 1280x800 | |
| 329 EXPECT_EQ(1.0f, ComputeDeviceScaleFactor(12.1f, gfx::Rect(1280, 800))); | |
| 330 | |
| 331 // 11.6" 1920x1080 | |
| 332 EXPECT_EQ(1.25f, ComputeDeviceScaleFactor(11.6f, gfx::Rect(1920, 1080))); | |
| 333 | |
| 334 // 13.3" 1920x1080 | |
| 335 EXPECT_EQ(1.25f, ComputeDeviceScaleFactor(13.3f, gfx::Rect(1920, 1080))); | |
| 336 | |
| 337 // 14" 1920x1080 | |
| 338 EXPECT_EQ(1.25f, ComputeDeviceScaleFactor(14.0f, gfx::Rect(1920, 1080))); | |
| 339 | |
| 340 // 12.85" 2560x1700 | |
| 341 EXPECT_EQ(2.0f, ComputeDeviceScaleFactor(12.85f, gfx::Rect(2560, 1700))); | |
| 342 | |
| 343 // Erroneous values should still work. | |
| 344 EXPECT_EQ(1.0f, DisplayChangeObserver::FindDeviceScaleFactor(-100.0f)); | |
| 345 EXPECT_EQ(1.0f, DisplayChangeObserver::FindDeviceScaleFactor(0.0f)); | |
| 346 EXPECT_EQ(2.0f, DisplayChangeObserver::FindDeviceScaleFactor(10000.0f)); | |
| 347 } | |
| 348 | |
| 349 TEST(DisplayChangeObserverTest, FindExternalDisplayNativeModeWhenOverwritten) { | |
| 350 std::unique_ptr<ui::DisplaySnapshot> display_snapshot = | |
| 351 display::FakeDisplaySnapshot::Builder() | |
| 352 .SetId(123) | |
| 353 .SetNativeMode(MakeDisplayMode(1920, 1080, true, 60)) | |
| 354 .AddMode(MakeDisplayMode(1920, 1080, false, 60)) | |
| 355 .Build(); | |
| 356 | |
| 357 display::ManagedDisplayInfo::ManagedDisplayModeList display_modes = | |
| 358 DisplayChangeObserver::GetExternalManagedDisplayModeList( | |
| 359 *display_snapshot); | |
| 360 ASSERT_EQ(2u, display_modes.size()); | |
| 361 EXPECT_EQ("1920x1080", display_modes[0]->size().ToString()); | |
| 362 EXPECT_FALSE(display_modes[0]->is_interlaced()); | |
| 363 EXPECT_FALSE(display_modes[0]->native()); | |
| 364 EXPECT_EQ(display_modes[0]->refresh_rate(), 60); | |
| 365 | |
| 366 EXPECT_EQ("1920x1080", display_modes[1]->size().ToString()); | |
| 367 EXPECT_TRUE(display_modes[1]->is_interlaced()); | |
| 368 EXPECT_TRUE(display_modes[1]->native()); | |
| 369 EXPECT_EQ(display_modes[1]->refresh_rate(), 60); | |
| 370 } | |
| 371 | |
| 372 } // namespace ash | |
| OLD | NEW |