diff options
Diffstat (limited to 'libs/input/tests/PointerController_test.cpp')
-rw-r--r-- | libs/input/tests/PointerController_test.cpp | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp new file mode 100644 index 000000000000..92efb4ea86ff --- /dev/null +++ b/libs/input/tests/PointerController_test.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mocks/MockSprite.h" +#include "mocks/MockSpriteController.h" + +#include <input/PointerController.h> +#include <input/SpriteController.h> + +#include <atomic> +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <thread> + +namespace android { + +enum TestCursorType { + CURSOR_TYPE_DEFAULT = 0, + CURSOR_TYPE_HOVER, + CURSOR_TYPE_TOUCH, + CURSOR_TYPE_ANCHOR, + CURSOR_TYPE_ADDITIONAL_1, + CURSOR_TYPE_ADDITIONAL_2, + CURSOR_TYPE_CUSTOM = -1, +}; + +using ::testing::AllOf; +using ::testing::Field; +using ::testing::NiceMock; +using ::testing::Mock; +using ::testing::Return; +using ::testing::Test; + +std::pair<float, float> getHotSpotCoordinatesForType(int32_t type) { + return std::make_pair(type * 10, type * 10 + 5); +} + +class MockPointerControllerPolicyInterface : public PointerControllerPolicyInterface { +public: + virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) override; + virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) override; + virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources, + std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) override; + virtual int32_t getDefaultPointerIconId() override; + virtual int32_t getCustomPointerIconId() override; + +private: + void loadPointerIconForType(SpriteIcon* icon, int32_t cursorType); +}; + +void MockPointerControllerPolicyInterface::loadPointerIcon(SpriteIcon* icon, int32_t) { + loadPointerIconForType(icon, CURSOR_TYPE_DEFAULT); +} + +void MockPointerControllerPolicyInterface::loadPointerResources(PointerResources* outResources, + int32_t) { + loadPointerIconForType(&outResources->spotHover, CURSOR_TYPE_HOVER); + loadPointerIconForType(&outResources->spotTouch, CURSOR_TYPE_TOUCH); + loadPointerIconForType(&outResources->spotAnchor, CURSOR_TYPE_ANCHOR); +} + +void MockPointerControllerPolicyInterface::loadAdditionalMouseResources( + std::map<int32_t, SpriteIcon>* outResources, + std::map<int32_t, PointerAnimation>* outAnimationResources, + int32_t) { + SpriteIcon icon; + PointerAnimation anim; + + for (int32_t cursorType : {CURSOR_TYPE_ADDITIONAL_1, CURSOR_TYPE_ADDITIONAL_2}) { + loadPointerIconForType(&icon, cursorType); + anim.animationFrames.push_back(icon); + anim.durationPerFrame = 10; + (*outResources)[cursorType] = icon; + (*outAnimationResources)[cursorType] = anim; + } +} + +int32_t MockPointerControllerPolicyInterface::getDefaultPointerIconId() { + return CURSOR_TYPE_DEFAULT; +} + +int32_t MockPointerControllerPolicyInterface::getCustomPointerIconId() { + return CURSOR_TYPE_CUSTOM; +} + +void MockPointerControllerPolicyInterface::loadPointerIconForType(SpriteIcon* icon, int32_t type) { + icon->style = type; + std::pair<float, float> hotSpot = getHotSpotCoordinatesForType(type); + icon->hotSpotX = hotSpot.first; + icon->hotSpotY = hotSpot.second; +} + +class PointerControllerTest : public Test { +protected: + PointerControllerTest(); + ~PointerControllerTest(); + + sp<MockSprite> mPointerSprite; + sp<MockPointerControllerPolicyInterface> mPolicy; + sp<MockSpriteController> mSpriteController; + sp<PointerController> mPointerController; + +private: + void loopThread(); + + std::atomic<bool> mRunning = true; + class MyLooper : public Looper { + public: + MyLooper() : Looper(false) {} + ~MyLooper() = default; + }; + sp<MyLooper> mLooper; + std::thread mThread; +}; + +PointerControllerTest::PointerControllerTest() : mPointerSprite(new NiceMock<MockSprite>), + mLooper(new MyLooper), mThread(&PointerControllerTest::loopThread, this) { + + mSpriteController = new NiceMock<MockSpriteController>(mLooper); + mPolicy = new MockPointerControllerPolicyInterface(); + + EXPECT_CALL(*mSpriteController, createSprite()) + .WillOnce(Return(mPointerSprite)); + + mPointerController = new PointerController(mPolicy, mLooper, mSpriteController); + + DisplayViewport viewport; + viewport.displayId = ADISPLAY_ID_DEFAULT; + viewport.logicalRight = 1600; + viewport.logicalBottom = 1200; + viewport.physicalRight = 800; + viewport.physicalBottom = 600; + viewport.deviceWidth = 400; + viewport.deviceHeight = 300; + mPointerController->setDisplayViewport(viewport); +} + +PointerControllerTest::~PointerControllerTest() { + mRunning.store(false, std::memory_order_relaxed); + mThread.join(); +} + +void PointerControllerTest::loopThread() { + Looper::setForThread(mLooper); + + while (mRunning.load(std::memory_order_relaxed)) { + mLooper->pollOnce(100); + } +} + +TEST_F(PointerControllerTest, useDefaultCursorTypeByDefault) { + mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE); + + std::pair<float, float> hotspot = getHotSpotCoordinatesForType(CURSOR_TYPE_DEFAULT); + EXPECT_CALL(*mPointerSprite, setVisible(true)); + EXPECT_CALL(*mPointerSprite, setAlpha(1.0f)); + EXPECT_CALL(*mPointerSprite, setIcon( + AllOf( + Field(&SpriteIcon::style, CURSOR_TYPE_DEFAULT), + Field(&SpriteIcon::hotSpotX, hotspot.first), + Field(&SpriteIcon::hotSpotY, hotspot.second)))); + mPointerController->reloadPointerResources(); +} + +TEST_F(PointerControllerTest, updatePointerIcon) { + mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE); + + int32_t type = CURSOR_TYPE_ADDITIONAL_1; + std::pair<float, float> hotspot = getHotSpotCoordinatesForType(type); + EXPECT_CALL(*mPointerSprite, setVisible(true)); + EXPECT_CALL(*mPointerSprite, setAlpha(1.0f)); + EXPECT_CALL(*mPointerSprite, setIcon( + AllOf( + Field(&SpriteIcon::style, type), + Field(&SpriteIcon::hotSpotX, hotspot.first), + Field(&SpriteIcon::hotSpotY, hotspot.second)))); + mPointerController->updatePointerIcon(type); +} + +TEST_F(PointerControllerTest, setCustomPointerIcon) { + mPointerController->unfade(PointerController::TRANSITION_IMMEDIATE); + + int32_t style = CURSOR_TYPE_CUSTOM; + float hotSpotX = 15; + float hotSpotY = 20; + + SpriteIcon icon; + icon.style = style; + icon.hotSpotX = hotSpotX; + icon.hotSpotY = hotSpotY; + + EXPECT_CALL(*mPointerSprite, setVisible(true)); + EXPECT_CALL(*mPointerSprite, setAlpha(1.0f)); + EXPECT_CALL(*mPointerSprite, setIcon( + AllOf( + Field(&SpriteIcon::style, style), + Field(&SpriteIcon::hotSpotX, hotSpotX), + Field(&SpriteIcon::hotSpotY, hotSpotY)))); + mPointerController->setCustomPointerIcon(icon); +} + +} // namespace android |