am 38f96e50: Add support for injecting events into ActivityContainers. (DO NOT MERGE)
* commit '38f96e5020b3e82b98fe97b0be363a5ad185860f': Add support for injecting events into ActivityContainers. (DO NOT MERGE)
This commit is contained in:
@@ -27,6 +27,9 @@ import android.os.RemoteException;
|
|||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.InputDevice;
|
||||||
|
import android.view.InputEvent;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.TextureView;
|
import android.view.TextureView;
|
||||||
import android.view.TextureView.SurfaceTextureListener;
|
import android.view.TextureView.SurfaceTextureListener;
|
||||||
@@ -112,6 +115,29 @@ public class ActivityView extends ViewGroup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean injectInputEvent(InputEvent event) {
|
||||||
|
try {
|
||||||
|
return mActivityContainer != null && mActivityContainer.injectEvent(event);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
return injectInputEvent(event) || super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onGenericMotionEvent(MotionEvent event) {
|
||||||
|
if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
|
||||||
|
if (injectInputEvent(event)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onGenericMotionEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isAttachedToDisplay() {
|
public boolean isAttachedToDisplay() {
|
||||||
return mSurface != null;
|
return mSurface != null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import android.app.IActivityContainerCallback;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IIntentSender;
|
import android.content.IIntentSender;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.view.InputEvent;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
@@ -30,4 +31,5 @@ interface IActivityContainer {
|
|||||||
int startActivity(in Intent intent);
|
int startActivity(in Intent intent);
|
||||||
int startActivityIntentSender(in IIntentSender intentSender);
|
int startActivityIntentSender(in IIntentSender intentSender);
|
||||||
int getDisplayId();
|
int getDisplayId();
|
||||||
|
boolean injectEvent(in InputEvent event);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package android.hardware.input;
|
package android.hardware.input;
|
||||||
|
|
||||||
import android.hardware.display.DisplayViewport;
|
import android.hardware.display.DisplayViewport;
|
||||||
|
import android.view.InputEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Input manager local system service interface.
|
* Input manager local system service interface.
|
||||||
@@ -30,4 +31,6 @@ public abstract class InputManagerInternal {
|
|||||||
*/
|
*/
|
||||||
public abstract void setDisplayViewports(DisplayViewport defaultViewport,
|
public abstract void setDisplayViewports(DisplayViewport defaultViewport,
|
||||||
DisplayViewport externalTouchViewport);
|
DisplayViewport externalTouchViewport);
|
||||||
|
|
||||||
|
public abstract boolean injectInputEvent(InputEvent event, int displayId, int mode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1020,7 +1020,14 @@ void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout
|
|||||||
sp<InputWindowHandle> windowHandle = connection->inputWindowHandle;
|
sp<InputWindowHandle> windowHandle = connection->inputWindowHandle;
|
||||||
|
|
||||||
if (windowHandle != NULL) {
|
if (windowHandle != NULL) {
|
||||||
mTouchState.removeWindow(windowHandle);
|
const InputWindowInfo* info = windowHandle->getInfo();
|
||||||
|
if (info) {
|
||||||
|
ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(info->displayId);
|
||||||
|
if (stateIndex >= 0) {
|
||||||
|
mTouchStatesByDisplay.editValueAt(stateIndex).removeWindow(
|
||||||
|
windowHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection->status == Connection::STATUS_NORMAL) {
|
if (connection->status == Connection::STATUS_NORMAL) {
|
||||||
@@ -1161,11 +1168,21 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
|
|||||||
InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
|
InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
|
||||||
sp<InputWindowHandle> newHoverWindowHandle;
|
sp<InputWindowHandle> newHoverWindowHandle;
|
||||||
|
|
||||||
bool isSplit = mTouchState.split;
|
// Copy current touch state into mTempTouchState.
|
||||||
bool switchedDevice = mTouchState.deviceId >= 0 && mTouchState.displayId >= 0
|
// This state is always reset at the end of this function, so if we don't find state
|
||||||
&& (mTouchState.deviceId != entry->deviceId
|
// for the specified display then our initial state will be empty.
|
||||||
|| mTouchState.source != entry->source
|
const TouchState* oldState = NULL;
|
||||||
|| mTouchState.displayId != displayId);
|
ssize_t oldStateIndex = mTouchStatesByDisplay.indexOfKey(displayId);
|
||||||
|
if (oldStateIndex >= 0) {
|
||||||
|
oldState = &mTouchStatesByDisplay.valueAt(oldStateIndex);
|
||||||
|
mTempTouchState.copyFrom(*oldState);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSplit = mTempTouchState.split;
|
||||||
|
bool switchedDevice = mTempTouchState.deviceId >= 0 && mTempTouchState.displayId >= 0
|
||||||
|
&& (mTempTouchState.deviceId != entry->deviceId
|
||||||
|
|| mTempTouchState.source != entry->source
|
||||||
|
|| mTempTouchState.displayId != displayId);
|
||||||
bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
|
bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
|
||||||
|| maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
|
|| maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
|
||||||
|| maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
|
|| maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
|
||||||
@@ -1175,11 +1192,10 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
|
|||||||
bool wrongDevice = false;
|
bool wrongDevice = false;
|
||||||
if (newGesture) {
|
if (newGesture) {
|
||||||
bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
|
bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
|
||||||
if (switchedDevice && mTouchState.down && !down) {
|
if (switchedDevice && mTempTouchState.down && !down) {
|
||||||
#if DEBUG_FOCUS
|
#if DEBUG_FOCUS
|
||||||
ALOGD("Dropping event because a pointer for a different device is already down.");
|
ALOGD("Dropping event because a pointer for a different device is already down.");
|
||||||
#endif
|
#endif
|
||||||
mTempTouchState.copyFrom(mTouchState);
|
|
||||||
injectionResult = INPUT_EVENT_INJECTION_FAILED;
|
injectionResult = INPUT_EVENT_INJECTION_FAILED;
|
||||||
switchedDevice = false;
|
switchedDevice = false;
|
||||||
wrongDevice = true;
|
wrongDevice = true;
|
||||||
@@ -1191,8 +1207,6 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
|
|||||||
mTempTouchState.source = entry->source;
|
mTempTouchState.source = entry->source;
|
||||||
mTempTouchState.displayId = displayId;
|
mTempTouchState.displayId = displayId;
|
||||||
isSplit = false;
|
isSplit = false;
|
||||||
} else {
|
|
||||||
mTempTouchState.copyFrom(mTouchState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
|
if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
|
||||||
@@ -1515,32 +1529,31 @@ Failed:
|
|||||||
|
|
||||||
if (isHoverAction) {
|
if (isHoverAction) {
|
||||||
// Started hovering, therefore no longer down.
|
// Started hovering, therefore no longer down.
|
||||||
if (mTouchState.down) {
|
if (oldState && oldState->down) {
|
||||||
#if DEBUG_FOCUS
|
#if DEBUG_FOCUS
|
||||||
ALOGD("Conflicting pointer actions: Hover received while pointer was down.");
|
ALOGD("Conflicting pointer actions: Hover received while pointer was down.");
|
||||||
#endif
|
#endif
|
||||||
*outConflictingPointerActions = true;
|
*outConflictingPointerActions = true;
|
||||||
}
|
}
|
||||||
mTouchState.reset();
|
mTempTouchState.reset();
|
||||||
if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
|
if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
|
||||||
|| maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
|
|| maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
|
||||||
mTouchState.deviceId = entry->deviceId;
|
mTempTouchState.deviceId = entry->deviceId;
|
||||||
mTouchState.source = entry->source;
|
mTempTouchState.source = entry->source;
|
||||||
mTouchState.displayId = displayId;
|
mTempTouchState.displayId = displayId;
|
||||||
}
|
}
|
||||||
} else if (maskedAction == AMOTION_EVENT_ACTION_UP
|
} else if (maskedAction == AMOTION_EVENT_ACTION_UP
|
||||||
|| maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
|
|| maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
|
||||||
// All pointers up or canceled.
|
// All pointers up or canceled.
|
||||||
mTouchState.reset();
|
mTempTouchState.reset();
|
||||||
} else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
|
} else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
|
||||||
// First pointer went down.
|
// First pointer went down.
|
||||||
if (mTouchState.down) {
|
if (oldState && oldState->down) {
|
||||||
#if DEBUG_FOCUS
|
#if DEBUG_FOCUS
|
||||||
ALOGD("Conflicting pointer actions: Down received while already down.");
|
ALOGD("Conflicting pointer actions: Down received while already down.");
|
||||||
#endif
|
#endif
|
||||||
*outConflictingPointerActions = true;
|
*outConflictingPointerActions = true;
|
||||||
}
|
}
|
||||||
mTouchState.copyFrom(mTempTouchState);
|
|
||||||
} else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
|
} else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
|
||||||
// One pointer went up.
|
// One pointer went up.
|
||||||
if (isSplit) {
|
if (isSplit) {
|
||||||
@@ -1559,12 +1572,20 @@ Failed:
|
|||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mTouchState.copyFrom(mTempTouchState);
|
}
|
||||||
} else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
|
|
||||||
// Discard temporary touch state since it was only valid for this action.
|
// Save changes unless the action was scroll in which case the temporary touch
|
||||||
} else {
|
// state was only valid for this one action.
|
||||||
// Save changes to touch state as-is for all other actions.
|
if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) {
|
||||||
mTouchState.copyFrom(mTempTouchState);
|
if (mTempTouchState.displayId >= 0) {
|
||||||
|
if (oldStateIndex >= 0) {
|
||||||
|
mTouchStatesByDisplay.editValueAt(oldStateIndex).copyFrom(mTempTouchState);
|
||||||
|
} else {
|
||||||
|
mTouchStatesByDisplay.add(displayId, mTempTouchState);
|
||||||
|
}
|
||||||
|
} else if (oldStateIndex >= 0) {
|
||||||
|
mTouchStatesByDisplay.removeItemsAt(oldStateIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update hover state.
|
// Update hover state.
|
||||||
@@ -2316,7 +2337,7 @@ InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet
|
|||||||
originalMotionEntry->yPrecision,
|
originalMotionEntry->yPrecision,
|
||||||
originalMotionEntry->downTime,
|
originalMotionEntry->downTime,
|
||||||
originalMotionEntry->displayId,
|
originalMotionEntry->displayId,
|
||||||
splitPointerCount, splitPointerProperties, splitPointerCoords);
|
splitPointerCount, splitPointerProperties, splitPointerCoords, 0, 0);
|
||||||
|
|
||||||
if (originalMotionEntry->injectionState) {
|
if (originalMotionEntry->injectionState) {
|
||||||
splitMotionEntry->injectionState = originalMotionEntry->injectionState;
|
splitMotionEntry->injectionState = originalMotionEntry->injectionState;
|
||||||
@@ -2488,7 +2509,7 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
|
|||||||
args->action, args->flags, args->metaState, args->buttonState,
|
args->action, args->flags, args->metaState, args->buttonState,
|
||||||
args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
|
args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
|
||||||
args->displayId,
|
args->displayId,
|
||||||
args->pointerCount, args->pointerProperties, args->pointerCoords);
|
args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
|
||||||
|
|
||||||
needWake = enqueueInboundEventLocked(newEntry);
|
needWake = enqueueInboundEventLocked(newEntry);
|
||||||
mLock.unlock();
|
mLock.unlock();
|
||||||
@@ -2536,7 +2557,7 @@ void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
|
int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t displayId,
|
||||||
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
|
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
|
||||||
uint32_t policyFlags) {
|
uint32_t policyFlags) {
|
||||||
#if DEBUG_INBOUND_EVENT_DETAILS
|
#if DEBUG_INBOUND_EVENT_DETAILS
|
||||||
@@ -2587,7 +2608,6 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
|
|||||||
|
|
||||||
case AINPUT_EVENT_TYPE_MOTION: {
|
case AINPUT_EVENT_TYPE_MOTION: {
|
||||||
const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
|
const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
|
||||||
int32_t displayId = ADISPLAY_ID_DEFAULT;
|
|
||||||
int32_t action = motionEvent->getAction();
|
int32_t action = motionEvent->getAction();
|
||||||
size_t pointerCount = motionEvent->getPointerCount();
|
size_t pointerCount = motionEvent->getPointerCount();
|
||||||
const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
|
const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
|
||||||
@@ -2610,7 +2630,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
|
|||||||
motionEvent->getEdgeFlags(),
|
motionEvent->getEdgeFlags(),
|
||||||
motionEvent->getXPrecision(), motionEvent->getYPrecision(),
|
motionEvent->getXPrecision(), motionEvent->getYPrecision(),
|
||||||
motionEvent->getDownTime(), displayId,
|
motionEvent->getDownTime(), displayId,
|
||||||
uint32_t(pointerCount), pointerProperties, samplePointerCoords);
|
uint32_t(pointerCount), pointerProperties, samplePointerCoords,
|
||||||
|
motionEvent->getXOffset(), motionEvent->getYOffset());
|
||||||
lastInjectedEntry = firstInjectedEntry;
|
lastInjectedEntry = firstInjectedEntry;
|
||||||
for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
|
for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
|
||||||
sampleEventTimes += 1;
|
sampleEventTimes += 1;
|
||||||
@@ -2622,7 +2643,8 @@ int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
|
|||||||
motionEvent->getEdgeFlags(),
|
motionEvent->getEdgeFlags(),
|
||||||
motionEvent->getXPrecision(), motionEvent->getYPrecision(),
|
motionEvent->getXPrecision(), motionEvent->getYPrecision(),
|
||||||
motionEvent->getDownTime(), displayId,
|
motionEvent->getDownTime(), displayId,
|
||||||
uint32_t(pointerCount), pointerProperties, samplePointerCoords);
|
uint32_t(pointerCount), pointerProperties, samplePointerCoords,
|
||||||
|
motionEvent->getXOffset(), motionEvent->getYOffset());
|
||||||
lastInjectedEntry->next = nextInjectedEntry;
|
lastInjectedEntry->next = nextInjectedEntry;
|
||||||
lastInjectedEntry = nextInjectedEntry;
|
lastInjectedEntry = nextInjectedEntry;
|
||||||
}
|
}
|
||||||
@@ -2847,22 +2869,25 @@ void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inpu
|
|||||||
mFocusedWindowHandle = newFocusedWindowHandle;
|
mFocusedWindowHandle = newFocusedWindowHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < mTouchState.windows.size(); i++) {
|
for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
|
||||||
TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
|
TouchState& state = mTouchStatesByDisplay.editValueAt(d);
|
||||||
if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
|
for (size_t i = 0; i < state.windows.size(); i++) {
|
||||||
|
TouchedWindow& touchedWindow = state.windows.editItemAt(i);
|
||||||
|
if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
|
||||||
#if DEBUG_FOCUS
|
#if DEBUG_FOCUS
|
||||||
ALOGD("Touched window was removed: %s",
|
ALOGD("Touched window was removed: %s",
|
||||||
touchedWindow.windowHandle->getName().string());
|
touchedWindow.windowHandle->getName().string());
|
||||||
#endif
|
#endif
|
||||||
sp<InputChannel> touchedInputChannel =
|
sp<InputChannel> touchedInputChannel =
|
||||||
touchedWindow.windowHandle->getInputChannel();
|
touchedWindow.windowHandle->getInputChannel();
|
||||||
if (touchedInputChannel != NULL) {
|
if (touchedInputChannel != NULL) {
|
||||||
CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
|
CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
|
||||||
"touched window was removed");
|
"touched window was removed");
|
||||||
synthesizeCancelationEventsForInputChannelLocked(
|
synthesizeCancelationEventsForInputChannelLocked(
|
||||||
touchedInputChannel, options);
|
touchedInputChannel, options);
|
||||||
|
}
|
||||||
|
state.windows.removeAt(i--);
|
||||||
}
|
}
|
||||||
mTouchState.windows.removeAt(i--);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3003,23 +3028,27 @@ bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (size_t i = 0; i < mTouchState.windows.size(); i++) {
|
for (size_t d = 0; d < mTouchStatesByDisplay.size(); d++) {
|
||||||
const TouchedWindow& touchedWindow = mTouchState.windows[i];
|
TouchState& state = mTouchStatesByDisplay.editValueAt(d);
|
||||||
if (touchedWindow.windowHandle == fromWindowHandle) {
|
for (size_t i = 0; i < state.windows.size(); i++) {
|
||||||
int32_t oldTargetFlags = touchedWindow.targetFlags;
|
const TouchedWindow& touchedWindow = state.windows[i];
|
||||||
BitSet32 pointerIds = touchedWindow.pointerIds;
|
if (touchedWindow.windowHandle == fromWindowHandle) {
|
||||||
|
int32_t oldTargetFlags = touchedWindow.targetFlags;
|
||||||
|
BitSet32 pointerIds = touchedWindow.pointerIds;
|
||||||
|
|
||||||
mTouchState.windows.removeAt(i);
|
state.windows.removeAt(i);
|
||||||
|
|
||||||
int32_t newTargetFlags = oldTargetFlags
|
int32_t newTargetFlags = oldTargetFlags
|
||||||
& (InputTarget::FLAG_FOREGROUND
|
& (InputTarget::FLAG_FOREGROUND
|
||||||
| InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
|
| InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
|
||||||
mTouchState.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
|
state.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
|
||||||
|
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
goto Found;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Found:
|
||||||
|
|
||||||
if (! found) {
|
if (! found) {
|
||||||
#if DEBUG_FOCUS
|
#if DEBUG_FOCUS
|
||||||
@@ -3063,7 +3092,7 @@ void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
|
|||||||
drainInboundQueueLocked();
|
drainInboundQueueLocked();
|
||||||
resetANRTimeoutsLocked();
|
resetANRTimeoutsLocked();
|
||||||
|
|
||||||
mTouchState.reset();
|
mTouchStatesByDisplay.clear();
|
||||||
mLastHoverWindowHandle.clear();
|
mLastHoverWindowHandle.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3098,22 +3127,28 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
|
|||||||
dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
|
dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
|
||||||
mFocusedWindowHandle != NULL ? mFocusedWindowHandle->getName().string() : "<null>");
|
mFocusedWindowHandle != NULL ? mFocusedWindowHandle->getName().string() : "<null>");
|
||||||
|
|
||||||
dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
|
if (!mTouchStatesByDisplay.isEmpty()) {
|
||||||
dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
|
dump.appendFormat(INDENT "TouchStatesByDisplay:\n");
|
||||||
dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId);
|
for (size_t i = 0; i < mTouchStatesByDisplay.size(); i++) {
|
||||||
dump.appendFormat(INDENT "TouchSource: 0x%08x\n", mTouchState.source);
|
const TouchState& state = mTouchStatesByDisplay.valueAt(i);
|
||||||
dump.appendFormat(INDENT "TouchDisplayId: %d\n", mTouchState.displayId);
|
dump.appendFormat(INDENT2 "%d: down=%s, split=%s, deviceId=%d, source=0x%08x\n",
|
||||||
if (!mTouchState.windows.isEmpty()) {
|
state.displayId, toString(state.down), toString(state.split),
|
||||||
dump.append(INDENT "TouchedWindows:\n");
|
state.deviceId, state.source);
|
||||||
for (size_t i = 0; i < mTouchState.windows.size(); i++) {
|
if (!state.windows.isEmpty()) {
|
||||||
const TouchedWindow& touchedWindow = mTouchState.windows[i];
|
dump.append(INDENT3 "Windows:\n");
|
||||||
dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
|
for (size_t i = 0; i < state.windows.size(); i++) {
|
||||||
i, touchedWindow.windowHandle->getName().string(),
|
const TouchedWindow& touchedWindow = state.windows[i];
|
||||||
touchedWindow.pointerIds.value,
|
dump.appendFormat(INDENT4 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
|
||||||
touchedWindow.targetFlags);
|
i, touchedWindow.windowHandle->getName().string(),
|
||||||
|
touchedWindow.pointerIds.value,
|
||||||
|
touchedWindow.targetFlags);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dump.append(INDENT3 "Windows: <none>\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dump.append(INDENT "TouchedWindows: <none>\n");
|
dump.append(INDENT "TouchStates: <no displays touched>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mWindowHandles.isEmpty()) {
|
if (!mWindowHandles.isEmpty()) {
|
||||||
@@ -3898,7 +3933,8 @@ InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime,
|
|||||||
int32_t metaState, int32_t buttonState,
|
int32_t metaState, int32_t buttonState,
|
||||||
int32_t edgeFlags, float xPrecision, float yPrecision,
|
int32_t edgeFlags, float xPrecision, float yPrecision,
|
||||||
nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
|
nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
|
||||||
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) :
|
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
|
||||||
|
float xOffset, float yOffset) :
|
||||||
EventEntry(TYPE_MOTION, eventTime, policyFlags),
|
EventEntry(TYPE_MOTION, eventTime, policyFlags),
|
||||||
eventTime(eventTime),
|
eventTime(eventTime),
|
||||||
deviceId(deviceId), source(source), action(action), flags(flags),
|
deviceId(deviceId), source(source), action(action), flags(flags),
|
||||||
@@ -3908,6 +3944,9 @@ InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime,
|
|||||||
for (uint32_t i = 0; i < pointerCount; i++) {
|
for (uint32_t i = 0; i < pointerCount; i++) {
|
||||||
this->pointerProperties[i].copyFrom(pointerProperties[i]);
|
this->pointerProperties[i].copyFrom(pointerProperties[i]);
|
||||||
this->pointerCoords[i].copyFrom(pointerCoords[i]);
|
this->pointerCoords[i].copyFrom(pointerCoords[i]);
|
||||||
|
if (xOffset || yOffset) {
|
||||||
|
this->pointerCoords[i].applyOffset(xOffset, yOffset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4201,7 +4240,8 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim
|
|||||||
memento.flags, 0, 0, 0,
|
memento.flags, 0, 0, 0,
|
||||||
memento.xPrecision, memento.yPrecision, memento.downTime,
|
memento.xPrecision, memento.yPrecision, memento.downTime,
|
||||||
memento.displayId,
|
memento.displayId,
|
||||||
memento.pointerCount, memento.pointerProperties, memento.pointerCoords));
|
memento.pointerCount, memento.pointerProperties, memento.pointerCoords,
|
||||||
|
0, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ public:
|
|||||||
*
|
*
|
||||||
* This method may be called on any thread (usually by the input manager).
|
* This method may be called on any thread (usually by the input manager).
|
||||||
*/
|
*/
|
||||||
virtual int32_t injectInputEvent(const InputEvent* event,
|
virtual int32_t injectInputEvent(const InputEvent* event, int32_t displayId,
|
||||||
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
|
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
|
||||||
uint32_t policyFlags) = 0;
|
uint32_t policyFlags) = 0;
|
||||||
|
|
||||||
@@ -381,7 +381,7 @@ public:
|
|||||||
virtual void notifySwitch(const NotifySwitchArgs* args);
|
virtual void notifySwitch(const NotifySwitchArgs* args);
|
||||||
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
|
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
|
||||||
|
|
||||||
virtual int32_t injectInputEvent(const InputEvent* event,
|
virtual int32_t injectInputEvent(const InputEvent* event, int32_t displayId,
|
||||||
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
|
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
|
||||||
uint32_t policyFlags);
|
uint32_t policyFlags);
|
||||||
|
|
||||||
@@ -525,7 +525,8 @@ private:
|
|||||||
int32_t metaState, int32_t buttonState, int32_t edgeFlags,
|
int32_t metaState, int32_t buttonState, int32_t edgeFlags,
|
||||||
float xPrecision, float yPrecision,
|
float xPrecision, float yPrecision,
|
||||||
nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
|
nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
|
||||||
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords);
|
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
|
||||||
|
float xOffset, float yOffset);
|
||||||
virtual void appendDescription(String8& msg) const;
|
virtual void appendDescription(String8& msg) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -959,7 +960,7 @@ private:
|
|||||||
bool isSlippery() const;
|
bool isSlippery() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
TouchState mTouchState;
|
KeyedVector<int32_t, TouchState> mTouchStatesByDisplay;
|
||||||
TouchState mTempTouchState;
|
TouchState mTempTouchState;
|
||||||
|
|
||||||
// Focused application.
|
// Focused application.
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ static const nsecs_t ARBITRARY_TIME = 1234;
|
|||||||
// An arbitrary device id.
|
// An arbitrary device id.
|
||||||
static const int32_t DEVICE_ID = 1;
|
static const int32_t DEVICE_ID = 1;
|
||||||
|
|
||||||
|
// An arbitrary display id.
|
||||||
|
static const int32_t DISPLAY_ID = 0;
|
||||||
|
|
||||||
// An arbitrary injector pid / uid pair that has permission to inject events.
|
// An arbitrary injector pid / uid pair that has permission to inject events.
|
||||||
static const int32_t INJECTOR_PID = 999;
|
static const int32_t INJECTOR_PID = 999;
|
||||||
static const int32_t INJECTOR_UID = 1001;
|
static const int32_t INJECTOR_UID = 1001;
|
||||||
@@ -126,7 +129,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
|
|||||||
event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
|
||||||
/*action*/ -1, 0,
|
/*action*/ -1, 0,
|
||||||
AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
|
AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
|
||||||
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
|
||||||
|
&event, DISPLAY_ID,
|
||||||
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
||||||
<< "Should reject key events with undefined action.";
|
<< "Should reject key events with undefined action.";
|
||||||
|
|
||||||
@@ -134,7 +138,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
|
|||||||
event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
|
event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
|
||||||
AKEY_EVENT_ACTION_MULTIPLE, 0,
|
AKEY_EVENT_ACTION_MULTIPLE, 0,
|
||||||
AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
|
AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
|
||||||
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
|
||||||
|
&event, DISPLAY_ID,
|
||||||
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
||||||
<< "Should reject key events with ACTION_MULTIPLE.";
|
<< "Should reject key events with ACTION_MULTIPLE.";
|
||||||
}
|
}
|
||||||
@@ -154,7 +159,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
|
|||||||
/*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
/*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
||||||
ARBITRARY_TIME, ARBITRARY_TIME,
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
||||||
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
|
||||||
|
&event, DISPLAY_ID,
|
||||||
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
||||||
<< "Should reject motion events with undefined action.";
|
<< "Should reject motion events with undefined action.";
|
||||||
|
|
||||||
@@ -164,7 +170,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
|
|||||||
0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
||||||
ARBITRARY_TIME, ARBITRARY_TIME,
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
||||||
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
|
||||||
|
&event, DISPLAY_ID,
|
||||||
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
||||||
<< "Should reject motion events with pointer down index too large.";
|
<< "Should reject motion events with pointer down index too large.";
|
||||||
|
|
||||||
@@ -173,7 +180,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
|
|||||||
0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
||||||
ARBITRARY_TIME, ARBITRARY_TIME,
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
||||||
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
|
||||||
|
&event, DISPLAY_ID,
|
||||||
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
||||||
<< "Should reject motion events with pointer down index too small.";
|
<< "Should reject motion events with pointer down index too small.";
|
||||||
|
|
||||||
@@ -183,7 +191,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
|
|||||||
0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
||||||
ARBITRARY_TIME, ARBITRARY_TIME,
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
||||||
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
|
||||||
|
&event, DISPLAY_ID,
|
||||||
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
||||||
<< "Should reject motion events with pointer up index too large.";
|
<< "Should reject motion events with pointer up index too large.";
|
||||||
|
|
||||||
@@ -192,7 +201,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
|
|||||||
0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
||||||
ARBITRARY_TIME, ARBITRARY_TIME,
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
||||||
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
|
||||||
|
&event, DISPLAY_ID,
|
||||||
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
||||||
<< "Should reject motion events with pointer up index too small.";
|
<< "Should reject motion events with pointer up index too small.";
|
||||||
|
|
||||||
@@ -201,7 +211,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
|
|||||||
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
||||||
ARBITRARY_TIME, ARBITRARY_TIME,
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
/*pointerCount*/ 0, pointerProperties, pointerCoords);
|
/*pointerCount*/ 0, pointerProperties, pointerCoords);
|
||||||
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
|
||||||
|
&event, DISPLAY_ID,
|
||||||
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
||||||
<< "Should reject motion events with 0 pointers.";
|
<< "Should reject motion events with 0 pointers.";
|
||||||
|
|
||||||
@@ -209,7 +220,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
|
|||||||
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
||||||
ARBITRARY_TIME, ARBITRARY_TIME,
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
/*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
|
/*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
|
||||||
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
|
||||||
|
&event, DISPLAY_ID,
|
||||||
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
||||||
<< "Should reject motion events with more than MAX_POINTERS pointers.";
|
<< "Should reject motion events with more than MAX_POINTERS pointers.";
|
||||||
|
|
||||||
@@ -219,7 +231,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
|
|||||||
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
||||||
ARBITRARY_TIME, ARBITRARY_TIME,
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
||||||
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
|
||||||
|
&event, DISPLAY_ID,
|
||||||
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
||||||
<< "Should reject motion events with pointer ids less than 0.";
|
<< "Should reject motion events with pointer ids less than 0.";
|
||||||
|
|
||||||
@@ -228,7 +241,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
|
|||||||
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
||||||
ARBITRARY_TIME, ARBITRARY_TIME,
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
/*pointerCount*/ 1, pointerProperties, pointerCoords);
|
||||||
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
|
||||||
|
&event, DISPLAY_ID,
|
||||||
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
||||||
<< "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
|
<< "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
|
||||||
|
|
||||||
@@ -239,7 +253,8 @@ TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
|
|||||||
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
|
||||||
ARBITRARY_TIME, ARBITRARY_TIME,
|
ARBITRARY_TIME, ARBITRARY_TIME,
|
||||||
/*pointerCount*/ 2, pointerProperties, pointerCoords);
|
/*pointerCount*/ 2, pointerProperties, pointerCoords);
|
||||||
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
|
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
|
||||||
|
&event, DISPLAY_ID,
|
||||||
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
|
||||||
<< "Should reject motion events with duplicate pointer ids.";
|
<< "Should reject motion events with duplicate pointer ids.";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ import android.hardware.display.DisplayManager;
|
|||||||
import android.hardware.display.DisplayManager.DisplayListener;
|
import android.hardware.display.DisplayManager.DisplayListener;
|
||||||
import android.hardware.display.DisplayManagerGlobal;
|
import android.hardware.display.DisplayManagerGlobal;
|
||||||
import android.hardware.display.VirtualDisplay;
|
import android.hardware.display.VirtualDisplay;
|
||||||
|
import android.hardware.input.InputManager;
|
||||||
|
import android.hardware.input.InputManagerInternal;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Debug;
|
import android.os.Debug;
|
||||||
@@ -81,9 +83,11 @@ import android.util.SparseArray;
|
|||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.DisplayInfo;
|
import android.view.DisplayInfo;
|
||||||
|
import android.view.InputEvent;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import com.android.internal.app.HeavyWeightSwitcherActivity;
|
import com.android.internal.app.HeavyWeightSwitcherActivity;
|
||||||
import com.android.internal.os.TransferPipe;
|
import com.android.internal.os.TransferPipe;
|
||||||
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
|
import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
|
||||||
import com.android.server.am.ActivityStack.ActivityState;
|
import com.android.server.am.ActivityStack.ActivityState;
|
||||||
import com.android.server.wm.WindowManagerService;
|
import com.android.server.wm.WindowManagerService;
|
||||||
@@ -225,6 +229,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
|||||||
/** Mapping from displayId to display current state */
|
/** Mapping from displayId to display current state */
|
||||||
private SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<ActivityDisplay>();
|
private SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<ActivityDisplay>();
|
||||||
|
|
||||||
|
InputManagerInternal mInputManagerInternal;
|
||||||
|
|
||||||
public ActivityStackSupervisor(ActivityManagerService service) {
|
public ActivityStackSupervisor(ActivityManagerService service) {
|
||||||
mService = service;
|
mService = service;
|
||||||
PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE);
|
PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE);
|
||||||
@@ -255,6 +261,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
|||||||
|
|
||||||
createStackOnDisplay(null, HOME_STACK_ID, Display.DEFAULT_DISPLAY);
|
createStackOnDisplay(null, HOME_STACK_ID, Display.DEFAULT_DISPLAY);
|
||||||
mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);
|
mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);
|
||||||
|
|
||||||
|
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2940,7 +2948,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void attachToDisplay(int displayId) throws RemoteException {
|
public void attachToDisplay(int displayId) {
|
||||||
synchronized (mService) {
|
synchronized (mService) {
|
||||||
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
|
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
|
||||||
if (activityDisplay == null) {
|
if (activityDisplay == null) {
|
||||||
@@ -2951,13 +2959,28 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDisplayId() throws RemoteException {
|
public int getDisplayId() {
|
||||||
if (mActivityDisplay != null) {
|
if (mActivityDisplay != null) {
|
||||||
return mActivityDisplay.mDisplayId;
|
return mActivityDisplay.mDisplayId;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean injectEvent(InputEvent event) {
|
||||||
|
final long origId = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
if (mActivityDisplay != null) {
|
||||||
|
return mInputManagerInternal.injectInputEvent(event,
|
||||||
|
mActivityDisplay.mDisplayId,
|
||||||
|
InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(origId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void detachLocked() {
|
private void detachLocked() {
|
||||||
if (DEBUG_STACK) Slog.d(TAG, "detachLocked: " + this + " from display="
|
if (DEBUG_STACK) Slog.d(TAG, "detachLocked: " + this + " from display="
|
||||||
+ mActivityDisplay + " Callers=" + Debug.getCallers(2));
|
+ mActivityDisplay + " Callers=" + Debug.getCallers(2));
|
||||||
@@ -2971,7 +2994,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void detachFromDisplay() throws RemoteException {
|
public void detachFromDisplay() {
|
||||||
synchronized (mService) {
|
synchronized (mService) {
|
||||||
detachLocked();
|
detachLocked();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server.input;
|
package com.android.server.input;
|
||||||
|
|
||||||
|
import android.view.Display;
|
||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
import com.android.internal.util.XmlUtils;
|
import com.android.internal.util.XmlUtils;
|
||||||
import com.android.server.DisplayThread;
|
import com.android.server.DisplayThread;
|
||||||
@@ -169,7 +170,7 @@ public class InputManagerService extends IInputManager.Stub
|
|||||||
InputWindowHandle inputWindowHandle, boolean monitor);
|
InputWindowHandle inputWindowHandle, boolean monitor);
|
||||||
private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel);
|
private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel);
|
||||||
private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
|
private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
|
||||||
private static native int nativeInjectInputEvent(long ptr, InputEvent event,
|
private static native int nativeInjectInputEvent(long ptr, InputEvent event, int displayId,
|
||||||
int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
|
int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
|
||||||
int policyFlags);
|
int policyFlags);
|
||||||
private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
|
private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
|
||||||
@@ -508,6 +509,10 @@ public class InputManagerService extends IInputManager.Stub
|
|||||||
|
|
||||||
@Override // Binder call
|
@Override // Binder call
|
||||||
public boolean injectInputEvent(InputEvent event, int mode) {
|
public boolean injectInputEvent(InputEvent event, int mode) {
|
||||||
|
return injectInputEventInternal(event, Display.DEFAULT_DISPLAY, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean injectInputEventInternal(InputEvent event, int displayId, int mode) {
|
||||||
if (event == null) {
|
if (event == null) {
|
||||||
throw new IllegalArgumentException("event must not be null");
|
throw new IllegalArgumentException("event must not be null");
|
||||||
}
|
}
|
||||||
@@ -522,7 +527,7 @@ public class InputManagerService extends IInputManager.Stub
|
|||||||
final long ident = Binder.clearCallingIdentity();
|
final long ident = Binder.clearCallingIdentity();
|
||||||
final int result;
|
final int result;
|
||||||
try {
|
try {
|
||||||
result = nativeInjectInputEvent(mPtr, event, pid, uid, mode,
|
result = nativeInjectInputEvent(mPtr, event, displayId, pid, uid, mode,
|
||||||
INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
|
INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
@@ -1552,7 +1557,7 @@ public class InputManagerService extends IInputManager.Stub
|
|||||||
|
|
||||||
synchronized (mInputFilterLock) {
|
synchronized (mInputFilterLock) {
|
||||||
if (!mDisconnected) {
|
if (!mDisconnected) {
|
||||||
nativeInjectInputEvent(mPtr, event, 0, 0,
|
nativeInjectInputEvent(mPtr, event, Display.DEFAULT_DISPLAY, 0, 0,
|
||||||
InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
|
InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
|
||||||
policyFlags | WindowManagerPolicy.FLAG_FILTERED);
|
policyFlags | WindowManagerPolicy.FLAG_FILTERED);
|
||||||
}
|
}
|
||||||
@@ -1649,5 +1654,10 @@ public class InputManagerService extends IInputManager.Stub
|
|||||||
DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) {
|
DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) {
|
||||||
setDisplayViewportsInternal(defaultViewport, externalTouchViewport);
|
setDisplayViewportsInternal(defaultViewport, externalTouchViewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean injectInputEvent(InputEvent event, int displayId, int mode) {
|
||||||
|
return injectInputEventInternal(event, displayId, mode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1143,7 +1143,7 @@ static void nativeSetInputFilterEnabled(JNIEnv* env, jclass clazz,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz,
|
static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz,
|
||||||
jlong ptr, jobject inputEventObj, jint injectorPid, jint injectorUid,
|
jlong ptr, jobject inputEventObj, jint displayId, jint injectorPid, jint injectorUid,
|
||||||
jint syncMode, jint timeoutMillis, jint policyFlags) {
|
jint syncMode, jint timeoutMillis, jint policyFlags) {
|
||||||
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
|
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
|
||||||
|
|
||||||
@@ -1156,7 +1156,7 @@ static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
|
return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
|
||||||
& keyEvent, injectorPid, injectorUid, syncMode, timeoutMillis,
|
& keyEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,
|
||||||
uint32_t(policyFlags));
|
uint32_t(policyFlags));
|
||||||
} else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
|
} else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
|
||||||
const MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, inputEventObj);
|
const MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, inputEventObj);
|
||||||
@@ -1166,7 +1166,7 @@ static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
|
return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
|
||||||
motionEvent, injectorPid, injectorUid, syncMode, timeoutMillis,
|
motionEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,
|
||||||
uint32_t(policyFlags));
|
uint32_t(policyFlags));
|
||||||
} else {
|
} else {
|
||||||
jniThrowRuntimeException(env, "Invalid input event type.");
|
jniThrowRuntimeException(env, "Invalid input event type.");
|
||||||
@@ -1326,7 +1326,7 @@ static JNINativeMethod gInputManagerMethods[] = {
|
|||||||
(void*) nativeUnregisterInputChannel },
|
(void*) nativeUnregisterInputChannel },
|
||||||
{ "nativeSetInputFilterEnabled", "(JZ)V",
|
{ "nativeSetInputFilterEnabled", "(JZ)V",
|
||||||
(void*) nativeSetInputFilterEnabled },
|
(void*) nativeSetInputFilterEnabled },
|
||||||
{ "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIII)I",
|
{ "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I",
|
||||||
(void*) nativeInjectInputEvent },
|
(void*) nativeInjectInputEvent },
|
||||||
{ "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V",
|
{ "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;)V",
|
||||||
(void*) nativeSetInputWindows },
|
(void*) nativeSetInputWindows },
|
||||||
|
|||||||
Reference in New Issue
Block a user