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:
Jeff Brown
2014-02-12 00:37:24 +00:00
committed by Android Git Automerger
9 changed files with 218 additions and 98 deletions

View File

@@ -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;
} }

View File

@@ -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);
} }

View File

@@ -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);
} }

View File

@@ -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));
} }
} }
} }

View File

@@ -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.

View File

@@ -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.";
} }

View File

@@ -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();
} }

View File

@@ -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);
}
} }
} }

View File

@@ -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 },