/* * 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. */ #pragma once #include #include #include #include #include #include #include constexpr size_t kValidTypes[] = {EV_SW, EV_SYN, EV_ABS, EV_KEY, EV_MSC, EV_REL, android::EventHubInterface::DEVICE_ADDED, android::EventHubInterface::DEVICE_REMOVED, android::EventHubInterface::FINISHED_DEVICE_SCAN}; constexpr size_t kValidCodes[] = { SYN_REPORT, ABS_MT_SLOT, SYN_MT_REPORT, ABS_MT_POSITION_X, ABS_MT_POSITION_Y, ABS_MT_TOUCH_MAJOR, ABS_MT_TOUCH_MINOR, ABS_MT_WIDTH_MAJOR, ABS_MT_WIDTH_MINOR, ABS_MT_ORIENTATION, ABS_MT_TRACKING_ID, ABS_MT_PRESSURE, ABS_MT_DISTANCE, ABS_MT_TOOL_TYPE, MSC_SCAN, REL_X, REL_Y, REL_WHEEL, REL_HWHEEL, BTN_LEFT, BTN_RIGHT, BTN_MIDDLE, BTN_BACK, BTN_SIDE, BTN_FORWARD, BTN_EXTRA, BTN_TASK, }; constexpr size_t kMaxSize = 256; namespace android { template ToolType getFuzzedToolType(Fdp& fdp) { const int32_t toolType = fdp.template ConsumeIntegralInRange( static_cast(ToolType::ftl_first), static_cast(ToolType::ftl_last)); return static_cast(toolType); } template RawEvent getFuzzedRawEvent(Fdp& fdp) { const int32_t type = fdp.ConsumeBool() ? fdp.PickValueInArray(kValidTypes) : fdp.template ConsumeIntegral(); const int32_t code = fdp.ConsumeBool() ? fdp.PickValueInArray(kValidCodes) : fdp.template ConsumeIntegral(); return RawEvent{ .when = fdp.template ConsumeIntegral(), .readTime = fdp.template ConsumeIntegral(), .deviceId = fdp.template ConsumeIntegral(), .type = type, .code = code, .value = fdp.template ConsumeIntegral(), }; } class FuzzEventHub : public EventHubInterface { InputDeviceIdentifier mIdentifier; std::vector mVideoFrames; PropertyMap mFuzzConfig; std::map> mAxes; std::shared_ptr mFdp; public: FuzzEventHub(std::shared_ptr fdp) : mFdp(std::move(fdp)) {} ~FuzzEventHub() {} void addProperty(std::string key, std::string value) { mFuzzConfig.addProperty(key, value); } ftl::Flags getDeviceClasses(int32_t deviceId) const override { return ftl::Flags(mFdp->ConsumeIntegral()); } InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override { return mIdentifier; } int32_t getDeviceControllerNumber(int32_t deviceId) const override { return mFdp->ConsumeIntegral(); } std::optional getConfiguration(int32_t deviceId) const override { return mFuzzConfig; } void setAbsoluteAxisInfo(int32_t deviceId, int axis, const RawAbsoluteAxisInfo& axisInfo) { mAxes[deviceId][axis] = axisInfo; } status_t getAbsoluteAxisInfo(int32_t deviceId, int axis, RawAbsoluteAxisInfo* outAxisInfo) const override { if (auto deviceAxesIt = mAxes.find(deviceId); deviceAxesIt != mAxes.end()) { const std::map& deviceAxes = deviceAxesIt->second; if (auto axisInfoIt = deviceAxes.find(axis); axisInfoIt != deviceAxes.end()) { *outAxisInfo = axisInfoIt->second; return OK; } } return mFdp->ConsumeIntegral(); } bool hasRelativeAxis(int32_t deviceId, int axis) const override { return mFdp->ConsumeBool(); } bool hasInputProperty(int32_t deviceId, int property) const override { return mFdp->ConsumeBool(); } bool hasMscEvent(int32_t deviceId, int mscEvent) const override { return mFdp->ConsumeBool(); } status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState, int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override { return mFdp->ConsumeIntegral(); } status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const override { return mFdp->ConsumeIntegral(); } void setExcludedDevices(const std::vector& devices) override {} std::vector getEvents(int timeoutMillis) override { std::vector events; const size_t count = mFdp->ConsumeIntegralInRange(0, kMaxSize); for (size_t i = 0; i < count; ++i) { events.push_back(getFuzzedRawEvent(*mFdp)); } return events; } std::vector getVideoFrames(int32_t deviceId) override { return mVideoFrames; } base::Result> mapSensor( int32_t deviceId, int32_t absCode) const override { return base::ResultError("Fuzzer", UNKNOWN_ERROR); }; // Raw batteries are sysfs power_supply nodes we found from the EventHub device sysfs node, // containing the raw info of the sysfs node structure. std::vector getRawBatteryIds(int32_t deviceId) const override { return {}; } std::optional getRawBatteryInfo(int32_t deviceId, int32_t BatteryId) const override { return std::nullopt; }; std::vector getRawLightIds(int32_t deviceId) const override { return {}; }; std::optional getRawLightInfo(int32_t deviceId, int32_t lightId) const override { return std::nullopt; }; std::optional getLightBrightness(int32_t deviceId, int32_t lightId) const override { return std::nullopt; }; void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) override{}; std::optional> getLightIntensities( int32_t deviceId, int32_t lightId) const override { return std::nullopt; }; void setLightIntensities(int32_t deviceId, int32_t lightId, std::unordered_map intensities) override{}; std::optional getRawLayoutInfo(int32_t deviceId) const override { return std::nullopt; }; int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override { return mFdp->ConsumeIntegral(); } int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override { return mFdp->ConsumeIntegral(); } int32_t getSwitchState(int32_t deviceId, int32_t sw) const override { return mFdp->ConsumeIntegral(); } void addKeyRemapping(int32_t deviceId, int32_t fromKeyCode, int32_t toKeyCode) const override {} int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const override { return mFdp->ConsumeIntegral(); } status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const override { return mFdp->ConsumeIntegral(); } base::Result> getMtSlotValues(int32_t deviceId, int32_t axis, size_t slotCount) const override { if (mFdp->ConsumeBool()) { std::vector outValues(slotCount + 1); for (size_t i = 0; i < outValues.size(); i++) { outValues.push_back(mFdp->ConsumeIntegral()); } return std::move(outValues); } else { return base::ResultError("Fuzzer", UNKNOWN_ERROR); } } bool markSupportedKeyCodes(int32_t deviceId, const std::vector& keyCodes, uint8_t* outFlags) const override { return mFdp->ConsumeBool(); } bool hasScanCode(int32_t deviceId, int32_t scanCode) const override { return mFdp->ConsumeBool(); } bool hasKeyCode(int32_t deviceId, int32_t keyCode) const override { return mFdp->ConsumeBool(); } bool hasLed(int32_t deviceId, int32_t led) const override { return mFdp->ConsumeBool(); } void setLedState(int32_t deviceId, int32_t led, bool on) override {} void getVirtualKeyDefinitions( int32_t deviceId, std::vector& outVirtualKeys) const override {} const std::shared_ptr getKeyCharacterMap(int32_t deviceId) const override { return nullptr; } bool setKeyboardLayoutOverlay(int32_t deviceId, std::shared_ptr map) override { return mFdp->ConsumeBool(); } void vibrate(int32_t deviceId, const VibrationElement& effect) override {} void cancelVibrate(int32_t deviceId) override {} std::vector getVibratorIds(int32_t deviceId) const override { return {}; }; /* Query battery level. */ std::optional getBatteryCapacity(int32_t deviceId, int32_t batteryId) const override { return std::nullopt; }; /* Query battery status. */ std::optional getBatteryStatus(int32_t deviceId, int32_t batteryId) const override { return std::nullopt; }; void requestReopenDevices() override {} void wake() override {} void dump(std::string& dump) const override {} void monitor() const override {} bool isDeviceEnabled(int32_t deviceId) const override { return mFdp->ConsumeBool(); } status_t enableDevice(int32_t deviceId) override { return mFdp->ConsumeIntegral(); } status_t disableDevice(int32_t deviceId) override { return mFdp->ConsumeIntegral(); } void sysfsNodeChanged(const std::string& sysfsNodePath) override {} }; class FuzzInputReaderPolicy : public InputReaderPolicyInterface { TouchAffineTransformation mTransform; std::shared_ptr mFdp; protected: ~FuzzInputReaderPolicy() {} public: FuzzInputReaderPolicy(std::shared_ptr mFdp) : mFdp(mFdp) {} void getReaderConfiguration(InputReaderConfiguration* outConfig) override {} void notifyInputDevicesChanged(const std::vector& inputDevices) override {} std::shared_ptr getKeyboardLayoutOverlay( const InputDeviceIdentifier& identifier, const std::optional layoutInfo) override { return nullptr; } std::string getDeviceAlias(const InputDeviceIdentifier& identifier) { return mFdp->ConsumeRandomLengthString(32); } TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor, ui::Rotation surfaceRotation) override { return mTransform; } void setTouchAffineTransformation(const TouchAffineTransformation t) { mTransform = t; } void notifyStylusGestureStarted(int32_t, nsecs_t) {} bool isInputMethodConnectionActive() override { return mFdp->ConsumeBool(); } std::optional getPointerViewportForAssociatedDisplay( ui::LogicalDisplayId associatedDisplayId) override { return {}; } }; class FuzzInputListener : public virtual InputListenerInterface { public: void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override {} void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override {} void notifyKey(const NotifyKeyArgs& args) override {} void notifyMotion(const NotifyMotionArgs& args) override {} void notifySwitch(const NotifySwitchArgs& args) override {} void notifySensor(const NotifySensorArgs& args) override{}; void notifyVibratorState(const NotifyVibratorStateArgs& args) override{}; void notifyDeviceReset(const NotifyDeviceResetArgs& args) override {} void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override{}; }; class FuzzInputReaderContext : public InputReaderContext { std::shared_ptr mEventHub; sp mPolicy; std::shared_ptr mFdp; public: FuzzInputReaderContext(std::shared_ptr eventHub, std::shared_ptr fdp) : mEventHub(eventHub), mPolicy(sp::make(fdp)), mFdp(fdp) {} ~FuzzInputReaderContext() {} void updateGlobalMetaState() override {} int32_t getGlobalMetaState() { return mFdp->ConsumeIntegral(); } void disableVirtualKeysUntil(nsecs_t time) override {} bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) override { return mFdp->ConsumeBool(); } void requestTimeoutAtTime(nsecs_t when) override {} int32_t bumpGeneration() override { return mFdp->ConsumeIntegral(); } void getExternalStylusDevices(std::vector& outDevices) override {} std::list dispatchExternalStylusState(const StylusState& outState) override { return {}; } InputReaderPolicyInterface* getPolicy() override { return mPolicy.get(); } EventHubInterface* getEventHub() override { return mEventHub.get(); } int32_t getNextId() override { return mFdp->ConsumeIntegral(); } void updateLedMetaState(int32_t metaState) override{}; int32_t getLedMetaState() override { return mFdp->ConsumeIntegral(); }; void notifyStylusGestureStarted(int32_t, nsecs_t) {} void setPreventingTouchpadTaps(bool prevent) {} bool isPreventingTouchpadTaps() { return mFdp->ConsumeBool(); }; void setLastKeyDownTimestamp(nsecs_t when) { mLastKeyDownTimestamp = when; }; nsecs_t getLastKeyDownTimestamp() { return mLastKeyDownTimestamp; }; KeyboardClassifier& getKeyboardClassifier() override { return *mClassifier; } private: nsecs_t mLastKeyDownTimestamp; std::unique_ptr mClassifier = std::make_unique(); }; template InputDevice getFuzzedInputDevice(Fdp& fdp, FuzzInputReaderContext* context) { InputDeviceIdentifier identifier; identifier.name = fdp.ConsumeRandomLengthString(16); identifier.location = fdp.ConsumeRandomLengthString(12); int32_t deviceID = fdp.ConsumeIntegralInRange(0, 5); int32_t deviceGeneration = fdp.ConsumeIntegralInRange(0, 5); return InputDevice(context, deviceID, deviceGeneration, identifier); } template void configureAndResetDevice(Fdp& fdp, InputDevice& device) { nsecs_t arbitraryTime = fdp.template ConsumeIntegral(); std::list out; out += device.configure(arbitraryTime, /*readerConfig=*/{}, /*changes=*/{}); out += device.reset(arbitraryTime); } template T& getMapperForDevice(Fdp& fdp, InputDevice& device, Args... args) { int32_t eventhubId = fdp.template ConsumeIntegral(); // ensure a device entry exists for this eventHubId device.addEmptyEventHubDevice(eventhubId); configureAndResetDevice(fdp, device); return device.template constructAndAddMapper(eventhubId, args...); } } // namespace android