Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / ash / wm / maximize_mode / maximize_mode_controller_unittest.cc
blob143ca0f106248db2633d23f6276490a451bdb6b5
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>
6 #include <map>
7 #include <string>
9 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
11 #include "ash/ash_switches.h"
12 #include "ash/display/display_manager.h"
13 #include "ash/shell.h"
14 #include "ash/system/tray/system_tray_delegate.h"
15 #include "ash/test/ash_test_base.h"
16 #include "ash/test/display_manager_test_api.h"
17 #include "ash/test/test_system_tray_delegate.h"
18 #include "ash/test/test_volume_control_delegate.h"
19 #include "ash/wm/overview/window_selector_controller.h"
20 #include "base/bind.h"
21 #include "base/command_line.h"
22 #include "base/metrics/user_metrics.h"
23 #include "base/test/simple_test_tick_clock.h"
24 #include "chromeos/accelerometer/accelerometer_reader.h"
25 #include "chromeos/accelerometer/accelerometer_types.h"
26 #include "ui/events/event_handler.h"
27 #include "ui/events/test/event_generator.h"
28 #include "ui/gfx/geometry/vector3d_f.h"
29 #include "ui/message_center/message_center.h"
31 #if defined(USE_X11)
32 #include "ui/events/test/events_test_utils_x11.h"
33 #endif
35 namespace ash {
37 namespace {
39 const float kDegreesToRadians = 3.1415926f / 180.0f;
40 const float kMeanGravity = 9.8066f;
42 const char kTouchViewInitiallyDisabled[] = "Touchview_Initially_Disabled";
43 const char kTouchViewEnabled[] = "Touchview_Enabled";
44 const char kTouchViewDisabled[] = "Touchview_Disabled";
46 // TODO(bruthig): Move this to base/metrics/ so that it can be reused.
47 // This class observes and collects user action notifications that are sent
48 // by the tests, so that they can be examined afterwards for correctness.
49 class UserActionObserver {
50 public:
51 UserActionObserver();
52 ~UserActionObserver();
54 int GetMetricCount(const std::string& name) const;
56 void ResetCounts();
58 private:
59 typedef std::map<std::string, int> UserActionCountMap;
61 void OnUserAction(const std::string& action);
63 UserActionCountMap count_map_;
65 base::ActionCallback action_callback_;
67 DISALLOW_COPY_AND_ASSIGN(UserActionObserver);
70 UserActionObserver::UserActionObserver()
71 : action_callback_(base::Bind(&UserActionObserver::OnUserAction,
72 base::Unretained(this))) {
73 base::AddActionCallback(action_callback_);
76 UserActionObserver::~UserActionObserver() {
77 base::RemoveActionCallback(action_callback_);
80 int UserActionObserver::GetMetricCount(const std::string& name) const {
81 UserActionCountMap::const_iterator i = count_map_.find(name);
82 return i == count_map_.end() ? 0 : i->second;
85 void UserActionObserver::ResetCounts() {
86 count_map_.clear();
89 void UserActionObserver::OnUserAction(const std::string& action) {
90 ++(count_map_[action]);
93 } // namespace
95 // Test accelerometer data taken with the lid at less than 180 degrees while
96 // shaking the device around. The data is to be interpreted in groups of 6 where
97 // each 6 values corresponds to the X, Y, and Z readings from the base and lid
98 // accelerometers in this order.
99 extern const float kAccelerometerLaptopModeTestData[];
100 extern const size_t kAccelerometerLaptopModeTestDataLength;
102 // Test accelerometer data taken with the lid open 360 degrees while
103 // shaking the device around. The data is to be interpreted in groups of 6 where
104 // each 6 values corresponds to the X, Y, and Z readings from the base and lid
105 // accelerometers in this order.
106 extern const float kAccelerometerFullyOpenTestData[];
107 extern const size_t kAccelerometerFullyOpenTestDataLength;
109 class MaximizeModeControllerTest : public test::AshTestBase {
110 public:
111 MaximizeModeControllerTest() {}
112 ~MaximizeModeControllerTest() override {}
114 void SetUp() override {
115 test::AshTestBase::SetUp();
116 chromeos::AccelerometerReader::GetInstance()->RemoveObserver(
117 maximize_mode_controller());
119 // Set the first display to be the internal display for the accelerometer
120 // screen rotation tests.
121 test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()).
122 SetFirstDisplayAsInternalDisplay();
125 void TearDown() override {
126 chromeos::AccelerometerReader::GetInstance()->AddObserver(
127 maximize_mode_controller());
128 test::AshTestBase::TearDown();
131 MaximizeModeController* maximize_mode_controller() {
132 return Shell::GetInstance()->maximize_mode_controller();
135 void TriggerLidUpdate(const gfx::Vector3dF& lid) {
136 scoped_refptr<chromeos::AccelerometerUpdate> update(
137 new chromeos::AccelerometerUpdate());
138 update->Set(chromeos::ACCELEROMETER_SOURCE_SCREEN, lid.x(), lid.y(),
139 lid.z());
140 maximize_mode_controller()->OnAccelerometerUpdated(update);
143 void TriggerBaseAndLidUpdate(const gfx::Vector3dF& base,
144 const gfx::Vector3dF& lid) {
145 scoped_refptr<chromeos::AccelerometerUpdate> update(
146 new chromeos::AccelerometerUpdate());
147 update->Set(chromeos::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD, base.x(),
148 base.y(), base.z());
149 update->Set(chromeos::ACCELEROMETER_SOURCE_SCREEN, lid.x(), lid.y(),
150 lid.z());
151 maximize_mode_controller()->OnAccelerometerUpdated(update);
154 bool IsMaximizeModeStarted() {
155 return maximize_mode_controller()->IsMaximizeModeWindowManagerEnabled();
158 gfx::Display::Rotation GetInternalDisplayRotation() const {
159 return Shell::GetInstance()->display_manager()->GetDisplayInfo(
160 gfx::Display::InternalDisplayId()).rotation();
163 void SetInternalDisplayRotation(gfx::Display::Rotation rotation) const {
164 Shell::GetInstance()->display_manager()->
165 SetDisplayRotation(gfx::Display::InternalDisplayId(), rotation);
168 // Attaches a SimpleTestTickClock to the MaximizeModeController with a non
169 // null value initial value.
170 void AttachTickClockForTest() {
171 scoped_ptr<base::TickClock> tick_clock(
172 test_tick_clock_ = new base::SimpleTestTickClock());
173 test_tick_clock_->Advance(base::TimeDelta::FromSeconds(1));
174 maximize_mode_controller()->SetTickClockForTest(tick_clock.Pass());
177 void AdvanceTickClock(const base::TimeDelta& delta) {
178 DCHECK(test_tick_clock_);
179 test_tick_clock_->Advance(delta);
182 void OpenLidToAngle(float degrees) {
183 DCHECK(degrees >= 0.0f);
184 DCHECK(degrees <= 360.0f);
186 float radians = degrees * kDegreesToRadians;
187 gfx::Vector3dF base_vector(0.0f, -kMeanGravity, 0.0f);
188 gfx::Vector3dF lid_vector(0.0f,
189 kMeanGravity * cos(radians),
190 kMeanGravity * sin(radians));
191 TriggerBaseAndLidUpdate(base_vector, lid_vector);
194 void OpenLid() {
195 maximize_mode_controller()->LidEventReceived(true /* open */,
196 maximize_mode_controller()->tick_clock_->NowTicks());
199 void CloseLid() {
200 maximize_mode_controller()->LidEventReceived(false /* open */,
201 maximize_mode_controller()->tick_clock_->NowTicks());
204 bool WasLidOpenedRecently() {
205 return maximize_mode_controller()->WasLidOpenedRecently();
208 UserActionObserver* user_action_observer() { return &user_action_observer_; }
210 private:
211 base::SimpleTestTickClock* test_tick_clock_;
213 // Tracks user action counts.
214 UserActionObserver user_action_observer_;
216 DISALLOW_COPY_AND_ASSIGN(MaximizeModeControllerTest);
219 // Verify TouchView enabled/disabled user action metrics are recorded.
220 TEST_F(MaximizeModeControllerTest, VerifyTouchViewEnabledDisabledCounts) {
221 ASSERT_EQ(
222 1, user_action_observer()->GetMetricCount(kTouchViewInitiallyDisabled));
223 ASSERT_EQ(0, user_action_observer()->GetMetricCount(kTouchViewEnabled));
224 ASSERT_EQ(0, user_action_observer()->GetMetricCount(kTouchViewDisabled));
226 user_action_observer()->ResetCounts();
227 maximize_mode_controller()->EnableMaximizeModeWindowManager(true);
228 EXPECT_EQ(1, user_action_observer()->GetMetricCount(kTouchViewEnabled));
229 EXPECT_EQ(0, user_action_observer()->GetMetricCount(kTouchViewDisabled));
230 maximize_mode_controller()->EnableMaximizeModeWindowManager(true);
231 EXPECT_EQ(1, user_action_observer()->GetMetricCount(kTouchViewEnabled));
232 EXPECT_EQ(0, user_action_observer()->GetMetricCount(kTouchViewDisabled));
234 user_action_observer()->ResetCounts();
235 maximize_mode_controller()->EnableMaximizeModeWindowManager(false);
236 EXPECT_EQ(0, user_action_observer()->GetMetricCount(kTouchViewEnabled));
237 EXPECT_EQ(1, user_action_observer()->GetMetricCount(kTouchViewDisabled));
238 maximize_mode_controller()->EnableMaximizeModeWindowManager(false);
239 EXPECT_EQ(0, user_action_observer()->GetMetricCount(kTouchViewEnabled));
240 EXPECT_EQ(1, user_action_observer()->GetMetricCount(kTouchViewDisabled));
243 // Verify that closing the lid will exit maximize mode.
244 TEST_F(MaximizeModeControllerTest, CloseLidWhileInMaximizeMode) {
245 OpenLidToAngle(315.0f);
246 ASSERT_TRUE(IsMaximizeModeStarted());
248 CloseLid();
249 EXPECT_FALSE(IsMaximizeModeStarted());
252 // Verify that maximize mode will not be entered when the lid is closed.
253 TEST_F(MaximizeModeControllerTest,
254 HingeAnglesWithLidClosed) {
255 AttachTickClockForTest();
257 CloseLid();
259 OpenLidToAngle(270.0f);
260 EXPECT_FALSE(IsMaximizeModeStarted());
262 OpenLidToAngle(315.0f);
263 EXPECT_FALSE(IsMaximizeModeStarted());
265 OpenLidToAngle(355.0f);
266 EXPECT_FALSE(IsMaximizeModeStarted());
269 // Verify the maximize mode state for unstable hinge angles when the lid was
270 // recently open.
271 TEST_F(MaximizeModeControllerTest,
272 UnstableHingeAnglesWhenLidRecentlyOpened) {
273 AttachTickClockForTest();
275 OpenLid();
276 ASSERT_TRUE(WasLidOpenedRecently());
278 OpenLidToAngle(5.0f);
279 EXPECT_FALSE(IsMaximizeModeStarted());
281 OpenLidToAngle(355.0f);
282 EXPECT_FALSE(IsMaximizeModeStarted());
284 // This is a stable reading and should clear the last lid opened time.
285 OpenLidToAngle(45.0f);
286 EXPECT_FALSE(IsMaximizeModeStarted());
287 EXPECT_FALSE(WasLidOpenedRecently());
289 OpenLidToAngle(355.0f);
290 EXPECT_TRUE(IsMaximizeModeStarted());
293 // Verify the WasLidOpenedRecently signal with respect to time.
294 TEST_F(MaximizeModeControllerTest, WasLidOpenedRecentlyOverTime) {
295 AttachTickClockForTest();
297 // No lid open time initially.
298 ASSERT_FALSE(WasLidOpenedRecently());
300 CloseLid();
301 EXPECT_FALSE(WasLidOpenedRecently());
303 OpenLid();
304 EXPECT_TRUE(WasLidOpenedRecently());
306 // 1 second after lid open.
307 AdvanceTickClock(base::TimeDelta::FromSeconds(1));
308 EXPECT_TRUE(WasLidOpenedRecently());
310 // 3 seconds after lid open.
311 AdvanceTickClock(base::TimeDelta::FromSeconds(2));
312 EXPECT_FALSE(WasLidOpenedRecently());
315 // Verify the maximize mode enter/exit thresholds for stable angles.
316 TEST_F(MaximizeModeControllerTest, StableHingeAnglesWithLidOpened) {
317 ASSERT_FALSE(IsMaximizeModeStarted());
318 ASSERT_FALSE(WasLidOpenedRecently());
320 OpenLidToAngle(180.0f);
321 EXPECT_FALSE(IsMaximizeModeStarted());
323 OpenLidToAngle(315.0f);
324 EXPECT_TRUE(IsMaximizeModeStarted());
326 OpenLidToAngle(180.0f);
327 EXPECT_TRUE(IsMaximizeModeStarted());
329 OpenLidToAngle(45.0f);
330 EXPECT_FALSE(IsMaximizeModeStarted());
332 OpenLidToAngle(270.0f);
333 EXPECT_TRUE(IsMaximizeModeStarted());
335 OpenLidToAngle(90.0f);
336 EXPECT_FALSE(IsMaximizeModeStarted());
339 // Verify the maximize mode state for unstable hinge angles when the lid is open
340 // but not recently.
341 TEST_F(MaximizeModeControllerTest, UnstableHingeAnglesWithLidOpened) {
342 AttachTickClockForTest();
344 ASSERT_FALSE(WasLidOpenedRecently());
345 ASSERT_FALSE(IsMaximizeModeStarted());
347 OpenLidToAngle(5.0f);
348 EXPECT_FALSE(IsMaximizeModeStarted());
350 OpenLidToAngle(355.0f);
351 EXPECT_TRUE(IsMaximizeModeStarted());
353 OpenLidToAngle(5.0f);
354 EXPECT_TRUE(IsMaximizeModeStarted());
357 // Tests that when the hinge is nearly vertically aligned, the current state
358 // persists as the computed angle is highly inaccurate in this orientation.
359 TEST_F(MaximizeModeControllerTest, HingeAligned) {
360 // Laptop in normal orientation lid open 90 degrees.
361 TriggerBaseAndLidUpdate(gfx::Vector3dF(0.0f, 0.0f, -kMeanGravity),
362 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f));
363 EXPECT_FALSE(IsMaximizeModeStarted());
365 // Completely vertical.
366 TriggerBaseAndLidUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, 0.0f),
367 gfx::Vector3dF(kMeanGravity, 0.0f, 0.0f));
368 EXPECT_FALSE(IsMaximizeModeStarted());
370 // Close to vertical but with hinge appearing to be open 270 degrees.
371 TriggerBaseAndLidUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, -0.1f),
372 gfx::Vector3dF(kMeanGravity, 0.1f, 0.0f));
373 EXPECT_FALSE(IsMaximizeModeStarted());
375 // Flat and open 270 degrees should start maximize mode.
376 TriggerBaseAndLidUpdate(gfx::Vector3dF(0.0f, 0.0f, -kMeanGravity),
377 gfx::Vector3dF(0.0f, kMeanGravity, 0.0f));
378 EXPECT_TRUE(IsMaximizeModeStarted());
380 // Normal 90 degree orientation but near vertical should stay in maximize
381 // mode.
382 TriggerBaseAndLidUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, -0.1f),
383 gfx::Vector3dF(kMeanGravity, -0.1f, 0.0f));
384 EXPECT_TRUE(IsMaximizeModeStarted());
387 TEST_F(MaximizeModeControllerTest, LaptopTest) {
388 // Feeds in sample accelerometer data and verifies that there are no
389 // transitions into touchview / maximize mode while shaking the device around
390 // with the hinge at less than 180 degrees. Note the conversion from device
391 // data to accelerometer updates consistent with accelerometer_reader.cc.
392 ASSERT_EQ(0u, kAccelerometerLaptopModeTestDataLength % 6);
393 for (size_t i = 0; i < kAccelerometerLaptopModeTestDataLength / 6; ++i) {
394 gfx::Vector3dF base(-kAccelerometerLaptopModeTestData[i * 6 + 1],
395 -kAccelerometerLaptopModeTestData[i * 6],
396 -kAccelerometerLaptopModeTestData[i * 6 + 2]);
397 base.Scale(kMeanGravity);
398 gfx::Vector3dF lid(-kAccelerometerLaptopModeTestData[i * 6 + 4],
399 kAccelerometerLaptopModeTestData[i * 6 + 3],
400 kAccelerometerLaptopModeTestData[i * 6 + 5]);
401 lid.Scale(kMeanGravity);
402 TriggerBaseAndLidUpdate(base, lid);
403 // There are a lot of samples, so ASSERT rather than EXPECT to only generate
404 // one failure rather than potentially hundreds.
405 ASSERT_FALSE(IsMaximizeModeStarted());
409 TEST_F(MaximizeModeControllerTest, MaximizeModeTest) {
410 // Trigger maximize mode by opening to 270 to begin the test in maximize mode.
411 TriggerBaseAndLidUpdate(gfx::Vector3dF(0.0f, 0.0f, kMeanGravity),
412 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f));
413 ASSERT_TRUE(IsMaximizeModeStarted());
415 // Feeds in sample accelerometer data and verifies that there are no
416 // transitions out of touchview / maximize mode while shaking the device
417 // around. Note the conversion from device data to accelerometer updates
418 // consistent with accelerometer_reader.cc.
419 ASSERT_EQ(0u, kAccelerometerFullyOpenTestDataLength % 6);
420 for (size_t i = 0; i < kAccelerometerFullyOpenTestDataLength / 6; ++i) {
421 gfx::Vector3dF base(-kAccelerometerFullyOpenTestData[i * 6 + 1],
422 -kAccelerometerFullyOpenTestData[i * 6],
423 -kAccelerometerFullyOpenTestData[i * 6 + 2]);
424 base.Scale(kMeanGravity);
425 gfx::Vector3dF lid(-kAccelerometerFullyOpenTestData[i * 6 + 4],
426 kAccelerometerFullyOpenTestData[i * 6 + 3],
427 kAccelerometerFullyOpenTestData[i * 6 + 5]);
428 lid.Scale(kMeanGravity);
429 TriggerBaseAndLidUpdate(base, lid);
430 // There are a lot of samples, so ASSERT rather than EXPECT to only generate
431 // one failure rather than potentially hundreds.
432 ASSERT_TRUE(IsMaximizeModeStarted());
436 // Tests that CanEnterMaximizeMode returns false until a valid accelerometer
437 // event has been received, and that it returns true afterwards.
438 TEST_F(MaximizeModeControllerTest,
439 CanEnterMaximizeModeRequiresValidAccelerometerUpdate) {
440 // Should be false until an accelerometer event is sent.
441 ASSERT_FALSE(maximize_mode_controller()->CanEnterMaximizeMode());
442 OpenLidToAngle(90.0f);
443 EXPECT_TRUE(maximize_mode_controller()->CanEnterMaximizeMode());
446 // Tests that when an accelerometer event is received which has no keyboard that
447 // we enter maximize mode.
448 TEST_F(MaximizeModeControllerTest,
449 NoKeyboardAccelerometerTriggersMaximizeMode) {
450 ASSERT_FALSE(IsMaximizeModeStarted());
451 TriggerLidUpdate(gfx::Vector3dF(0.0f, 0.0f, kMeanGravity));
452 ASSERT_TRUE(IsMaximizeModeStarted());
455 // Test if this case does not crash. See http://crbug.com/462806
456 TEST_F(MaximizeModeControllerTest, DisplayDisconnectionDuringOverview) {
457 if (!SupportsMultipleDisplays())
458 return;
460 UpdateDisplay("800x600,800x600");
461 scoped_ptr<aura::Window> w1(
462 CreateTestWindowInShellWithBounds(gfx::Rect(0, 0, 100, 100)));
463 scoped_ptr<aura::Window> w2(
464 CreateTestWindowInShellWithBounds(gfx::Rect(800, 0, 100, 100)));
465 ASSERT_NE(w1->GetRootWindow(), w2->GetRootWindow());
467 maximize_mode_controller()->EnableMaximizeModeWindowManager(true);
468 Shell::GetInstance()->window_selector_controller()->ToggleOverview();
470 UpdateDisplay("800x600");
471 EXPECT_FALSE(
472 Shell::GetInstance()->window_selector_controller()->IsSelecting());
473 EXPECT_EQ(w1->GetRootWindow(), w2->GetRootWindow());
476 class MaximizeModeControllerSwitchesTest : public MaximizeModeControllerTest {
477 public:
478 MaximizeModeControllerSwitchesTest() {}
479 ~MaximizeModeControllerSwitchesTest() override {}
481 void SetUp() override {
482 base::CommandLine::ForCurrentProcess()->AppendSwitch(
483 switches::kAshEnableTouchViewTesting);
484 MaximizeModeControllerTest::SetUp();
486 private:
487 DISALLOW_COPY_AND_ASSIGN(MaximizeModeControllerSwitchesTest);
490 // Tests that when the command line switch for testing maximize mode is on, that
491 // accelerometer updates which would normally cause it to exit do not.
492 TEST_F(MaximizeModeControllerSwitchesTest, IgnoreHingeAngles) {
493 maximize_mode_controller()->EnableMaximizeModeWindowManager(true);
495 // Would normally trigger an exit from maximize mode.
496 OpenLidToAngle(90.0f);
497 EXPECT_TRUE(IsMaximizeModeStarted());
500 } // namespace ash