| /* | 
 |  * Copyright 2022 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 "FakeInputReaderPolicy.h" | 
 |  | 
 | #include <android-base/thread_annotations.h> | 
 | #include <gtest/gtest.h> | 
 |  | 
 | #include "TestConstants.h" | 
 | #include "ui/Rotation.h" | 
 |  | 
 | namespace android { | 
 |  | 
 | void FakeInputReaderPolicy::assertInputDevicesChanged() { | 
 |     waitForInputDevices([](bool devicesChanged) { | 
 |         if (!devicesChanged) { | 
 |             FAIL() << "Timed out waiting for notifyInputDevicesChanged() to be called."; | 
 |         } | 
 |     }); | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::assertInputDevicesNotChanged() { | 
 |     waitForInputDevices([](bool devicesChanged) { | 
 |         if (devicesChanged) { | 
 |             FAIL() << "Expected notifyInputDevicesChanged() to not be called."; | 
 |         } | 
 |     }); | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::assertStylusGestureNotified(int32_t deviceId) { | 
 |     std::scoped_lock lock(mLock); | 
 |     ASSERT_TRUE(mStylusGestureNotified); | 
 |     ASSERT_EQ(deviceId, *mStylusGestureNotified); | 
 |     mStylusGestureNotified.reset(); | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::assertStylusGestureNotNotified() { | 
 |     std::scoped_lock lock(mLock); | 
 |     ASSERT_FALSE(mStylusGestureNotified); | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::clearViewports() { | 
 |     mViewports.clear(); | 
 |     mConfig.setDisplayViewports(mViewports); | 
 | } | 
 |  | 
 | std::optional<DisplayViewport> FakeInputReaderPolicy::getDisplayViewportByUniqueId( | 
 |         const std::string& uniqueId) const { | 
 |     return mConfig.getDisplayViewportByUniqueId(uniqueId); | 
 | } | 
 | std::optional<DisplayViewport> FakeInputReaderPolicy::getDisplayViewportByType( | 
 |         ViewportType type) const { | 
 |     return mConfig.getDisplayViewportByType(type); | 
 | } | 
 |  | 
 | std::optional<DisplayViewport> FakeInputReaderPolicy::getDisplayViewportByPort( | 
 |         uint8_t displayPort) const { | 
 |     return mConfig.getDisplayViewportByPort(displayPort); | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::addDisplayViewport(DisplayViewport viewport) { | 
 |     mViewports.push_back(std::move(viewport)); | 
 |     mConfig.setDisplayViewports(mViewports); | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::addDisplayViewport(int32_t displayId, int32_t width, int32_t height, | 
 |                                                ui::Rotation orientation, bool isActive, | 
 |                                                const std::string& uniqueId, | 
 |                                                std::optional<uint8_t> physicalPort, | 
 |                                                ViewportType type) { | 
 |     const bool isRotated = orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270; | 
 |     DisplayViewport v; | 
 |     v.displayId = displayId; | 
 |     v.orientation = orientation; | 
 |     v.logicalLeft = 0; | 
 |     v.logicalTop = 0; | 
 |     v.logicalRight = isRotated ? height : width; | 
 |     v.logicalBottom = isRotated ? width : height; | 
 |     v.physicalLeft = 0; | 
 |     v.physicalTop = 0; | 
 |     v.physicalRight = isRotated ? height : width; | 
 |     v.physicalBottom = isRotated ? width : height; | 
 |     v.deviceWidth = isRotated ? height : width; | 
 |     v.deviceHeight = isRotated ? width : height; | 
 |     v.isActive = isActive; | 
 |     v.uniqueId = uniqueId; | 
 |     v.physicalPort = physicalPort; | 
 |     v.type = type; | 
 |  | 
 |     addDisplayViewport(v); | 
 | } | 
 |  | 
 | bool FakeInputReaderPolicy::updateViewport(const DisplayViewport& viewport) { | 
 |     size_t count = mViewports.size(); | 
 |     for (size_t i = 0; i < count; i++) { | 
 |         const DisplayViewport& currentViewport = mViewports[i]; | 
 |         if (currentViewport.displayId == viewport.displayId) { | 
 |             mViewports[i] = viewport; | 
 |             mConfig.setDisplayViewports(mViewports); | 
 |             return true; | 
 |         } | 
 |     } | 
 |     // no viewport found. | 
 |     return false; | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::addExcludedDeviceName(const std::string& deviceName) { | 
 |     mConfig.excludedDeviceNames.push_back(deviceName); | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::addInputPortAssociation(const std::string& inputPort, | 
 |                                                     uint8_t displayPort) { | 
 |     mConfig.portAssociations.insert({inputPort, displayPort}); | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::addDeviceTypeAssociation(const std::string& inputPort, | 
 |                                                      const std::string& type) { | 
 |     mConfig.deviceTypeAssociations.insert({inputPort, type}); | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::addInputUniqueIdAssociation(const std::string& inputUniqueId, | 
 |                                                         const std::string& displayUniqueId) { | 
 |     mConfig.uniqueIdAssociations.insert({inputUniqueId, displayUniqueId}); | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::addKeyboardLayoutAssociation(const std::string& inputUniqueId, | 
 |                                                          const KeyboardLayoutInfo& layoutInfo) { | 
 |     mConfig.keyboardLayoutAssociations.insert({inputUniqueId, layoutInfo}); | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::addDisabledDevice(int32_t deviceId) { | 
 |     mConfig.disabledDevices.insert(deviceId); | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::removeDisabledDevice(int32_t deviceId) { | 
 |     mConfig.disabledDevices.erase(deviceId); | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::setPointerController( | 
 |         std::shared_ptr<FakePointerController> controller) { | 
 |     mPointerController = std::move(controller); | 
 | } | 
 |  | 
 | const InputReaderConfiguration& FakeInputReaderPolicy::getReaderConfiguration() const { | 
 |     return mConfig; | 
 | } | 
 |  | 
 | const std::vector<InputDeviceInfo>& FakeInputReaderPolicy::getInputDevices() const { | 
 |     return mInputDevices; | 
 | } | 
 |  | 
 | TouchAffineTransformation FakeInputReaderPolicy::getTouchAffineTransformation( | 
 |         const std::string& inputDeviceDescriptor, ui::Rotation surfaceRotation) { | 
 |     return transform; | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::setTouchAffineTransformation(const TouchAffineTransformation t) { | 
 |     transform = t; | 
 | } | 
 |  | 
 | PointerCaptureRequest FakeInputReaderPolicy::setPointerCapture(bool enabled) { | 
 |     mConfig.pointerCaptureRequest = {enabled, mNextPointerCaptureSequenceNumber++}; | 
 |     return mConfig.pointerCaptureRequest; | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::setShowTouches(bool enabled) { | 
 |     mConfig.showTouches = enabled; | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::setDefaultPointerDisplayId(int32_t pointerDisplayId) { | 
 |     mConfig.defaultPointerDisplayId = pointerDisplayId; | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::setPointerGestureEnabled(bool enabled) { | 
 |     mConfig.pointerGesturesEnabled = enabled; | 
 | } | 
 |  | 
 | float FakeInputReaderPolicy::getPointerGestureMovementSpeedRatio() { | 
 |     return mConfig.pointerGestureMovementSpeedRatio; | 
 | } | 
 |  | 
 | float FakeInputReaderPolicy::getPointerGestureZoomSpeedRatio() { | 
 |     return mConfig.pointerGestureZoomSpeedRatio; | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::setVelocityControlParams(const VelocityControlParameters& params) { | 
 |     mConfig.pointerVelocityControlParameters = params; | 
 |     mConfig.wheelVelocityControlParameters = params; | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::setStylusButtonMotionEventsEnabled(bool enabled) { | 
 |     mConfig.stylusButtonMotionEventsEnabled = enabled; | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::setStylusPointerIconEnabled(bool enabled) { | 
 |     mConfig.stylusPointerIconEnabled = enabled; | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::setIsInputMethodConnectionActive(bool active) { | 
 |     mIsInputMethodConnectionActive = active; | 
 | } | 
 |  | 
 | bool FakeInputReaderPolicy::isInputMethodConnectionActive() { | 
 |     return mIsInputMethodConnectionActive; | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::getReaderConfiguration(InputReaderConfiguration* outConfig) { | 
 |     *outConfig = mConfig; | 
 | } | 
 |  | 
 | std::shared_ptr<PointerControllerInterface> FakeInputReaderPolicy::obtainPointerController( | 
 |         int32_t /*deviceId*/) { | 
 |     return mPointerController; | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::notifyInputDevicesChanged( | 
 |         const std::vector<InputDeviceInfo>& inputDevices) { | 
 |     std::scoped_lock<std::mutex> lock(mLock); | 
 |     mInputDevices = inputDevices; | 
 |     mInputDevicesChanged = true; | 
 |     mDevicesChangedCondition.notify_all(); | 
 | } | 
 |  | 
 | std::shared_ptr<KeyCharacterMap> FakeInputReaderPolicy::getKeyboardLayoutOverlay( | 
 |         const InputDeviceIdentifier&) { | 
 |     return nullptr; | 
 | } | 
 |  | 
 | std::string FakeInputReaderPolicy::getDeviceAlias(const InputDeviceIdentifier&) { | 
 |     return ""; | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::waitForInputDevices(std::function<void(bool)> processDevicesChanged) { | 
 |     std::unique_lock<std::mutex> lock(mLock); | 
 |     base::ScopedLockAssertion assumeLocked(mLock); | 
 |  | 
 |     const bool devicesChanged = | 
 |             mDevicesChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) { | 
 |                 return mInputDevicesChanged; | 
 |             }); | 
 |     ASSERT_NO_FATAL_FAILURE(processDevicesChanged(devicesChanged)); | 
 |     mInputDevicesChanged = false; | 
 | } | 
 |  | 
 | void FakeInputReaderPolicy::notifyStylusGestureStarted(int32_t deviceId, nsecs_t eventTime) { | 
 |     std::scoped_lock<std::mutex> lock(mLock); | 
 |     mStylusGestureNotified = deviceId; | 
 | } | 
 |  | 
 | } // namespace android |