diff options
10 files changed, 101 insertions, 177 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 9c391abe6204..157319cca8a7 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -562,15 +562,14 @@ public abstract class ActivityManagerInternal { public abstract void unregisterProcessObserver(IProcessObserver processObserver); /** - * Gets the uid of the instrumentation source if there is an unfinished instrumentation that - * targets the given uid. + * Checks if there is an unfinished instrumentation that targets the given uid. * * @param uid The uid to be checked for * - * @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. + * @return True, if there is an instrumentation whose target application uid matches the given + * uid, false otherwise */ - public abstract int getInstrumentationSourceUid(int uid); + public abstract boolean isUidCurrentlyInstrumented(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 8984c4292023..99d7c63cde42 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -1058,11 +1058,10 @@ public class Instrumentation { } /** - * 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) + * Sends the key events corresponding to the text to the app being + * instrumented. + * + * @param text The text to be sent. */ public void sendStringSync(String text) { if (text == null) { @@ -1085,12 +1084,11 @@ public class Instrumentation { } /** - * 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. + * 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. * * @param event The event to send to the current focus. */ @@ -1118,42 +1116,34 @@ public class Instrumentation { } /** - * Sends up and down key events with the given key code to the currently focused window, and - * waits for it to be processed. + * Sends an up and down key event sync to the currently focused window. * - * @param keyCode The key code for the events to send. - * @see #sendKeySync(KeyEvent) + * @param key The integer keycode for the event. */ - public void sendKeyDownUpSync(int keyCode) { - sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode)); - sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode)); + public void sendKeyDownUpSync(int key) { + sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key)); + sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key)); } /** - * 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)}. - * + * 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. + * * @param keyCode The key code of the character to send. - * @see #sendKeySync(KeyEvent) */ public void sendCharacterSync(int keyCode) { - sendKeyDownUpSync(keyCode); + sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode)); + sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode)); } - + /** - * 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. + * 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. * * @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 @@ -1165,10 +1155,10 @@ public class Instrumentation { event.setSource(InputDevice.SOURCE_TOUCHSCREEN); } - syncInputTransactionsAndInjectEventIntoSelf(event); + syncInputTransactionsAndInjectEvent(event); } - private void syncInputTransactionsAndInjectEventIntoSelf(MotionEvent event) { + private void syncInputTransactionsAndInjectEvent(MotionEvent event) { final boolean syncBefore = event.getAction() == MotionEvent.ACTION_DOWN || event.isFromSource(InputDevice.SOURCE_MOUSE); final boolean syncAfter = event.getAction() == MotionEvent.ACTION_UP; @@ -1179,9 +1169,8 @@ 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, Process.myUid()); + event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); if (syncAfter) { WindowManagerGlobal.getWindowManagerService() @@ -1193,21 +1182,19 @@ public class Instrumentation { } /** - * 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. - * + * 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. + * * @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.isFromSource(InputDevice.SOURCE_CLASS_TRACKBALL)) { + if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) { 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 57e84bdb686d..e1ffd4a6761d 100644 --- a/core/java/android/hardware/input/IInputManager.aidl +++ b/core/java/android/hardware/input/IInputManager.aidl @@ -57,11 +57,10 @@ interface IInputManager { // Temporarily changes the pointer speed. void tryPointerSpeed(int speed); - // 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. + // Injects an input event into the system. To inject into windows owned by other + // applications, the caller must have the INJECT_EVENTS permission. @UnsupportedAppUsage - boolean injectInputEvent(in InputEvent ev, int mode, int targetUid); + boolean injectInputEvent(in InputEvent ev, int mode); VerifiedInputEvent verifyInputEvent(in InputEvent ev); diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 0bcabddddf51..cc5b275bbf5a 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -45,7 +45,6 @@ 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; @@ -1108,18 +1107,14 @@ public final class InputManager { } } + /** - * 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. - * + * 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. + * Requires {@link android.Manifest.permission.INJECT_EVENTS} to inject into + * windows that are owned by other applications. * </p><p> * Make sure you correctly set the event time and input source of the event * before calling this method. @@ -1130,14 +1125,12 @@ 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 */ - @RequiresPermission(Manifest.permission.INJECT_EVENTS) - public boolean injectInputEvent(InputEvent event, int mode, int targetUid) { + @UnsupportedAppUsage + public boolean injectInputEvent(InputEvent event, int mode) { if (event == null) { throw new IllegalArgumentException("event must not be null"); } @@ -1148,39 +1141,13 @@ public final class InputManager { } try { - return mIm.injectInputEvent(event, mode, targetUid); + return mIm.injectInputEvent(event, mode); } 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 ba1a19906af9..cddd019093c7 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -17203,17 +17203,17 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public int getInstrumentationSourceUid(int uid) { + public boolean isUidCurrentlyInstrumented(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 activeInst.mSourceUid; + return true; } } } - return INVALID_UID; + return false; } @Override diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 752e17e59a6e..361629b0a629 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -2367,8 +2367,7 @@ 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.getInstrumentationSourceUid(Binder.getCallingUid()) != Process.INVALID_UID; + boolean isCallerInstrumented = ami.isUidCurrentlyInstrumented(Binder.getCallingUid()); boolean isCallerSystem = Binder.getCallingPid() == Process.myPid(); boolean isCallerPermissionController; try { @@ -6895,8 +6894,7 @@ public class AppOpsService extends IAppOpsService.Stub { @Override public @Nullable RuntimeAppOpAccessMessage collectRuntimeAppOpAccessMessage() { ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class); - boolean isCallerInstrumented = - ami.getInstrumentationSourceUid(Binder.getCallingUid()) != Process.INVALID_UID; + boolean isCallerInstrumented = ami.isUidCurrentlyInstrumented(Binder.getCallingUid()); 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 71afc40831c5..8ab0b931be11 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -20,7 +20,6 @@ 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; @@ -838,15 +837,7 @@ public class InputManagerService extends IInputManager.Stub } @Override // Binder call - 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. + public boolean injectInputEvent(InputEvent event, int mode) { Objects.requireNonNull(event, "event must not be null"); if (mode != InputEventInjectionSync.NONE && mode != InputEventInjectionSync.WAIT_FOR_FINISHED @@ -855,41 +846,22 @@ 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, injectIntoUid, - targetUid, mode, INJECTION_TIMEOUT_MILLIS, - WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT); + result = mNative.injectInputEvent(event, pid, uid, 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; @@ -2725,12 +2697,8 @@ 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) { + private boolean checkCallingPermission(String permission, String func) { // Quick check: if the calling permission is me, it's all okay. if (Binder.getCallingPid() == Process.myPid()) { return true; @@ -2739,18 +2707,6 @@ 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() @@ -2996,6 +2952,13 @@ 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); } @@ -3436,17 +3399,12 @@ 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, false /* injectIntoUid */, -1 /* uid */, - InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0 /* timeout */, + mNative.injectInputEvent(event, 0, 0, + InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0, 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 854170ef79bd..2169155343cd 100644 --- a/services/core/java/com/android/server/input/NativeInputManagerService.java +++ b/services/core/java/com/android/server/input/NativeInputManagerService.java @@ -70,7 +70,7 @@ public interface NativeInputManagerService { void setBlockUntrustedTouchesMode(int mode); - int injectInputEvent(InputEvent event, boolean injectIntoUid, int uid, int syncMode, + int injectInputEvent(InputEvent event, int pid, int uid, int syncMode, int timeoutMillis, int policyFlags); VerifiedInputEvent verifyInputEvent(InputEvent event); @@ -237,8 +237,7 @@ public interface NativeInputManagerService { public native void setBlockUntrustedTouchesMode(int mode); @Override - public native int injectInputEvent(InputEvent event, boolean injectIntoUid, int uid, - int syncMode, + public native int injectInputEvent(InputEvent event, int pid, 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 4c265ad5ff88..f856193bca9f 100644 --- a/services/core/java/com/android/server/logcat/LogcatManagerService.java +++ b/services/core/java/com/android/server/logcat/LogcatManagerService.java @@ -192,8 +192,7 @@ public final class LogcatManagerService extends SystemService { ActivityManagerInternal ami = LocalServices.getService( ActivityManagerInternal.class); - boolean isCallerInstrumented = - ami.getInstrumentationSourceUid(mUid) != android.os.Process.INVALID_UID; + boolean isCallerInstrumented = ami.isUidCurrentlyInstrumented(mUid); // 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 479ddcea5956..3c5ebe7c62ee 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -106,6 +106,7 @@ static struct { jmethodID interceptMotionBeforeQueueingNonInteractive; jmethodID interceptKeyBeforeDispatching; jmethodID dispatchUnhandledKey; + jmethodID checkInjectEventsPermission; jmethodID onPointerDownOutsideFocus; jmethodID getVirtualKeyQuietTimeMillis; jmethodID getExcludedDeviceNames; @@ -332,6 +333,7 @@ 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; @@ -1369,6 +1371,19 @@ 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(); @@ -1697,11 +1712,10 @@ static void nativeSetBlockUntrustedTouchesMode(JNIEnv* env, jobject nativeImplOb } static jint nativeInjectInputEvent(JNIEnv* env, jobject nativeImplObj, jobject inputEventObj, - jboolean injectIntoUid, jint uid, jint syncMode, + jint injectorPid, jint injectorUid, 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); @@ -1714,7 +1728,8 @@ static jint nativeInjectInputEvent(JNIEnv* env, jobject nativeImplObj, jobject i } const InputEventInjectionResult result = - im->getInputManager()->getDispatcher().injectInputEvent(&keyEvent, targetUid, mode, + im->getInputManager()->getDispatcher().injectInputEvent(&keyEvent, injectorPid, + injectorUid, mode, std::chrono::milliseconds( timeoutMillis), uint32_t(policyFlags)); @@ -1727,8 +1742,8 @@ static jint nativeInjectInputEvent(JNIEnv* env, jobject nativeImplObj, jobject i } const InputEventInjectionResult result = - im->getInputManager()->getDispatcher().injectInputEvent(motionEvent, targetUid, - mode, + im->getInputManager()->getDispatcher().injectInputEvent(motionEvent, injectorPid, + injectorUid, mode, std::chrono::milliseconds( timeoutMillis), uint32_t(policyFlags)); @@ -2333,7 +2348,7 @@ static const JNINativeMethod gInputManagerMethods[] = { {"setMaximumObscuringOpacityForTouch", "(F)V", (void*)nativeSetMaximumObscuringOpacityForTouch}, {"setBlockUntrustedTouchesMode", "(I)V", (void*)nativeSetBlockUntrustedTouchesMode}, - {"injectInputEvent", "(Landroid/view/InputEvent;ZIIII)I", (void*)nativeInjectInputEvent}, + {"injectInputEvent", "(Landroid/view/InputEvent;IIIII)I", (void*)nativeInjectInputEvent}, {"verifyInputEvent", "(Landroid/view/InputEvent;)Landroid/view/VerifiedInputEvent;", (void*)nativeVerifyInputEvent}, {"toggleCapsLock", "(I)V", (void*)nativeToggleCapsLock}, @@ -2480,6 +2495,9 @@ 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"); |