summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Prabir Pradhan <prabirmsp@google.com> 2022-03-08 21:28:19 +0000
committer Prabir Pradhan <prabirmsp@google.com> 2022-04-04 19:22:51 +0000
commitedff3851325467a3f56ebe87af67df326b00a318 (patch)
treef570244e59d2c19cad240ebe2d2bcb03e8f1dc80
parent23b8a6d6407c4685dd82a08c87d4f60f8ebfa09e (diff)
Change input injection security model to require INJECT_EVENTS permission
Previously, any app could inject input events into the system via the IInputManager#injectInputEvent API. The injection was only allowed if the input event targeted a window owned by the same UID as that of the process calling the API. This had drawbacks metioned in the bug. Here, we change the input injection security model so that the signature permission INJECT_EVENTS is required to inject events. This permission is given to the system and the shell, so input injection can still be done through the 'adb shell input' command. We also allow injection from instrumeted processes where the instrumentation source has the permission. For exmaple, running a test from the shell allows for the test to inject events. We also add support for a targeted injection mode, where the input injection succeeds only if the target window for the event is owned by the provided UID. This allows us to support injection from the Instrumentation class, which only allows for injection into windows owned by the same UID. In contrast to this, injection from the UiAutomation class will target all windows, including system and spy windows. Bug: 207667844 Bug: 194952792 Test: atest inputflinger_tests Test: atest WindowInputTests Test: manual with test app: app cannot inject navigation gestures Change-Id: Ib0d66eff3fc2f061e7c0d3b7e139a841a9bcebc7
-rw-r--r--core/java/android/app/ActivityManagerInternal.java9
-rw-r--r--core/java/android/app/Instrumentation.java92
-rw-r--r--core/java/android/hardware/input/IInputManager.aidl7
-rw-r--r--core/java/android/hardware/input/InputManager.java47
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java6
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java6
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java81
-rw-r--r--services/core/java/com/android/server/logcat/LogcatManagerService.java3
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp33
9 files changed, 182 insertions, 102 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index c022bf370e7e..faf64c2ec22b 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -562,14 +562,15 @@ public abstract class ActivityManagerInternal {
public abstract void unregisterProcessObserver(IProcessObserver processObserver);
/**
- * Checks if there is an unfinished instrumentation that targets the given uid.
+ * Gets the uid of the instrumentation source if there is an unfinished instrumentation that
+ * targets the given uid.
*
* @param uid The uid to be checked for
*
- * @return True, if there is an instrumentation whose target application uid matches the given
- * uid, false otherwise
+ * @return the uid of the instrumentation source, if there is an instrumentation whose target
+ * application uid matches the given uid, and {@link android.os.Process#INVALID_UID} otherwise.
*/
- public abstract boolean isUidCurrentlyInstrumented(int uid);
+ public abstract int getInstrumentationSourceUid(int uid);
/** Is this a device owner app? */
public abstract boolean isDeviceOwner(int uid);
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 638b30e3b46f..e9df50f1d987 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1058,10 +1058,11 @@ public class Instrumentation {
}
/**
- * Sends the key events corresponding to the text to the app being
- * instrumented.
- *
- * @param text The text to be sent.
+ * Sends the key events that result in the given text being typed into the currently focused
+ * window, and waits for it to be processed.
+ *
+ * @param text The text to be sent.
+ * @see #sendKeySync(KeyEvent)
*/
public void sendStringSync(String text) {
if (text == null) {
@@ -1084,11 +1085,12 @@ public class Instrumentation {
}
/**
- * Send a key event to the currently focused window/view and wait for it to
- * be processed. Finished at some point after the recipient has returned
- * from its event processing, though it may <em>not</em> have completely
- * finished reacting from the event -- for example, if it needs to update
- * its display as a result, it may still be in the process of doing that.
+ * Sends a key event to the currently focused window, and waits for it to be processed.
+ * <p>
+ * This method blocks until the recipient has finished handling the event. Note that the
+ * recipient may <em>not</em> have completely finished reacting from the event when this method
+ * returns. For example, it may still be in the process of updating its display or UI contents
+ * upon reacting to the injected event.
*
* @param event The event to send to the current focus.
*/
@@ -1116,34 +1118,42 @@ public class Instrumentation {
}
/**
- * Sends an up and down key event sync to the currently focused window.
+ * Sends up and down key events with the given key code to the currently focused window, and
+ * waits for it to be processed.
*
- * @param key The integer keycode for the event.
+ * @param keyCode The key code for the events to send.
+ * @see #sendKeySync(KeyEvent)
*/
- public void sendKeyDownUpSync(int key) {
- sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
- sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
+ public void sendKeyDownUpSync(int keyCode) {
+ sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
+ sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
}
/**
- * Higher-level method for sending both the down and up key events for a
- * particular character key code. Equivalent to creating both KeyEvent
- * objects by hand and calling {@link #sendKeySync}. The event appears
- * as if it came from keyboard 0, the built in one.
- *
+ * Sends up and down key events with the given key code to the currently focused window, and
+ * waits for it to be processed.
+ * <p>
+ * Equivalent to {@link #sendKeyDownUpSync(int)}.
+ *
* @param keyCode The key code of the character to send.
+ * @see #sendKeySync(KeyEvent)
*/
public void sendCharacterSync(int keyCode) {
- sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
- sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
+ sendKeyDownUpSync(keyCode);
}
-
+
/**
- * Dispatch a pointer event. Finished at some point after the recipient has
- * returned from its event processing, though it may <em>not</em> have
- * completely finished reacting from the event -- for example, if it needs
- * to update its display as a result, it may still be in the process of
- * doing that.
+ * Dispatches a pointer event into a window owned by the instrumented application, and waits for
+ * it to be processed.
+ * <p>
+ * If the motion event being injected is targeted at a window that is not owned by the
+ * instrumented application, the input injection will fail. See {@link #getUiAutomation()} for
+ * injecting events into all windows.
+ * <p>
+ * This method blocks until the recipient has finished handling the event. Note that the
+ * recipient may <em>not</em> have completely finished reacting from the event when this method
+ * returns. For example, it may still be in the process of updating its display or UI contents
+ * upon reacting to the injected event.
*
* @param event A motion event describing the pointer action. (As noted in
* {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
@@ -1155,10 +1165,10 @@ public class Instrumentation {
event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
}
- syncInputTransactionsAndInjectEvent(event);
+ syncInputTransactionsAndInjectEventIntoSelf(event);
}
- private void syncInputTransactionsAndInjectEvent(MotionEvent event) {
+ private void syncInputTransactionsAndInjectEventIntoSelf(MotionEvent event) {
final boolean syncBefore = event.getAction() == MotionEvent.ACTION_DOWN
|| event.isFromSource(InputDevice.SOURCE_MOUSE);
final boolean syncAfter = event.getAction() == MotionEvent.ACTION_UP;
@@ -1169,8 +1179,9 @@ public class Instrumentation {
.syncInputTransactions(true /*waitForAnimations*/);
}
+ // Direct the injected event into windows owned by the instrumentation target.
InputManager.getInstance().injectInputEvent(
- event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT);
+ event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT, Process.myUid());
if (syncAfter) {
WindowManagerGlobal.getWindowManagerService()
@@ -1182,19 +1193,26 @@ public class Instrumentation {
}
/**
- * Dispatch a trackball event. Finished at some point after the recipient has
- * returned from its event processing, though it may <em>not</em> have
- * completely finished reacting from the event -- for example, if it needs
- * to update its display as a result, it may still be in the process of
- * doing that.
- *
+ * Dispatches a trackball event into the currently focused window, and waits for it to be
+ * processed.
+ * <p>
+ * This method blocks until the recipient has finished handling the event. Note that the
+ * recipient may <em>not</em> have completely finished reacting from the event when this method
+ * returns. For example, it may still be in the process of updating its display or UI contents
+ * upon reacting to the injected event.
+ *
* @param event A motion event describing the trackball action. (As noted in
* {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
* {@link SystemClock#uptimeMillis()} as the timebase.
*/
public void sendTrackballEventSync(MotionEvent event) {
validateNotAppThread();
- if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
+ if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
+ throw new IllegalArgumentException(
+ "Cannot inject pointer events from sendTrackballEventSync()."
+ + " Use sendPointerSync() to inject pointer events.");
+ }
+ if (!event.isFromSource(InputDevice.SOURCE_CLASS_TRACKBALL)) {
event.setSource(InputDevice.SOURCE_TRACKBALL);
}
InputManager.getInstance().injectInputEvent(event,
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index e1ffd4a6761d..57e84bdb686d 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -57,10 +57,11 @@ interface IInputManager {
// Temporarily changes the pointer speed.
void tryPointerSpeed(int speed);
- // Injects an input event into the system. To inject into windows owned by other
- // applications, the caller must have the INJECT_EVENTS permission.
+ // Injects an input event into the system. The caller must have the INJECT_EVENTS permission.
+ // The caller can target windows owned by a certain UID by providing a valid UID, or by
+ // providing {@link android.os.Process#INVALID_UID} to target all windows.
@UnsupportedAppUsage
- boolean injectInputEvent(in InputEvent ev, int mode);
+ boolean injectInputEvent(in InputEvent ev, int mode, int targetUid);
VerifiedInputEvent verifyInputEvent(in InputEvent ev);
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index c38a847dfb9f..7a258599250a 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -45,6 +45,7 @@ import android.os.IVibratorStateListener;
import android.os.InputEventInjectionSync;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
@@ -1107,14 +1108,18 @@ public final class InputManager {
}
}
-
/**
- * Injects an input event into the event system on behalf of an application.
+ * Injects an input event into the event system, targeting windows owned by the provided uid.
+ *
+ * If a valid targetUid is provided, the system 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 and a RemoteException will be
+ * thrown.
+ *
* The synchronization mode determines whether the method blocks while waiting for
* input injection to proceed.
* <p>
- * Requires {@link android.Manifest.permission.INJECT_EVENTS} to inject into
- * windows that are owned by other applications.
+ * Requires the {@link android.Manifest.permission.INJECT_EVENTS} permission.
* </p><p>
* Make sure you correctly set the event time and input source of the event
* before calling this method.
@@ -1125,12 +1130,14 @@ public final class InputManager {
* {@link android.os.InputEventInjectionSync.NONE},
* {@link android.os.InputEventInjectionSync.WAIT_FOR_RESULT}, or
* {@link android.os.InputEventInjectionSync.WAIT_FOR_FINISHED}.
+ * @param targetUid The uid to target, or {@link android.os.Process#INVALID_UID} to target all
+ * windows.
* @return True if input event injection succeeded.
*
* @hide
*/
- @UnsupportedAppUsage
- public boolean injectInputEvent(InputEvent event, int mode) {
+ @RequiresPermission(Manifest.permission.INJECT_EVENTS)
+ public boolean injectInputEvent(InputEvent event, int mode, int targetUid) {
if (event == null) {
throw new IllegalArgumentException("event must not be null");
}
@@ -1141,13 +1148,39 @@ public final class InputManager {
}
try {
- return mIm.injectInputEvent(event, mode);
+ return mIm.injectInputEvent(event, mode, targetUid);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
/**
+ * Injects an input event into the event system on behalf of an application.
+ * The synchronization mode determines whether the method blocks while waiting for
+ * input injection to proceed.
+ * <p>
+ * Requires the {@link android.Manifest.permission.INJECT_EVENTS} permission.
+ * </p><p>
+ * Make sure you correctly set the event time and input source of the event
+ * before calling this method.
+ * </p>
+ *
+ * @param event The event to inject.
+ * @param mode The synchronization mode. One of:
+ * {@link android.os.InputEventInjectionSync.NONE},
+ * {@link android.os.InputEventInjectionSync.WAIT_FOR_RESULT}, or
+ * {@link android.os.InputEventInjectionSync.WAIT_FOR_FINISHED}.
+ * @return True if input event injection succeeded.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.INJECT_EVENTS)
+ @UnsupportedAppUsage
+ public boolean injectInputEvent(InputEvent event, int mode) {
+ return injectInputEvent(event, mode, Process.INVALID_UID);
+ }
+
+ /**
* Verify the details of an {@link android.view.InputEvent} that came from the system.
* If the event did not come from the system, or its details could not be verified, then this
* will return {@code null}. Receiving {@code null} does not mean that the event did not
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2904b74df7ea..b900c428b69b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17234,17 +17234,17 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
- public boolean isUidCurrentlyInstrumented(int uid) {
+ public int getInstrumentationSourceUid(int uid) {
synchronized (mProcLock) {
for (int i = mActiveInstrumentation.size() - 1; i >= 0; i--) {
ActiveInstrumentation activeInst = mActiveInstrumentation.get(i);
if (!activeInst.mFinished && activeInst.mTargetInfo != null
&& activeInst.mTargetInfo.uid == uid) {
- return true;
+ return activeInst.mSourceUid;
}
}
}
- return false;
+ return INVALID_UID;
}
@Override
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 361629b0a629..752e17e59a6e 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -2367,7 +2367,8 @@ public class AppOpsService extends IAppOpsService.Stub {
ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
boolean isSelfRequest = (filter & FILTER_BY_UID) != 0 && uid == Binder.getCallingUid();
if (!isSelfRequest) {
- boolean isCallerInstrumented = ami.isUidCurrentlyInstrumented(Binder.getCallingUid());
+ boolean isCallerInstrumented =
+ ami.getInstrumentationSourceUid(Binder.getCallingUid()) != Process.INVALID_UID;
boolean isCallerSystem = Binder.getCallingPid() == Process.myPid();
boolean isCallerPermissionController;
try {
@@ -6894,7 +6895,8 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public @Nullable RuntimeAppOpAccessMessage collectRuntimeAppOpAccessMessage() {
ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
- boolean isCallerInstrumented = ami.isUidCurrentlyInstrumented(Binder.getCallingUid());
+ boolean isCallerInstrumented =
+ ami.getInstrumentationSourceUid(Binder.getCallingUid()) != Process.INVALID_UID;
boolean isCallerSystem = Binder.getCallingPid() == Process.myPid();
if (!isCallerSystem && !isCallerInstrumented) {
return null;
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 7360bbc5e54d..385aa698543d 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -20,6 +20,7 @@ import static android.view.KeyEvent.KEYCODE_UNKNOWN;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManagerInternal;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -325,8 +326,7 @@ public class InputManagerService extends IInputManager.Stub
private static native void nativeSetMaximumObscuringOpacityForTouch(long ptr, float opacity);
private static native void nativeSetBlockUntrustedTouchesMode(long ptr, int mode);
private static native int nativeInjectInputEvent(long ptr, InputEvent event,
- int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
- int policyFlags);
+ boolean injectIntoUid, int uid, int syncMode, int timeoutMillis, int policyFlags);
private static native VerifiedInputEvent nativeVerifyInputEvent(long ptr, InputEvent event);
private static native void nativeToggleCapsLock(long ptr, int deviceId);
private static native void nativeDisplayRemoved(long ptr, int displayId);
@@ -897,7 +897,15 @@ public class InputManagerService extends IInputManager.Stub
}
@Override // Binder call
- public boolean injectInputEvent(InputEvent event, int mode) {
+ public boolean injectInputEvent(InputEvent event, int mode, int targetUid) {
+ if (!checkCallingPermission(android.Manifest.permission.INJECT_EVENTS,
+ "injectInputEvent()", true /*checkInstrumentationSource*/)) {
+ throw new SecurityException(
+ "Injecting input events requires the caller (or the source of the "
+ + "instrumentation, if any) to have the INJECT_EVENTS permission.");
+ }
+ // We are not checking if targetUid matches the callingUid, since having the permission
+ // already means you can inject into any window.
Objects.requireNonNull(event, "event must not be null");
if (mode != InputEventInjectionSync.NONE
&& mode != InputEventInjectionSync.WAIT_FOR_FINISHED
@@ -906,22 +914,41 @@ public class InputManagerService extends IInputManager.Stub
}
final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
+ final boolean injectIntoUid = targetUid != Process.INVALID_UID;
final int result;
try {
- result = nativeInjectInputEvent(mPtr, event, pid, uid, mode,
- INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
+ result = nativeInjectInputEvent(mPtr, event, injectIntoUid,
+ targetUid, mode, INJECTION_TIMEOUT_MILLIS,
+ WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
} finally {
Binder.restoreCallingIdentity(ident);
}
switch (result) {
- case InputEventInjectionResult.PERMISSION_DENIED:
- Slog.w(TAG, "Input event injection from pid " + pid + " permission denied.");
- throw new SecurityException(
- "Injecting to another application requires INJECT_EVENTS permission");
case InputEventInjectionResult.SUCCEEDED:
return true;
+ case InputEventInjectionResult.TARGET_MISMATCH:
+ if (!injectIntoUid) {
+ throw new IllegalStateException("Injection should not result in TARGET_MISMATCH"
+ + " when it is not targeted into to a specific uid.");
+ }
+ // Attempt to inject into a window owned by the instrumentation source of the caller
+ // because it is possible that tests adopt the identity of the shell when launching
+ // activities that they would like to inject into.
+ final ActivityManagerInternal ami =
+ LocalServices.getService(ActivityManagerInternal.class);
+ Objects.requireNonNull(ami, "ActivityManagerInternal should not be null.");
+ final int instrUid = ami.getInstrumentationSourceUid(Binder.getCallingUid());
+ if (instrUid != Process.INVALID_UID && targetUid != instrUid) {
+ Slog.w(TAG, "Targeted input event was not directed at a window owned by uid "
+ + targetUid + ". Attempting to inject into window owned by "
+ + "instrumentation source uid " + instrUid + ".");
+ return injectInputEvent(event, mode, instrUid);
+ }
+ throw new IllegalArgumentException(
+ "Targeted input event injection from pid " + pid
+ + " was not directed at a window owned by uid "
+ + targetUid + ".");
case InputEventInjectionResult.TIMED_OUT:
Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");
return false;
@@ -2757,8 +2784,12 @@ public class InputManagerService extends IInputManager.Stub
}
}
}
-
private boolean checkCallingPermission(String permission, String func) {
+ return checkCallingPermission(permission, func, false /*checkInstrumentationSource*/);
+ }
+
+ private boolean checkCallingPermission(String permission, String func,
+ boolean checkInstrumentationSource) {
// Quick check: if the calling permission is me, it's all okay.
if (Binder.getCallingPid() == Process.myPid()) {
return true;
@@ -2767,6 +2798,18 @@ public class InputManagerService extends IInputManager.Stub
if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
return true;
}
+
+ if (checkInstrumentationSource) {
+ final ActivityManagerInternal ami =
+ LocalServices.getService(ActivityManagerInternal.class);
+ Objects.requireNonNull(ami, "ActivityManagerInternal should not be null.");
+ final int instrumentationUid = ami.getInstrumentationSourceUid(Binder.getCallingUid());
+ if (instrumentationUid != Process.INVALID_UID && mContext.checkPermission(permission,
+ -1 /*pid*/, instrumentationUid) == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ }
+
String msg = "Permission Denial: " + func + " from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid()
@@ -3012,13 +3055,6 @@ public class InputManagerService extends IInputManager.Stub
// Native callback.
@SuppressWarnings("unused")
- private boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
- return mContext.checkPermission(android.Manifest.permission.INJECT_EVENTS,
- injectorPid, injectorUid) == PackageManager.PERMISSION_GRANTED;
- }
-
- // Native callback.
- @SuppressWarnings("unused")
private void onPointerDownOutsideFocus(IBinder touchedToken) {
mWindowManagerCallbacks.onPointerDownOutsideFocus(touchedToken);
}
@@ -3459,12 +3495,17 @@ public class InputManagerService extends IInputManager.Stub
@Override
public void sendInputEvent(InputEvent event, int policyFlags) {
+ if (!checkCallingPermission(android.Manifest.permission.INJECT_EVENTS,
+ "sendInputEvent()")) {
+ throw new SecurityException(
+ "The INJECT_EVENTS permission is required for injecting input events.");
+ }
Objects.requireNonNull(event, "event must not be null");
synchronized (mInputFilterLock) {
if (!mDisconnected) {
- nativeInjectInputEvent(mPtr, event, 0, 0,
- InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
+ nativeInjectInputEvent(mPtr, event, false /* injectIntoUid */, -1 /* uid */,
+ InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0 /* timeout */,
policyFlags | WindowManagerPolicy.FLAG_FILTERED);
}
}
diff --git a/services/core/java/com/android/server/logcat/LogcatManagerService.java b/services/core/java/com/android/server/logcat/LogcatManagerService.java
index 0aa384cedbf1..015bf3c5e390 100644
--- a/services/core/java/com/android/server/logcat/LogcatManagerService.java
+++ b/services/core/java/com/android/server/logcat/LogcatManagerService.java
@@ -183,7 +183,8 @@ public final class LogcatManagerService extends SystemService {
ActivityManagerInternal ami = LocalServices.getService(
ActivityManagerInternal.class);
- boolean isCallerInstrumented = ami.isUidCurrentlyInstrumented(mUid);
+ boolean isCallerInstrumented =
+ ami.getInstrumentationSourceUid(mUid) != android.os.Process.INVALID_UID;
// The instrumented apks only run for testing, so we don't check user permission.
if (isCallerInstrumented) {
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 31b557949e36..17016a6eb314 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -106,7 +106,6 @@ static struct {
jmethodID interceptMotionBeforeQueueingNonInteractive;
jmethodID interceptKeyBeforeDispatching;
jmethodID dispatchUnhandledKey;
- jmethodID checkInjectEventsPermission;
jmethodID onPointerDownOutsideFocus;
jmethodID getVirtualKeyQuietTimeMillis;
jmethodID getExcludedDeviceNames;
@@ -329,7 +328,6 @@ public:
bool dispatchUnhandledKey(const sp<IBinder>& token, const KeyEvent* keyEvent,
uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) override;
void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) override;
- bool checkInjectEventsPermissionNonReentrant(int32_t injectorPid, int32_t injectorUid) override;
void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) override;
void setPointerCapture(const PointerCaptureRequest& request) override;
void notifyDropWindow(const sp<IBinder>& token, float x, float y) override;
@@ -1368,18 +1366,6 @@ void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType,
android_server_PowerManagerService_userActivity(eventTime, eventType, displayId);
}
-bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
- int32_t injectorPid, int32_t injectorUid) {
- ATRACE_CALL();
- JNIEnv* env = jniEnv();
- jboolean result = env->CallBooleanMethod(mServiceObj,
- gServiceClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
- if (checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission")) {
- result = false;
- }
- return result;
-}
-
void NativeInputManager::onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) {
ATRACE_CALL();
JNIEnv* env = jniEnv();
@@ -1706,11 +1692,12 @@ static void nativeSetBlockUntrustedTouchesMode(JNIEnv* env, jclass /* clazz */,
static_cast<BlockUntrustedTouchesMode>(mode));
}
-static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */,
- jlong ptr, jobject inputEventObj, jint injectorPid, jint injectorUid,
- jint syncMode, jint timeoutMillis, jint policyFlags) {
+static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */, jlong ptr,
+ jobject inputEventObj, jboolean injectIntoUid, jint uid,
+ jint syncMode, jint timeoutMillis, jint policyFlags) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+ const std::optional<int32_t> targetUid = injectIntoUid ? std::make_optional(uid) : std::nullopt;
// static_cast is safe because the value was already checked at the Java layer
InputEventInjectionSync mode = static_cast<InputEventInjectionSync>(syncMode);
@@ -1723,8 +1710,7 @@ static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */,
}
const InputEventInjectionResult result =
- im->getInputManager()->getDispatcher().injectInputEvent(&keyEvent, injectorPid,
- injectorUid, mode,
+ im->getInputManager()->getDispatcher().injectInputEvent(&keyEvent, targetUid, mode,
std::chrono::milliseconds(
timeoutMillis),
uint32_t(policyFlags));
@@ -1737,8 +1723,8 @@ static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */,
}
const InputEventInjectionResult result =
- im->getInputManager()->getDispatcher().injectInputEvent(motionEvent, injectorPid,
- injectorUid, mode,
+ im->getInputManager()->getDispatcher().injectInputEvent(motionEvent, targetUid,
+ mode,
std::chrono::milliseconds(
timeoutMillis),
uint32_t(policyFlags));
@@ -2359,7 +2345,7 @@ static const JNINativeMethod gInputManagerMethods[] = {
{"nativeSetMaximumObscuringOpacityForTouch", "(JF)V",
(void*)nativeSetMaximumObscuringOpacityForTouch},
{"nativeSetBlockUntrustedTouchesMode", "(JI)V", (void*)nativeSetBlockUntrustedTouchesMode},
- {"nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIII)I",
+ {"nativeInjectInputEvent", "(JLandroid/view/InputEvent;ZIIII)I",
(void*)nativeInjectInputEvent},
{"nativeVerifyInputEvent", "(JLandroid/view/InputEvent;)Landroid/view/VerifiedInputEvent;",
(void*)nativeVerifyInputEvent},
@@ -2499,9 +2485,6 @@ int register_android_server_InputManager(JNIEnv* env) {
"dispatchUnhandledKey",
"(Landroid/os/IBinder;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
- GET_METHOD_ID(gServiceClassInfo.checkInjectEventsPermission, clazz,
- "checkInjectEventsPermission", "(II)Z");
-
GET_METHOD_ID(gServiceClassInfo.onPointerDownOutsideFocus, clazz,
"onPointerDownOutsideFocus", "(Landroid/os/IBinder;)V");