Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ash / wm / maximize_mode / maximize_mode_controller_unittest.cc
blob6153984b586d0cb0d40aff72456aab4fe94b02f9
1 // Copyright 2014 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.
5 #include <math.h>
7 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
9 #include "ash/ash_switches.h"
10 #include "ash/display/display_manager.h"
11 #include "ash/shell.h"
12 #include "ash/system/tray/system_tray_delegate.h"
13 #include "ash/test/ash_test_base.h"
14 #include "ash/test/display_manager_test_api.h"
15 #include "ash/test/test_system_tray_delegate.h"
16 #include "ash/test/test_volume_control_delegate.h"
17 #include "ash/wm/overview/window_selector_controller.h"
18 #include "base/command_line.h"
19 #include "base/test/simple_test_tick_clock.h"
20 #include "base/test/user_action_tester.h"
21 #include "chromeos/accelerometer/accelerometer_reader.h"
22 #include "chromeos/accelerometer/accelerometer_types.h"
23 #include "ui/events/event_handler.h"
24 #include "ui/events/test/event_generator.h"
25 #include "ui/gfx/geometry/vector3d_f.h"
26 #include "ui/message_center/message_center.h"
28 #if defined(USE_X11)
29 #include "ui/events/test/events_test_utils_x11.h"
30 #endif
32 namespace ash {
34 namespace {
36 const float kDegreesToRadians = 3.1415926f / 180.0f;
37 const float kMeanGravity = 9.8066f;
39 const char kTouchViewInitiallyDisabled[] = "Touchview_Initially_Disabled";
40 const char kTouchViewEnabled[] = "Touchview_Enabled";
41 const char kTouchViewDisabled[] = "Touchview_Disabled";
43 } // namespace
45 // Test accelerometer data taken with the lid at less than 180 degrees while
46 // shaking the device around. The data is to be interpreted in groups of 6 where
47 // each 6 values corresponds to the base accelerometer (-y / g, -x / g, -z / g)
48 // followed by the lid accelerometer (-y / g , x / g, z / g).
49 extern const float kAccelerometerLaptopModeTestData[];
50 extern const size_t kAccelerometerLaptopModeTestDataLength;
52 // Test accelerometer data taken with the lid open 360 degrees while
53 // shaking the device around. The data is to be interpreted in groups of 6 where
54 // each 6 values corresponds to the base accelerometer (-y / g, -x / g, -z / g)
55 // followed by the lid accelerometer (-y / g , x / g, z / g).
56 extern const float kAccelerometerFullyOpenTestData[];
57 extern const size_t kAccelerometerFullyOpenTestDataLength;
59 // Test accelerometer data taken with the lid open 360 degrees while the device
60 // hinge was nearly vertical, while shaking the device around. The data is to be
61 // interpreted in groups of 6 where each 6 values corresponds to the X, Y, and Z
62 // readings from the base and lid accelerometers in this order.
63 extern const float kAccelerometerVerticalHingeTestData[];
64 extern const size_t kAccelerometerVerticalHingeTestDataLength;
66 class MaximizeModeControllerTest : public test::AshTestBase {
67 public:
68 MaximizeModeControllerTest() {}
69 ~MaximizeModeControllerTest() override {}
71 void SetUp() override {
72 test::AshTestBase::SetUp();
73 chromeos::AccelerometerReader::GetInstance()->RemoveObserver(
74 maximize_mode_controller());
76 // Set the first display to be the internal display for the accelerometer
77 // screen rotation tests.
78 test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()).
79 SetFirstDisplayAsInternalDisplay();
82 void TearDown() override {
83 chromeos::AccelerometerReader::GetInstance()->AddObserver(
84 maximize_mode_controller());
85 test::AshTestBase::TearDown();
88 MaximizeModeController* maximize_mode_controller() {
89 return Shell::GetInstance()->maximize_mode_controller();
92 void TriggerLidUpdate(const gfx::Vector3dF& lid) {
93 scoped_refptr<chromeos::AccelerometerUpdate> update(
94 new chromeos::AccelerometerUpdate());
95 update->Set(chromeos::ACCELEROMETER_SOURCE_SCREEN, lid.x(), lid.y(),
96 lid.z());
97 maximize_mode_controller()->OnAccelerometerUpdated(update);
100 void TriggerBaseAndLidUpdate(const gfx::Vector3dF& base,
101 const gfx::Vector3dF& lid) {
102 scoped_refptr<chromeos::AccelerometerUpdate> update(
103 new chromeos::AccelerometerUpdate());
104 update->Set(chromeos::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD, base.x(),
105 base.y(), base.z());
106 update->Set(chromeos::ACCELEROMETER_SOURCE_SCREEN, lid.x(), lid.y(),
107 lid.z());
108 maximize_mode_controller()->OnAccelerometerUpdated(update);
111 bool IsMaximizeModeStarted() {
112 return maximize_mode_controller()->IsMaximizeModeWindowManagerEnabled();
115 // Attaches a SimpleTestTickClock to the MaximizeModeController with a non
116 // null value initial value.
117 void AttachTickClockForTest() {
118 scoped_ptr<base::TickClock> tick_clock(
119 test_tick_clock_ = new base::SimpleTestTickClock());
120 test_tick_clock_->Advance(base::TimeDelta::FromSeconds(1));
121 maximize_mode_controller()->SetTickClockForTest(tick_clock.Pass());
124 void AdvanceTickClock(const base::TimeDelta& delta) {
125 DCHECK(test_tick_clock_);
126 test_tick_clock_->Advance(delta);
129 void OpenLidToAngle(float degrees) {
130 DCHECK(degrees >= 0.0f);
131 DCHECK(degrees <= 360.0f);
133 float radians = degrees * kDegreesToRadians;
134 gfx::Vector3dF base_vector(0.0f, -kMeanGravity, 0.0f);
135 gfx::Vector3dF lid_vector(0.0f,
136 kMeanGravity * cos(radians),
137 kMeanGravity * sin(radians));
138 TriggerBaseAndLidUpdate(base_vector, lid_vector);
141 void OpenLid() {
142 maximize_mode_controller()->LidEventReceived(true /* open */,
143 maximize_mode_controller()->tick_clock_->NowTicks());
146 void CloseLid() {
147 maximize_mode_controller()->LidEventReceived(false /* open */,
148 maximize_mode_controller()->tick_clock_->NowTicks());
151 bool WasLidOpenedRecently() {
152 return maximize_mode_controller()->WasLidOpenedRecently();
155 base::UserActionTester* user_action_tester() { return &user_action_tester_; }
157 private:
158 base::SimpleTestTickClock* test_tick_clock_;
160 // Tracks user action counts.
161 base::UserActionTester user_action_tester_;
163 DISALLOW_COPY_AND_ASSIGN(MaximizeModeControllerTest);
166 // Verify TouchView enabled/disabled user action metrics are recorded.
167 TEST_F(MaximizeModeControllerTest, VerifyTouchViewEnabledDisabledCounts) {
168 ASSERT_EQ(1,
169 user_action_tester()->GetActionCount(kTouchViewInitiallyDisabled));
170 ASSERT_EQ(0, user_action_tester()->GetActionCount(kTouchViewEnabled));
171 ASSERT_EQ(0, user_action_tester()->GetActionCount(kTouchViewDisabled));
173 user_action_tester()->ResetCounts();
174 maximize_mode_controller()->EnableMaximizeModeWindowManager(true);
175 EXPECT_EQ(1, user_action_tester()->GetActionCount(kTouchViewEnabled));
176 EXPECT_EQ(0, user_action_tester()->GetActionCount(kTouchViewDisabled));
177 maximize_mode_controller()->EnableMaximizeModeWindowManager(true);
178 EXPECT_EQ(1, user_action_tester()->GetActionCount(kTouchViewEnabled));
179 EXPECT_EQ(0, user_action_tester()->GetActionCount(kTouchViewDisabled));
181 user_action_tester()->ResetCounts();
182 maximize_mode_controller()->EnableMaximizeModeWindowManager(false);
183 EXPECT_EQ(0, user_action_tester()->GetActionCount(kTouchViewEnabled));
184 EXPECT_EQ(1, user_action_tester()->GetActionCount(kTouchViewDisabled));
185 maximize_mode_controller()->EnableMaximizeModeWindowManager(false);
186 EXPECT_EQ(0, user_action_tester()->GetActionCount(kTouchViewEnabled));
187 EXPECT_EQ(1, user_action_tester()->GetActionCount(kTouchViewDisabled));
190 // Verify that closing the lid will exit maximize mode.
191 TEST_F(MaximizeModeControllerTest, CloseLidWhileInMaximizeMode) {
192 OpenLidToAngle(315.0f);
193 ASSERT_TRUE(IsMaximizeModeStarted());
195 CloseLid();
196 EXPECT_FALSE(IsMaximizeModeStarted());
199 // Verify that maximize mode will not be entered when the lid is closed.
200 TEST_F(MaximizeModeControllerTest,
201 HingeAnglesWithLidClosed) {
202 AttachTickClockForTest();
204 CloseLid();
206 OpenLidToAngle(270.0f);
207 EXPECT_FALSE(IsMaximizeModeStarted());
209 OpenLidToAngle(315.0f);
210 EXPECT_FALSE(IsMaximizeModeStarted());
212 OpenLidToAngle(355.0f);
213 EXPECT_FALSE(IsMaximizeModeStarted());
216 // Verify the maximize mode state for unstable hinge angles when the lid was
217 // recently open.
218 TEST_F(MaximizeModeControllerTest,
219 UnstableHingeAnglesWhenLidRecentlyOpened) {
220 AttachTickClockForTest();
222 OpenLid();
223 ASSERT_TRUE(WasLidOpenedRecently());
225 OpenLidToAngle(5.0f);
226 EXPECT_FALSE(IsMaximizeModeStarted());
228 OpenLidToAngle(355.0f);
229 EXPECT_FALSE(IsMaximizeModeStarted());
231 // This is a stable reading and should clear the last lid opened time.
232 OpenLidToAngle(45.0f);
233 EXPECT_FALSE(IsMaximizeModeStarted());
234 EXPECT_FALSE(WasLidOpenedRecently());
236 OpenLidToAngle(355.0f);
237 EXPECT_TRUE(IsMaximizeModeStarted());
240 // Verify the WasLidOpenedRecently signal with respect to time.
241 TEST_F(MaximizeModeControllerTest, WasLidOpenedRecentlyOverTime) {
242 AttachTickClockForTest();
244 // No lid open time initially.
245 ASSERT_FALSE(WasLidOpenedRecently());
247 CloseLid();
248 EXPECT_FALSE(WasLidOpenedRecently());
250 OpenLid();
251 EXPECT_TRUE(WasLidOpenedRecently());
253 // 1 second after lid open.
254 AdvanceTickClock(base::TimeDelta::FromSeconds(1));
255 EXPECT_TRUE(WasLidOpenedRecently());
257 // 3 seconds after lid open.
258 AdvanceTickClock(base::TimeDelta::FromSeconds(2));
259 EXPECT_FALSE(WasLidOpenedRecently());
262 // Verify the maximize mode enter/exit thresholds for stable angles.
263 TEST_F(MaximizeModeControllerTest, StableHingeAnglesWithLidOpened) {
264 ASSERT_FALSE(IsMaximizeModeStarted());
265 ASSERT_FALSE(WasLidOpenedRecently());
267 OpenLidToAngle(180.0f);
268 EXPECT_FALSE(IsMaximizeModeStarted());
270 OpenLidToAngle(315.0f);
271 EXPECT_TRUE(IsMaximizeModeStarted());
273 OpenLidToAngle(180.0f);
274 EXPECT_TRUE(IsMaximizeModeStarted());
276 OpenLidToAngle(45.0f);
277 EXPECT_FALSE(IsMaximizeModeStarted());
279 OpenLidToAngle(270.0f);
280 EXPECT_TRUE(IsMaximizeModeStarted());
282 OpenLidToAngle(90.0f);
283 EXPECT_FALSE(IsMaximizeModeStarted());
286 // Verify the maximize mode state for unstable hinge angles when the lid is open
287 // but not recently.
288 TEST_F(MaximizeModeControllerTest, UnstableHingeAnglesWithLidOpened) {
289 AttachTickClockForTest();
291 ASSERT_FALSE(WasLidOpenedRecently());
292 ASSERT_FALSE(IsMaximizeModeStarted());
294 OpenLidToAngle(5.0f);
295 EXPECT_FALSE(IsMaximizeModeStarted());
297 OpenLidToAngle(355.0f);
298 EXPECT_TRUE(IsMaximizeModeStarted());
300 OpenLidToAngle(5.0f);
301 EXPECT_TRUE(IsMaximizeModeStarted());
304 // Tests that when the hinge is nearly vertically aligned, the current state
305 // persists as the computed angle is highly inaccurate in this orientation.
306 TEST_F(MaximizeModeControllerTest, HingeAligned) {
307 // Laptop in normal orientation lid open 90 degrees.
308 TriggerBaseAndLidUpdate(gfx::Vector3dF(0.0f, 0.0f, -kMeanGravity),
309 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f));
310 EXPECT_FALSE(IsMaximizeModeStarted());
312 // Completely vertical.
313 TriggerBaseAndLidUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, 0.0f),
314 gfx::Vector3dF(kMeanGravity, 0.0f, 0.0f));
315 EXPECT_FALSE(IsMaximizeModeStarted());
317 // Close to vertical but with hinge appearing to be open 270 degrees.
318 TriggerBaseAndLidUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, -0.1f),
319 gfx::Vector3dF(kMeanGravity, 0.1f, 0.0f));
320 EXPECT_FALSE(IsMaximizeModeStarted());
322 // Flat and open 270 degrees should start maximize mode.
323 TriggerBaseAndLidUpdate(gfx::Vector3dF(0.0f, 0.0f, -kMeanGravity),
324 gfx::Vector3dF(0.0f, kMeanGravity, 0.0f));
325 EXPECT_TRUE(IsMaximizeModeStarted());
327 // Normal 90 degree orientation but near vertical should stay in maximize
328 // mode.
329 TriggerBaseAndLidUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, -0.1f),
330 gfx::Vector3dF(kMeanGravity, -0.1f, 0.0f));
331 EXPECT_TRUE(IsMaximizeModeStarted());
334 TEST_F(MaximizeModeControllerTest, LaptopTest) {
335 // Feeds in sample accelerometer data and verifies that there are no
336 // transitions into touchview / maximize mode while shaking the device around
337 // with the hinge at less than 180 degrees. Note the conversion from device
338 // data to accelerometer updates consistent with accelerometer_reader.cc.
339 ASSERT_EQ(0u, kAccelerometerLaptopModeTestDataLength % 6);
340 for (size_t i = 0; i < kAccelerometerLaptopModeTestDataLength / 6; ++i) {
341 gfx::Vector3dF base(-kAccelerometerLaptopModeTestData[i * 6 + 1],
342 -kAccelerometerLaptopModeTestData[i * 6],
343 -kAccelerometerLaptopModeTestData[i * 6 + 2]);
344 base.Scale(kMeanGravity);
345 gfx::Vector3dF lid(-kAccelerometerLaptopModeTestData[i * 6 + 4],
346 kAccelerometerLaptopModeTestData[i * 6 + 3],
347 kAccelerometerLaptopModeTestData[i * 6 + 5]);
348 lid.Scale(kMeanGravity);
349 TriggerBaseAndLidUpdate(base, lid);
350 // There are a lot of samples, so ASSERT rather than EXPECT to only generate
351 // one failure rather than potentially hundreds.
352 ASSERT_FALSE(IsMaximizeModeStarted());
356 TEST_F(MaximizeModeControllerTest, MaximizeModeTest) {
357 // Trigger maximize mode by opening to 270 to begin the test in maximize mode.
358 TriggerBaseAndLidUpdate(gfx::Vector3dF(0.0f, 0.0f, kMeanGravity),
359 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f));
360 ASSERT_TRUE(IsMaximizeModeStarted());
362 // Feeds in sample accelerometer data and verifies that there are no
363 // transitions out of touchview / maximize mode while shaking the device
364 // around. Note the conversion from device data to accelerometer updates
365 // consistent with accelerometer_reader.cc.
366 ASSERT_EQ(0u, kAccelerometerFullyOpenTestDataLength % 6);
367 for (size_t i = 0; i < kAccelerometerFullyOpenTestDataLength / 6; ++i) {
368 gfx::Vector3dF base(-kAccelerometerFullyOpenTestData[i * 6 + 1],
369 -kAccelerometerFullyOpenTestData[i * 6],
370 -kAccelerometerFullyOpenTestData[i * 6 + 2]);
371 base.Scale(kMeanGravity);
372 gfx::Vector3dF lid(-kAccelerometerFullyOpenTestData[i * 6 + 4],
373 kAccelerometerFullyOpenTestData[i * 6 + 3],
374 kAccelerometerFullyOpenTestData[i * 6 + 5]);
375 lid.Scale(kMeanGravity);
376 TriggerBaseAndLidUpdate(base, lid);
377 // There are a lot of samples, so ASSERT rather than EXPECT to only generate
378 // one failure rather than potentially hundreds.
379 ASSERT_TRUE(IsMaximizeModeStarted());
383 TEST_F(MaximizeModeControllerTest, VerticalHingeTest) {
384 // Feeds in sample accelerometer data and verifies that there are no
385 // transitions out of touchview / maximize mode while shaking the device
386 // around, while the hinge is nearly vertical. The data was captured from
387 // maxmimize_mode_controller.cc and does not require conversion.
388 ASSERT_EQ(0u, kAccelerometerVerticalHingeTestDataLength % 6);
389 for (size_t i = 0; i < kAccelerometerVerticalHingeTestDataLength / 6; ++i) {
390 gfx::Vector3dF base(kAccelerometerVerticalHingeTestData[i * 6],
391 kAccelerometerVerticalHingeTestData[i * 6 + 1],
392 kAccelerometerVerticalHingeTestData[i * 6 + 2]);
393 gfx::Vector3dF lid(kAccelerometerVerticalHingeTestData[i * 6 + 3],
394 kAccelerometerVerticalHingeTestData[i * 6 + 4],
395 kAccelerometerVerticalHingeTestData[i * 6 + 5]);
396 TriggerBaseAndLidUpdate(base, lid);
397 // There are a lot of samples, so ASSERT rather than EXPECT to only generate
398 // one failure rather than potentially hundreds.
399 ASSERT_TRUE(IsMaximizeModeStarted());
403 // Tests that CanEnterMaximizeMode returns false until a valid accelerometer
404 // event has been received, and that it returns true afterwards.
405 TEST_F(MaximizeModeControllerTest,
406 CanEnterMaximizeModeRequiresValidAccelerometerUpdate) {
407 // Should be false until an accelerometer event is sent.
408 ASSERT_FALSE(maximize_mode_controller()->CanEnterMaximizeMode());
409 OpenLidToAngle(90.0f);
410 EXPECT_TRUE(maximize_mode_controller()->CanEnterMaximizeMode());
413 // Tests that when an accelerometer event is received which has no keyboard that
414 // we enter maximize mode.
415 TEST_F(MaximizeModeControllerTest,
416 NoKeyboardAccelerometerTriggersMaximizeMode) {
417 ASSERT_FALSE(IsMaximizeModeStarted());
418 TriggerLidUpdate(gfx::Vector3dF(0.0f, 0.0f, kMeanGravity));
419 ASSERT_TRUE(IsMaximizeModeStarted());
422 // Test if this case does not crash. See http://crbug.com/462806
423 TEST_F(MaximizeModeControllerTest, DisplayDisconnectionDuringOverview) {
424 if (!SupportsMultipleDisplays())
425 return;
427 UpdateDisplay("800x600,800x600");
428 scoped_ptr<aura::Window> w1(
429 CreateTestWindowInShellWithBounds(gfx::Rect(0, 0, 100, 100)));
430 scoped_ptr<aura::Window> w2(
431 CreateTestWindowInShellWithBounds(gfx::Rect(800, 0, 100, 100)));
432 ASSERT_NE(w1->GetRootWindow(), w2->GetRootWindow());
434 maximize_mode_controller()->EnableMaximizeModeWindowManager(true);
435 Shell::GetInstance()->window_selector_controller()->ToggleOverview();
437 UpdateDisplay("800x600");
438 EXPECT_FALSE(
439 Shell::GetInstance()->window_selector_controller()->IsSelecting());
440 EXPECT_EQ(w1->GetRootWindow(), w2->GetRootWindow());
443 class MaximizeModeControllerSwitchesTest : public MaximizeModeControllerTest {
444 public:
445 MaximizeModeControllerSwitchesTest() {}
446 ~MaximizeModeControllerSwitchesTest() override {}
448 void SetUp() override {
449 base::CommandLine::ForCurrentProcess()->AppendSwitch(
450 switches::kAshEnableTouchViewTesting);
451 MaximizeModeControllerTest::SetUp();
453 private:
454 DISALLOW_COPY_AND_ASSIGN(MaximizeModeControllerSwitchesTest);
457 // Tests that when the command line switch for testing maximize mode is on, that
458 // accelerometer updates which would normally cause it to exit do not.
459 TEST_F(MaximizeModeControllerSwitchesTest, IgnoreHingeAngles) {
460 maximize_mode_controller()->EnableMaximizeModeWindowManager(true);
462 // Would normally trigger an exit from maximize mode.
463 OpenLidToAngle(90.0f);
464 EXPECT_TRUE(IsMaximizeModeStarted());
467 } // namespace ash