Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31f05298 authored by Solti Ho's avatar Solti Ho
Browse files

Revert "uinput: Specify timestamps when injecting events from evemu"

Revert submission 26154399

Reason for revert: b/324707605

Reverted changes: /q/submissionid:26154399

Change-Id: I2a9bc83e94a28691a1e3c6e3aaa8bb6d77ab17a5
parent b2cba9ef
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -166,14 +166,14 @@ UinputDevice::~UinputDevice() {
    ::ioctl(mFd, UI_DEV_DESTROY);
}

void UinputDevice::injectEvent(std::chrono::microseconds timestamp, uint16_t type, uint16_t code,
                               int32_t value) {
void UinputDevice::injectEvent(uint16_t type, uint16_t code, int32_t value) {
    struct input_event event = {};
    event.type = type;
    event.code = code;
    event.value = value;
    event.time.tv_sec = timestamp.count() / 1'000'000;
    event.time.tv_usec = timestamp.count() % 1'000'000;
    timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    TIMESPEC_TO_TIMEVAL(&event.time, &ts);

    if (::write(mFd, &event, sizeof(input_event)) < 0) {
        ALOGE("Could not write event %" PRIu16 " %" PRIu16 " with value %" PRId32 " : %s", type,
@@ -268,12 +268,12 @@ static void closeUinputDevice(JNIEnv* /* env */, jclass /* clazz */, jlong ptr)
    }
}

static void injectEvent(JNIEnv* /* env */, jclass /* clazz */, jlong ptr, jlong timestampMicros,
                        jint type, jint code, jint value) {
static void injectEvent(JNIEnv* /* env */, jclass /* clazz */, jlong ptr, jint type, jint code,
                        jint value) {
    uinput::UinputDevice* d = reinterpret_cast<uinput::UinputDevice*>(ptr);
    if (d != nullptr) {
        d->injectEvent(std::chrono::microseconds(timestampMicros), static_cast<uint16_t>(type),
                       static_cast<uint16_t>(code), static_cast<int32_t>(value));
        d->injectEvent(static_cast<uint16_t>(type), static_cast<uint16_t>(code),
                       static_cast<int32_t>(value));
    } else {
        ALOGE("Could not inject event, Device* is null!");
    }
@@ -330,7 +330,7 @@ static JNINativeMethod sMethods[] = {
         "(Ljava/lang/String;IIIIIILjava/lang/String;"
         "Lcom/android/commands/uinput/Device$DeviceCallback;)J",
         reinterpret_cast<void*>(openUinputDevice)},
        {"nativeInjectEvent", "(JJIII)V", reinterpret_cast<void*>(injectEvent)},
        {"nativeInjectEvent", "(JIII)V", reinterpret_cast<void*>(injectEvent)},
        {"nativeConfigure", "(II[I)V", reinterpret_cast<void*>(configure)},
        {"nativeSetAbsInfo", "(IILandroid/os/Parcel;)V", reinterpret_cast<void*>(setAbsInfo)},
        {"nativeCloseUinputDevice", "(J)V", reinterpret_cast<void*>(closeUinputDevice)},
+5 −7
Original line number Diff line number Diff line
@@ -14,14 +14,13 @@
 * limitations under the License.
 */

#include <android-base/unique_fd.h>
#include <jni.h>
#include <linux/input.h>

#include <chrono>
#include <memory>
#include <vector>

#include <jni.h>
#include <linux/input.h>

#include <android-base/unique_fd.h>
#include "src/com/android/commands/uinput/InputAbsInfo.h"

namespace android {
@@ -54,8 +53,7 @@ public:

    virtual ~UinputDevice();

    void injectEvent(std::chrono::microseconds timestamp, uint16_t type, uint16_t code,
                     int32_t value);
    void injectEvent(uint16_t type, uint16_t code, int32_t value);
    int handleEvents(int events);

private:
+13 −59
Original line number Diff line number Diff line
@@ -65,8 +65,7 @@ public class Device {
            int productId, int versionId, int bus, int ffEffectsMax, String port,
            DeviceCallback callback);
    private static native void nativeCloseUinputDevice(long ptr);
    private static native void nativeInjectEvent(long ptr, long timestampMicros, int type, int code,
                                                 int value);
    private static native void nativeInjectEvent(long ptr, int type, int code, int value);
    private static native void nativeConfigure(int handle, int code, int[] configs);
    private static native void nativeSetAbsInfo(int handle, int axisCode, Parcel axisParcel);
    private static native int nativeGetEvdevEventTypeByLabel(String label);
@@ -106,11 +105,6 @@ public class Device {
    }

    private long getTimeToSendMillis() {
        // Since we can only specify delays in milliseconds but evemu timestamps are in
        // microseconds, we have to round up the delays to avoid setting event timestamps
        // which are in the future (which the kernel would silently reject and replace with
        // the current time).
        //
        // This should be the same as (long) Math.ceil(mTimeToSendNanos / 1_000_000.0), except
        // without the precision loss that comes from converting from long to double and back.
        return mTimeToSendNanos / 1_000_000 + ((mTimeToSendNanos % 1_000_000 > 0) ? 1 : 0);
@@ -120,17 +114,10 @@ public class Device {
     * Inject uinput events to device
     *
     * @param events  Array of raw uinput events.
     * @param offsetMicros The difference in microseconds between the timestamps of the previous
     *                     batch of events injected and this batch. If set to -1, the current
     *                     timestamp will be used.
     */
    public void injectEvent(int[] events, long offsetMicros) {
    public void injectEvent(int[] events) {
        // if two messages are sent at identical time, they will be processed in order received
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = events;
        args.argl1 = offsetMicros;
        args.argl2 = mTimeToSendNanos;
        Message msg = mHandler.obtainMessage(MSG_INJECT_EVENT, args);
        Message msg = mHandler.obtainMessage(MSG_INJECT_EVENT, events);
        mHandler.sendMessageAtTime(msg, getTimeToSendMillis());
    }

@@ -182,7 +169,6 @@ public class Device {

    private class DeviceHandler extends Handler {
        private long mPtr;
        private long mLastInjectTimestampMicros = -1;
        private int mBarrierToken;

        DeviceHandler(Looper looper) {
@@ -192,7 +178,7 @@ public class Device {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_OPEN_UINPUT_DEVICE: {
                case MSG_OPEN_UINPUT_DEVICE:
                    SomeArgs args = (SomeArgs) msg.obj;
                    String name = (String) args.arg1;
                    mPtr = nativeOpenUinputDevice(name, args.argi1 /* id */,
@@ -207,44 +193,15 @@ public class Device {
                        throw ex;
                    }
                    break;
                }
                case MSG_INJECT_EVENT: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    if (mPtr == 0) {
                        args.recycle();
                        break;
                    }
                    long offsetMicros = args.argl1;
                    if (mLastInjectTimestampMicros == -1 || offsetMicros == -1) {
                        // There's often a delay of a few milliseconds between the time specified to
                        // Handler.sendMessageAtTime and the handler actually being called, due to
                        // the way threads are scheduled. We don't take this into account when
                        // calling addDelayNanos between the first batch of event injections (when
                        // we set the "base timestamp" from which all others will be offset) and the
                        // second batch, meaning that the actual time between the handler calls for
                        // those batches may be less than the offset between their timestamps. When
                        // that happens, we would pass a timestamp for the second batch that's
                        // actually in the future. The kernel's uinput API rejects timestamps that
                        // are in the future and uses the current time instead, making the reported
                        // timestamps inconsistent with the recording we're replaying.
                        //
                        // To prevent this, we need to use the time we scheduled this first batch
                        // for (in microseconds, to avoid potential rounding up from
                        // getTimeToSendMillis), rather than the actual current time.
                        mLastInjectTimestampMicros = args.argl2 / 1000;
                    } else {
                        mLastInjectTimestampMicros += offsetMicros;
                    }

                    int[] events = (int[]) args.arg1;
                case MSG_INJECT_EVENT:
                    if (mPtr != 0) {
                        int[] events = (int[]) msg.obj;
                        for (int pos = 0; pos + 2 < events.length; pos += 3) {
                        nativeInjectEvent(mPtr, mLastInjectTimestampMicros, events[pos],
                                events[pos + 1], events[pos + 2]);
                            nativeInjectEvent(mPtr, events[pos], events[pos + 1], events[pos + 2]);
                        }
                    args.recycle();
                    break;
                    }
                case MSG_CLOSE_UINPUT_DEVICE: {
                    break;
                case MSG_CLOSE_UINPUT_DEVICE:
                    if (mPtr != 0) {
                        nativeCloseUinputDevice(mPtr);
                        getLooper().quitSafely();
@@ -257,16 +214,13 @@ public class Device {
                        mCond.notify();
                    }
                    break;
                }
                case MSG_SYNC_EVENT: {
                case MSG_SYNC_EVENT:
                    handleSyncEvent((String) msg.obj);
                    break;
                }
                default: {
                default:
                    throw new IllegalArgumentException("Unknown device message");
            }
        }
        }

        public void pauseEvents() {
            mBarrierToken = getLooper().myQueue().postSyncBarrier();
+14 −10
Original line number Diff line number Diff line
@@ -175,6 +175,7 @@ public class EvemuParser implements EventParser {
            throw new ParsingException(
                    "Invalid timestamp '" + parts[0] + "' (should contain a single '.')", mReader);
        }
        // TODO(b/310958309): use timeMicros to set the timestamp on the event being sent.
        final long timeMicros =
                parseLong(timeParts[0], 10) * 1_000_000 + parseInt(timeParts[1], 10);
        final Event.Builder eb = new Event.Builder();
@@ -191,10 +192,12 @@ public class EvemuParser implements EventParser {
            return eb.build();
        } else {
            final long delayMicros = timeMicros - mLastEventTimeMicros;
            eb.setTimestampOffsetMicros(delayMicros);
            if (delayMicros == 0) {
            // The shortest delay supported by Handler.sendMessageAtTime (used for timings by the
            // Device class) is 1ms, so ignore time differences smaller than that.
            if (delayMicros < 1000) {
                mLastEventTimeMicros = timeMicros;
                return eb.build();
            }
            } else {
                // Send a delay now, and queue the actual event for the next call.
                mQueuedEvents.add(eb.build());
                mLastEventTimeMicros = timeMicros;
@@ -205,6 +208,7 @@ public class EvemuParser implements EventParser {
                return delayEb.build();
            }
        }
    }

    private Event parseRegistrationEvent() throws IOException {
        // The registration details at the start of a recording are specified by a set of lines
+1 −15
Original line number Diff line number Diff line
@@ -99,7 +99,6 @@ public class Event {
    private int mVersionId;
    private int mBusId;
    private int[] mInjections;
    private long mTimestampOffsetMicros = -1;
    private SparseArray<int[]> mConfiguration;
    private long mDurationNanos;
    private int mFfEffectsMax = 0;
@@ -139,21 +138,12 @@ public class Event {
        return mInjections;
    }

    /**
     * Returns the number of microseconds that should be added to the previous {@code INJECT}
     * event's timestamp to produce the timestamp for this {@code INJECT} event. A value of -1
     * indicates that the current timestamp should be used instead.
     */
    public long getTimestampOffsetMicros() {
        return mTimestampOffsetMicros;
    }

    /**
     * Returns a {@link SparseArray} describing the event codes that should be registered for the
     * device. The keys are uinput ioctl codes (such as those returned from {@link
     * UinputControlCode#getValue()}, while the values are arrays of event codes to be enabled with
     * those ioctls. For example, key 101 (corresponding to {@link UinputControlCode#UI_SET_KEYBIT})
     * could have values 0x110 ({@code BTN_LEFT}), 0x111 ({@code BTN_RIGHT}), and 0x112
     * could have values 0x110 ({@code BTN_LEFT}, 0x111 ({@code BTN_RIGHT}), and 0x112
     * ({@code BTN_MIDDLE}).
     */
    public SparseArray<int[]> getConfiguration() {
@@ -221,10 +211,6 @@ public class Event {
            mEvent.mInjections = events;
        }

        public void setTimestampOffsetMicros(long offsetMicros) {
            mEvent.mTimestampOffsetMicros = offsetMicros;
        }

        /**
         * Sets the event codes that should be registered with a {@code register} command.
         *
Loading