blob: fa8270a3d9f78773134a12d334c3fb7433f22aa5 [file] [log] [blame]
Michael Ensingb8d93262020-05-12 00:41:30 -07001/*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Michael Ensingb8d93262020-05-12 00:41:30 -070016#pragma once
17
Harry Cuttsccb75e82023-06-23 14:08:06 +000018#include <map>
Harry Cuttsf61c0472023-07-10 14:45:15 +000019#include <memory>
Harry Cutts207674d2024-06-06 18:53:41 +000020#include <optional>
Harry Cuttsccb75e82023-06-23 14:08:06 +000021
22#include <EventHub.h>
Michael Ensingb8d93262020-05-12 00:41:30 -070023#include <InputDevice.h>
24#include <InputMapper.h>
25#include <InputReader.h>
Aditya Wazireea5be02022-10-31 12:40:10 +053026#include <ThreadSafeFuzzedDataProvider.h>
Michael Ensingb8d93262020-05-12 00:41:30 -070027
28constexpr size_t kValidTypes[] = {EV_SW,
29 EV_SYN,
Michael Ensingb8d93262020-05-12 00:41:30 -070030 EV_ABS,
31 EV_KEY,
32 EV_MSC,
33 EV_REL,
34 android::EventHubInterface::DEVICE_ADDED,
Liana Kazanova5b8217b2024-07-18 17:44:51 +000035 android::EventHubInterface::DEVICE_REMOVED};
Michael Ensingb8d93262020-05-12 00:41:30 -070036
37constexpr size_t kValidCodes[] = {
38 SYN_REPORT,
39 ABS_MT_SLOT,
40 SYN_MT_REPORT,
41 ABS_MT_POSITION_X,
42 ABS_MT_POSITION_Y,
43 ABS_MT_TOUCH_MAJOR,
44 ABS_MT_TOUCH_MINOR,
45 ABS_MT_WIDTH_MAJOR,
46 ABS_MT_WIDTH_MINOR,
47 ABS_MT_ORIENTATION,
48 ABS_MT_TRACKING_ID,
49 ABS_MT_PRESSURE,
50 ABS_MT_DISTANCE,
51 ABS_MT_TOOL_TYPE,
Michael Ensingb8d93262020-05-12 00:41:30 -070052 MSC_SCAN,
53 REL_X,
54 REL_Y,
55 REL_WHEEL,
56 REL_HWHEEL,
57 BTN_LEFT,
58 BTN_RIGHT,
59 BTN_MIDDLE,
60 BTN_BACK,
61 BTN_SIDE,
62 BTN_FORWARD,
63 BTN_EXTRA,
64 BTN_TASK,
65};
66
Michael Ensingb8d93262020-05-12 00:41:30 -070067constexpr size_t kMaxSize = 256;
68
69namespace android {
70
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070071template<class Fdp>
72ToolType getFuzzedToolType(Fdp& fdp) {
73 const int32_t toolType = fdp.template ConsumeIntegralInRange<int32_t>(
74 static_cast<int32_t>(ToolType::ftl_first),
75 static_cast<int32_t>(ToolType::ftl_last));
76 return static_cast<ToolType>(toolType);
77}
78
Harry Cutts656e0ad2023-06-16 16:39:55 +000079template <class Fdp>
80RawEvent getFuzzedRawEvent(Fdp& fdp) {
81 const int32_t type = fdp.ConsumeBool() ? fdp.PickValueInArray(kValidTypes)
82 : fdp.template ConsumeIntegral<int32_t>();
83 const int32_t code = fdp.ConsumeBool() ? fdp.PickValueInArray(kValidCodes)
84 : fdp.template ConsumeIntegral<int32_t>();
85 return RawEvent{
86 .when = fdp.template ConsumeIntegral<nsecs_t>(),
87 .readTime = fdp.template ConsumeIntegral<nsecs_t>(),
88 .deviceId = fdp.template ConsumeIntegral<int32_t>(),
89 .type = type,
90 .code = code,
91 .value = fdp.template ConsumeIntegral<int32_t>(),
92 };
93}
94
Michael Ensingb8d93262020-05-12 00:41:30 -070095class FuzzEventHub : public EventHubInterface {
96 InputDeviceIdentifier mIdentifier;
97 std::vector<TouchVideoFrame> mVideoFrames;
98 PropertyMap mFuzzConfig;
Harry Cuttsccb75e82023-06-23 14:08:06 +000099 std::map<int32_t /* deviceId */, std::map<int /* axis */, RawAbsoluteAxisInfo>> mAxes;
Aditya Wazireea5be02022-10-31 12:40:10 +0530100 std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp;
Michael Ensingb8d93262020-05-12 00:41:30 -0700101
102public:
Aditya Wazireea5be02022-10-31 12:40:10 +0530103 FuzzEventHub(std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp) : mFdp(std::move(fdp)) {}
Michael Ensingb8d93262020-05-12 00:41:30 -0700104 ~FuzzEventHub() {}
105 void addProperty(std::string key, std::string value) { mFuzzConfig.addProperty(key, value); }
Michael Ensingb8d93262020-05-12 00:41:30 -0700106
107 ftl::Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override {
108 return ftl::Flags<InputDeviceClass>(mFdp->ConsumeIntegral<uint32_t>());
109 }
110 InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override {
111 return mIdentifier;
112 }
113 int32_t getDeviceControllerNumber(int32_t deviceId) const override {
114 return mFdp->ConsumeIntegral<int32_t>();
115 }
Harry Cuttsc34f7582023-03-07 16:23:30 +0000116 std::optional<PropertyMap> getConfiguration(int32_t deviceId) const override {
117 return mFuzzConfig;
Michael Ensingb8d93262020-05-12 00:41:30 -0700118 }
Harry Cuttsccb75e82023-06-23 14:08:06 +0000119 void setAbsoluteAxisInfo(int32_t deviceId, int axis, const RawAbsoluteAxisInfo& axisInfo) {
120 mAxes[deviceId][axis] = axisInfo;
121 }
Harry Cutts207674d2024-06-06 18:53:41 +0000122 std::optional<RawAbsoluteAxisInfo> getAbsoluteAxisInfo(int32_t deviceId,
123 int axis) const override {
Harry Cuttsccb75e82023-06-23 14:08:06 +0000124 if (auto deviceAxesIt = mAxes.find(deviceId); deviceAxesIt != mAxes.end()) {
125 const std::map<int, RawAbsoluteAxisInfo>& deviceAxes = deviceAxesIt->second;
126 if (auto axisInfoIt = deviceAxes.find(axis); axisInfoIt != deviceAxes.end()) {
Harry Cutts207674d2024-06-06 18:53:41 +0000127 return axisInfoIt->second;
Harry Cuttsccb75e82023-06-23 14:08:06 +0000128 }
129 }
Harry Cutts207674d2024-06-06 18:53:41 +0000130 if (mFdp->ConsumeBool()) {
131 return std::optional<RawAbsoluteAxisInfo>({
Harry Cutts207674d2024-06-06 18:53:41 +0000132 .minValue = mFdp->ConsumeIntegral<int32_t>(),
133 .maxValue = mFdp->ConsumeIntegral<int32_t>(),
134 .flat = mFdp->ConsumeIntegral<int32_t>(),
135 .fuzz = mFdp->ConsumeIntegral<int32_t>(),
136 .resolution = mFdp->ConsumeIntegral<int32_t>(),
137 });
138 } else {
139 return std::nullopt;
140 }
Michael Ensingb8d93262020-05-12 00:41:30 -0700141 }
142 bool hasRelativeAxis(int32_t deviceId, int axis) const override { return mFdp->ConsumeBool(); }
143 bool hasInputProperty(int32_t deviceId, int property) const override {
144 return mFdp->ConsumeBool();
145 }
146 bool hasMscEvent(int32_t deviceId, int mscEvent) const override { return mFdp->ConsumeBool(); }
147 status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
148 int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override {
149 return mFdp->ConsumeIntegral<status_t>();
150 }
151 status_t mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const override {
152 return mFdp->ConsumeIntegral<status_t>();
153 }
154 void setExcludedDevices(const std::vector<std::string>& devices) override {}
Siarhei Vishniakou7b3ea0b2022-09-16 14:23:20 -0700155 std::vector<RawEvent> getEvents(int timeoutMillis) override {
156 std::vector<RawEvent> events;
157 const size_t count = mFdp->ConsumeIntegralInRange<size_t>(0, kMaxSize);
158 for (size_t i = 0; i < count; ++i) {
Harry Cutts656e0ad2023-06-16 16:39:55 +0000159 events.push_back(getFuzzedRawEvent(*mFdp));
Siarhei Vishniakou7b3ea0b2022-09-16 14:23:20 -0700160 }
161 return events;
Michael Ensingb8d93262020-05-12 00:41:30 -0700162 }
163 std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override { return mVideoFrames; }
164
165 base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(
166 int32_t deviceId, int32_t absCode) const override {
167 return base::ResultError("Fuzzer", UNKNOWN_ERROR);
168 };
169 // Raw batteries are sysfs power_supply nodes we found from the EventHub device sysfs node,
170 // containing the raw info of the sysfs node structure.
171 std::vector<int32_t> getRawBatteryIds(int32_t deviceId) const override { return {}; }
172 std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId,
173 int32_t BatteryId) const override {
174 return std::nullopt;
175 };
176
177 std::vector<int32_t> getRawLightIds(int32_t deviceId) const override { return {}; };
178 std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) const override {
179 return std::nullopt;
180 };
181 std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) const override {
182 return std::nullopt;
183 };
184 void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) override{};
185 std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
186 int32_t deviceId, int32_t lightId) const override {
187 return std::nullopt;
188 };
189 void setLightIntensities(int32_t deviceId, int32_t lightId,
190 std::unordered_map<LightColor, int32_t> intensities) override{};
191
Vaibhav Devmurari7fb41132023-01-02 13:30:26 +0000192 std::optional<RawLayoutInfo> getRawLayoutInfo(int32_t deviceId) const override {
193 return std::nullopt;
Michael Ensingb8d93262020-05-12 00:41:30 -0700194 };
195
196 int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override {
197 return mFdp->ConsumeIntegral<int32_t>();
198 }
199 int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override {
200 return mFdp->ConsumeIntegral<int32_t>();
201 }
202 int32_t getSwitchState(int32_t deviceId, int32_t sw) const override {
203 return mFdp->ConsumeIntegral<int32_t>();
204 }
Linnan Lie5657f22024-09-13 21:54:37 +0800205 void setKeyRemapping(int32_t deviceId,
206 const std::map<int32_t, int32_t>& keyRemapping) const override {}
Michael Ensingb8d93262020-05-12 00:41:30 -0700207 int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const override {
208 return mFdp->ConsumeIntegral<int32_t>();
209 }
Harry Cuttse2c5e202024-06-21 17:08:48 +0000210 std::optional<int32_t> getAbsoluteAxisValue(int32_t deviceId, int32_t axis) const override {
211 if (mFdp->ConsumeBool()) {
212 return mFdp->ConsumeIntegral<int32_t>();
213 } else {
214 return std::nullopt;
215 }
Michael Ensingb8d93262020-05-12 00:41:30 -0700216 }
Arpit Singh4b4a4572023-11-24 18:19:56 +0000217 base::Result<std::vector<int32_t>> getMtSlotValues(int32_t deviceId, int32_t axis,
218 size_t slotCount) const override {
219 if (mFdp->ConsumeBool()) {
220 std::vector<int32_t> outValues(slotCount + 1);
221 for (size_t i = 0; i < outValues.size(); i++) {
222 outValues.push_back(mFdp->ConsumeIntegral<int32_t>());
223 }
224 return std::move(outValues);
225 } else {
226 return base::ResultError("Fuzzer", UNKNOWN_ERROR);
227 }
228 }
Michael Ensingb8d93262020-05-12 00:41:30 -0700229 bool markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t>& keyCodes,
230 uint8_t* outFlags) const override {
231 return mFdp->ConsumeBool();
232 }
233 bool hasScanCode(int32_t deviceId, int32_t scanCode) const override {
234 return mFdp->ConsumeBool();
235 }
236 bool hasKeyCode(int32_t deviceId, int32_t keyCode) const override {
237 return mFdp->ConsumeBool();
238 }
239 bool hasLed(int32_t deviceId, int32_t led) const override { return mFdp->ConsumeBool(); }
240 void setLedState(int32_t deviceId, int32_t led, bool on) override {}
241 void getVirtualKeyDefinitions(
242 int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const override {}
243 const std::shared_ptr<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const override {
244 return nullptr;
245 }
246 bool setKeyboardLayoutOverlay(int32_t deviceId, std::shared_ptr<KeyCharacterMap> map) override {
247 return mFdp->ConsumeBool();
248 }
249 void vibrate(int32_t deviceId, const VibrationElement& effect) override {}
250 void cancelVibrate(int32_t deviceId) override {}
251
252 std::vector<int32_t> getVibratorIds(int32_t deviceId) const override { return {}; };
253
254 /* Query battery level. */
255 std::optional<int32_t> getBatteryCapacity(int32_t deviceId, int32_t batteryId) const override {
256 return std::nullopt;
257 };
258
259 /* Query battery status. */
260 std::optional<int32_t> getBatteryStatus(int32_t deviceId, int32_t batteryId) const override {
261 return std::nullopt;
262 };
263
264 void requestReopenDevices() override {}
265 void wake() override {}
266 void dump(std::string& dump) const override {}
267 void monitor() const override {}
268 bool isDeviceEnabled(int32_t deviceId) const override { return mFdp->ConsumeBool(); }
269 status_t enableDevice(int32_t deviceId) override { return mFdp->ConsumeIntegral<status_t>(); }
270 status_t disableDevice(int32_t deviceId) override { return mFdp->ConsumeIntegral<status_t>(); }
Vaibhav Devmurari5fc7d852023-03-17 18:43:33 +0000271 void sysfsNodeChanged(const std::string& sysfsNodePath) override {}
Michael Ensingb8d93262020-05-12 00:41:30 -0700272};
273
Michael Ensingb8d93262020-05-12 00:41:30 -0700274class FuzzInputReaderPolicy : public InputReaderPolicyInterface {
275 TouchAffineTransformation mTransform;
Aditya Wazireea5be02022-10-31 12:40:10 +0530276 std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp;
Michael Ensingb8d93262020-05-12 00:41:30 -0700277
278protected:
279 ~FuzzInputReaderPolicy() {}
280
281public:
Prabir Pradhan2120b9e2024-05-04 00:06:37 +0000282 FuzzInputReaderPolicy(std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp) : mFdp(mFdp) {}
Michael Ensingb8d93262020-05-12 00:41:30 -0700283 void getReaderConfiguration(InputReaderConfiguration* outConfig) override {}
Michael Ensingb8d93262020-05-12 00:41:30 -0700284 void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override {}
Abdelrahman Awadalla8c4160d2024-08-05 16:26:10 +0000285 void notifyTouchpadHardwareState(const SelfContainedHardwareState& schs,
286 int32_t deviceId) override {}
Omar Abdelmonem5ebf21f2024-09-12 11:44:15 +0000287 void notifyTouchpadGestureInfo(GestureType type, int32_t deviceId) override {}
Michael Ensingb8d93262020-05-12 00:41:30 -0700288 std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
Vaibhav Devmuraridec30802023-07-11 15:02:03 +0000289 const InputDeviceIdentifier& identifier,
290 const std::optional<KeyboardLayoutInfo> layoutInfo) override {
Michael Ensingb8d93262020-05-12 00:41:30 -0700291 return nullptr;
292 }
293 std::string getDeviceAlias(const InputDeviceIdentifier& identifier) {
294 return mFdp->ConsumeRandomLengthString(32);
295 }
296 TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
Michael Wrighta9cf4192022-12-01 23:46:39 +0000297 ui::Rotation surfaceRotation) override {
Michael Ensingb8d93262020-05-12 00:41:30 -0700298 return mTransform;
299 }
300 void setTouchAffineTransformation(const TouchAffineTransformation t) { mTransform = t; }
Prabir Pradhanda20b172022-09-26 17:01:18 +0000301 void notifyStylusGestureStarted(int32_t, nsecs_t) {}
Arpit Singhb3b3f732023-07-04 14:30:05 +0000302 bool isInputMethodConnectionActive() override { return mFdp->ConsumeBool(); }
Prabir Pradhan19767602023-11-03 16:53:31 +0000303 std::optional<DisplayViewport> getPointerViewportForAssociatedDisplay(
Linnan Li13bf76a2024-05-05 19:18:02 +0800304 ui::LogicalDisplayId associatedDisplayId) override {
Byoungho Jungda10dd32023-10-06 17:03:45 +0900305 return {};
306 }
Michael Ensingb8d93262020-05-12 00:41:30 -0700307};
308
309class FuzzInputListener : public virtual InputListenerInterface {
310public:
Prabir Pradhane3da4bb2023-04-05 23:51:23 +0000311 void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override {}
Prabir Pradhanc392d8f2023-04-13 19:32:51 +0000312 void notifyKey(const NotifyKeyArgs& args) override {}
313 void notifyMotion(const NotifyMotionArgs& args) override {}
314 void notifySwitch(const NotifySwitchArgs& args) override {}
315 void notifySensor(const NotifySensorArgs& args) override{};
316 void notifyVibratorState(const NotifyVibratorStateArgs& args) override{};
317 void notifyDeviceReset(const NotifyDeviceResetArgs& args) override {}
318 void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override{};
Michael Ensingb8d93262020-05-12 00:41:30 -0700319};
320
321class FuzzInputReaderContext : public InputReaderContext {
322 std::shared_ptr<EventHubInterface> mEventHub;
323 sp<InputReaderPolicyInterface> mPolicy;
Aditya Wazireea5be02022-10-31 12:40:10 +0530324 std::shared_ptr<ThreadSafeFuzzedDataProvider> mFdp;
Michael Ensingb8d93262020-05-12 00:41:30 -0700325
326public:
327 FuzzInputReaderContext(std::shared_ptr<EventHubInterface> eventHub,
Harry Cuttsf61c0472023-07-10 14:45:15 +0000328 std::shared_ptr<ThreadSafeFuzzedDataProvider> fdp)
329 : mEventHub(eventHub), mPolicy(sp<FuzzInputReaderPolicy>::make(fdp)), mFdp(fdp) {}
Michael Ensingb8d93262020-05-12 00:41:30 -0700330 ~FuzzInputReaderContext() {}
331 void updateGlobalMetaState() override {}
332 int32_t getGlobalMetaState() { return mFdp->ConsumeIntegral<int32_t>(); }
333 void disableVirtualKeysUntil(nsecs_t time) override {}
334 bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) override {
335 return mFdp->ConsumeBool();
336 }
Michael Ensingb8d93262020-05-12 00:41:30 -0700337 void requestTimeoutAtTime(nsecs_t when) override {}
338 int32_t bumpGeneration() override { return mFdp->ConsumeIntegral<int32_t>(); }
339 void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) override {}
Siarhei Vishniakou2935db72022-09-22 13:35:22 -0700340 std::list<NotifyArgs> dispatchExternalStylusState(const StylusState& outState) override {
341 return {};
342 }
Michael Ensingb8d93262020-05-12 00:41:30 -0700343 InputReaderPolicyInterface* getPolicy() override { return mPolicy.get(); }
Michael Ensingb8d93262020-05-12 00:41:30 -0700344 EventHubInterface* getEventHub() override { return mEventHub.get(); }
345 int32_t getNextId() override { return mFdp->ConsumeIntegral<int32_t>(); }
346
347 void updateLedMetaState(int32_t metaState) override{};
348 int32_t getLedMetaState() override { return mFdp->ConsumeIntegral<int32_t>(); };
Prabir Pradhanda20b172022-09-26 17:01:18 +0000349 void notifyStylusGestureStarted(int32_t, nsecs_t) {}
Arpit Singha5ea7c12023-07-05 15:39:25 +0000350
Arpit Singh849beb42024-06-06 07:14:17 +0000351 void setPreventingTouchpadTaps(bool prevent) override {}
352 bool isPreventingTouchpadTaps() override { return mFdp->ConsumeBool(); };
Arpit Singh82e413e2023-10-10 19:30:58 +0000353
354 void setLastKeyDownTimestamp(nsecs_t when) { mLastKeyDownTimestamp = when; };
355 nsecs_t getLastKeyDownTimestamp() { return mLastKeyDownTimestamp; };
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000356 KeyboardClassifier& getKeyboardClassifier() override { return *mClassifier; }
Arpit Singh82e413e2023-10-10 19:30:58 +0000357
358private:
359 nsecs_t mLastKeyDownTimestamp;
Vaibhav Devmurarie58ffb92024-05-22 17:38:25 +0000360 std::unique_ptr<KeyboardClassifier> mClassifier = std::make_unique<KeyboardClassifier>();
Michael Ensingb8d93262020-05-12 00:41:30 -0700361};
362
Harry Cuttsf61c0472023-07-10 14:45:15 +0000363template <class Fdp>
364InputDevice getFuzzedInputDevice(Fdp& fdp, FuzzInputReaderContext* context) {
365 InputDeviceIdentifier identifier;
366 identifier.name = fdp.ConsumeRandomLengthString(16);
367 identifier.location = fdp.ConsumeRandomLengthString(12);
368 int32_t deviceID = fdp.ConsumeIntegralInRange(0, 5);
369 int32_t deviceGeneration = fdp.ConsumeIntegralInRange(0, 5);
370 return InputDevice(context, deviceID, deviceGeneration, identifier);
371}
372
373template <class Fdp>
374void configureAndResetDevice(Fdp& fdp, InputDevice& device) {
375 nsecs_t arbitraryTime = fdp.template ConsumeIntegral<nsecs_t>();
376 std::list<NotifyArgs> out;
377 out += device.configure(arbitraryTime, /*readerConfig=*/{}, /*changes=*/{});
378 out += device.reset(arbitraryTime);
379}
380
381template <class Fdp, class T, typename... Args>
382T& getMapperForDevice(Fdp& fdp, InputDevice& device, Args... args) {
383 int32_t eventhubId = fdp.template ConsumeIntegral<int32_t>();
384 // ensure a device entry exists for this eventHubId
385 device.addEmptyEventHubDevice(eventhubId);
386 configureAndResetDevice(fdp, device);
387
388 return device.template constructAndAddMapper<T>(eventhubId, args...);
389}
390
Michael Ensingb8d93262020-05-12 00:41:30 -0700391} // namespace android