1 // 2 // Copyright 2010 The Android Open Source Project 3 // 4 5 #include <ui/InputTransport.h> 6 #include <utils/Timers.h> 7 #include <utils/StopWatch.h> 8 #include <gtest/gtest.h> 9 #include <unistd.h> 10 #include <time.h> 11 #include <sys/mman.h> 12 #include <cutils/ashmem.h> 13 14 #include "../../utils/tests/TestHelpers.h" 15 16 namespace android { 17 18 class InputPublisherAndConsumerTest : public testing::Test { 19 protected: 20 sp<InputChannel> serverChannel, clientChannel; 21 InputPublisher* mPublisher; 22 InputConsumer* mConsumer; 23 PreallocatedInputEventFactory mEventFactory; 24 25 virtual void SetUp() { 26 status_t result = InputChannel::openInputChannelPair(String8("channel name"), 27 serverChannel, clientChannel); 28 29 mPublisher = new InputPublisher(serverChannel); 30 mConsumer = new InputConsumer(clientChannel); 31 } 32 33 virtual void TearDown() { 34 if (mPublisher) { 35 delete mPublisher; 36 mPublisher = NULL; 37 } 38 39 if (mConsumer) { 40 delete mConsumer; 41 mConsumer = NULL; 42 } 43 44 serverChannel.clear(); 45 clientChannel.clear(); 46 } 47 48 void Initialize(); 49 void PublishAndConsumeKeyEvent(); 50 void PublishAndConsumeMotionEvent( 51 size_t samplesToAppendBeforeDispatch = 0, 52 size_t samplesToAppendAfterDispatch = 0); 53 }; 54 55 TEST_F(InputPublisherAndConsumerTest, GetChannel_ReturnsTheChannel) { 56 EXPECT_EQ(serverChannel.get(), mPublisher->getChannel().get()); 57 EXPECT_EQ(clientChannel.get(), mConsumer->getChannel().get()); 58 } 59 60 void InputPublisherAndConsumerTest::Initialize() { 61 status_t status; 62 63 status = mPublisher->initialize(); 64 ASSERT_EQ(OK, status) 65 << "publisher initialize should return OK"; 66 67 status = mConsumer->initialize(); 68 ASSERT_EQ(OK, status) 69 << "consumer initialize should return OK"; 70 } 71 72 void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() { 73 status_t status; 74 75 const int32_t deviceId = 1; 76 const int32_t source = AINPUT_SOURCE_KEYBOARD; 77 const int32_t action = AKEY_EVENT_ACTION_DOWN; 78 const int32_t flags = AKEY_EVENT_FLAG_FROM_SYSTEM; 79 const int32_t keyCode = AKEYCODE_ENTER; 80 const int32_t scanCode = 13; 81 const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON; 82 const int32_t repeatCount = 1; 83 const nsecs_t downTime = 3; 84 const nsecs_t eventTime = 4; 85 86 status = mPublisher->publishKeyEvent(deviceId, source, action, flags, 87 keyCode, scanCode, metaState, repeatCount, downTime, eventTime); 88 ASSERT_EQ(OK, status) 89 << "publisher publishKeyEvent should return OK"; 90 91 status = mPublisher->sendDispatchSignal(); 92 ASSERT_EQ(OK, status) 93 << "publisher sendDispatchSignal should return OK"; 94 95 status = mConsumer->receiveDispatchSignal(); 96 ASSERT_EQ(OK, status) 97 << "consumer receiveDispatchSignal should return OK"; 98 99 InputEvent* event; 100 status = mConsumer->consume(& mEventFactory, & event); 101 ASSERT_EQ(OK, status) 102 << "consumer consume should return OK"; 103 104 ASSERT_TRUE(event != NULL) 105 << "consumer should have returned non-NULL event"; 106 ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event->getType()) 107 << "consumer should have returned a key event"; 108 109 KeyEvent* keyEvent = static_cast<KeyEvent*>(event); 110 EXPECT_EQ(deviceId, keyEvent->getDeviceId()); 111 EXPECT_EQ(source, keyEvent->getSource()); 112 EXPECT_EQ(action, keyEvent->getAction()); 113 EXPECT_EQ(flags, keyEvent->getFlags()); 114 EXPECT_EQ(keyCode, keyEvent->getKeyCode()); 115 EXPECT_EQ(scanCode, keyEvent->getScanCode()); 116 EXPECT_EQ(metaState, keyEvent->getMetaState()); 117 EXPECT_EQ(repeatCount, keyEvent->getRepeatCount()); 118 EXPECT_EQ(downTime, keyEvent->getDownTime()); 119 EXPECT_EQ(eventTime, keyEvent->getEventTime()); 120 121 status = mConsumer->sendFinishedSignal(); 122 ASSERT_EQ(OK, status) 123 << "consumer sendFinishedSignal should return OK"; 124 125 status = mPublisher->receiveFinishedSignal(); 126 ASSERT_EQ(OK, status) 127 << "publisher receiveFinishedSignal should return OK"; 128 129 status = mPublisher->reset(); 130 ASSERT_EQ(OK, status) 131 << "publisher reset should return OK"; 132 } 133 134 void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent( 135 size_t samplesToAppendBeforeDispatch, size_t samplesToAppendAfterDispatch) { 136 status_t status; 137 138 const int32_t deviceId = 1; 139 const int32_t source = AINPUT_SOURCE_TOUCHSCREEN; 140 const int32_t action = AMOTION_EVENT_ACTION_MOVE; 141 const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED; 142 const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP; 143 const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON; 144 const float xOffset = -10; 145 const float yOffset = -20; 146 const float xPrecision = 0.25; 147 const float yPrecision = 0.5; 148 const nsecs_t downTime = 3; 149 const size_t pointerCount = 3; 150 const int32_t pointerIds[pointerCount] = { 2, 0, 1 }; 151 152 Vector<nsecs_t> sampleEventTimes; 153 Vector<PointerCoords> samplePointerCoords; 154 155 for (size_t i = 0; i <= samplesToAppendAfterDispatch + samplesToAppendBeforeDispatch; i++) { 156 sampleEventTimes.push(i + 10); 157 for (size_t j = 0; j < pointerCount; j++) { 158 samplePointerCoords.push(); 159 samplePointerCoords.editTop().x = 100 * i + j; 160 samplePointerCoords.editTop().y = 200 * i + j; 161 samplePointerCoords.editTop().pressure = 0.5 * i + j; 162 samplePointerCoords.editTop().size = 0.7 * i + j; 163 samplePointerCoords.editTop().touchMajor = 1.5 * i + j; 164 samplePointerCoords.editTop().touchMinor = 1.7 * i + j; 165 samplePointerCoords.editTop().toolMajor = 2.5 * i + j; 166 samplePointerCoords.editTop().toolMinor = 2.7 * i + j; 167 samplePointerCoords.editTop().orientation = 3.5 * i + j; 168 } 169 } 170 171 status = mPublisher->publishMotionEvent(deviceId, source, action, flags, edgeFlags, 172 metaState, xOffset, yOffset, xPrecision, yPrecision, 173 downTime, sampleEventTimes[0], pointerCount, pointerIds, samplePointerCoords.array()); 174 ASSERT_EQ(OK, status) 175 << "publisher publishMotionEvent should return OK"; 176 177 for (size_t i = 0; i < samplesToAppendBeforeDispatch; i++) { 178 size_t sampleIndex = i + 1; 179 status = mPublisher->appendMotionSample(sampleEventTimes[sampleIndex], 180 samplePointerCoords.array() + sampleIndex * pointerCount); 181 ASSERT_EQ(OK, status) 182 << "publisher appendMotionEvent should return OK"; 183 } 184 185 status = mPublisher->sendDispatchSignal(); 186 ASSERT_EQ(OK, status) 187 << "publisher sendDispatchSignal should return OK"; 188 189 for (size_t i = 0; i < samplesToAppendAfterDispatch; i++) { 190 size_t sampleIndex = i + 1 + samplesToAppendBeforeDispatch; 191 status = mPublisher->appendMotionSample(sampleEventTimes[sampleIndex], 192 samplePointerCoords.array() + sampleIndex * pointerCount); 193 ASSERT_EQ(OK, status) 194 << "publisher appendMotionEvent should return OK"; 195 } 196 197 status = mConsumer->receiveDispatchSignal(); 198 ASSERT_EQ(OK, status) 199 << "consumer receiveDispatchSignal should return OK"; 200 201 InputEvent* event; 202 status = mConsumer->consume(& mEventFactory, & event); 203 ASSERT_EQ(OK, status) 204 << "consumer consume should return OK"; 205 206 ASSERT_TRUE(event != NULL) 207 << "consumer should have returned non-NULL event"; 208 ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()) 209 << "consumer should have returned a motion event"; 210 211 size_t lastSampleIndex = samplesToAppendBeforeDispatch + samplesToAppendAfterDispatch; 212 213 MotionEvent* motionEvent = static_cast<MotionEvent*>(event); 214 EXPECT_EQ(deviceId, motionEvent->getDeviceId()); 215 EXPECT_EQ(source, motionEvent->getSource()); 216 EXPECT_EQ(action, motionEvent->getAction()); 217 EXPECT_EQ(flags, motionEvent->getFlags()); 218 EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags()); 219 EXPECT_EQ(metaState, motionEvent->getMetaState()); 220 EXPECT_EQ(xPrecision, motionEvent->getXPrecision()); 221 EXPECT_EQ(yPrecision, motionEvent->getYPrecision()); 222 EXPECT_EQ(downTime, motionEvent->getDownTime()); 223 EXPECT_EQ(sampleEventTimes[lastSampleIndex], motionEvent->getEventTime()); 224 EXPECT_EQ(pointerCount, motionEvent->getPointerCount()); 225 EXPECT_EQ(lastSampleIndex, motionEvent->getHistorySize()); 226 227 for (size_t i = 0; i < pointerCount; i++) { 228 SCOPED_TRACE(i); 229 EXPECT_EQ(pointerIds[i], motionEvent->getPointerId(i)); 230 } 231 232 for (size_t sampleIndex = 0; sampleIndex < lastSampleIndex; sampleIndex++) { 233 SCOPED_TRACE(sampleIndex); 234 EXPECT_EQ(sampleEventTimes[sampleIndex], 235 motionEvent->getHistoricalEventTime(sampleIndex)); 236 for (size_t i = 0; i < pointerCount; i++) { 237 SCOPED_TRACE(i); 238 size_t offset = sampleIndex * pointerCount + i; 239 EXPECT_EQ(samplePointerCoords[offset].x, 240 motionEvent->getHistoricalRawX(i, sampleIndex)); 241 EXPECT_EQ(samplePointerCoords[offset].y, 242 motionEvent->getHistoricalRawY(i, sampleIndex)); 243 EXPECT_EQ(samplePointerCoords[offset].x + xOffset, 244 motionEvent->getHistoricalX(i, sampleIndex)); 245 EXPECT_EQ(samplePointerCoords[offset].y + yOffset, 246 motionEvent->getHistoricalY(i, sampleIndex)); 247 EXPECT_EQ(samplePointerCoords[offset].pressure, 248 motionEvent->getHistoricalPressure(i, sampleIndex)); 249 EXPECT_EQ(samplePointerCoords[offset].size, 250 motionEvent->getHistoricalSize(i, sampleIndex)); 251 EXPECT_EQ(samplePointerCoords[offset].touchMajor, 252 motionEvent->getHistoricalTouchMajor(i, sampleIndex)); 253 EXPECT_EQ(samplePointerCoords[offset].touchMinor, 254 motionEvent->getHistoricalTouchMinor(i, sampleIndex)); 255 EXPECT_EQ(samplePointerCoords[offset].toolMajor, 256 motionEvent->getHistoricalToolMajor(i, sampleIndex)); 257 EXPECT_EQ(samplePointerCoords[offset].toolMinor, 258 motionEvent->getHistoricalToolMinor(i, sampleIndex)); 259 EXPECT_EQ(samplePointerCoords[offset].orientation, 260 motionEvent->getHistoricalOrientation(i, sampleIndex)); 261 } 262 } 263 264 SCOPED_TRACE(lastSampleIndex); 265 EXPECT_EQ(sampleEventTimes[lastSampleIndex], motionEvent->getEventTime()); 266 for (size_t i = 0; i < pointerCount; i++) { 267 SCOPED_TRACE(i); 268 size_t offset = lastSampleIndex * pointerCount + i; 269 EXPECT_EQ(samplePointerCoords[offset].x, motionEvent->getRawX(i)); 270 EXPECT_EQ(samplePointerCoords[offset].y, motionEvent->getRawY(i)); 271 EXPECT_EQ(samplePointerCoords[offset].x + xOffset, motionEvent->getX(i)); 272 EXPECT_EQ(samplePointerCoords[offset].y + yOffset, motionEvent->getY(i)); 273 EXPECT_EQ(samplePointerCoords[offset].pressure, motionEvent->getPressure(i)); 274 EXPECT_EQ(samplePointerCoords[offset].size, motionEvent->getSize(i)); 275 EXPECT_EQ(samplePointerCoords[offset].touchMajor, motionEvent->getTouchMajor(i)); 276 EXPECT_EQ(samplePointerCoords[offset].touchMinor, motionEvent->getTouchMinor(i)); 277 EXPECT_EQ(samplePointerCoords[offset].toolMajor, motionEvent->getToolMajor(i)); 278 EXPECT_EQ(samplePointerCoords[offset].toolMinor, motionEvent->getToolMinor(i)); 279 EXPECT_EQ(samplePointerCoords[offset].orientation, motionEvent->getOrientation(i)); 280 } 281 282 status = mConsumer->sendFinishedSignal(); 283 ASSERT_EQ(OK, status) 284 << "consumer sendFinishedSignal should return OK"; 285 286 status = mPublisher->receiveFinishedSignal(); 287 ASSERT_EQ(OK, status) 288 << "publisher receiveFinishedSignal should return OK"; 289 290 status = mPublisher->reset(); 291 ASSERT_EQ(OK, status) 292 << "publisher reset should return OK"; 293 } 294 295 TEST_F(InputPublisherAndConsumerTest, PublishKeyEvent_EndToEnd) { 296 ASSERT_NO_FATAL_FAILURE(Initialize()); 297 ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent()); 298 } 299 300 TEST_F(InputPublisherAndConsumerTest, PublishKeyEvent_WhenNotReset_ReturnsError) { 301 status_t status; 302 ASSERT_NO_FATAL_FAILURE(Initialize()); 303 304 status = mPublisher->publishKeyEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 305 ASSERT_EQ(OK, status) 306 << "publisher publishKeyEvent should return OK first time"; 307 308 status = mPublisher->publishKeyEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); 309 ASSERT_EQ(INVALID_OPERATION, status) 310 << "publisher publishKeyEvent should return INVALID_OPERATION because " 311 "the publisher was not reset"; 312 } 313 314 TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_EndToEnd) { 315 ASSERT_NO_FATAL_FAILURE(Initialize()); 316 ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent()); 317 } 318 319 TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenNotReset_ReturnsError) { 320 status_t status; 321 ASSERT_NO_FATAL_FAILURE(Initialize()); 322 323 const size_t pointerCount = 1; 324 int32_t pointerIds[pointerCount] = { 0 }; 325 PointerCoords pointerCoords[pointerCount] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; 326 327 status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 328 pointerCount, pointerIds, pointerCoords); 329 ASSERT_EQ(OK, status) 330 << "publisher publishMotionEvent should return OK"; 331 332 status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 333 pointerCount, pointerIds, pointerCoords); 334 ASSERT_EQ(INVALID_OPERATION, status) 335 << "publisher publishMotionEvent should return INVALID_OPERATION because "; 336 "the publisher was not reset"; 337 } 338 339 TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessThan1_ReturnsError) { 340 status_t status; 341 ASSERT_NO_FATAL_FAILURE(Initialize()); 342 343 const size_t pointerCount = 0; 344 int32_t pointerIds[pointerCount]; 345 PointerCoords pointerCoords[pointerCount]; 346 347 status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 348 pointerCount, pointerIds, pointerCoords); 349 ASSERT_EQ(BAD_VALUE, status) 350 << "publisher publishMotionEvent should return BAD_VALUE"; 351 } 352 353 TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountGreaterThanMax_ReturnsError) { 354 status_t status; 355 ASSERT_NO_FATAL_FAILURE(Initialize()); 356 357 const size_t pointerCount = MAX_POINTERS + 1; 358 int32_t pointerIds[pointerCount]; 359 PointerCoords pointerCoords[pointerCount]; 360 361 status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 362 pointerCount, pointerIds, pointerCoords); 363 ASSERT_EQ(BAD_VALUE, status) 364 << "publisher publishMotionEvent should return BAD_VALUE"; 365 } 366 367 TEST_F(InputPublisherAndConsumerTest, PublishMultipleEvents_EndToEnd) { 368 ASSERT_NO_FATAL_FAILURE(Initialize()); 369 ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent()); 370 ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent()); 371 ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent()); 372 ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent()); 373 ASSERT_NO_FATAL_FAILURE(PublishAndConsumeKeyEvent()); 374 } 375 376 TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenCalledBeforeDispatchSignal_AppendsSamples) { 377 status_t status; 378 ASSERT_NO_FATAL_FAILURE(Initialize()); 379 ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent(3, 0)); 380 } 381 382 TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenCalledAfterDispatchSignalAndNotConsumed_AppendsSamples) { 383 status_t status; 384 ASSERT_NO_FATAL_FAILURE(Initialize()); 385 ASSERT_NO_FATAL_FAILURE(PublishAndConsumeMotionEvent(0, 4)); 386 } 387 388 TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenNoMotionEventPublished_ReturnsError) { 389 status_t status; 390 ASSERT_NO_FATAL_FAILURE(Initialize()); 391 392 PointerCoords pointerCoords[1]; 393 status = mPublisher->appendMotionSample(0, pointerCoords); 394 ASSERT_EQ(INVALID_OPERATION, status) 395 << "publisher appendMotionSample should return INVALID_OPERATION"; 396 } 397 398 TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenPublishedMotionEventIsNotAMove_ReturnsError) { 399 status_t status; 400 ASSERT_NO_FATAL_FAILURE(Initialize()); 401 402 const size_t pointerCount = MAX_POINTERS; 403 int32_t pointerIds[pointerCount]; 404 PointerCoords pointerCoords[pointerCount]; 405 406 status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_DOWN, 407 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords); 408 ASSERT_EQ(OK, status); 409 410 status = mPublisher->appendMotionSample(0, pointerCoords); 411 ASSERT_EQ(INVALID_OPERATION, status) 412 << "publisher appendMotionSample should return INVALID_OPERATION"; 413 } 414 415 TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenAlreadyConsumed_ReturnsError) { 416 status_t status; 417 ASSERT_NO_FATAL_FAILURE(Initialize()); 418 419 const size_t pointerCount = MAX_POINTERS; 420 int32_t pointerIds[pointerCount]; 421 PointerCoords pointerCoords[pointerCount]; 422 423 status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE, 424 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords); 425 ASSERT_EQ(OK, status); 426 427 status = mPublisher->sendDispatchSignal(); 428 ASSERT_EQ(OK, status); 429 430 status = mConsumer->receiveDispatchSignal(); 431 ASSERT_EQ(OK, status); 432 433 InputEvent* event; 434 status = mConsumer->consume(& mEventFactory, & event); 435 ASSERT_EQ(OK, status); 436 437 status = mPublisher->appendMotionSample(0, pointerCoords); 438 ASSERT_EQ(status_t(FAILED_TRANSACTION), status) 439 << "publisher appendMotionSample should return FAILED_TRANSACTION"; 440 } 441 442 TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenBufferFull_ReturnsError) { 443 status_t status; 444 ASSERT_NO_FATAL_FAILURE(Initialize()); 445 446 const size_t pointerCount = MAX_POINTERS; 447 int32_t pointerIds[pointerCount]; 448 PointerCoords pointerCoords[pointerCount]; 449 450 status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE, 451 0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords); 452 ASSERT_EQ(OK, status); 453 454 for (int count = 1;; count++) { 455 ASSERT_LT(count, 100000) << "should eventually reach OOM"; 456 457 status = mPublisher->appendMotionSample(0, pointerCoords); 458 if (status != OK) { 459 ASSERT_GT(count, 12) << "should be able to add at least a dozen samples"; 460 ASSERT_EQ(NO_MEMORY, status) 461 << "publisher appendMotionSample should return NO_MEMORY when buffer is full"; 462 break; 463 } 464 } 465 466 status = mPublisher->appendMotionSample(0, pointerCoords); 467 ASSERT_EQ(NO_MEMORY, status) 468 << "publisher appendMotionSample should return NO_MEMORY persistently until reset"; 469 } 470 471 } // namespace android 472