Revert "Change input injection security model to require INJECT_..."
Revert submission 17125748-require-inject-events-permission
Reason for revert: b/228203157, b/228194124
Reverted Changes:
Ib0d66eff3:Change input injection security model to require I...
Ief1a2f10c:Update WindowInputTests after changing injection p...
Ie2d8d0c3d:Change input injection security model to require I...
Change-Id: Iab079575c41821f5330002e23dc13884676a5249
diff --git a/libs/input/android/os/InputEventInjectionResult.aidl b/libs/input/android/os/InputEventInjectionResult.aidl
index 3bc7068..34f10ec 100644
--- a/libs/input/android/os/InputEventInjectionResult.aidl
+++ b/libs/input/android/os/InputEventInjectionResult.aidl
@@ -29,8 +29,9 @@
/* Injection succeeded. */
SUCCEEDED = 0,
- /* Injection failed because the injected event did not target the appropriate window. */
- TARGET_MISMATCH = 1,
+ /* Injection failed because the injector did not have permission to inject
+ * into the application with input focus. */
+ PERMISSION_DENIED = 1,
/* Injection failed because there were no available input targets. */
FAILED = 2,
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index a2e60c4..32eec29 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -31,11 +31,11 @@
namespace android::inputdispatcher {
// An arbitrary device id.
-constexpr int32_t DEVICE_ID = 1;
+static const int32_t DEVICE_ID = 1;
-// The default pid and uid for windows created by the test.
-constexpr int32_t WINDOW_PID = 999;
-constexpr int32_t WINDOW_UID = 1001;
+// 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;
static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 5s;
static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 100ms;
@@ -108,6 +108,8 @@
void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
+ bool checkInjectEventsPermissionNonReentrant(int32_t, int32_t) override { return false; }
+
void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {}
void setPointerCapture(const PointerCaptureRequest&) override {}
@@ -194,8 +196,8 @@
mInfo.globalScaleFactor = 1.0;
mInfo.touchableRegion.clear();
mInfo.addTouchableRegion(mFrame);
- mInfo.ownerPid = WINDOW_PID;
- mInfo.ownerUid = WINDOW_UID;
+ mInfo.ownerPid = INJECTOR_PID;
+ mInfo.ownerUid = INJECTOR_UID;
mInfo.displayId = ADISPLAY_ID_DEFAULT;
}
@@ -308,14 +310,14 @@
for (auto _ : state) {
MotionEvent event = generateMotionEvent();
// Send ACTION_DOWN
- dispatcher.injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- INJECT_EVENT_TIMEOUT,
+ dispatcher.injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, INJECT_EVENT_TIMEOUT,
POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
// Send ACTION_UP
event.setAction(AMOTION_EVENT_ACTION_UP);
- dispatcher.injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- INJECT_EVENT_TIMEOUT,
+ dispatcher.injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, INJECT_EVENT_TIMEOUT,
POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
window->consumeEvent();
diff --git a/services/inputflinger/dispatcher/InjectionState.cpp b/services/inputflinger/dispatcher/InjectionState.cpp
index c2d3ad6..c8024a6 100644
--- a/services/inputflinger/dispatcher/InjectionState.cpp
+++ b/services/inputflinger/dispatcher/InjectionState.cpp
@@ -20,9 +20,10 @@
namespace android::inputdispatcher {
-InjectionState::InjectionState(const std::optional<int32_t>& targetUid)
+InjectionState::InjectionState(int32_t injectorPid, int32_t injectorUid)
: refCount(1),
- targetUid(targetUid),
+ injectorPid(injectorPid),
+ injectorUid(injectorUid),
injectionResult(android::os::InputEventInjectionResult::PENDING),
injectionIsAsync(false),
pendingForegroundDispatches(0) {}
diff --git a/services/inputflinger/dispatcher/InjectionState.h b/services/inputflinger/dispatcher/InjectionState.h
index 90cf150..0bfafb1 100644
--- a/services/inputflinger/dispatcher/InjectionState.h
+++ b/services/inputflinger/dispatcher/InjectionState.h
@@ -27,12 +27,13 @@
struct InjectionState {
mutable int32_t refCount;
- std::optional<int32_t> targetUid;
+ int32_t injectorPid;
+ int32_t injectorUid;
android::os::InputEventInjectionResult injectionResult; // initially PENDING
bool injectionIsAsync; // set to true if injection is not waiting for the result
int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress
- explicit InjectionState(const std::optional<int32_t>& targetUid);
+ InjectionState(int32_t injectorPid, int32_t injectorUid);
void release();
private:
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index f3d0b65..11cceaa 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -578,27 +578,6 @@
return false;
}
-// Checks targeted injection using the window's owner's uid.
-// Returns an empty string if an entry can be sent to the given window, or an error message if the
-// entry is a targeted injection whose uid target doesn't match the window owner.
-std::optional<std::string> verifyTargetedInjection(const sp<WindowInfoHandle>& window,
- const EventEntry& entry) {
- if (entry.injectionState == nullptr || !entry.injectionState->targetUid) {
- // The event was not injected, or the injected event does not target a window.
- return {};
- }
- const int32_t uid = *entry.injectionState->targetUid;
- if (window == nullptr) {
- return StringPrintf("No valid window target for injection into uid %d.", uid);
- }
- if (entry.injectionState->targetUid != window->getInfo()->ownerUid) {
- return StringPrintf("Injected event targeted at uid %d would be dispatched to window '%s' "
- "owned by uid %d.",
- uid, window->getName().c_str(), window->getInfo()->ownerUid);
- }
- return {};
-}
-
} // namespace
// --- InputDispatcher ---
@@ -1057,8 +1036,6 @@
switch (entry.type) {
case EventEntry::Type::KEY: {
- LOG_ALWAYS_FATAL_IF((entry.policyFlags & POLICY_FLAG_TRUSTED) == 0,
- "Unexpected untrusted event.");
// Optimize app switch latency.
// If the application takes too long to catch up then we drop all events preceding
// the app switch key.
@@ -1096,8 +1073,6 @@
}
case EventEntry::Type::MOTION: {
- LOG_ALWAYS_FATAL_IF((entry.policyFlags & POLICY_FLAG_TRUSTED) == 0,
- "Unexpected untrusted event.");
if (shouldPruneInboundQueueLocked(static_cast<MotionEntry&>(entry))) {
mNextUnblockedEvent = mInboundQueue.back();
needWake = true;
@@ -1743,7 +1718,8 @@
}
setInjectionResult(*entry, injectionResult);
- if (injectionResult == InputEventInjectionResult::TARGET_MISMATCH) {
+ if (injectionResult == InputEventInjectionResult::PERMISSION_DENIED) {
+ ALOGW("Permission denied, dropping the motion (isPointer=%s)", toString(isPointerEvent));
return true;
}
if (injectionResult != InputEventInjectionResult::SUCCEEDED) {
@@ -2000,10 +1976,9 @@
// we have a valid, non-null focused window
resetNoFocusedWindowTimeoutLocked();
- // Verify targeted injection.
- if (const auto err = verifyTargetedInjection(focusedWindowHandle, entry); err) {
- ALOGW("Dropping injected event: %s", (*err).c_str());
- return InputEventInjectionResult::TARGET_MISMATCH;
+ // Check permissions.
+ if (!checkInjectionPermission(focusedWindowHandle, entry.injectionState)) {
+ return InputEventInjectionResult::PERMISSION_DENIED;
}
if (focusedWindowHandle->getInfo()->inputConfig.test(
@@ -2069,6 +2044,11 @@
nsecs_t currentTime, const MotionEntry& entry, std::vector<InputTarget>& inputTargets,
nsecs_t* nextWakeupTime, bool* outConflictingPointerActions) {
ATRACE_CALL();
+ enum InjectionPermission {
+ INJECTION_PERMISSION_UNKNOWN,
+ INJECTION_PERMISSION_GRANTED,
+ INJECTION_PERMISSION_DENIED
+ };
// For security reasons, we defer updating the touch state until we are sure that
// event injection will be allowed.
@@ -2078,6 +2058,7 @@
// Update the touch state as needed based on the properties of the touch event.
InputEventInjectionResult injectionResult = InputEventInjectionResult::PENDING;
+ InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
sp<WindowInfoHandle> newHoverWindowHandle(mLastHoverWindowHandle);
sp<WindowInfoHandle> newTouchedWindowHandle;
@@ -2126,7 +2107,7 @@
"in display %" PRId32,
displayId);
// TODO: test multiple simultaneous input streams.
- injectionResult = InputEventInjectionResult::FAILED;
+ injectionResult = InputEventInjectionResult::PERMISSION_DENIED;
switchedDevice = false;
wrongDevice = true;
goto Failed;
@@ -2159,14 +2140,6 @@
newTouchedWindowHandle = tempTouchState.getFirstForegroundWindowHandle();
}
- // Verify targeted injection.
- if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
- ALOGW("Dropping injected touch event: %s", (*err).c_str());
- injectionResult = os::InputEventInjectionResult::TARGET_MISMATCH;
- newTouchedWindowHandle = nullptr;
- goto Failed;
- }
-
// Figure out whether splitting will be allowed for this window.
if (newTouchedWindowHandle != nullptr) {
if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
@@ -2210,11 +2183,6 @@
for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) {
const WindowInfo& info = *windowHandle->getInfo();
- // Skip spy window targets that are not valid for targeted injection.
- if (const auto err = verifyTargetedInjection(windowHandle, entry); err) {
- continue;
- }
-
if (info.inputConfig.test(WindowInfo::InputConfig::PAUSE_DISPATCHING)) {
ALOGI("Not sending touch event to %s because it is paused",
windowHandle->getName().c_str());
@@ -2308,14 +2276,6 @@
newTouchedWindowHandle =
findTouchedWindowAtLocked(displayId, x, y, &tempTouchState, isStylus);
- // Verify targeted injection.
- if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
- ALOGW("Dropping injected event: %s", (*err).c_str());
- injectionResult = os::InputEventInjectionResult::TARGET_MISMATCH;
- newTouchedWindowHandle = nullptr;
- goto Failed;
- }
-
// Drop touch events if requested by input feature
if (newTouchedWindowHandle != nullptr &&
shouldDropInput(entry, newTouchedWindowHandle)) {
@@ -2407,26 +2367,19 @@
goto Failed;
}
- // Ensure that all touched windows are valid for injection.
- if (entry.injectionState != nullptr) {
- std::string errs;
- for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
- if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
- // Allow ACTION_OUTSIDE events generated by targeted injection to be
- // dispatched to any uid, since the coords will be zeroed out later.
- continue;
- }
- const auto err = verifyTargetedInjection(touchedWindow.windowHandle, entry);
- if (err) errs += "\n - " + *err;
- }
- if (!errs.empty()) {
- ALOGW("Dropping targeted injection: At least one touched window is not owned by uid "
- "%d:%s",
- *entry.injectionState->targetUid, errs.c_str());
- injectionResult = InputEventInjectionResult::TARGET_MISMATCH;
- goto Failed;
- }
+ // Check permission to inject into all touched foreground windows.
+ if (std::any_of(tempTouchState.windows.begin(), tempTouchState.windows.end(),
+ [this, &entry](const TouchedWindow& touchedWindow) {
+ return (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) != 0 &&
+ !checkInjectionPermission(touchedWindow.windowHandle,
+ entry.injectionState);
+ })) {
+ injectionResult = InputEventInjectionResult::PERMISSION_DENIED;
+ injectionPermission = INJECTION_PERMISSION_DENIED;
+ goto Failed;
}
+ // Permission granted to inject into all touched foreground windows.
+ injectionPermission = INJECTION_PERMISSION_GRANTED;
// Check whether windows listening for outside touches are owned by the same UID. If it is
// set the policy flag that we will not reveal coordinate information to this window.
@@ -2492,6 +2445,19 @@
tempTouchState.filterNonAsIsTouchWindows();
Failed:
+ // Check injection permission once and for all.
+ if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
+ if (checkInjectionPermission(nullptr, entry.injectionState)) {
+ injectionPermission = INJECTION_PERMISSION_GRANTED;
+ } else {
+ injectionPermission = INJECTION_PERMISSION_DENIED;
+ }
+ }
+
+ if (injectionPermission != INJECTION_PERMISSION_GRANTED) {
+ return injectionResult;
+ }
+
// Update final pieces of touch state if the injector had permission.
if (!wrongDevice) {
if (switchedDevice) {
@@ -2689,6 +2655,26 @@
}
}
+bool InputDispatcher::checkInjectionPermission(const sp<WindowInfoHandle>& windowHandle,
+ const InjectionState* injectionState) {
+ if (injectionState &&
+ (windowHandle == nullptr ||
+ windowHandle->getInfo()->ownerUid != injectionState->injectorUid) &&
+ !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
+ if (windowHandle != nullptr) {
+ ALOGW("Permission denied: injecting event from pid %d uid %d to window %s "
+ "owned by uid %d",
+ injectionState->injectorPid, injectionState->injectorUid,
+ windowHandle->getName().c_str(), windowHandle->getInfo()->ownerUid);
+ } else {
+ ALOGW("Permission denied: injecting event from pid %d uid %d",
+ injectionState->injectorPid, injectionState->injectorUid);
+ }
+ return false;
+ }
+ return true;
+}
+
/**
* Indicate whether one window handle should be considered as obscuring
* another window handle. We only check a few preconditions. Actually
@@ -4207,20 +4193,20 @@
}
}
-InputEventInjectionResult InputDispatcher::injectInputEvent(const InputEvent* event,
- std::optional<int32_t> targetUid,
- InputEventInjectionSync syncMode,
- std::chrono::milliseconds timeout,
- uint32_t policyFlags) {
+InputEventInjectionResult InputDispatcher::injectInputEvent(
+ const InputEvent* event, int32_t injectorPid, int32_t injectorUid,
+ InputEventInjectionSync syncMode, std::chrono::milliseconds timeout, uint32_t policyFlags) {
if (DEBUG_INBOUND_EVENT_DETAILS) {
- ALOGD("injectInputEvent - eventType=%d, targetUid=%s, syncMode=%d, timeout=%lld, "
- "policyFlags=0x%08x",
- event->getType(), targetUid ? std::to_string(*targetUid).c_str() : "none", syncMode,
- timeout.count(), policyFlags);
+ ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
+ "syncMode=%d, timeout=%lld, policyFlags=0x%08x",
+ event->getType(), injectorPid, injectorUid, syncMode, timeout.count(), policyFlags);
}
nsecs_t endTime = now() + std::chrono::duration_cast<std::chrono::nanoseconds>(timeout).count();
- policyFlags |= POLICY_FLAG_INJECTED | POLICY_FLAG_TRUSTED;
+ policyFlags |= POLICY_FLAG_INJECTED;
+ if (hasInjectionPermission(injectorPid, injectorUid)) {
+ policyFlags |= POLICY_FLAG_TRUSTED;
+ }
// For all injected events, set device id = VIRTUAL_KEYBOARD_ID. The only exception is events
// that have gone through the InputFilter. If the event passed through the InputFilter, assign
@@ -4361,7 +4347,7 @@
return InputEventInjectionResult::FAILED;
}
- InjectionState* injectionState = new InjectionState(targetUid);
+ InjectionState* injectionState = new InjectionState(injectorPid, injectorUid);
if (syncMode == InputEventInjectionSync::NONE) {
injectionState->injectionIsAsync = true;
}
@@ -4433,7 +4419,8 @@
} // release lock
if (DEBUG_INJECTION) {
- ALOGD("injectInputEvent - Finished with result %d.", injectionResult);
+ ALOGD("injectInputEvent - Finished with result %d. injectorPid=%d, injectorUid=%d",
+ injectionResult, injectorPid, injectorUid);
}
return injectionResult;
@@ -4472,12 +4459,19 @@
return result;
}
+bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
+ return injectorUid == 0 ||
+ mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
+}
+
void InputDispatcher::setInjectionResult(EventEntry& entry,
InputEventInjectionResult injectionResult) {
InjectionState* injectionState = entry.injectionState;
if (injectionState) {
if (DEBUG_INJECTION) {
- ALOGD("Setting input event injection result to %d.", injectionResult);
+ ALOGD("Setting input event injection result to %d. "
+ "injectorPid=%d, injectorUid=%d",
+ injectionResult, injectionState->injectorPid, injectionState->injectorUid);
}
if (injectionState->injectionIsAsync && !(entry.policyFlags & POLICY_FLAG_FILTERED)) {
@@ -4486,12 +4480,12 @@
case InputEventInjectionResult::SUCCEEDED:
ALOGV("Asynchronous input event injection succeeded.");
break;
- case InputEventInjectionResult::TARGET_MISMATCH:
- ALOGV("Asynchronous input event injection target mismatch.");
- break;
case InputEventInjectionResult::FAILED:
ALOGW("Asynchronous input event injection failed.");
break;
+ case InputEventInjectionResult::PERMISSION_DENIED:
+ ALOGW("Asynchronous input event injection permission denied.");
+ break;
case InputEventInjectionResult::TIMED_OUT:
ALOGW("Asynchronous input event injection timed out.");
break;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index a9fb5c6..ca24f17 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -104,7 +104,7 @@
void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
android::os::InputEventInjectionResult injectInputEvent(
- const InputEvent* event, std::optional<int32_t> targetUid,
+ const InputEvent* event, int32_t injectorPid, int32_t injectorUid,
android::os::InputEventInjectionSync syncMode, std::chrono::milliseconds timeout,
uint32_t policyFlags) override;
@@ -275,6 +275,7 @@
// Event injection and synchronization.
std::condition_variable mInjectionResultAvailable;
+ bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
void setInjectionResult(EventEntry& entry,
android::os::InputEventInjectionResult injectionResult);
void transformMotionEntryForInjectionLocked(MotionEntry&,
@@ -550,6 +551,8 @@
void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId)
REQUIRES(mLock);
void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock);
+ bool checkInjectionPermission(const sp<android::gui::WindowInfoHandle>& windowHandle,
+ const InjectionState* injectionState);
// Enqueue a drag event if needed, and update the touch state.
// Uses findTouchedWindowTargetsLocked to make the decision
void addDragEventLocked(const MotionEntry& entry) REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 100bd18..67e1b6f 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -68,16 +68,10 @@
* input injection to proceed.
* Returns one of the INPUT_EVENT_INJECTION_XXX constants.
*
- * If a targetUid is provided, InputDispatcher will only consider injecting the input event into
- * windows owned by the provided uid. If the input event is targeted at a window that is not
- * owned by the provided uid, input injection will fail. If no targetUid is provided, the input
- * event will be dispatched as-is.
- *
- * This method may be called on any thread (usually by the input manager). The caller must
- * perform all necessary permission checks prior to injecting events.
+ * This method may be called on any thread (usually by the input manager).
*/
virtual android::os::InputEventInjectionResult injectInputEvent(
- const InputEvent* event, std::optional<int32_t> targetUid,
+ const InputEvent* event, int32_t injectorPid, int32_t injectorUid,
android::os::InputEventInjectionSync syncMode, std::chrono::milliseconds timeout,
uint32_t policyFlags) = 0;
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index 575b3d7..de0b6da 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -125,6 +125,15 @@
/* Poke user activity for an event dispatched to a window. */
virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) = 0;
+ /* Checks whether a given application pid/uid has permission to inject input events
+ * into other applications.
+ *
+ * This method is special in that its implementation promises to be non-reentrant and
+ * is safe to call while holding other locks. (Most other methods make no such guarantees!)
+ */
+ virtual bool checkInjectEventsPermissionNonReentrant(int32_t injectorPid,
+ int32_t injectorUid) = 0;
+
/* Notifies the policy that a pointer down event has occurred outside the current focused
* window.
*
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 84ae31b..112b19a 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -45,10 +45,10 @@
using namespace ftl::flag_operators;
// An arbitrary time value.
-static constexpr nsecs_t ARBITRARY_TIME = 1234;
+static const nsecs_t ARBITRARY_TIME = 1234;
// An arbitrary device id.
-static constexpr int32_t DEVICE_ID = 1;
+static const int32_t DEVICE_ID = 1;
// An arbitrary display id.
static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
@@ -59,12 +59,9 @@
static constexpr int32_t POINTER_1_UP =
AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
-// The default pid and uid for windows created by the test.
-static constexpr int32_t WINDOW_PID = 999;
-static constexpr int32_t WINDOW_UID = 1001;
-
-// The default policy flags to use for event injection by tests.
-static constexpr uint32_t DEFAULT_POLICY_FLAGS = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
+// 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;
// An arbitrary pid of the gesture monitor window
static constexpr int32_t MONITOR_PID = 2001;
@@ -473,6 +470,10 @@
void pokeUserActivity(nsecs_t, int32_t, int32_t) override {}
+ bool checkInjectEventsPermissionNonReentrant(int32_t pid, int32_t uid) override {
+ return pid == INJECTOR_PID && uid == INJECTOR_UID;
+ }
+
void onPointerDownOutsideFocus(const sp<IBinder>& newToken) override {
std::scoped_lock lock(mLock);
mOnPointerDownToken = newToken;
@@ -557,8 +558,8 @@
/*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
ARBITRARY_TIME);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- 0ms, 0))
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, 0ms, 0))
<< "Should reject key events with undefined action.";
// Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
@@ -566,8 +567,8 @@
INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
ARBITRARY_TIME, ARBITRARY_TIME);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- 0ms, 0))
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, 0ms, 0))
<< "Should reject key events with ACTION_MULTIPLE.";
}
@@ -596,8 +597,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- 0ms, 0))
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, 0ms, 0))
<< "Should reject motion events with undefined action.";
// Rejects pointer down with invalid index.
@@ -608,8 +609,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- 0ms, 0))
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, 0ms, 0))
<< "Should reject motion events with pointer down index too large.";
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
@@ -620,8 +621,8 @@
identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- 0ms, 0))
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, 0ms, 0))
<< "Should reject motion events with pointer down index too small.";
// Rejects pointer up with invalid index.
@@ -632,8 +633,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- 0ms, 0))
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, 0ms, 0))
<< "Should reject motion events with pointer up index too large.";
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
@@ -644,8 +645,8 @@
identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- 0ms, 0))
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, 0ms, 0))
<< "Should reject motion events with pointer up index too small.";
// Rejects motion events with invalid number of pointers.
@@ -656,8 +657,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 0, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- 0ms, 0))
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, 0ms, 0))
<< "Should reject motion events with 0 pointers.";
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
@@ -667,8 +668,8 @@
ARBITRARY_TIME,
/*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- 0ms, 0))
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, 0ms, 0))
<< "Should reject motion events with more than MAX_POINTERS pointers.";
// Rejects motion events with invalid pointer ids.
@@ -680,8 +681,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- 0ms, 0))
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, 0ms, 0))
<< "Should reject motion events with pointer ids less than 0.";
pointerProperties[0].id = MAX_POINTER_ID + 1;
@@ -692,8 +693,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- 0ms, 0))
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, 0ms, 0))
<< "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
// Rejects motion events with duplicate pointer ids.
@@ -706,8 +707,8 @@
ARBITRARY_TIME,
/*pointerCount*/ 2, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/, InputEventInjectionSync::NONE,
- 0ms, 0))
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::NONE, 0ms, 0))
<< "Should reject motion events with duplicate pointer ids.";
}
@@ -1010,8 +1011,8 @@
mInfo.globalScaleFactor = 1.0;
mInfo.touchableRegion.clear();
mInfo.addTouchableRegion(Rect(0, 0, WIDTH, HEIGHT));
- mInfo.ownerPid = WINDOW_PID;
- mInfo.ownerUid = WINDOW_UID;
+ mInfo.ownerPid = INJECTOR_PID;
+ mInfo.ownerUid = INJECTOR_UID;
mInfo.displayId = displayId;
mInfo.inputConfig = WindowInfo::InputConfig::DEFAULT;
}
@@ -1293,8 +1294,7 @@
int32_t displayId = ADISPLAY_ID_NONE,
InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
- bool allowKeyRepeat = true, std::optional<int32_t> targetUid = {},
- uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
+ bool allowKeyRepeat = true) {
KeyEvent event;
nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -1303,11 +1303,13 @@
INVALID_HMAC, action, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
repeatCount, currentTime, currentTime);
+ int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
if (!allowKeyRepeat) {
policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
}
// Inject event until dispatch out.
- return dispatcher->injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
+ return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, syncMode,
+ injectionTimeout, policyFlags);
}
static InputEventInjectionResult injectKeyDown(const std::unique_ptr<InputDispatcher>& dispatcher,
@@ -1450,10 +1452,10 @@
static InputEventInjectionResult injectMotionEvent(
const std::unique_ptr<InputDispatcher>& dispatcher, const MotionEvent& event,
std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
- InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
- std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
- return dispatcher->injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
- policyFlags);
+ InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT) {
+ return dispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, injectionMode,
+ injectionTimeout,
+ POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER);
}
static InputEventInjectionResult injectMotionEvent(
@@ -1463,8 +1465,7 @@
AMOTION_EVENT_INVALID_CURSOR_POSITION},
std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
- nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
- std::optional<int32_t> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
+ nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC)) {
MotionEvent event = MotionEventBuilder(action, source)
.displayId(displayId)
.eventTime(eventTime)
@@ -1476,8 +1477,7 @@
.build();
// Inject event until dispatch out.
- return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode, targetUid,
- policyFlags);
+ return injectMotionEvent(dispatcher, event, injectionTimeout, injectionMode);
}
static InputEventInjectionResult injectMotionDown(
@@ -3466,8 +3466,8 @@
* FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
*/
TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
- constexpr int32_t SLIPPERY_PID = WINDOW_PID + 1;
- constexpr int32_t SLIPPERY_UID = WINDOW_UID + 1;
+ constexpr int32_t SLIPPERY_PID = INJECTOR_PID + 1;
+ constexpr int32_t SLIPPERY_UID = INJECTOR_UID + 1;
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
@@ -3994,7 +3994,7 @@
const int32_t additionalPolicyFlags =
POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
policyFlags | additionalPolicyFlags));
@@ -4029,7 +4029,7 @@
const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- mDispatcher->injectInputEvent(&event, {} /*targetUid*/,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
InputEventInjectionSync::WAIT_FOR_RESULT, 10ms,
policyFlags | additionalPolicyFlags));
@@ -4536,7 +4536,7 @@
const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
InputEventInjectionResult result =
- mDispatcher->injectInputEvent(&event, {} /* targetUid */,
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
InputEventInjectionSync::WAIT_FOR_RESULT,
INJECT_EVENT_TIMEOUT, policyFlags);
ASSERT_EQ(InputEventInjectionResult::FAILED, result)
@@ -6336,8 +6336,8 @@
mWindow->consumeFocusEvent(true);
// Set initial touch mode to InputDispatcher::kDefaultInTouchMode.
- if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
- WINDOW_UID, /* hasPermission */ true)) {
+ if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, INJECTOR_PID,
+ INJECTOR_UID, /* hasPermission */ true)) {
mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
}
@@ -6970,149 +6970,4 @@
window->assertNoEvents();
}
-struct User {
- int32_t mPid;
- int32_t mUid;
- uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
- std::unique_ptr<InputDispatcher>& mDispatcher;
-
- User(std::unique_ptr<InputDispatcher>& dispatcher, int32_t pid, int32_t uid)
- : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
-
- InputEventInjectionResult injectTargetedMotion(int32_t action) const {
- return injectMotionEvent(mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT, {100, 200},
- {AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION},
- INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
- systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
- }
-
- InputEventInjectionResult injectTargetedKey(int32_t action) const {
- return inputdispatcher::injectKey(mDispatcher, action, 0 /* repeatCount*/, ADISPLAY_ID_NONE,
- InputEventInjectionSync::WAIT_FOR_RESULT,
- INJECT_EVENT_TIMEOUT, false /*allowKeyRepeat*/, {mUid},
- mPolicyFlags);
- }
-
- sp<FakeWindowHandle> createWindow() const {
- std::shared_ptr<FakeApplicationHandle> overlayApplication =
- std::make_shared<FakeApplicationHandle>();
- sp<FakeWindowHandle> window = new FakeWindowHandle(overlayApplication, mDispatcher,
- "Owned Window", ADISPLAY_ID_DEFAULT);
- window->setOwnerInfo(mPid, mUid);
- return window;
- }
-};
-
-using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
-
-TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
- auto owner = User(mDispatcher, 10, 11);
- auto window = owner.createWindow();
- mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
-
- EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
- owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
- window->consumeMotionDown();
-
- setFocusedWindow(window);
- window->consumeFocusEvent(true);
-
- EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
- owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
- window->consumeKeyDown(ADISPLAY_ID_NONE);
-}
-
-TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
- auto owner = User(mDispatcher, 10, 11);
- auto window = owner.createWindow();
- mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
-
- auto rando = User(mDispatcher, 20, 21);
- EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
- rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
-
- setFocusedWindow(window);
- window->consumeFocusEvent(true);
-
- EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
- rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
- window->assertNoEvents();
-}
-
-TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
- auto owner = User(mDispatcher, 10, 11);
- auto window = owner.createWindow();
- auto spy = owner.createWindow();
- spy->setSpy(true);
- spy->setTrustedOverlay(true);
- mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
-
- EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
- owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
- spy->consumeMotionDown();
- window->consumeMotionDown();
-}
-
-TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
- auto owner = User(mDispatcher, 10, 11);
- auto window = owner.createWindow();
-
- auto rando = User(mDispatcher, 20, 21);
- auto randosSpy = rando.createWindow();
- randosSpy->setSpy(true);
- randosSpy->setTrustedOverlay(true);
- mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
-
- // The event is targeted at owner's window, so injection should succeed, but the spy should
- // not receive the event.
- EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
- owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
- randosSpy->assertNoEvents();
- window->consumeMotionDown();
-}
-
-TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
- auto owner = User(mDispatcher, 10, 11);
- auto window = owner.createWindow();
-
- auto rando = User(mDispatcher, 20, 21);
- auto randosSpy = rando.createWindow();
- randosSpy->setSpy(true);
- randosSpy->setTrustedOverlay(true);
- mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosSpy, window}}});
-
- // A user that has injection permission can inject into any window.
- EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
- injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT));
- randosSpy->consumeMotionDown();
- window->consumeMotionDown();
-
- setFocusedWindow(randosSpy);
- randosSpy->consumeFocusEvent(true);
-
- EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(mDispatcher));
- randosSpy->consumeKeyDown(ADISPLAY_ID_NONE);
- window->assertNoEvents();
-}
-
-TEST_F(InputDispatcherTargetedInjectionTest, CanGenerateActionOutsideToOtherUids) {
- auto owner = User(mDispatcher, 10, 11);
- auto window = owner.createWindow();
-
- auto rando = User(mDispatcher, 20, 21);
- auto randosWindow = rando.createWindow();
- randosWindow->setFrame(Rect{-10, -10, -5, -5});
- randosWindow->setWatchOutsideTouch(true);
- mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {randosWindow, window}}});
-
- // We allow generation of ACTION_OUTSIDE events into windows owned by different uids.
- EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
- owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
- window->consumeMotionDown();
- randosWindow->consumeMotionOutside();
-}
-
} // namespace android::inputdispatcher