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 221 @Test testEventParsing_MultipleFrames()222 public void testEventParsing_MultipleFrames() throws IOException { 223 StringReader reader = new StringReader(""" 224 N: ACME YesBird Typing Aid 225 I: 0001 1234 5678 9abc 226 E: 0.000001 0001 0015 0001 # KEY_Y press 227 E: 0.000001 0000 0000 0000 # SYN_REPORT 228 E: 0.010001 0001 0015 0000 # KEY_Y release 229 E: 0.010001 0000 0000 0000 # SYN_REPORT 230 E: 1.010001 0001 0015 0001 # KEY_Y press 231 E: 1.010001 0000 0000 0000 # SYN_REPORT 232 """); 233 EvemuParser parser = new EvemuParser(reader); 234 assertThat(parser.getNextEvent().getCommand()).isEqualTo(Event.Command.REGISTER); 235 assertThat(parser.getNextEvent().getCommand()).isEqualTo(Event.Command.DELAY); 236 237 assertInjectEvent(parser.getNextEvent(), 0x1, 0x15, 1, -1); 238 assertInjectEvent(parser.getNextEvent(), 0x0, 0x0, 0); 239 240 assertDelayEvent(parser.getNextEvent(), 10_000_000); 241 242 assertInjectEvent(parser.getNextEvent(), 0x1, 0x15, 0, 10_000); 243 assertInjectEvent(parser.getNextEvent(), 0x0, 0x0, 0); 244 245 assertDelayEvent(parser.getNextEvent(), 1_000_000_000); 246 247 assertInjectEvent(parser.getNextEvent(), 0x1, 0x15, 1, 1_000_000); 248 assertInjectEvent(parser.getNextEvent(), 0x0, 0x0, 0); 249 } 250 251 @Test testErrorLineNumberReporting()252 public void testErrorLineNumberReporting() throws IOException { 253 StringReader reader = new StringReader(""" 254 # EVEMU 1.3 255 N: ACME Widget 256 # Comment to make sure they're taken into account when numbering lines 257 I: 0001 1234 5678 9abc 258 00 00 00 00 00 00 00 00 # Missing a type 259 E: 0.000001 0001 0015 0001 # KEY_Y press 260 E: 0.000001 0000 0000 0000 # SYN_REPORT 261 """); 262 try { 263 new EvemuParser(reader); 264 fail("Parser should have thrown an error about the line with the missing type."); 265 } catch (EvemuParser.ParsingException ex) { 266 assertThat(ex.makeErrorMessage()).startsWith("Parsing error on line 5:"); 267 } 268 } 269 270 @Test testFreeDesktopEvemuRecording()271 public void testFreeDesktopEvemuRecording() throws IOException { 272 // This is a real recording from FreeDesktop's evemu-record tool, as a basic compatibility 273 // check with the FreeDesktop tools. 274 // (CheckStyle objects to the long line here. It can be split up with escaped newlines once 275 // the fix for b/306423115 reaches Android.) 276 StringReader reader = new StringReader(""" 277 # EVEMU 1.3 278 # Kernel: 6.5.6-1rodete4-amd64 279 # 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: 280 # Input device name: "Synaptics TM3289-021" 281 # Input device ID: bus 0x1d vendor 0x6cb product 0000 version 0000 282 # Size in mm: 96x52 283 # Supported events: 284 # Event type 0 (EV_SYN) 285 # Event code 0 (SYN_REPORT) 286 # Event code 1 (SYN_CONFIG) 287 # Event code 2 (SYN_MT_REPORT) 288 # Event code 3 (SYN_DROPPED) 289 # Event code 4 ((null)) 290 # Event code 5 ((null)) 291 # Event code 6 ((null)) 292 # Event code 7 ((null)) 293 # Event code 8 ((null)) 294 # Event code 9 ((null)) 295 # Event code 10 ((null)) 296 # Event code 11 ((null)) 297 # Event code 12 ((null)) 298 # Event code 13 ((null)) 299 # Event code 14 ((null)) 300 # Event code 15 (SYN_MAX) 301 # Event type 1 (EV_KEY) 302 # Event code 272 (BTN_LEFT) 303 # Event code 325 (BTN_TOOL_FINGER) 304 # Event code 328 (BTN_TOOL_QUINTTAP) 305 # Event code 330 (BTN_TOUCH) 306 # Event code 333 (BTN_TOOL_DOUBLETAP) 307 # Event code 334 (BTN_TOOL_TRIPLETAP) 308 # Event code 335 (BTN_TOOL_QUADTAP) 309 # Event type 3 (EV_ABS) 310 # Event code 0 (ABS_X) 311 # Value 0 312 # Min 0 313 # Max 1936 314 # Fuzz 0 315 # Flat 0 316 # Resolution 20 317 # Event code 1 (ABS_Y) 318 # Value 0 319 # Min 0 320 # Max 1057 321 # Fuzz 0 322 # Flat 0 323 # Resolution 20 324 # Event code 24 (ABS_PRESSURE) 325 # Value 0 326 # Min 0 327 # Max 255 328 # Fuzz 0 329 # Flat 0 330 # Resolution 0 331 # Event code 47 (ABS_MT_SLOT) 332 # Value 0 333 # Min 0 334 # Max 4 335 # Fuzz 0 336 # Flat 0 337 # Resolution 0 338 # Event code 48 (ABS_MT_TOUCH_MAJOR) 339 # Value 0 340 # Min 0 341 # Max 15 342 # Fuzz 0 343 # Flat 0 344 # Resolution 0 345 # Event code 49 (ABS_MT_TOUCH_MINOR) 346 # Value 0 347 # Min 0 348 # Max 15 349 # Fuzz 0 350 # Flat 0 351 # Resolution 0 352 # Event code 52 (ABS_MT_ORIENTATION) 353 # Value 0 354 # Min 0 355 # Max 1 356 # Fuzz 0 357 # Flat 0 358 # Resolution 0 359 # Event code 53 (ABS_MT_POSITION_X) 360 # Value 0 361 # Min 0 362 # Max 1936 363 # Fuzz 0 364 # Flat 0 365 # Resolution 20 366 # Event code 54 (ABS_MT_POSITION_Y) 367 # Value 0 368 # Min 0 369 # Max 1057 370 # Fuzz 0 371 # Flat 0 372 # Resolution 20 373 # Event code 55 (ABS_MT_TOOL_TYPE) 374 # Value 0 375 # Min 0 376 # Max 15 377 # Fuzz 0 378 # Flat 0 379 # Resolution 0 380 # Event code 57 (ABS_MT_TRACKING_ID) 381 # Value 0 382 # Min 0 383 # Max 65535 384 # Fuzz 0 385 # Flat 0 386 # Resolution 0 387 # Event code 58 (ABS_MT_PRESSURE) 388 # Value 0 389 # Min 0 390 # Max 255 391 # Fuzz 0 392 # Flat 0 393 # Resolution 0 394 # Properties: 395 # Property type 0 (INPUT_PROP_POINTER) 396 # Property type 2 (INPUT_PROP_BUTTONPAD) 397 N: Synaptics TM3289-021 398 I: 001d 06cb 0000 0000 399 P: 05 00 00 00 00 00 00 00 400 B: 00 0b 00 00 00 00 00 00 00 401 B: 01 00 00 00 00 00 00 00 00 402 B: 01 00 00 00 00 00 00 00 00 403 B: 01 00 00 00 00 00 00 00 00 404 B: 01 00 00 00 00 00 00 00 00 405 B: 01 00 00 01 00 00 00 00 00 406 B: 01 20 e5 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 00 00 00 00 00 00 411 B: 01 00 00 00 00 00 00 00 00 412 B: 01 00 00 00 00 00 00 00 00 413 B: 02 00 00 00 00 00 00 00 00 414 B: 03 03 00 00 01 00 80 f3 06 415 B: 04 00 00 00 00 00 00 00 00 416 B: 05 00 00 00 00 00 00 00 00 417 B: 11 00 00 00 00 00 00 00 00 418 B: 12 00 00 00 00 00 00 00 00 419 B: 14 00 00 00 00 00 00 00 00 420 B: 15 00 00 00 00 00 00 00 00 421 B: 15 00 00 00 00 00 00 00 00 422 A: 00 0 1936 0 0 20 423 A: 01 0 1057 0 0 20 424 A: 18 0 255 0 0 0 425 A: 2f 0 4 0 0 0 426 A: 30 0 15 0 0 0 427 A: 31 0 15 0 0 0 428 A: 34 0 1 0 0 0 429 A: 35 0 1936 0 0 20 430 A: 36 0 1057 0 0 20 431 A: 37 0 15 0 0 0 432 A: 39 0 65535 0 0 0 433 A: 3a 0 255 0 0 0 434 ################################ 435 # Waiting for events # 436 ################################ 437 E: 0.000001 0003 0039 0000\t# EV_ABS / ABS_MT_TRACKING_ID 0 438 E: 0.000001 0003 0035 0891\t# EV_ABS / ABS_MT_POSITION_X 891 439 E: 0.000001 0003 0036 0333\t# EV_ABS / ABS_MT_POSITION_Y 333 440 E: 0.000001 0003 003a 0056\t# EV_ABS / ABS_MT_PRESSURE 56 441 E: 0.000001 0003 0030 0001\t# EV_ABS / ABS_MT_TOUCH_MAJOR 1 442 E: 0.000001 0003 0031 0001\t# EV_ABS / ABS_MT_TOUCH_MINOR 1 443 E: 0.000001 0001 014a 0001\t# EV_KEY / BTN_TOUCH 1 444 E: 0.000001 0001 0145 0001\t# EV_KEY / BTN_TOOL_FINGER 1 445 E: 0.000001 0003 0000 0891\t# EV_ABS / ABS_X 891 446 E: 0.000001 0003 0001 0333\t# EV_ABS / ABS_Y 333 447 E: 0.000001 0003 0018 0056\t# EV_ABS / ABS_PRESSURE 56 448 E: 0.000001 0000 0000 0000\t# ------------ SYN_REPORT (0) ---------- +0ms 449 E: 0.006081 0003 0035 0888\t# EV_ABS / ABS_MT_POSITION_X 888 450 """); 451 EvemuParser parser = new EvemuParser(reader); 452 Event regEvent = parser.getNextEvent(); 453 assertThat(regEvent.getName()).isEqualTo("Synaptics TM3289-021"); 454 455 assertThat(regEvent.getBus()).isEqualTo(0x001d); 456 assertThat(regEvent.getVendorId()).isEqualTo(0x6cb); 457 assertThat(regEvent.getProductId()).isEqualTo(0x0000); 458 assertThat(regEvent.getVersionId()).isEqualTo(0x0000); 459 460 assertThat(regEvent.getConfiguration().get(UinputControlCode.UI_SET_PROPBIT.getValue())) 461 .asList().containsExactly(0, 2); 462 463 assertThat(regEvent.getConfiguration().get(UinputControlCode.UI_SET_EVBIT.getValue())) 464 .asList().containsExactly(Event.EV_KEY, Event.EV_ABS); 465 assertThat(regEvent.getConfiguration().get(UinputControlCode.UI_SET_KEYBIT.getValue())) 466 .asList().containsExactly(272, 325, 328, 330, 333, 334, 335); 467 assertThat(regEvent.getConfiguration().get(UinputControlCode.UI_SET_ABSBIT.getValue())) 468 .asList().containsExactly(0, 1, 24, 47, 48, 49, 52, 53, 54, 55, 57, 58); 469 470 SparseArray<InputAbsInfo> absInfos = regEvent.getAbsInfo(); 471 assertAbsInfo(absInfos.get(0), 0, 1936, 0, 0, 20); 472 assertAbsInfo(absInfos.get(1), 0, 1057, 0, 0, 20); 473 assertAbsInfo(absInfos.get(24), 0, 255, 0, 0, 0); 474 assertAbsInfo(absInfos.get(47), 0, 4, 0, 0, 0); 475 assertAbsInfo(absInfos.get(48), 0, 15, 0, 0, 0); 476 assertAbsInfo(absInfos.get(49), 0, 15, 0, 0, 0); 477 assertAbsInfo(absInfos.get(52), 0, 1, 0, 0, 0); 478 assertAbsInfo(absInfos.get(53), 0, 1936, 0, 0, 20); 479 assertAbsInfo(absInfos.get(54), 0, 1057, 0, 0, 20); 480 assertAbsInfo(absInfos.get(55), 0, 15, 0, 0, 0); 481 assertAbsInfo(absInfos.get(57), 0, 65535, 0, 0, 0); 482 assertAbsInfo(absInfos.get(58), 0, 255, 0, 0, 0); 483 484 assertThat(parser.getNextEvent().getCommand()).isEqualTo(Event.Command.DELAY); 485 486 assertInjectEvent(parser.getNextEvent(), 0x3, 0x39, 0, -1); 487 assertInjectEvent(parser.getNextEvent(), 0x3, 0x35, 891); 488 assertInjectEvent(parser.getNextEvent(), 0x3, 0x36, 333); 489 assertInjectEvent(parser.getNextEvent(), 0x3, 0x3a, 56); 490 assertInjectEvent(parser.getNextEvent(), 0x3, 0x30, 1); 491 assertInjectEvent(parser.getNextEvent(), 0x3, 0x31, 1); 492 assertInjectEvent(parser.getNextEvent(), 0x1, 0x14a, 1); 493 assertInjectEvent(parser.getNextEvent(), 0x1, 0x145, 1); 494 assertInjectEvent(parser.getNextEvent(), 0x3, 0x0, 891); 495 assertInjectEvent(parser.getNextEvent(), 0x3, 0x1, 333); 496 assertInjectEvent(parser.getNextEvent(), 0x3, 0x18, 56); 497 assertInjectEvent(parser.getNextEvent(), 0x0, 0x0, 0); 498 499 assertDelayEvent(parser.getNextEvent(), 6_080_000); 500 501 assertInjectEvent(parser.getNextEvent(), 0x3, 0x0035, 888, 6_080); 502 } 503 } 504