Skip to content

Commit 9dc348d

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Fix spurious ANRs in native activities."
2 parents f2fbd2e + 2b6c32c commit 9dc348d

File tree

6 files changed

+135
-66
lines changed

6 files changed

+135
-66
lines changed

core/jni/android_app_NativeActivity.cpp

Lines changed: 32 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,12 @@ int32_t AInputQueue::hasEvents() {
162162
int32_t AInputQueue::getEvent(AInputEvent** outEvent) {
163163
*outEvent = NULL;
164164

165-
bool finishNow = false;
166-
167165
char byteread;
168166
ssize_t nRead = read(mDispatchKeyRead, &byteread, 1);
167+
168+
Mutex::Autolock _l(mLock);
169+
169170
if (nRead == 1) {
170-
mLock.lock();
171171
if (mDispatchingKeys.size() > 0) {
172172
KeyEvent* kevent = mDispatchingKeys[0];
173173
*outEvent = kevent;
@@ -178,6 +178,8 @@ int32_t AInputQueue::getEvent(AInputEvent** outEvent) {
178178
inflight.finishSeq = 0;
179179
mInFlightEvents.push(inflight);
180180
}
181+
182+
bool finishNow = false;
181183
if (mFinishPreDispatches.size() > 0) {
182184
finish_pre_dispatch finish(mFinishPreDispatches[0]);
183185
mFinishPreDispatches.removeAt(0);
@@ -193,7 +195,6 @@ int32_t AInputQueue::getEvent(AInputEvent** outEvent) {
193195
ALOGW("getEvent couldn't find inflight for seq %d", finish.seq);
194196
}
195197
}
196-
mLock.unlock();
197198

198199
if (finishNow) {
199200
finishEvent(*outEvent, true, false);
@@ -206,7 +207,8 @@ int32_t AInputQueue::getEvent(AInputEvent** outEvent) {
206207

207208
uint32_t consumerSeq;
208209
InputEvent* myEvent = NULL;
209-
status_t res = mConsumer.consume(this, true /*consumeBatches*/, &consumerSeq, &myEvent);
210+
status_t res = mConsumer.consume(&mPooledInputEventFactory, true /*consumeBatches*/,
211+
&consumerSeq, &myEvent);
210212
if (res != android::OK) {
211213
if (res != android::WOULD_BLOCK) {
212214
ALOGW("channel '%s' ~ Failed to consume input event. status=%d",
@@ -215,6 +217,10 @@ int32_t AInputQueue::getEvent(AInputEvent** outEvent) {
215217
return -1;
216218
}
217219

220+
if (mConsumer.hasDeferredEvent()) {
221+
wakeupDispatchLocked();
222+
}
223+
218224
in_flight_event inflight;
219225
inflight.event = myEvent;
220226
inflight.seq = -1;
@@ -255,7 +261,8 @@ void AInputQueue::finishEvent(AInputEvent* event, bool handled, bool didDefaultH
255261
return;
256262
}
257263

258-
mLock.lock();
264+
Mutex::Autolock _l(mLock);
265+
259266
const size_t N = mInFlightEvents.size();
260267
for (size_t i=0; i<N; i++) {
261268
const in_flight_event& inflight(mInFlightEvents[i]);
@@ -267,111 +274,82 @@ void AInputQueue::finishEvent(AInputEvent* event, bool handled, bool didDefaultH
267274
mConsumer.getChannel()->getName().string(), res);
268275
}
269276
}
270-
if (static_cast<InputEvent*>(event)->getType() == AINPUT_EVENT_TYPE_KEY) {
271-
mAvailKeyEvents.push(static_cast<KeyEvent*>(event));
272-
} else {
273-
mAvailMotionEvents.push(static_cast<MotionEvent*>(event));
274-
}
277+
mPooledInputEventFactory.recycle(static_cast<InputEvent*>(event));
275278
mInFlightEvents.removeAt(i);
276-
mLock.unlock();
277279
return;
278280
}
279281
}
280-
mLock.unlock();
281-
282+
282283
ALOGW("finishEvent called for unknown event: %p", event);
283284
}
284285

285286
void AInputQueue::dispatchEvent(android::KeyEvent* event) {
286-
mLock.lock();
287+
Mutex::Autolock _l(mLock);
288+
287289
LOG_TRACE("dispatchEvent: dispatching=%d write=%d\n", mDispatchingKeys.size(),
288290
mDispatchKeyWrite);
289291
mDispatchingKeys.add(event);
290-
wakeupDispatch();
291-
mLock.unlock();
292+
wakeupDispatchLocked();
292293
}
293294

294295
void AInputQueue::finishPreDispatch(int seq, bool handled) {
295-
mLock.lock();
296+
Mutex::Autolock _l(mLock);
297+
296298
LOG_TRACE("finishPreDispatch: seq=%d handled=%d\n", seq, handled ? 1 : 0);
297299
finish_pre_dispatch finish;
298300
finish.seq = seq;
299301
finish.handled = handled;
300302
mFinishPreDispatches.add(finish);
301-
wakeupDispatch();
302-
mLock.unlock();
303+
wakeupDispatchLocked();
303304
}
304305

305306
KeyEvent* AInputQueue::consumeUnhandledEvent() {
306-
KeyEvent* event = NULL;
307+
Mutex::Autolock _l(mLock);
307308

308-
mLock.lock();
309+
KeyEvent* event = NULL;
309310
if (mUnhandledKeys.size() > 0) {
310311
event = mUnhandledKeys[0];
311312
mUnhandledKeys.removeAt(0);
312313
}
313-
mLock.unlock();
314314

315315
LOG_TRACE("consumeUnhandledEvent: KeyEvent=%p", event);
316-
317316
return event;
318317
}
319318

320319
KeyEvent* AInputQueue::consumePreDispatchingEvent(int* outSeq) {
321-
KeyEvent* event = NULL;
320+
Mutex::Autolock _l(mLock);
322321

323-
mLock.lock();
322+
KeyEvent* event = NULL;
324323
if (mPreDispatchingKeys.size() > 0) {
325324
const in_flight_event& inflight(mPreDispatchingKeys[0]);
326325
event = static_cast<KeyEvent*>(inflight.event);
327326
*outSeq = inflight.seq;
328327
mPreDispatchingKeys.removeAt(0);
329328
}
330-
mLock.unlock();
331329

332330
LOG_TRACE("consumePreDispatchingEvent: KeyEvent=%p", event);
333-
334331
return event;
335332
}
336333

337334
KeyEvent* AInputQueue::createKeyEvent() {
338-
mLock.lock();
339-
KeyEvent* event;
340-
if (mAvailKeyEvents.size() <= 0) {
341-
event = new KeyEvent();
342-
} else {
343-
event = mAvailKeyEvents.top();
344-
mAvailKeyEvents.pop();
345-
}
346-
mLock.unlock();
347-
return event;
348-
}
335+
Mutex::Autolock _l(mLock);
349336

350-
MotionEvent* AInputQueue::createMotionEvent() {
351-
mLock.lock();
352-
MotionEvent* event;
353-
if (mAvailMotionEvents.size() <= 0) {
354-
event = new MotionEvent();
355-
} else {
356-
event = mAvailMotionEvents.top();
357-
mAvailMotionEvents.pop();
358-
}
359-
mLock.unlock();
360-
return event;
337+
return mPooledInputEventFactory.createKeyEvent();
361338
}
362339

363340
void AInputQueue::doUnhandledKey(KeyEvent* keyEvent) {
364-
mLock.lock();
341+
Mutex::Autolock _l(mLock);
342+
365343
LOG_TRACE("Unhandled key: pending=%d write=%d\n", mUnhandledKeys.size(), mWorkWrite);
366344
if (mUnhandledKeys.size() <= 0 && mWorkWrite >= 0) {
367345
write_work(mWorkWrite, CMD_DEF_KEY);
368346
}
369347
mUnhandledKeys.add(keyEvent);
370-
mLock.unlock();
371348
}
372349

373350
bool AInputQueue::preDispatchKey(KeyEvent* keyEvent) {
374-
mLock.lock();
351+
Mutex::Autolock _l(mLock);
352+
375353
LOG_TRACE("preDispatch key: pending=%d write=%d\n", mPreDispatchingKeys.size(), mWorkWrite);
376354
const size_t N = mInFlightEvents.size();
377355
for (size_t i=0; i<N; i++) {
@@ -380,7 +358,6 @@ bool AInputQueue::preDispatchKey(KeyEvent* keyEvent) {
380358
if (inflight.seq >= 0) {
381359
// This event has already been pre-dispatched!
382360
LOG_TRACE("Event already pre-dispatched!");
383-
mLock.unlock();
384361
return false;
385362
}
386363
mSeq++;
@@ -391,7 +368,6 @@ bool AInputQueue::preDispatchKey(KeyEvent* keyEvent) {
391368
write_work(mWorkWrite, CMD_DEF_KEY);
392369
}
393370
mPreDispatchingKeys.add(inflight);
394-
mLock.unlock();
395371
return true;
396372
}
397373
}
@@ -400,7 +376,7 @@ bool AInputQueue::preDispatchKey(KeyEvent* keyEvent) {
400376
return false;
401377
}
402378

403-
void AInputQueue::wakeupDispatch() {
379+
void AInputQueue::wakeupDispatchLocked() {
404380
restart:
405381
char dummy = 0;
406382
int res = write(mDispatchKeyWrite, &dummy, sizeof(dummy));

include/android_runtime/android_app_NativeActivity.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ extern void android_NativeActivity_hideSoftInput(
6565
* b. Java sends event through default key handler.
6666
* c. event is finished.
6767
*/
68-
struct AInputQueue : public android::InputEventFactoryInterface {
68+
struct AInputQueue {
6969
public:
7070
/* Creates a consumer associated with an input channel. */
7171
explicit AInputQueue(const android::sp<android::InputChannel>& channel, int workWrite);
@@ -96,16 +96,16 @@ struct AInputQueue : public android::InputEventFactoryInterface {
9696
android::KeyEvent* consumeUnhandledEvent();
9797
android::KeyEvent* consumePreDispatchingEvent(int* outSeq);
9898

99-
virtual android::KeyEvent* createKeyEvent();
100-
virtual android::MotionEvent* createMotionEvent();
99+
android::KeyEvent* createKeyEvent();
101100

102101
int mWorkWrite;
103102

104103
private:
105104
void doUnhandledKey(android::KeyEvent* keyEvent);
106105
bool preDispatchKey(android::KeyEvent* keyEvent);
107-
void wakeupDispatch();
106+
void wakeupDispatchLocked();
108107

108+
android::PooledInputEventFactory mPooledInputEventFactory;
109109
android::InputConsumer mConsumer;
110110
android::sp<android::Looper> mLooper;
111111

@@ -127,11 +127,6 @@ struct AInputQueue : public android::InputEventFactoryInterface {
127127

128128
int mSeq;
129129

130-
// Cache of previously allocated key events.
131-
android::Vector<android::KeyEvent*> mAvailKeyEvents;
132-
// Cache of previously allocated motion events.
133-
android::Vector<android::MotionEvent*> mAvailMotionEvents;
134-
135130
// All input events that are actively being processed.
136131
android::Vector<in_flight_event> mInFlightEvents;
137132

include/androidfw/Input.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,26 @@ class PreallocatedInputEventFactory : public InputEventFactoryInterface {
615615
MotionEvent mMotionEvent;
616616
};
617617

618+
/*
619+
* An input event factory implementation that maintains a pool of input events.
620+
*/
621+
class PooledInputEventFactory : public InputEventFactoryInterface {
622+
public:
623+
PooledInputEventFactory(size_t maxPoolSize = 20);
624+
virtual ~PooledInputEventFactory();
625+
626+
virtual KeyEvent* createKeyEvent();
627+
virtual MotionEvent* createMotionEvent();
628+
629+
void recycle(InputEvent* event);
630+
631+
private:
632+
const size_t mMaxPoolSize;
633+
634+
Vector<KeyEvent*> mKeyEventPool;
635+
Vector<MotionEvent*> mMotionEventPool;
636+
};
637+
618638
/*
619639
* Calculates the velocity of pointer movements over time.
620640
*/

include/androidfw/InputTransport.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,29 @@ class InputConsumer {
292292
*/
293293
status_t sendFinishedSignal(uint32_t seq, bool handled);
294294

295-
/* Returns true if there is a pending batch. */
295+
/* Returns true if there is a deferred event waiting.
296+
*
297+
* Should be called after calling consume() to determine whether the consumer
298+
* has a deferred event to be processed. Deferred events are somewhat special in
299+
* that they have already been removed from the input channel. If the input channel
300+
* becomes empty, the client may need to do extra work to ensure that it processes
301+
* the deferred event despite the fact that the inptu channel's file descriptor
302+
* is not readable.
303+
*
304+
* One option is simply to call consume() in a loop until it returns WOULD_BLOCK.
305+
* This guarantees that all deferred events will be processed.
306+
*
307+
* Alternately, the caller can call hasDeferredEvent() to determine whether there is
308+
* a deferred event waiting and then ensure that its event loop wakes up at least
309+
* one more time to consume the deferred event.
310+
*/
311+
bool hasDeferredEvent() const;
312+
313+
/* Returns true if there is a pending batch.
314+
*
315+
* Should be called after calling consume() with consumeBatches == false to determine
316+
* whether consume() should be called again later on with consumeBatches == true.
317+
*/
296318
bool hasPendingBatch() const;
297319

298320
private:

libs/androidfw/Input.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,58 @@ bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
683683
}
684684

685685

686+
// --- PooledInputEventFactory ---
687+
688+
PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
689+
mMaxPoolSize(maxPoolSize) {
690+
}
691+
692+
PooledInputEventFactory::~PooledInputEventFactory() {
693+
for (size_t i = 0; i < mKeyEventPool.size(); i++) {
694+
delete mKeyEventPool.itemAt(i);
695+
}
696+
for (size_t i = 0; i < mMotionEventPool.size(); i++) {
697+
delete mMotionEventPool.itemAt(i);
698+
}
699+
}
700+
701+
KeyEvent* PooledInputEventFactory::createKeyEvent() {
702+
if (!mKeyEventPool.isEmpty()) {
703+
KeyEvent* event = mKeyEventPool.top();
704+
mKeyEventPool.pop();
705+
return event;
706+
}
707+
return new KeyEvent();
708+
}
709+
710+
MotionEvent* PooledInputEventFactory::createMotionEvent() {
711+
if (!mMotionEventPool.isEmpty()) {
712+
MotionEvent* event = mMotionEventPool.top();
713+
mMotionEventPool.pop();
714+
return event;
715+
}
716+
return new MotionEvent();
717+
}
718+
719+
void PooledInputEventFactory::recycle(InputEvent* event) {
720+
switch (event->getType()) {
721+
case AINPUT_EVENT_TYPE_KEY:
722+
if (mKeyEventPool.size() < mMaxPoolSize) {
723+
mKeyEventPool.push(static_cast<KeyEvent*>(event));
724+
return;
725+
}
726+
break;
727+
case AINPUT_EVENT_TYPE_MOTION:
728+
if (mMotionEventPool.size() < mMaxPoolSize) {
729+
mMotionEventPool.push(static_cast<MotionEvent*>(event));
730+
return;
731+
}
732+
break;
733+
}
734+
delete event;
735+
}
736+
737+
686738
// --- VelocityTracker ---
687739

688740
const uint32_t VelocityTracker::DEFAULT_DEGREE;

libs/androidfw/InputTransport.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,10 @@ status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled)
527527
return mChannel->sendMessage(&msg);
528528
}
529529

530+
bool InputConsumer::hasDeferredEvent() const {
531+
return mMsgDeferred;
532+
}
533+
530534
bool InputConsumer::hasPendingBatch() const {
531535
return !mBatches.isEmpty();
532536
}

0 commit comments

Comments
 (0)