• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 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  */
16 
17 package com.android.commands.uinput.tests;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.truth.Truth.assertWithMessage;
21 
22 import static org.junit.Assert.fail;
23 
24 import android.platform.test.annotations.Postsubmit;
25 import android.util.SparseArray;
26 
27 import androidx.test.filters.SmallTest;
28 import androidx.test.runner.AndroidJUnit4;
29 
30 import com.android.commands.uinput.EvemuParser;
31 import com.android.commands.uinput.Event;
32 import com.android.commands.uinput.Event.UinputControlCode;
33 
34 import org.junit.Test;
35 import org.junit.runner.RunWith;
36 
37 import java.io.IOException;
38 import java.io.StringReader;
39 
40 import src.com.android.commands.uinput.InputAbsInfo;
41 
42 @RunWith(AndroidJUnit4.class)
43 @SmallTest
44 @Postsubmit
45 public class EvemuParserTest {
46 
getRegistrationEvent(String fileContents)47     private Event getRegistrationEvent(String fileContents) throws IOException {
48         StringReader reader = new StringReader(fileContents);
49         EvemuParser parser = new EvemuParser(reader);
50         Event event = parser.getNextEvent();
51         assertThat(event.getCommand()).isEqualTo(Event.Command.REGISTER);
52         return event;
53     }
54 
55     @Test
testNameParsing()56     public void testNameParsing() throws IOException {
57         Event event = getRegistrationEvent("""
58                 N: ACME Pointing Widget #4
59                 I: 0001 1234 5678 9abc
60                 """);
61         assertThat(event.getName()).isEqualTo("ACME Pointing Widget #4");
62     }
63 
64     @Test
testIdParsing()65     public void testIdParsing() throws IOException {
66         Event event = getRegistrationEvent("""
67                 N: ACME Pointing Widget #4
68                 I: 0001 1234 5678 9abc
69                 """);
70         assertThat(event.getBus()).isEqualTo(0x0001);
71         assertThat(event.getVendorId()).isEqualTo(0x1234);
72         assertThat(event.getProductId()).isEqualTo(0x5678);
73         assertThat(event.getVersionId()).isEqualTo(0x9abc);
74     }
75 
76     @Test
testPropertyBitmapParsing()77     public void testPropertyBitmapParsing() throws IOException {
78         Event event = getRegistrationEvent("""
79                 N: ACME Pointing Widget #4
80                 I: 0001 1234 5678 9abc
81                 P: 05 00 00 00 00 00 00 00
82                 P: 01
83                 """);
84         assertThat(event.getConfiguration().get(UinputControlCode.UI_SET_PROPBIT.getValue()))
85                 .asList().containsExactly(0, 2, 64);
86     }
87 
88     @Test
testEventBitmapParsing()89     public void testEventBitmapParsing() throws IOException {
90         Event event = getRegistrationEvent("""
91                 N: ACME Pointing Widget #4
92                 I: 0001 1234 5678 9abc
93                 B: 00 0b 00 00 00 00 00 00 00  # SYN
94                 B: 01 00 00 03 00 00 00 00 00  # KEY
95                 B: 01 00 01 00 00 00 00 00 00
96                 B: 02 03 00 00 00 00 00 00 00  # REL
97                 B: 03 00 00                    # ABS
98                 """);
99         assertThat(event.getConfiguration().get(UinputControlCode.UI_SET_EVBIT.getValue()))
100                 .asList().containsExactly(Event.EV_KEY, Event.EV_REL);
101         assertThat(event.getConfiguration().get(UinputControlCode.UI_SET_KEYBIT.getValue()))
102                 .asList().containsExactly(16, 17, 72);
103         assertThat(event.getConfiguration().get(UinputControlCode.UI_SET_RELBIT.getValue()))
104                 .asList().containsExactly(0, 1);
105         assertThat(event.getConfiguration().contains(UinputControlCode.UI_SET_ABSBIT.getValue()))
106                 .isFalse();
107     }
108 
109     @Test
testEventBitmapParsing_WithForceFeedback()110     public void testEventBitmapParsing_WithForceFeedback() throws IOException {
111         Event event = getRegistrationEvent("""
112                 N: ACME Pointing Widget #4
113                 I: 0001 1234 5678 9abc
114                 B: 15 05  # FF
115                 """);
116         assertThat(event.getConfiguration().get(UinputControlCode.UI_SET_EVBIT.getValue()))
117                 .asList().containsExactly(Event.EV_FF);
118         assertThat(event.getConfiguration().get(UinputControlCode.UI_SET_FFBIT.getValue()))
119                 .asList().containsExactly(0, 2);
120         assertThat(event.getFfEffectsMax()).isEqualTo(2);
121     }
122 
assertAbsInfo(InputAbsInfo info, int minimum, int maximum, int fuzz, int flat, int resolution)123     private void assertAbsInfo(InputAbsInfo info, int minimum, int maximum, int fuzz, int flat,
124                                int resolution) {
125         assertThat(info).isNotNull();
126         assertWithMessage("Incorrect minimum").that(info.minimum).isEqualTo(minimum);
127         assertWithMessage("Incorrect maximum").that(info.maximum).isEqualTo(maximum);
128         assertWithMessage("Incorrect fuzz").that(info.fuzz).isEqualTo(fuzz);
129         assertWithMessage("Incorrect flat").that(info.flat).isEqualTo(flat);
130         assertWithMessage("Incorrect resolution").that(info.resolution).isEqualTo(resolution);
131     }
132 
133     @Test
testAbsInfoParsing_WithResolution()134     public void testAbsInfoParsing_WithResolution() throws IOException {
135         Event event = getRegistrationEvent("""
136                 N: ACME Weird Gamepad
137                 I: 0001 1234 5678 9abc
138                 A: 03 -128 128 4 4 0    # ABS_MT_RX
139                 A: 2f 0 9 0 0 0         # ABS_MT_SLOT
140                 A: 34 -4096 4096 0 0 0  # ABS_MT_ORIENTATION
141                 A: 35 0 1599 0 0 11     # ABS_MT_POSITION_X
142                 """);
143         SparseArray<InputAbsInfo> absInfos = event.getAbsInfo();
144         assertThat(absInfos.size()).isEqualTo(4);
145         assertAbsInfo(absInfos.get(0x03), -128, 128, 4, 4, 0);
146         assertAbsInfo(absInfos.get(0x2f), 0, 9, 0, 0, 0);
147         assertAbsInfo(absInfos.get(0x34), -4096, 4096, 0, 0, 0);
148         assertAbsInfo(absInfos.get(0x35), 0, 1599, 0, 0, 11);
149     }
150 
151     @Test
testAbsInfoParsing_WithoutResolution()152     public void testAbsInfoParsing_WithoutResolution() throws IOException {
153         Event event = getRegistrationEvent("""
154                 N: ACME Terrible Touchscreen
155                 I: 0001 1234 5678 9abc
156                 A: 2f 0 9 0 0         # ABS_MT_SLOT
157                 A: 35 0 1599 0 0      # ABS_MT_POSITION_X
158                 A: 36 0 2559 0 0      # ABS_MT_POSITION_X
159                 """);
160         SparseArray<InputAbsInfo> absInfos = event.getAbsInfo();
161         assertThat(absInfos.size()).isEqualTo(3);
162         assertAbsInfo(absInfos.get(0x2f), 0, 9, 0, 0, 0);
163         assertAbsInfo(absInfos.get(0x35), 0, 1599, 0, 0, 0);
164         assertAbsInfo(absInfos.get(0x36), 0, 2559, 0, 0, 0);
165     }
166 
167     @Test
testLedAndSwitchStatesIgnored()168     public void testLedAndSwitchStatesIgnored() throws IOException {
169         // We don't support L: and S: lines yet, so all we need to check here is that they don't
170         // prevent the other events from being parsed.
171         StringReader reader = new StringReader("""
172                 N: ACME Widget
173                 I: 0001 1234 5678 9abc
174                 L: 00 0
175                 L: 09 1
176                 S: 0a 1
177                 E: 0.000001 0 0 0  # SYN_REPORT
178                 """);
179         EvemuParser parser = new EvemuParser(reader);
180         assertThat(parser.getNextEvent().getCommand()).isEqualTo(Event.Command.REGISTER);
181         assertThat(parser.getNextEvent().getCommand()).isEqualTo(Event.Command.DELAY);
182         assertThat(parser.getNextEvent().getCommand()).isEqualTo(Event.Command.INJECT);
183     }
184 
assertInjectEvent(Event event, int eventType, int eventCode, int value)185     private void assertInjectEvent(Event event, int eventType, int eventCode, int value) {
186         assertInjectEvent(event, eventType, eventCode, value, 0);
187     }
188 
assertInjectEvent(Event event, int eventType, int eventCode, int value, long timestampOffsetMicros)189     private void assertInjectEvent(Event event, int eventType, int eventCode, int value,
190                                    long timestampOffsetMicros) {
191         assertThat(event).isNotNull();
192         assertThat(event.getCommand()).isEqualTo(Event.Command.INJECT);
193         assertThat(event.getInjections()).asList()
194                 .containsExactly(eventType, eventCode, value).inOrder();
195         assertThat(event.getTimestampOffsetMicros()).isEqualTo(timestampOffsetMicros);
196     }
197 
assertDelayEvent(Event event, int durationNanos)198     private void assertDelayEvent(Event event, int durationNanos) {
199         assertThat(event).isNotNull();
200         assertThat(event.getCommand()).isEqualTo(Event.Command.DELAY);
201         assertThat(event.getDurationNanos()).isEqualTo(durationNanos);
202     }
203 
204     @Test
testEventParsing_OneFrame()205     public void testEventParsing_OneFrame() throws IOException {
206         StringReader reader = new StringReader("""
207                 N: ACME Widget
208                 I: 0001 1234 5678 9abc
209                 E: 0.000001 0002 0000 0001   # REL_X +1
210                 E: 0.000001 0002 0001 -0002  # REL_Y -2
211                 E: 0.000001 0000 0000 0000   # SYN_REPORT
212                 """);
213         EvemuParser parser = new EvemuParser(reader);
214         assertThat(parser.getNextEvent().getCommand()).isEqualTo(Event.Command.REGISTER);
215         assertThat(parser.getNextEvent().getCommand()).isEqualTo(Event.Command.DELAY);
216         assertInjectEvent(parser.getNextEvent(), 0x2, 0x0, 1, -1);
217         assertInjectEvent(parser.getNextEvent(), 0x2, 0x1, -2);
218         assertInjectEvent(parser.getNextEvent(), 0x0, 0x0, 0);
219 
220         // Now we should be at the end of the file.
221         assertThat(parser.getNextEvent()).isNull();
222     }
223 
224     @Test
testEventParsing_MultipleFrames()225     public void testEventParsing_MultipleFrames() throws IOException {
226         StringReader reader = new StringReader("""
227                 N: ACME YesBird Typing Aid
228                 I: 0001 1234 5678 9abc
229                 E: 0.000001 0001 0015 0001   # KEY_Y press
230                 E: 0.000001 0000 0000 0000   # SYN_REPORT
231                 E: 0.010001 0001 0015 0000   # KEY_Y release
232                 E: 0.010001 0000 0000 0000   # SYN_REPORT
233                 E: 1.010001 0001 0015 0001   # KEY_Y press
234                 E: 1.010001 0000 0000 0000   # SYN_REPORT
235                 """);
236         EvemuParser parser = new EvemuParser(reader);
237         assertThat(parser.getNextEvent().getCommand()).isEqualTo(Event.Command.REGISTER);
238         assertThat(parser.getNextEvent().getCommand()).isEqualTo(Event.Command.DELAY);
239 
240         assertInjectEvent(parser.getNextEvent(), 0x1, 0x15, 1, -1);
241         assertInjectEvent(parser.getNextEvent(), 0x0, 0x0, 0);
242 
243         assertDelayEvent(parser.getNextEvent(), 10_000_000);
244 
245         assertInjectEvent(parser.getNextEvent(), 0x1, 0x15, 0, 10_000);
246         assertInjectEvent(parser.getNextEvent(), 0x0, 0x0, 0);
247 
248         assertDelayEvent(parser.getNextEvent(), 1_000_000_000);
249 
250         assertInjectEvent(parser.getNextEvent(), 0x1, 0x15, 1, 1_000_000);
251         assertInjectEvent(parser.getNextEvent(), 0x0, 0x0, 0);
252 
253         assertThat(parser.getNextEvent()).isNull();
254     }
255 
256     @Test
testErrorLineNumberReporting()257     public void testErrorLineNumberReporting() throws IOException {
258         StringReader reader = new StringReader("""
259                 # EVEMU 1.3
260                 N: ACME Widget
261                 # Comment to make sure they're taken into account when numbering lines
262                 I: 0001 1234 5678 9abc
263                 00 00 00 00 00 00 00 00  # Missing a type
264                 E: 0.000001 0001 0015 0001   # KEY_Y press
265                 E: 0.000001 0000 0000 0000   # SYN_REPORT
266                 """);
267         try {
268             new EvemuParser(reader);
269             fail("Parser should have thrown an error about the line with the missing type.");
270         } catch (EvemuParser.ParsingException ex) {
271             assertThat(ex.makeErrorMessage()).startsWith("Parsing error on line 5:");
272         }
273     }
274 
275     @Test
testFreeDesktopEvemuRecording()276     public void testFreeDesktopEvemuRecording() throws IOException {
277         // This is a real recording from FreeDesktop's evemu-record tool, as a basic compatibility
278         // check with the FreeDesktop tools.
279         // (CheckStyle objects to the long line here. It can be split up with escaped newlines once
280         // the fix for b/306423115 reaches Android.)
281         StringReader reader = new StringReader("""
282                 # EVEMU 1.3
283                 # Kernel: 6.5.6-1rodete4-amd64
284                 # DMI: dmi:bvnLENOVO:bvrXXXXXXXX(X.XX):bdXX/XX/XXXX:brX.XX:efrX.XX:svnLENOVO:pnXXXXXXXXXX:pvrThinkPadX1Carbon:rvnLENOVO:rnXXXXXXXXX:rvrXXXXX:cvnLENOVO:ctXX:cvrNone:skuLENOVO_MT_20KG_BU_Think_FM_ThinkPadX1Carbon:
285                 # Input device name: "Synaptics TM3289-021"
286                 # Input device ID: bus 0x1d vendor 0x6cb product 0000 version 0000
287                 # Size in mm: 96x52
288                 # Supported events:
289                 #   Event type 0 (EV_SYN)
290                 #     Event code 0 (SYN_REPORT)
291                 #     Event code 1 (SYN_CONFIG)
292                 #     Event code 2 (SYN_MT_REPORT)
293                 #     Event code 3 (SYN_DROPPED)
294                 #     Event code 4 ((null))
295                 #     Event code 5 ((null))
296                 #     Event code 6 ((null))
297                 #     Event code 7 ((null))
298                 #     Event code 8 ((null))
299                 #     Event code 9 ((null))
300                 #     Event code 10 ((null))
301                 #     Event code 11 ((null))
302                 #     Event code 12 ((null))
303                 #     Event code 13 ((null))
304                 #     Event code 14 ((null))
305                 #     Event code 15 (SYN_MAX)
306                 #   Event type 1 (EV_KEY)
307                 #     Event code 272 (BTN_LEFT)
308                 #     Event code 325 (BTN_TOOL_FINGER)
309                 #     Event code 328 (BTN_TOOL_QUINTTAP)
310                 #     Event code 330 (BTN_TOUCH)
311                 #     Event code 333 (BTN_TOOL_DOUBLETAP)
312                 #     Event code 334 (BTN_TOOL_TRIPLETAP)
313                 #     Event code 335 (BTN_TOOL_QUADTAP)
314                 #   Event type 3 (EV_ABS)
315                 #     Event code 0 (ABS_X)
316                 #       Value        0
317                 #       Min          0
318                 #       Max       1936
319                 #       Fuzz         0
320                 #       Flat         0
321                 #       Resolution  20
322                 #     Event code 1 (ABS_Y)
323                 #       Value        0
324                 #       Min          0
325                 #       Max       1057
326                 #       Fuzz         0
327                 #       Flat         0
328                 #       Resolution  20
329                 #     Event code 24 (ABS_PRESSURE)
330                 #       Value        0
331                 #       Min          0
332                 #       Max        255
333                 #       Fuzz         0
334                 #       Flat         0
335                 #       Resolution   0
336                 #     Event code 47 (ABS_MT_SLOT)
337                 #       Value        0
338                 #       Min          0
339                 #       Max          4
340                 #       Fuzz         0
341                 #       Flat         0
342                 #       Resolution   0
343                 #     Event code 48 (ABS_MT_TOUCH_MAJOR)
344                 #       Value        0
345                 #       Min          0
346                 #       Max         15
347                 #       Fuzz         0
348                 #       Flat         0
349                 #       Resolution   0
350                 #     Event code 49 (ABS_MT_TOUCH_MINOR)
351                 #       Value        0
352                 #       Min          0
353                 #       Max         15
354                 #       Fuzz         0
355                 #       Flat         0
356                 #       Resolution   0
357                 #     Event code 52 (ABS_MT_ORIENTATION)
358                 #       Value        0
359                 #       Min          0
360                 #       Max          1
361                 #       Fuzz         0
362                 #       Flat         0
363                 #       Resolution   0
364                 #     Event code 53 (ABS_MT_POSITION_X)
365                 #       Value        0
366                 #       Min          0
367                 #       Max       1936
368                 #       Fuzz         0
369                 #       Flat         0
370                 #       Resolution  20
371                 #     Event code 54 (ABS_MT_POSITION_Y)
372                 #       Value        0
373                 #       Min          0
374                 #       Max       1057
375                 #       Fuzz         0
376                 #       Flat         0
377                 #       Resolution  20
378                 #     Event code 55 (ABS_MT_TOOL_TYPE)
379                 #       Value        0
380                 #       Min          0
381                 #       Max         15
382                 #       Fuzz         0
383                 #       Flat         0
384                 #       Resolution   0
385                 #     Event code 57 (ABS_MT_TRACKING_ID)
386                 #       Value        0
387                 #       Min          0
388                 #       Max      65535
389                 #       Fuzz         0
390                 #       Flat         0
391                 #       Resolution   0
392                 #     Event code 58 (ABS_MT_PRESSURE)
393                 #       Value        0
394                 #       Min          0
395                 #       Max        255
396                 #       Fuzz         0
397                 #       Flat         0
398                 #       Resolution   0
399                 # Properties:
400                 #   Property  type 0 (INPUT_PROP_POINTER)
401                 #   Property  type 2 (INPUT_PROP_BUTTONPAD)
402                 N: Synaptics TM3289-021
403                 I: 001d 06cb 0000 0000
404                 P: 05 00 00 00 00 00 00 00
405                 B: 00 0b 00 00 00 00 00 00 00
406                 B: 01 00 00 00 00 00 00 00 00
407                 B: 01 00 00 00 00 00 00 00 00
408                 B: 01 00 00 00 00 00 00 00 00
409                 B: 01 00 00 00 00 00 00 00 00
410                 B: 01 00 00 01 00 00 00 00 00
411                 B: 01 20 e5 00 00 00 00 00 00
412                 B: 01 00 00 00 00 00 00 00 00
413                 B: 01 00 00 00 00 00 00 00 00
414                 B: 01 00 00 00 00 00 00 00 00
415                 B: 01 00 00 00 00 00 00 00 00
416                 B: 01 00 00 00 00 00 00 00 00
417                 B: 01 00 00 00 00 00 00 00 00
418                 B: 02 00 00 00 00 00 00 00 00
419                 B: 03 03 00 00 01 00 80 f3 06
420                 B: 04 00 00 00 00 00 00 00 00
421                 B: 05 00 00 00 00 00 00 00 00
422                 B: 11 00 00 00 00 00 00 00 00
423                 B: 12 00 00 00 00 00 00 00 00
424                 B: 14 00 00 00 00 00 00 00 00
425                 B: 15 00 00 00 00 00 00 00 00
426                 B: 15 00 00 00 00 00 00 00 00
427                 A: 00 0 1936 0 0 20
428                 A: 01 0 1057 0 0 20
429                 A: 18 0 255 0 0 0
430                 A: 2f 0 4 0 0 0
431                 A: 30 0 15 0 0 0
432                 A: 31 0 15 0 0 0
433                 A: 34 0 1 0 0 0
434                 A: 35 0 1936 0 0 20
435                 A: 36 0 1057 0 0 20
436                 A: 37 0 15 0 0 0
437                 A: 39 0 65535 0 0 0
438                 A: 3a 0 255 0 0 0
439                 ################################
440                 #      Waiting for events      #
441                 ################################
442                 E: 0.000001 0003 0039 0000\t# EV_ABS / ABS_MT_TRACKING_ID   0
443                 E: 0.000001 0003 0035 0891\t# EV_ABS / ABS_MT_POSITION_X    891
444                 E: 0.000001 0003 0036 0333\t# EV_ABS / ABS_MT_POSITION_Y    333
445                 E: 0.000001 0003 003a 0056\t# EV_ABS / ABS_MT_PRESSURE      56
446                 E: 0.000001 0003 0030 0001\t# EV_ABS / ABS_MT_TOUCH_MAJOR   1
447                 E: 0.000001 0003 0031 0001\t# EV_ABS / ABS_MT_TOUCH_MINOR   1
448                 E: 0.000001 0001 014a 0001\t# EV_KEY / BTN_TOUCH            1
449                 E: 0.000001 0001 0145 0001\t# EV_KEY / BTN_TOOL_FINGER      1
450                 E: 0.000001 0003 0000 0891\t# EV_ABS / ABS_X                891
451                 E: 0.000001 0003 0001 0333\t# EV_ABS / ABS_Y                333
452                 E: 0.000001 0003 0018 0056\t# EV_ABS / ABS_PRESSURE         56
453                 E: 0.000001 0000 0000 0000\t# ------------ SYN_REPORT (0) ---------- +0ms
454                 E: 0.006081 0003 0035 0888\t# EV_ABS / ABS_MT_POSITION_X    888
455                 """);
456         EvemuParser parser = new EvemuParser(reader);
457         Event regEvent = parser.getNextEvent();
458         assertThat(regEvent.getName()).isEqualTo("Synaptics TM3289-021");
459 
460         assertThat(regEvent.getBus()).isEqualTo(0x001d);
461         assertThat(regEvent.getVendorId()).isEqualTo(0x6cb);
462         assertThat(regEvent.getProductId()).isEqualTo(0x0000);
463         assertThat(regEvent.getVersionId()).isEqualTo(0x0000);
464 
465         assertThat(regEvent.getConfiguration().get(UinputControlCode.UI_SET_PROPBIT.getValue()))
466                 .asList().containsExactly(0, 2);
467 
468         assertThat(regEvent.getConfiguration().get(UinputControlCode.UI_SET_EVBIT.getValue()))
469                 .asList().containsExactly(Event.EV_KEY, Event.EV_ABS);
470         assertThat(regEvent.getConfiguration().get(UinputControlCode.UI_SET_KEYBIT.getValue()))
471                 .asList().containsExactly(272, 325, 328, 330, 333, 334, 335);
472         assertThat(regEvent.getConfiguration().get(UinputControlCode.UI_SET_ABSBIT.getValue()))
473                 .asList().containsExactly(0, 1, 24, 47, 48, 49, 52, 53, 54, 55, 57, 58);
474 
475         SparseArray<InputAbsInfo> absInfos = regEvent.getAbsInfo();
476         assertAbsInfo(absInfos.get(0), 0, 1936, 0, 0, 20);
477         assertAbsInfo(absInfos.get(1), 0, 1057, 0, 0, 20);
478         assertAbsInfo(absInfos.get(24), 0, 255, 0, 0, 0);
479         assertAbsInfo(absInfos.get(47), 0, 4, 0, 0, 0);
480         assertAbsInfo(absInfos.get(48), 0, 15, 0, 0, 0);
481         assertAbsInfo(absInfos.get(49), 0, 15, 0, 0, 0);
482         assertAbsInfo(absInfos.get(52), 0, 1, 0, 0, 0);
483         assertAbsInfo(absInfos.get(53), 0, 1936, 0, 0, 20);
484         assertAbsInfo(absInfos.get(54), 0, 1057, 0, 0, 20);
485         assertAbsInfo(absInfos.get(55), 0, 15, 0, 0, 0);
486         assertAbsInfo(absInfos.get(57), 0, 65535, 0, 0, 0);
487         assertAbsInfo(absInfos.get(58), 0, 255, 0, 0, 0);
488 
489         assertThat(parser.getNextEvent().getCommand()).isEqualTo(Event.Command.DELAY);
490 
491         assertInjectEvent(parser.getNextEvent(), 0x3, 0x39, 0, -1);
492         assertInjectEvent(parser.getNextEvent(), 0x3, 0x35, 891);
493         assertInjectEvent(parser.getNextEvent(), 0x3, 0x36, 333);
494         assertInjectEvent(parser.getNextEvent(), 0x3, 0x3a, 56);
495         assertInjectEvent(parser.getNextEvent(), 0x3, 0x30, 1);
496         assertInjectEvent(parser.getNextEvent(), 0x3, 0x31, 1);
497         assertInjectEvent(parser.getNextEvent(), 0x1, 0x14a, 1);
498         assertInjectEvent(parser.getNextEvent(), 0x1, 0x145, 1);
499         assertInjectEvent(parser.getNextEvent(), 0x3, 0x0, 891);
500         assertInjectEvent(parser.getNextEvent(), 0x3, 0x1, 333);
501         assertInjectEvent(parser.getNextEvent(), 0x3, 0x18, 56);
502         assertInjectEvent(parser.getNextEvent(), 0x0, 0x0, 0);
503 
504         assertDelayEvent(parser.getNextEvent(), 6_080_000);
505 
506         assertInjectEvent(parser.getNextEvent(), 0x3, 0x0035, 888, 6_080);
507     }
508 }
509