diff options
10 files changed, 203 insertions, 99 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 49a5c9f78230..f2ea060b1694 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -568,14 +568,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 99d7c63cde42..8984c4292023 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_FINISH); + event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH, Process.myUid()); if (syncAfter) { WindowManagerGlobal.getWindowManagerService() @@ -1182,19 +1193,21 @@ 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_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..2da12e6c5c9d 100644 --- a/core/java/android/hardware/input/IInputManager.aidl +++ b/core/java/android/hardware/input/IInputManager.aidl @@ -57,11 +57,16 @@ 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 permssion. + // This method exists only for compatibility purposes and may be removed in a future release. @UnsupportedAppUsage boolean injectInputEvent(in InputEvent ev, int mode); + // 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. + boolean injectInputEventToTarget(in InputEvent ev, int mode, int targetUid); + VerifiedInputEvent verifyInputEvent(in InputEvent ev); // Calibrate input device position diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index cc5b275bbf5a..d17a9523ab37 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.injectInputEventToTarget(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 dea8cc015272..7e624e05405c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -17195,17 +17195,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 36afb3677438..8cef0b0130f6 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -2368,7 +2368,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 { @@ -6924,7 +6925,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 e4e9d1d49a6e..b624d438a4f7 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; @@ -860,6 +861,19 @@ public class InputManagerService extends IInputManager.Stub @Override // Binder call public boolean injectInputEvent(InputEvent event, int mode) { + return injectInputEventToTarget(event, mode, Process.INVALID_UID); + } + + @Override // Binder call + public boolean injectInputEventToTarget(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 @@ -868,22 +882,39 @@ 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 = mNative.injectInputEvent(event, pid, uid, mode, - INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT); + result = mNative.injectInputEvent(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."); + } + // TODO(b/228161340): Remove the fallback of targeting injection into all windows + // when the caller has the injection permission. + // Explicitly maintain the same behavior as previous versions of Android, where + // injection is allowed into all windows if the caller has the INJECT_EVENTS + // permission, even if it is targeting a certain uid. + if (checkCallingPermission(android.Manifest.permission.INJECT_EVENTS, + "injectInputEvent-target-mismatch-fallback")) { + Slog.w(TAG, "Targeted input event was not directed at a window owned by uid " + + targetUid + ". Falling back to injecting into all windows."); + return injectInputEventToTarget(event, mode, Process.INVALID_UID); + } + 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; @@ -2780,8 +2811,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; @@ -2790,6 +2825,28 @@ 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) { + // Clear the calling identity when checking if the instrumentation source has + // permission because PackageManager will deny all permissions to some callers, + // such as instant apps. + final long token = Binder.clearCallingIdentity(); + try { + if (mContext.checkPermission(permission, -1 /*pid*/, instrumentationUid) + == PackageManager.PERMISSION_GRANTED) { + return true; + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + } + String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() @@ -3035,13 +3092,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); } @@ -3501,12 +3551,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) { - mNative.injectInputEvent(event, 0, 0, - InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0, + mNative.injectInputEvent(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/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java index 81882d277a99..9cf80737e67d 100644 --- a/services/core/java/com/android/server/input/NativeInputManagerService.java +++ b/services/core/java/com/android/server/input/NativeInputManagerService.java @@ -70,7 +70,18 @@ public interface NativeInputManagerService { void setBlockUntrustedTouchesMode(int mode); - int injectInputEvent(InputEvent event, int pid, int uid, int syncMode, + /** + * Inject an input event into the system. + * + * @param event the input event to inject + * @param injectIntoUid true if the event should target windows owned by uid, false otherwise + * @param uid the uid whose windows should be targeted, if any + * @param syncMode {@link android.os.InputEventInjectionSync} + * @param timeoutMillis timeout to wait for input injection to complete, in milliseconds + * @param policyFlags defined in {@link android.view.WindowManagerPolicyConstants} + * @return {@link android.os.InputEventInjectionResult} + */ + int injectInputEvent(InputEvent event, boolean injectIntoUid, int uid, int syncMode, int timeoutMillis, int policyFlags); VerifiedInputEvent verifyInputEvent(InputEvent event); @@ -240,7 +251,8 @@ public interface NativeInputManagerService { public native void setBlockUntrustedTouchesMode(int mode); @Override - public native int injectInputEvent(InputEvent event, int pid, int uid, int syncMode, + public native int injectInputEvent(InputEvent event, boolean injectIntoUid, int uid, + int syncMode, int timeoutMillis, int policyFlags); @Override diff --git a/services/core/java/com/android/server/logcat/LogcatManagerService.java b/services/core/java/com/android/server/logcat/LogcatManagerService.java index 21beb964529a..1bcc21e66302 100644 --- a/services/core/java/com/android/server/logcat/LogcatManagerService.java +++ b/services/core/java/com/android/server/logcat/LogcatManagerService.java @@ -410,7 +410,8 @@ public final class LogcatManagerService extends SystemService { } private void processNewLogAccessRequest(LogAccessClient client) { - boolean isInstrumented = mActivityManagerInternal.isUidCurrentlyInstrumented(client.mUid); + boolean isInstrumented = mActivityManagerInternal.getInstrumentationSourceUid(client.mUid) + != android.os.Process.INVALID_UID; // The instrumented apks only run for testing, so we don't check user permission. if (isInstrumented) { diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 32adac7f282b..287fb8219650 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 onPointerDisplayIdChanged; jmethodID onPointerDownOutsideFocus; jmethodID getVirtualKeyQuietTimeMillis; @@ -333,7 +332,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; @@ -1380,19 +1378,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(); @@ -1709,10 +1694,11 @@ static void nativeSetBlockUntrustedTouchesMode(JNIEnv* env, jobject nativeImplOb } static jint nativeInjectInputEvent(JNIEnv* env, jobject nativeImplObj, jobject inputEventObj, - jint injectorPid, jint injectorUid, jint syncMode, + jboolean injectIntoUid, jint uid, jint syncMode, jint timeoutMillis, jint policyFlags) { NativeInputManager* im = getNativeInputManager(env, nativeImplObj); + 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); @@ -1725,8 +1711,7 @@ static jint nativeInjectInputEvent(JNIEnv* env, jobject nativeImplObj, jobject i } 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)); @@ -1739,8 +1724,8 @@ static jint nativeInjectInputEvent(JNIEnv* env, jobject nativeImplObj, jobject i } 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)); @@ -2345,7 +2330,7 @@ static const JNINativeMethod gInputManagerMethods[] = { {"setMaximumObscuringOpacityForTouch", "(F)V", (void*)nativeSetMaximumObscuringOpacityForTouch}, {"setBlockUntrustedTouchesMode", "(I)V", (void*)nativeSetBlockUntrustedTouchesMode}, - {"injectInputEvent", "(Landroid/view/InputEvent;IIIII)I", (void*)nativeInjectInputEvent}, + {"injectInputEvent", "(Landroid/view/InputEvent;ZIIII)I", (void*)nativeInjectInputEvent}, {"verifyInputEvent", "(Landroid/view/InputEvent;)Landroid/view/VerifiedInputEvent;", (void*)nativeVerifyInputEvent}, {"toggleCapsLock", "(I)V", (void*)nativeToggleCapsLock}, @@ -2492,9 +2477,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.onPointerDisplayIdChanged, clazz, "onPointerDisplayIdChanged", "(IFF)V"); |