121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown/* 221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Copyright (C) 2010 The Android Open Source Project 321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * 421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * you may not use this file except in compliance with the License. 621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * You may obtain a copy of the License at 721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * 821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * 1021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Unless required by applicable law or agreed to in writing, software 1121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 1221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * See the License for the specific language governing permissions and 1421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * limitations under the License. 1521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown */ 1621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 1721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brownpackage android.view; 1821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 1921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brownimport android.os.Build; 2021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brownimport android.util.Log; 2121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 2221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown/** 2321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Checks whether a sequence of input events is self-consistent. 2421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Logs a description of each problem detected. 2521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * <p> 2621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * When a problem is detected, the event is tainted. This mechanism prevents the same 2721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * error from being reported multiple times. 2821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * </p> 2921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * 3021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @hide 3121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown */ 3221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brownpublic final class InputEventConsistencyVerifier { 3321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private static final boolean IS_ENG_BUILD = "eng".equals(Build.TYPE); 3421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 35738e7e431c71777100726f6c870e47c354db1337Jeff Brown private static final String EVENT_TYPE_KEY = "KeyEvent"; 36738e7e431c71777100726f6c870e47c354db1337Jeff Brown private static final String EVENT_TYPE_TRACKBALL = "TrackballEvent"; 37738e7e431c71777100726f6c870e47c354db1337Jeff Brown private static final String EVENT_TYPE_TOUCH = "TouchEvent"; 38738e7e431c71777100726f6c870e47c354db1337Jeff Brown private static final String EVENT_TYPE_GENERIC_MOTION = "GenericMotionEvent"; 39738e7e431c71777100726f6c870e47c354db1337Jeff Brown 4021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // The number of recent events to log when a problem is detected. 4121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // Can be set to 0 to disable logging recent events but the runtime overhead of 4221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // this feature is negligible on current hardware. 4321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private static final int RECENT_EVENTS_TO_LOG = 5; 4421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 4521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // The object to which the verifier is attached. 4621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private final Object mCaller; 4721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 4821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // Consistency verifier flags. 4921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private final int mFlags; 5021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 51736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov // Tag for logging which a client can set to help distinguish the output 52736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov // from different verifiers since several can be active at the same time. 53736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov // If not provided defaults to the simple class name. 54736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov private final String mLogTag; 55736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov 5621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // The most recently checked event and the nesting level at which it was checked. 5721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // This is only set when the verifier is called from a nesting level greater than 0 5821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // so that the verifier can detect when it has been asked to verify the same event twice. 5921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // It does not make sense to examine the contents of the last event since it may have 6021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // been recycled. 6132cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown private int mLastEventSeq; 62738e7e431c71777100726f6c870e47c354db1337Jeff Brown private String mLastEventType; 6321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private int mLastNestingLevel; 6421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 6521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // Copy of the most recent events. 6621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private InputEvent[] mRecentEvents; 67bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown private boolean[] mRecentEventsUnhandled; 6821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private int mMostRecentEventIndex; 6921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 7021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // Current event and its type. 7121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private InputEvent mCurrentEvent; 7221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private String mCurrentEventType; 7321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 7421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // Linked list of key state objects. 7521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private KeyState mKeyStateList; 7621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 7721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // Current state of the trackball. 7821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private boolean mTrackballDown; 79bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown private boolean mTrackballUnhandled; 8021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 8121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // Bitfield of pointer ids that are currently down. 8221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // Assumes that the largest possible pointer id is 31, which is potentially subject to change. 8321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // (See MAX_POINTER_ID in frameworks/base/include/ui/Input.h) 8421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private int mTouchEventStreamPointers; 8521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 8621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // The device id and source of the current stream of touch events. 8721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private int mTouchEventStreamDeviceId = -1; 8821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private int mTouchEventStreamSource; 8921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 9021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // Set to true when we discover that the touch event stream is inconsistent. 9121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // Reset on down or cancel. 9221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private boolean mTouchEventStreamIsTainted; 9321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 94bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown // Set to true if the touch event stream is partially unhandled. 95bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown private boolean mTouchEventStreamUnhandled; 96bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown 9721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // Set to true if we received hover enter. 9821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private boolean mHoverEntered; 9921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 1005bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright // The bitset of buttons which we've received ACTION_BUTTON_PRESS for. 1015bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright private int mButtonsPressed; 1025bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright 10321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // The current violation message. 10421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private StringBuilder mViolationMessage; 10521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 10621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown /** 10721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Indicates that the verifier is intended to act on raw device input event streams. 10821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Disables certain checks for invariants that are established by the input dispatcher 10921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * itself as it delivers input events, such as key repeating behavior. 11021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown */ 11121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public static final int FLAG_RAW_DEVICE_INPUT = 1 << 0; 11221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 11321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown /** 11421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Creates an input consistency verifier. 11521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @param caller The object to which the verifier is attached. 11621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @param flags Flags to the verifier, or 0 if none. 11721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown */ 11821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public InputEventConsistencyVerifier(Object caller, int flags) { 119957d620267045521603051a2816d5c538ba8d0a7Michael Wright this(caller, flags, null); 120736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov } 121736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov 122736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov /** 123736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov * Creates an input consistency verifier. 124736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov * @param caller The object to which the verifier is attached. 125736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov * @param flags Flags to the verifier, or 0 if none. 126736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov * @param logTag Tag for logging. If null defaults to the short class name. 127736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov */ 128736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov public InputEventConsistencyVerifier(Object caller, int flags, String logTag) { 12921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown this.mCaller = caller; 13021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown this.mFlags = flags; 131736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov this.mLogTag = (logTag != null) ? logTag : "InputEventConsistencyVerifier"; 13221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 13321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 13421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown /** 13521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Determines whether the instrumentation should be enabled. 13621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @return True if it should be enabled. 13721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown */ 13821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public static boolean isInstrumentationEnabled() { 13921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown return IS_ENG_BUILD; 14021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 14121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 14221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown /** 14321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Resets the state of the input event consistency verifier. 14421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown */ 14521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public void reset() { 14632cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown mLastEventSeq = -1; 14721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mLastNestingLevel = 0; 14821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTrackballDown = false; 149bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown mTrackballUnhandled = false; 15021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamPointers = 0; 15121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamIsTainted = false; 152bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown mTouchEventStreamUnhandled = false; 15321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mHoverEntered = false; 1545bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright mButtonsPressed = 0; 155bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown 156bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown while (mKeyStateList != null) { 157bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown final KeyState state = mKeyStateList; 158bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown mKeyStateList = state.next; 159bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown state.recycle(); 160bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } 16121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 16221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 16321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown /** 16421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Checks an arbitrary input event. 16521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @param event The event. 16621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @param nestingLevel The nesting level: 0 if called from the base class, 16721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * or 1 from a subclass. If the event was already checked by this consistency verifier 16821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * at a higher nesting level, it will not be checked again. Used to handle the situation 16921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * where a subclass dispatching method delegates to its superclass's dispatching method 17021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * and both dispatching methods call into the consistency verifier. 17121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown */ 17221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public void onInputEvent(InputEvent event, int nestingLevel) { 17321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (event instanceof KeyEvent) { 17421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final KeyEvent keyEvent = (KeyEvent)event; 17521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown onKeyEvent(keyEvent, nestingLevel); 17621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 17721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final MotionEvent motionEvent = (MotionEvent)event; 17821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (motionEvent.isTouchEvent()) { 17921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown onTouchEvent(motionEvent, nestingLevel); 18021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else if ((motionEvent.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) { 18121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown onTrackballEvent(motionEvent, nestingLevel); 18221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 18321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown onGenericMotionEvent(motionEvent, nestingLevel); 18421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 18521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 18621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 18721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 18821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown /** 18921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Checks a key event. 19021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @param event The event. 19121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @param nestingLevel The nesting level: 0 if called from the base class, 19221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * or 1 from a subclass. If the event was already checked by this consistency verifier 19321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * at a higher nesting level, it will not be checked again. Used to handle the situation 19421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * where a subclass dispatching method delegates to its superclass's dispatching method 19521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * and both dispatching methods call into the consistency verifier. 19621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown */ 19721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public void onKeyEvent(KeyEvent event, int nestingLevel) { 198738e7e431c71777100726f6c870e47c354db1337Jeff Brown if (!startEvent(event, nestingLevel, EVENT_TYPE_KEY)) { 19921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown return; 20021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 20121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 20221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown try { 20321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensureMetaStateIsNormalized(event.getMetaState()); 20421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 20521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int action = event.getAction(); 20621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int deviceId = event.getDeviceId(); 20721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int source = event.getSource(); 20821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int keyCode = event.getKeyCode(); 20921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown switch (action) { 21021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case KeyEvent.ACTION_DOWN: { 21121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown KeyState state = findKeyState(deviceId, source, keyCode, /*remove*/ false); 21221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (state != null) { 21321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // If the key is already down, ensure it is a repeat. 21421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // We don't perform this check when processing raw device input 21521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // because the input dispatcher itself is responsible for setting 21621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // the key repeat count before it delivers input events. 217bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown if (state.unhandled) { 218bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown state.unhandled = false; 219bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } else if ((mFlags & FLAG_RAW_DEVICE_INPUT) == 0 22021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown && event.getRepeatCount() == 0) { 22121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("ACTION_DOWN but key is already down and this event " 22221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + "is not a key repeat."); 22321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 22421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 22521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown addKeyState(deviceId, source, keyCode); 22621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 22721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 22821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 22921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case KeyEvent.ACTION_UP: { 23021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown KeyState state = findKeyState(deviceId, source, keyCode, /*remove*/ true); 23121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (state == null) { 23221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("ACTION_UP but key was not down."); 23321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 23421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown state.recycle(); 23521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 23621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 23721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 23821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case KeyEvent.ACTION_MULTIPLE: 23921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 24021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown default: 24121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("Invalid action " + KeyEvent.actionToString(action) 24221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + " for key event."); 24321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 24421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 24521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } finally { 2468134681b25dfff814ffeaad8ff70e84316c1869fJeff Brown finishEvent(); 24721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 24821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 24921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 25021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown /** 25121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Checks a trackball event. 25221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @param event The event. 25321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @param nestingLevel The nesting level: 0 if called from the base class, 25421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * or 1 from a subclass. If the event was already checked by this consistency verifier 25521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * at a higher nesting level, it will not be checked again. Used to handle the situation 25621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * where a subclass dispatching method delegates to its superclass's dispatching method 25721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * and both dispatching methods call into the consistency verifier. 25821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown */ 25921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public void onTrackballEvent(MotionEvent event, int nestingLevel) { 260738e7e431c71777100726f6c870e47c354db1337Jeff Brown if (!startEvent(event, nestingLevel, EVENT_TYPE_TRACKBALL)) { 26121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown return; 26221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 26321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 26421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown try { 26521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensureMetaStateIsNormalized(event.getMetaState()); 26621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 26721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int action = event.getAction(); 26821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int source = event.getSource(); 26921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) { 27021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown switch (action) { 27121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case MotionEvent.ACTION_DOWN: 272bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown if (mTrackballDown && !mTrackballUnhandled) { 27321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("ACTION_DOWN but trackball is already down."); 27421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 27521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTrackballDown = true; 276bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown mTrackballUnhandled = false; 27721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 27821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensureHistorySizeIsZeroForThisAction(event); 27921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensurePointerCountIsOneForThisAction(event); 28021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 28121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case MotionEvent.ACTION_UP: 28221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (!mTrackballDown) { 28321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("ACTION_UP but trackball is not down."); 28421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 28521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTrackballDown = false; 286bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown mTrackballUnhandled = false; 28721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 28821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensureHistorySizeIsZeroForThisAction(event); 28921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensurePointerCountIsOneForThisAction(event); 29021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 29121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case MotionEvent.ACTION_MOVE: 29221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensurePointerCountIsOneForThisAction(event); 29321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 29421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown default: 29521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("Invalid action " + MotionEvent.actionToString(action) 29621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + " for trackball event."); 29721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 29821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 29921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 30021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (mTrackballDown && event.getPressure() <= 0) { 30121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("Trackball is down but pressure is not greater than 0."); 30221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else if (!mTrackballDown && event.getPressure() != 0) { 30321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("Trackball is up but pressure is not equal to 0."); 30421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 30521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 30621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("Source was not SOURCE_CLASS_TRACKBALL."); 30721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 30821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } finally { 3098134681b25dfff814ffeaad8ff70e84316c1869fJeff Brown finishEvent(); 31021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 31121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 31221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 31321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown /** 31421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Checks a touch event. 31521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @param event The event. 31621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @param nestingLevel The nesting level: 0 if called from the base class, 31721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * or 1 from a subclass. If the event was already checked by this consistency verifier 31821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * at a higher nesting level, it will not be checked again. Used to handle the situation 31921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * where a subclass dispatching method delegates to its superclass's dispatching method 32021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * and both dispatching methods call into the consistency verifier. 32121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown */ 32221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public void onTouchEvent(MotionEvent event, int nestingLevel) { 323738e7e431c71777100726f6c870e47c354db1337Jeff Brown if (!startEvent(event, nestingLevel, EVENT_TYPE_TOUCH)) { 32421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown return; 32521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 32621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 32721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int action = event.getAction(); 32821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final boolean newStream = action == MotionEvent.ACTION_DOWN 329b38070caa5143ab9fd1883e0c7c879533a480bc7Victoria Lease || action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_OUTSIDE; 330738e7e431c71777100726f6c870e47c354db1337Jeff Brown if (newStream && (mTouchEventStreamIsTainted || mTouchEventStreamUnhandled)) { 331738e7e431c71777100726f6c870e47c354db1337Jeff Brown mTouchEventStreamIsTainted = false; 332738e7e431c71777100726f6c870e47c354db1337Jeff Brown mTouchEventStreamUnhandled = false; 333738e7e431c71777100726f6c870e47c354db1337Jeff Brown mTouchEventStreamPointers = 0; 33421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 3358134681b25dfff814ffeaad8ff70e84316c1869fJeff Brown if (mTouchEventStreamIsTainted) { 3368134681b25dfff814ffeaad8ff70e84316c1869fJeff Brown event.setTainted(true); 3378134681b25dfff814ffeaad8ff70e84316c1869fJeff Brown } 33821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 33921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown try { 34021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensureMetaStateIsNormalized(event.getMetaState()); 34121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 34221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int deviceId = event.getDeviceId(); 34321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int source = event.getSource(); 34421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 34521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (!newStream && mTouchEventStreamDeviceId != -1 34621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown && (mTouchEventStreamDeviceId != deviceId 34721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown || mTouchEventStreamSource != source)) { 34821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("Touch event stream contains events from multiple sources: " 34921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + "previous device id " + mTouchEventStreamDeviceId 35021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + ", previous source " + Integer.toHexString(mTouchEventStreamSource) 35121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + ", new device id " + deviceId 35221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + ", new source " + Integer.toHexString(source)); 35321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 35421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamDeviceId = deviceId; 35521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamSource = source; 35621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 35721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int pointerCount = event.getPointerCount(); 35821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { 35921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown switch (action) { 36021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case MotionEvent.ACTION_DOWN: 36121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (mTouchEventStreamPointers != 0) { 36221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("ACTION_DOWN but pointers are already down. " 36321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + "Probably missing ACTION_UP from previous gesture."); 36421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 36521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensureHistorySizeIsZeroForThisAction(event); 36621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensurePointerCountIsOneForThisAction(event); 36721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamPointers = 1 << event.getPointerId(0); 36821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 36921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case MotionEvent.ACTION_UP: 37021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensureHistorySizeIsZeroForThisAction(event); 37121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensurePointerCountIsOneForThisAction(event); 37221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamPointers = 0; 37321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamIsTainted = false; 37421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 37521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case MotionEvent.ACTION_MOVE: { 37621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int expectedPointerCount = 37721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown Integer.bitCount(mTouchEventStreamPointers); 37821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (pointerCount != expectedPointerCount) { 37921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("ACTION_MOVE contained " + pointerCount 38021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + " pointers but there are currently " 38121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + expectedPointerCount + " pointers down."); 38221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamIsTainted = true; 38321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 38421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 38521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 38621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case MotionEvent.ACTION_CANCEL: 38721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamPointers = 0; 38821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamIsTainted = false; 38921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 39021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case MotionEvent.ACTION_OUTSIDE: 39121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (mTouchEventStreamPointers != 0) { 39221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("ACTION_OUTSIDE but pointers are still down."); 39321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 39421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensureHistorySizeIsZeroForThisAction(event); 39521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensurePointerCountIsOneForThisAction(event); 39621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamIsTainted = false; 39721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 39821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown default: { 39921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int actionMasked = event.getActionMasked(); 40021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int actionIndex = event.getActionIndex(); 40121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (actionMasked == MotionEvent.ACTION_POINTER_DOWN) { 40221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (mTouchEventStreamPointers == 0) { 40321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("ACTION_POINTER_DOWN but no other pointers were down."); 40421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamIsTainted = true; 40521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 40621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (actionIndex < 0 || actionIndex >= pointerCount) { 40721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("ACTION_POINTER_DOWN index is " + actionIndex 40821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + " but the pointer count is " + pointerCount + "."); 40921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamIsTainted = true; 41021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 41121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int id = event.getPointerId(actionIndex); 41221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int idBit = 1 << id; 41321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if ((mTouchEventStreamPointers & idBit) != 0) { 41421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("ACTION_POINTER_DOWN specified pointer id " + id 41521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + " which is already down."); 41621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamIsTainted = true; 41721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 41821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamPointers |= idBit; 41921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 42021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 42121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensureHistorySizeIsZeroForThisAction(event); 42221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else if (actionMasked == MotionEvent.ACTION_POINTER_UP) { 42321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (actionIndex < 0 || actionIndex >= pointerCount) { 42421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("ACTION_POINTER_UP index is " + actionIndex 42521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + " but the pointer count is " + pointerCount + "."); 42621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamIsTainted = true; 42721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 42821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int id = event.getPointerId(actionIndex); 42921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int idBit = 1 << id; 43021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if ((mTouchEventStreamPointers & idBit) == 0) { 43121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("ACTION_POINTER_UP specified pointer id " + id 43221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + " which is not currently down."); 43321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamIsTainted = true; 43421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 43521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mTouchEventStreamPointers &= ~idBit; 43621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 43721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 43821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensureHistorySizeIsZeroForThisAction(event); 43921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 44021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("Invalid action " + MotionEvent.actionToString(action) 44121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + " for touch event."); 44221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 44321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 44421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 44521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 44621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 44721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("Source was not SOURCE_CLASS_POINTER."); 44821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 44921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } finally { 4508134681b25dfff814ffeaad8ff70e84316c1869fJeff Brown finishEvent(); 45121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 45221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 45321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 45421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown /** 45521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * Checks a generic motion event. 45621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @param event The event. 45721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * @param nestingLevel The nesting level: 0 if called from the base class, 45821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * or 1 from a subclass. If the event was already checked by this consistency verifier 45921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * at a higher nesting level, it will not be checked again. Used to handle the situation 46021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * where a subclass dispatching method delegates to its superclass's dispatching method 46121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown * and both dispatching methods call into the consistency verifier. 46221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown */ 46321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public void onGenericMotionEvent(MotionEvent event, int nestingLevel) { 464738e7e431c71777100726f6c870e47c354db1337Jeff Brown if (!startEvent(event, nestingLevel, EVENT_TYPE_GENERIC_MOTION)) { 46521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown return; 46621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 46721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 46821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown try { 46921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensureMetaStateIsNormalized(event.getMetaState()); 47021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 47121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int action = event.getAction(); 47221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int source = event.getSource(); 4735bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright final int buttonState = event.getButtonState(); 4745bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright final int actionButton = event.getActionButton(); 47521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { 47621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown switch (action) { 47721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case MotionEvent.ACTION_HOVER_ENTER: 47821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensurePointerCountIsOneForThisAction(event); 47921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mHoverEntered = true; 48021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 48121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case MotionEvent.ACTION_HOVER_MOVE: 48221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensurePointerCountIsOneForThisAction(event); 48321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 48421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case MotionEvent.ACTION_HOVER_EXIT: 48521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensurePointerCountIsOneForThisAction(event); 48621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (!mHoverEntered) { 48721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("ACTION_HOVER_EXIT without prior ACTION_HOVER_ENTER"); 48821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 48921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mHoverEntered = false; 49021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 49121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case MotionEvent.ACTION_SCROLL: 49221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensureHistorySizeIsZeroForThisAction(event); 49321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensurePointerCountIsOneForThisAction(event); 49421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 4955bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright case MotionEvent.ACTION_BUTTON_PRESS: 4965bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright ensureActionButtonIsNonZeroForThisAction(event); 4975bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright if ((mButtonsPressed & actionButton) != 0) { 4985bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright problem("Action button for ACTION_BUTTON_PRESS event is " + 4995bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright actionButton + ", but it has already been pressed and " + 5005bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright "has yet to be released."); 5015bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright } 5025bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright 5035bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright mButtonsPressed |= actionButton; 5045bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright // The system will automatically mirror the stylus buttons onto the button 5055bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright // state as the old set of generic buttons for apps targeting pre-M. If 5065bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright // it looks this has happened, go ahead and set the generic buttons as 5075bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright // pressed to prevent spurious errors. 5085bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright if (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY && 5095bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright (buttonState & MotionEvent.BUTTON_SECONDARY) != 0) { 5105bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright mButtonsPressed |= MotionEvent.BUTTON_SECONDARY; 5115bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright } else if (actionButton == MotionEvent.BUTTON_STYLUS_SECONDARY && 5125bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright (buttonState & MotionEvent.BUTTON_TERTIARY) != 0) { 5135bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright mButtonsPressed |= MotionEvent.BUTTON_TERTIARY; 5145bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright } 5155bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright 5165bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright if (mButtonsPressed != buttonState) { 5175bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright problem(String.format("Reported button state differs from " + 5185bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright "expected button state based on press and release events. " + 5195bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright "Is 0x%08x but expected 0x%08x.", 5205bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright buttonState, mButtonsPressed)); 5215bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright } 5225bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright break; 5235bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright case MotionEvent.ACTION_BUTTON_RELEASE: 5245bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright ensureActionButtonIsNonZeroForThisAction(event); 5255bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright if ((mButtonsPressed & actionButton) != actionButton) { 5265bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright problem("Action button for ACTION_BUTTON_RELEASE event is " + 5275bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright actionButton + ", but it was either never pressed or has " + 5285bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright "already been released."); 5295bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright } 5305bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright 5315bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright mButtonsPressed &= ~actionButton; 5325bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright // The system will automatically mirror the stylus buttons onto the button 5335bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright // state as the old set of generic buttons for apps targeting pre-M. If 5345bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright // it looks this has happened, go ahead and set the generic buttons as 5355bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright // released to prevent spurious errors. 5365bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright if (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY && 5375bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright (buttonState & MotionEvent.BUTTON_SECONDARY) == 0) { 5385bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright mButtonsPressed &= ~MotionEvent.BUTTON_SECONDARY; 5395bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright } else if (actionButton == MotionEvent.BUTTON_STYLUS_SECONDARY && 5405bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright (buttonState & MotionEvent.BUTTON_TERTIARY) == 0) { 5415bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright mButtonsPressed &= ~MotionEvent.BUTTON_TERTIARY; 5425bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright } 5435bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright 5445bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright if (mButtonsPressed != buttonState) { 5455bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright problem(String.format("Reported button state differs from " + 5465bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright "expected button state based on press and release events. " + 5475bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright "Is 0x%08x but expected 0x%08x.", 5485bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright buttonState, mButtonsPressed)); 5495bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright } 5505bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright break; 55121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown default: 55221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("Invalid action for generic pointer event."); 55321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 55421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 55521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else if ((source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) { 55621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown switch (action) { 55721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown case MotionEvent.ACTION_MOVE: 55821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown ensurePointerCountIsOneForThisAction(event); 55921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 56021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown default: 56121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("Invalid action for generic joystick event."); 56221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown break; 56321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 56421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 56521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } finally { 5668134681b25dfff814ffeaad8ff70e84316c1869fJeff Brown finishEvent(); 56721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 56821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 56921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 570bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown /** 571bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown * Notifies the verifier that a given event was unhandled and the rest of the 572bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown * trace for the event should be ignored. 573bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown * This method should only be called if the event was previously checked by 574bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown * the consistency verifier using {@link #onInputEvent} and other methods. 575bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown * @param event The event. 576bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown * @param nestingLevel The nesting level: 0 if called from the base class, 577bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown * or 1 from a subclass. If the event was already checked by this consistency verifier 578bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown * at a higher nesting level, it will not be checked again. Used to handle the situation 579bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown * where a subclass dispatching method delegates to its superclass's dispatching method 580bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown * and both dispatching methods call into the consistency verifier. 581bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown */ 582bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown public void onUnhandledEvent(InputEvent event, int nestingLevel) { 583bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown if (nestingLevel != mLastNestingLevel) { 584bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown return; 585bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } 586bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown 587bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown if (mRecentEventsUnhandled != null) { 588bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown mRecentEventsUnhandled[mMostRecentEventIndex] = true; 589bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } 590bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown 591bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown if (event instanceof KeyEvent) { 592bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown final KeyEvent keyEvent = (KeyEvent)event; 593bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown final int deviceId = keyEvent.getDeviceId(); 594bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown final int source = keyEvent.getSource(); 595bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown final int keyCode = keyEvent.getKeyCode(); 596bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown final KeyState state = findKeyState(deviceId, source, keyCode, /*remove*/ false); 597bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown if (state != null) { 598bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown state.unhandled = true; 599bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } 600bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } else { 601bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown final MotionEvent motionEvent = (MotionEvent)event; 602bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown if (motionEvent.isTouchEvent()) { 603bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown mTouchEventStreamUnhandled = true; 604bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } else if ((motionEvent.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) { 605bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown if (mTrackballDown) { 606bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown mTrackballUnhandled = true; 607bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } 608bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } 609bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } 610bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } 611bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown 61221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private void ensureMetaStateIsNormalized(int metaState) { 61321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int normalizedMetaState = KeyEvent.normalizeMetaState(metaState); 61421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (normalizedMetaState != metaState) { 61521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem(String.format("Metastate not normalized. Was 0x%08x but expected 0x%08x.", 61621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown metaState, normalizedMetaState)); 61721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 61821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 61921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 62021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private void ensurePointerCountIsOneForThisAction(MotionEvent event) { 62121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int pointerCount = event.getPointerCount(); 62221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (pointerCount != 1) { 62321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("Pointer count is " + pointerCount + " but it should always be 1 for " 62421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + MotionEvent.actionToString(event.getAction())); 62521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 62621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 62721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 6285bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright private void ensureActionButtonIsNonZeroForThisAction(MotionEvent event) { 6295bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright final int actionButton = event.getActionButton(); 6305bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright if (actionButton == 0) { 6315bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright problem("No action button set. Action button should always be non-zero for " + 6325bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright MotionEvent.actionToString(event.getAction())); 6335bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright 6345bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright } 6355bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright } 6365bd69e6e6164c59a0423edd0d5243fc8c07e6af3Michael Wright 63721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private void ensureHistorySizeIsZeroForThisAction(MotionEvent event) { 63821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int historySize = event.getHistorySize(); 63921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (historySize != 0) { 64021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown problem("History size is " + historySize + " but it should always be 0 for " 64121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown + MotionEvent.actionToString(event.getAction())); 64221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 64321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 64421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 64521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private boolean startEvent(InputEvent event, int nestingLevel, String eventType) { 64621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown // Ignore the event if we already checked it at a higher nesting level. 64732cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown final int seq = event.getSequenceNumber(); 64832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown if (seq == mLastEventSeq && nestingLevel < mLastNestingLevel 649738e7e431c71777100726f6c870e47c354db1337Jeff Brown && eventType == mLastEventType) { 65021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown return false; 65121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 65221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 65321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (nestingLevel > 0) { 65432cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown mLastEventSeq = seq; 655738e7e431c71777100726f6c870e47c354db1337Jeff Brown mLastEventType = eventType; 65621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mLastNestingLevel = nestingLevel; 65721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 65832cbc3855c2a971aa5a801fd339fb6a37db91a1aJeff Brown mLastEventSeq = -1; 659738e7e431c71777100726f6c870e47c354db1337Jeff Brown mLastEventType = null; 66021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mLastNestingLevel = 0; 66121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 66221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 66321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mCurrentEvent = event; 66421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mCurrentEventType = eventType; 66521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown return true; 66621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 66721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 6688134681b25dfff814ffeaad8ff70e84316c1869fJeff Brown private void finishEvent() { 66921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (mViolationMessage != null && mViolationMessage.length() != 0) { 6708134681b25dfff814ffeaad8ff70e84316c1869fJeff Brown if (!mCurrentEvent.isTainted()) { 671738e7e431c71777100726f6c870e47c354db1337Jeff Brown // Write a log message only if the event was not already tainted. 672738e7e431c71777100726f6c870e47c354db1337Jeff Brown mViolationMessage.append("\n in ").append(mCaller); 673738e7e431c71777100726f6c870e47c354db1337Jeff Brown mViolationMessage.append("\n "); 674738e7e431c71777100726f6c870e47c354db1337Jeff Brown appendEvent(mViolationMessage, 0, mCurrentEvent, false); 675738e7e431c71777100726f6c870e47c354db1337Jeff Brown 676738e7e431c71777100726f6c870e47c354db1337Jeff Brown if (RECENT_EVENTS_TO_LOG != 0 && mRecentEvents != null) { 677738e7e431c71777100726f6c870e47c354db1337Jeff Brown mViolationMessage.append("\n -- recent events --"); 678738e7e431c71777100726f6c870e47c354db1337Jeff Brown for (int i = 0; i < RECENT_EVENTS_TO_LOG; i++) { 679738e7e431c71777100726f6c870e47c354db1337Jeff Brown final int index = (mMostRecentEventIndex + RECENT_EVENTS_TO_LOG - i) 680738e7e431c71777100726f6c870e47c354db1337Jeff Brown % RECENT_EVENTS_TO_LOG; 681738e7e431c71777100726f6c870e47c354db1337Jeff Brown final InputEvent event = mRecentEvents[index]; 682738e7e431c71777100726f6c870e47c354db1337Jeff Brown if (event == null) { 683738e7e431c71777100726f6c870e47c354db1337Jeff Brown break; 684738e7e431c71777100726f6c870e47c354db1337Jeff Brown } 685738e7e431c71777100726f6c870e47c354db1337Jeff Brown mViolationMessage.append("\n "); 686738e7e431c71777100726f6c870e47c354db1337Jeff Brown appendEvent(mViolationMessage, i + 1, event, mRecentEventsUnhandled[index]); 68721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 68821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 68921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 690738e7e431c71777100726f6c870e47c354db1337Jeff Brown Log.d(mLogTag, mViolationMessage.toString()); 6918134681b25dfff814ffeaad8ff70e84316c1869fJeff Brown 6928134681b25dfff814ffeaad8ff70e84316c1869fJeff Brown // Taint the event so that we do not generate additional violations from it 6938134681b25dfff814ffeaad8ff70e84316c1869fJeff Brown // further downstream. 6948134681b25dfff814ffeaad8ff70e84316c1869fJeff Brown mCurrentEvent.setTainted(true); 695738e7e431c71777100726f6c870e47c354db1337Jeff Brown } 69621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mViolationMessage.setLength(0); 69721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 69821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 69921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (RECENT_EVENTS_TO_LOG != 0) { 70021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (mRecentEvents == null) { 70121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mRecentEvents = new InputEvent[RECENT_EVENTS_TO_LOG]; 702bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown mRecentEventsUnhandled = new boolean[RECENT_EVENTS_TO_LOG]; 70321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 70421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown final int index = (mMostRecentEventIndex + 1) % RECENT_EVENTS_TO_LOG; 70521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mMostRecentEventIndex = index; 70621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (mRecentEvents[index] != null) { 70721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mRecentEvents[index].recycle(); 70821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 70921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mRecentEvents[index] = mCurrentEvent.copy(); 710bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown mRecentEventsUnhandled[index] = false; 71121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 71221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 71321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mCurrentEvent = null; 71421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mCurrentEventType = null; 71521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 71621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 717bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown private static void appendEvent(StringBuilder message, int index, 718bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown InputEvent event, boolean unhandled) { 719bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown message.append(index).append(": sent at ").append(event.getEventTimeNano()); 720bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown message.append(", "); 721bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown if (unhandled) { 722bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown message.append("(unhandled) "); 723bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } 724bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown message.append(event); 725bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown } 726bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown 72721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private void problem(String message) { 72821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (mViolationMessage == null) { 72921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mViolationMessage = new StringBuilder(); 73021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 73121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (mViolationMessage.length() == 0) { 73221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mViolationMessage.append(mCurrentEventType).append(": "); 73321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 73421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mViolationMessage.append("\n "); 73521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 73621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mViolationMessage.append(message); 73721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 73821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 73921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private KeyState findKeyState(int deviceId, int source, int keyCode, boolean remove) { 74021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown KeyState last = null; 74121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown KeyState state = mKeyStateList; 74221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown while (state != null) { 74321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (state.deviceId == deviceId && state.source == source 74421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown && state.keyCode == keyCode) { 74521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (remove) { 74621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (last != null) { 74721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown last.next = state.next; 74821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 74921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mKeyStateList = state.next; 75021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 75121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown state.next = null; 75221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 75321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown return state; 75421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 75521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown last = state; 75621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown state = state.next; 75721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 75821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown return null; 75921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 76021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 76121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private void addKeyState(int deviceId, int source, int keyCode) { 76221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown KeyState state = KeyState.obtain(deviceId, source, keyCode); 76321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown state.next = mKeyStateList; 76421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mKeyStateList = state; 76521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 76621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 76721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private static final class KeyState { 76821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private static Object mRecycledListLock = new Object(); 76921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private static KeyState mRecycledList; 77021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 77121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public KeyState next; 77221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public int deviceId; 77321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public int source; 77421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public int keyCode; 775bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown public boolean unhandled; 77621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 77721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown private KeyState() { 77821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 77921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 78021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public static KeyState obtain(int deviceId, int source, int keyCode) { 78121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown KeyState state; 78221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown synchronized (mRecycledListLock) { 78321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown state = mRecycledList; 78421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown if (state != null) { 78521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mRecycledList = state.next; 78621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } else { 78721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown state = new KeyState(); 78821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 78921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 79021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown state.deviceId = deviceId; 79121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown state.source = source; 79221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown state.keyCode = keyCode; 793bbdc50b102faf52768ac3028bc49e027ff140656Jeff Brown state.unhandled = false; 79421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown return state; 79521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 79621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown 79721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown public void recycle() { 79821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown synchronized (mRecycledListLock) { 79921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown next = mRecycledList; 80021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown mRecycledList = next; 80121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 80221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 80321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown } 80421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown} 805