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