Add new MotionEvent flag for partially obscured windows.

Due to more complex window layouts resulting in lots of overlapping
windows, the policy around FLAG_WINDOW_IS_OBSCURED has changed to
only be set when the point at which the window was touched is
obscured. Unfortunately, this doesn't prevent tapjacking attacks that
overlay the dialog's text, making a potentially dangerous operation
seem innocuous. To avoid this on particularly sensitive dialogs,
introduce a new flag that really does tell you when your window is
being even partially overlapped.

We aren't exposing this as API since we plan on making the original
flag more robust. This is really a workaround for system dialogs
since we generally know their layout and screen position, and that
they're unlikely to be overlapped by other applications.

Bug: 26677796
Change-Id: I9e336afe90f262ba22015876769a9c510048fd47

bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry,
 int32_t action, int32_t flags) {
 int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
 switch (actionMasked) {
 case AMOTION_EVENT_ACTION_UP:
 case AMOTION_EVENT_ACTION_CANCEL: {
 ssize_t index = findMotionMemento(entry, false /*hovering*/);
 if (index >= 0) {
            mMotionMementos.removeAt(index);
 return true;
 }
#if DEBUG_OUTBOUND_EVENT_DETAILS
        ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
 "actionMasked=%d",
                entry->deviceId, entry->source, actionMasked);
#endif
 return false;
 }

 case AMOTION_EVENT_ACTION_DOWN: {
 ssize_t index = findMotionMemento(entry, false /*hovering*/);
 if (index >= 0) {
            mMotionMementos.removeAt(index);
 }
        addMotionMemento(entry, flags, false /*hovering*/);
 return true;
 }

 case AMOTION_EVENT_ACTION_POINTER_UP:
 case AMOTION_EVENT_ACTION_POINTER_DOWN:
 case AMOTION_EVENT_ACTION_MOVE: {
 if (entry->source & AINPUT_SOURCE_CLASS_NAVIGATION) {
 return true;
 }

 ssize_t index = findMotionMemento(entry, false /*hovering*/);

 if (entry->source & AINPUT_SOURCE_CLASS_JOYSTICK) {
 if (index >= 0) {
 if (entry->pointerCoords[0].isEmpty()) {
                    mMotionMementos.removeAt(index);
 } else {
 MotionMemento& memento = mMotionMementos.editItemAt(index);
                    memento.setPointers(entry);
 }
 } else if (!entry->pointerCoords[0].isEmpty()) {
                addMotionMemento(entry, flags, false /*hovering*/);
 }

 return true;
 }
 if (index >= 0) {
 MotionMemento& memento = mMotionMementos.editItemAt(index);
            memento.setPointers(entry);
 return true;
 }
#if DEBUG_OUTBOUND_EVENT_DETAILS
        ALOGD("Dropping inconsistent motion pointer up/down or move event: "
 "deviceId=%d, source=%08x, actionMasked=%d",
                entry->deviceId, entry->source, actionMasked);
#endif
 return false;
 }

 case AMOTION_EVENT_ACTION_HOVER_EXIT: {
 ssize_t index = findMotionMemento(entry, true /*hovering*/);
 if (index >= 0) {
            mMotionMementos.removeAt(index);
 return true;
 }
#if DEBUG_OUTBOUND_EVENT_DETAILS
        ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x",
                entry->deviceId, entry->source);
#endif
 return false;
 }

 case AMOTION_EVENT_ACTION_HOVER_ENTER:
 case AMOTION_EVENT_ACTION_HOVER_MOVE: {
 ssize_t index = findMotionMemento(entry, true /*hovering*/);
 if (index >= 0) {
            mMotionMementos.removeAt(index);
 }
        addMotionMemento(entry, flags, true /*hovering*/);
 return true;
 }

 default:
 return true;
 }
}

bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry,
 int32_t action, int32_t flags) {
 int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
 switch (actionMasked) {
 case AMOTION_EVENT_ACTION_UP:
 case AMOTION_EVENT_ACTION_CANCEL: {
 ssize_t index = findMotionMemento(entry, false /*hovering*/);
 if (index >= 0) {
            mMotionMementos.removeAt(index);
 return true;
 }
#if DEBUG_OUTBOUND_EVENT_DETAILS
        ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
 "actionMasked=%d",
                entry->deviceId, entry->source, actionMasked);
#endif
 return false;
 }

 case AMOTION_EVENT_ACTION_DOWN: {
 ssize_t index = findMotionMemento(entry, false /*hovering*/);
 if (index >= 0) {
            mMotionMementos.removeAt(index);
 }
        addMotionMemento(entry, flags, false /*hovering*/);
 return true;
 }

 case AMOTION_EVENT_ACTION_POINTER_UP:
 case AMOTION_EVENT_ACTION_POINTER_DOWN:
 case AMOTION_EVENT_ACTION_MOVE: {
 if (entry->source & AINPUT_SOURCE_CLASS_NAVIGATION) {
 return true;
 }

 ssize_t index = findMotionMemento(entry, false /*hovering*/);

 if (entry->source & AINPUT_SOURCE_CLASS_JOYSTICK) {
 if (index >= 0) {
 if (entry->pointerCoords[0].isEmpty()) {
                    mMotionMementos.removeAt(index);
 } else {
 MotionMemento& memento = mMotionMementos.editItemAt(index);
                    memento.setPointers(entry);
 }
 } else if (!entry->pointerCoords[0].isEmpty()) {
                addMotionMemento(entry, flags, false /*hovering*/);
 }

 return true;
 }
 if (index >= 0) {
 MotionMemento& memento = mMotionMementos.editItemAt(index);
            memento.setPointers(entry);
 return true;
 }
#if DEBUG_OUTBOUND_EVENT_DETAILS
        ALOGD("Dropping inconsistent motion pointer up/down or move event: "
 "deviceId=%d, source=%08x, actionMasked=%d",
                entry->deviceId, entry->source, actionMasked);
#endif
 return false;
 }

 case AMOTION_EVENT_ACTION_HOVER_EXIT: {
 ssize_t index = findMotionMemento(entry, true /*hovering*/);
 if (index >= 0) {
            mMotionMementos.removeAt(index);
 return true;
 }
#if DEBUG_OUTBOUND_EVENT_DETAILS
        ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x",
                entry->deviceId, entry->source);
#endif
 return false;
 }

 case AMOTION_EVENT_ACTION_HOVER_ENTER:
 case AMOTION_EVENT_ACTION_HOVER_MOVE: {
 ssize_t index = findMotionMemento(entry, true /*hovering*/);
 if (index >= 0) {
            mMotionMementos.removeAt(index);
 }
        addMotionMemento(entry, flags, true /*hovering*/);
 return true;
 }

 default:
 return true;
 }
}
