Add support for secure views.

Added the MotionEvent.FLAG_WINDOW_IS_OBSCURED flag which is set by the
input manager whenever another visible window is partly or wholly obscured
the target of a touch event so that applications can filter touches
accordingly.

Added a "filterTouchesWhenObscured" attribute to View which can be used to
enable filtering of touches when the view's window is obscured.

Change-Id: I936d9c85013fd2d77fb296a600528d30a29027d2
This commit is contained in:
Jeff Brown 2010-09-01 17:01:00 -07:00
parent d71a3160ae
commit af30ff6020
8 changed files with 76 additions and 38 deletions

View File

@ -78,6 +78,11 @@ enum {
POLICY_FLAG_RAW_MASK = 0x0000ffff,
/* These flags are set by the input dispatcher. */
// Indicates that the input event was injected.
POLICY_FLAG_INJECTED = 0x01000000,
/* These flags are set by the input reader policy as it intercepts each event. */
// Indicates that the screen was off when the event was received and the event
@ -225,6 +230,8 @@ public:
inline int32_t getAction() const { return mAction; }
inline int32_t getFlags() const { return mFlags; }
inline int32_t getEdgeFlags() const { return mEdgeFlags; }
inline int32_t getMetaState() const { return mMetaState; }
@ -343,6 +350,7 @@ public:
int32_t deviceId,
int32_t source,
int32_t action,
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
float xOffset,
@ -370,6 +378,7 @@ public:
private:
int32_t mAction;
int32_t mFlags;
int32_t mEdgeFlags;
int32_t mMetaState;
float mXOffset;

View File

@ -84,14 +84,22 @@ struct InputTarget {
* current event is delivered to this target or a timeout occurs. */
FLAG_SYNC = 0x01,
/* This flag indicates that a MotionEvent with ACTION_DOWN falls outside of the area of
* this target and so should instead be delivered as an ACTION_OUTSIDE to this target. */
/* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
* of the area of this target and so should instead be delivered as an
* AMOTION_EVENT_ACTION_OUTSIDE to this target. */
FLAG_OUTSIDE = 0x02,
/* This flag indicates that a KeyEvent or MotionEvent is being canceled.
* In the case of a key event, it should be delivered with KeyEvent.FLAG_CANCELED set.
* In the case of a motion event, it should be delivered as MotionEvent.ACTION_CANCEL. */
FLAG_CANCEL = 0x04
* In the case of a key event, it should be delivered with flag
* AKEY_EVENT_FLAG_CANCELED set.
* In the case of a motion event, it should be delivered with action
* AMOTION_EVENT_ACTION_CANCEL instead. */
FLAG_CANCEL = 0x04,
/* This flag indicates that the target of a MotionEvent is partly or wholly
* obscured by another visible window above it. The motion event should be
* delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
FLAG_WINDOW_IS_OBSCURED = 0x08,
};
// The input channel to be targeted.
@ -193,7 +201,8 @@ public:
uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
int32_t scanCode, int32_t metaState, nsecs_t downTime) = 0;
virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
uint32_t policyFlags, int32_t action, int32_t flags,
int32_t metaState, int32_t edgeFlags,
uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime) = 0;
@ -257,7 +266,8 @@ public:
uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
int32_t scanCode, int32_t metaState, nsecs_t downTime);
virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
uint32_t policyFlags, int32_t action, int32_t flags,
int32_t metaState, int32_t edgeFlags,
uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime);
@ -327,6 +337,7 @@ private:
int32_t source;
uint32_t policyFlags;
int32_t action;
int32_t flags;
int32_t metaState;
int32_t edgeFlags;
float xPrecision;
@ -458,7 +469,8 @@ private:
int32_t repeatCount, nsecs_t downTime);
MotionEntry* obtainMotionEntry(nsecs_t eventTime,
int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
int32_t flags, int32_t metaState, int32_t edgeFlags,
float xPrecision, float yPrecision,
nsecs_t downTime, uint32_t pointerCount,
const int32_t* pointerIds, const PointerCoords* pointerCoords);
DispatchEntry* obtainDispatchEntry(EventEntry* eventEntry);

View File

@ -135,6 +135,7 @@ struct InputMessage {
struct {
int32_t action;
int32_t flags;
int32_t metaState;
int32_t edgeFlags;
nsecs_t downTime;
@ -218,6 +219,7 @@ public:
int32_t deviceId,
int32_t source,
int32_t action,
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
float xOffset,

View File

@ -129,6 +129,7 @@ void MotionEvent::initialize(
int32_t deviceId,
int32_t source,
int32_t action,
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
float xOffset,
@ -142,6 +143,7 @@ void MotionEvent::initialize(
const PointerCoords* pointerCoords) {
InputEvent::initialize(deviceId, source);
mAction = action;
mFlags = flags;
mEdgeFlags = edgeFlags;
mMetaState = metaState;
mXOffset = xOffset;

View File

@ -392,9 +392,11 @@ void InputDispatcher::processKeyRepeatLockedInterruptible(
void InputDispatcher::processMotionLockedInterruptible(
nsecs_t currentTime, MotionEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, action=0x%x, "
LOGD("processMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
"action=0x%x, flags=0x%x, "
"metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
entry->eventTime, entry->deviceId, entry->source, entry->policyFlags, entry->action,
entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
entry->action, entry->flags,
entry->metaState, entry->edgeFlags, entry->xPrecision, entry->yPrecision,
entry->downTime);
@ -406,7 +408,7 @@ void InputDispatcher::processMotionLockedInterruptible(
}
for (uint32_t i = 0; i < entry->pointerCount; i++) {
LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
"touchMajor=%f, touchMinor=%d, toolMajor=%f, toolMinor=%f, "
"touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
"orientation=%f",
i, entry->pointerIds[i],
sample->pointerCoords[i].x, sample->pointerCoords[i].y,
@ -465,7 +467,7 @@ void InputDispatcher::identifyInputTargetsAndDispatchMotionLockedInterruptible(
mCurrentInputTargetsValid = false;
mLock.unlock();
mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action,
mReusableMotionEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags,
entry->edgeFlags, entry->metaState,
0, 0, entry->xPrecision, entry->yPrecision,
entry->downTime, entry->eventTime, entry->pointerCount, entry->pointerIds,
@ -698,12 +700,16 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
// Apply target flags.
int32_t action = motionEntry->action;
int32_t flags = motionEntry->flags;
if (dispatchEntry->targetFlags & InputTarget::FLAG_OUTSIDE) {
action = AMOTION_EVENT_ACTION_OUTSIDE;
}
if (dispatchEntry->targetFlags & InputTarget::FLAG_CANCEL) {
action = AMOTION_EVENT_ACTION_CANCEL;
}
if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
}
// If headMotionSample is non-NULL, then it points to the first new sample that we
// were unable to dispatch during the previous cycle so we resume dispatching from
@ -726,7 +732,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
// Publish the motion event and the first motion sample.
status = connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
motionEntry->source, action, motionEntry->edgeFlags, motionEntry->metaState,
motionEntry->source, action, flags, motionEntry->edgeFlags, motionEntry->metaState,
xOffset, yOffset,
motionEntry->xPrecision, motionEntry->yPrecision,
motionEntry->downTime, firstMotionSample->eventTime,
@ -1073,18 +1079,18 @@ void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t sou
}
void InputDispatcher::notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
uint32_t policyFlags, int32_t action, int32_t metaState, int32_t edgeFlags,
uint32_t policyFlags, int32_t action, int32_t flags, int32_t metaState, int32_t edgeFlags,
uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime) {
#if DEBUG_INBOUND_EVENT_DETAILS
LOGD("notifyMotion - eventTime=%lld, deviceId=0x%x, source=0x%x, policyFlags=0x%x, "
"action=0x%x, metaState=0x%x, edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, "
"downTime=%lld",
eventTime, deviceId, source, policyFlags, action, metaState, edgeFlags,
"action=0x%x, flags=0x%x, metaState=0x%x, edgeFlags=0x%x, "
"xPrecision=%f, yPrecision=%f, downTime=%lld",
eventTime, deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
xPrecision, yPrecision, downTime);
for (uint32_t i = 0; i < pointerCount; i++) {
LOGD(" Pointer %d: id=%d, x=%f, y=%f, pressure=%f, size=%f, "
"touchMajor=%f, touchMinor=%d, toolMajor=%f, toolMinor=%f, "
"touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
"orientation=%f",
i, pointerIds[i], pointerCoords[i].x, pointerCoords[i].y,
pointerCoords[i].pressure, pointerCoords[i].size,
@ -1209,7 +1215,7 @@ NoBatchingOrStreaming:;
// Just enqueue a new motion event.
MotionEntry* newEntry = mAllocator.obtainMotionEntry(eventTime,
deviceId, source, policyFlags, action, metaState, edgeFlags,
deviceId, source, policyFlags, action, flags, metaState, edgeFlags,
xPrecision, yPrecision, downTime,
pointerCount, pointerIds, pointerCoords);
@ -1359,7 +1365,7 @@ InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
switch (event->getType()) {
case AINPUT_EVENT_TYPE_KEY: {
const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
uint32_t policyFlags = POLICY_FLAG_INJECTED;
KeyEntry* keyEntry = mAllocator.obtainKeyEntry(keyEvent->getEventTime(),
keyEvent->getDeviceId(), keyEvent->getSource(), policyFlags,
@ -1371,7 +1377,7 @@ InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
case AINPUT_EVENT_TYPE_MOTION: {
const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
uint32_t policyFlags = 0; // XXX consider adding a policy flag to track injected events
uint32_t policyFlags = POLICY_FLAG_INJECTED;
const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
@ -1379,7 +1385,8 @@ InputDispatcher::EventEntry* InputDispatcher::createEntryFromInputEventLocked(
MotionEntry* motionEntry = mAllocator.obtainMotionEntry(*sampleEventTimes,
motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
motionEvent->getAction(), motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
motionEvent->getAction(), motionEvent->getFlags(),
motionEvent->getMetaState(), motionEvent->getEdgeFlags(),
motionEvent->getXPrecision(), motionEvent->getYPrecision(),
motionEvent->getDownTime(), uint32_t(pointerCount),
motionEvent->getPointerIds(), samplePointerCoords);
@ -1664,7 +1671,7 @@ InputDispatcher::KeyEntry* InputDispatcher::Allocator::obtainKeyEntry(nsecs_t ev
}
InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsecs_t eventTime,
int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action,
int32_t deviceId, int32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
int32_t metaState, int32_t edgeFlags, float xPrecision, float yPrecision,
nsecs_t downTime, uint32_t pointerCount,
const int32_t* pointerIds, const PointerCoords* pointerCoords) {
@ -1676,6 +1683,7 @@ InputDispatcher::MotionEntry* InputDispatcher::Allocator::obtainMotionEntry(nsec
entry->source = source;
entry->policyFlags = policyFlags;
entry->action = action;
entry->flags = flags;
entry->metaState = metaState;
entry->edgeFlags = edgeFlags;
entry->xPrecision = xPrecision;

View File

@ -1153,7 +1153,7 @@ void TrackballInputMapper::applyPolicyAndDispatch(nsecs_t when, int32_t motionEv
int32_t pointerId = 0;
getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TRACKBALL, policyFlags,
motionEventAction, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1, & pointerId, pointerCoords, mXPrecision, mYPrecision, downTime);
}
@ -2324,7 +2324,7 @@ void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
} // release lock
getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
motionEventAction, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
pointerCount, pointerIds, pointerCoords,
xPrecision, yPrecision, mDownTime);
}

View File

@ -318,8 +318,8 @@ status_t InputPublisher::publishKeyEvent(
nsecs_t downTime,
nsecs_t eventTime) {
#if DEBUG_TRANSPORT_ACTIONS
LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=%d, "
"action=%d, flags=%d, keyCode=%d, scanCode=%d, metaState=%d, repeatCount=%d,"
LOGD("channel '%s' publisher ~ publishKeyEvent: deviceId=%d, source=0x%x, "
"action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
"downTime=%lld, eventTime=%lld",
mChannel->getName().string(),
deviceId, source, action, flags, keyCode, scanCode, metaState, repeatCount,
@ -346,6 +346,7 @@ status_t InputPublisher::publishMotionEvent(
int32_t deviceId,
int32_t source,
int32_t action,
int32_t flags,
int32_t edgeFlags,
int32_t metaState,
float xOffset,
@ -358,12 +359,12 @@ status_t InputPublisher::publishMotionEvent(
const int32_t* pointerIds,
const PointerCoords* pointerCoords) {
#if DEBUG_TRANSPORT_ACTIONS
LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=%d, "
"action=%d, edgeFlags=%d, metaState=%d, xOffset=%f, yOffset=%f, "
LOGD("channel '%s' publisher ~ publishMotionEvent: deviceId=%d, source=0x%x, "
"action=0x%x, flags=0x%x, edgeFlags=0x%x, metaState=0x%x, xOffset=%f, yOffset=%f, "
"xPrecision=%f, yPrecision=%f, downTime=%lld, eventTime=%lld, "
"pointerCount=%d",
mChannel->getName().string(),
deviceId, source, action, edgeFlags, metaState, xOffset, yOffset,
deviceId, source, action, flags, edgeFlags, metaState, xOffset, yOffset,
xPrecision, yPrecision, downTime, eventTime, pointerCount);
#endif
@ -379,6 +380,7 @@ status_t InputPublisher::publishMotionEvent(
}
mSharedMessage->motion.action = action;
mSharedMessage->motion.flags = flags;
mSharedMessage->motion.edgeFlags = edgeFlags;
mSharedMessage->motion.metaState = metaState;
mSharedMessage->motion.xOffset = xOffset;
@ -664,6 +666,7 @@ void InputConsumer::populateMotionEvent(MotionEvent* motionEvent) const {
mSharedMessage->deviceId,
mSharedMessage->source,
mSharedMessage->motion.action,
mSharedMessage->motion.flags,
mSharedMessage->motion.edgeFlags,
mSharedMessage->motion.metaState,
mSharedMessage->motion.xOffset,

View File

@ -138,6 +138,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
const int32_t deviceId = 1;
const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
const int32_t action = AMOTION_EVENT_ACTION_MOVE;
const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
const float xOffset = -10;
@ -167,7 +168,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
}
}
status = mPublisher->publishMotionEvent(deviceId, source, action, edgeFlags,
status = mPublisher->publishMotionEvent(deviceId, source, action, flags, edgeFlags,
metaState, xOffset, yOffset, xPrecision, yPrecision,
downTime, sampleEventTimes[0], pointerCount, pointerIds, samplePointerCoords.array());
ASSERT_EQ(OK, status)
@ -213,6 +214,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
EXPECT_EQ(deviceId, motionEvent->getDeviceId());
EXPECT_EQ(source, motionEvent->getSource());
EXPECT_EQ(action, motionEvent->getAction());
EXPECT_EQ(flags, motionEvent->getFlags());
EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags());
EXPECT_EQ(metaState, motionEvent->getMetaState());
EXPECT_EQ(xPrecision, motionEvent->getXPrecision());
@ -322,12 +324,12 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenNotReset_ReturnsErr
int32_t pointerIds[pointerCount] = { 0 };
PointerCoords pointerCoords[pointerCount] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(OK, status)
<< "publisher publishMotionEvent should return OK";
status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(INVALID_OPERATION, status)
<< "publisher publishMotionEvent should return INVALID_OPERATION because ";
@ -342,7 +344,7 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountLessTha
int32_t pointerIds[pointerCount];
PointerCoords pointerCoords[pointerCount];
status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
@ -356,7 +358,7 @@ TEST_F(InputPublisherAndConsumerTest, PublishMotionEvent_WhenPointerCountGreater
int32_t pointerIds[pointerCount];
PointerCoords pointerCoords[pointerCount];
status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
status = mPublisher->publishMotionEvent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
@ -402,7 +404,7 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenPublishedMotionEven
PointerCoords pointerCoords[pointerCount];
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_DOWN,
0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(OK, status);
status = mPublisher->appendMotionSample(0, pointerCoords);
@ -419,7 +421,7 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenAlreadyConsumed_Ret
PointerCoords pointerCoords[pointerCount];
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(OK, status);
status = mPublisher->sendDispatchSignal();
@ -446,7 +448,7 @@ TEST_F(InputPublisherAndConsumerTest, AppendMotionSample_WhenBufferFull_ReturnsE
PointerCoords pointerCoords[pointerCount];
status = mPublisher->publishMotionEvent(0, 0, AMOTION_EVENT_ACTION_MOVE,
0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
0, 0, 0, 0, 0, 0, 0, 0, 0, pointerCount, pointerIds, pointerCoords);
ASSERT_EQ(OK, status);
for (int count = 1;; count++) {