0

我尝试使用 /dev/uinput 在 Android 中模拟触摸事件,一些代码如下:

首先打开“/dev/uinput”文件,并创建一个udev:

static int open_uinput_device(){
uinp_fd = open(uinput_deivce_path, O_WRONLY | O_NDELAY);
if (uinp_fd <= 0) {
    debug("could not open %s, %s", uinput_deivce_path, strerror(errno));
    return -1;
}

memset(&ui_dev, 0, sizeof(ui_dev));
strncpy(ui_dev.name, "RemoteTV Event", UINPUT_MAX_NAME_SIZE);
ui_dev.id.bustype = BUS_USB;
ui_dev.id.vendor = 0x1341;
ui_dev.id.product = 0x0001;
ui_dev.id.version = 4;

ui_dev.absmin[ABS_MT_SLOT] = 0;
ui_dev.absmax[ABS_MT_SLOT] = 9;
ui_dev.absmin[ABS_MT_TOUCH_MAJOR] = 0;
ui_dev.absmax[ABS_MT_TOUCH_MAJOR] = 255;
ui_dev.absmin[ABS_MT_POSITION_X] = 0;
ui_dev.absmax[ABS_MT_POSITION_X] = screen_width - 1;
ui_dev.absmin[ABS_MT_POSITION_Y] = 0;
ui_dev.absmax[ABS_MT_POSITION_Y] = screen_Height - 1;
ui_dev.absmin[ABS_MT_TRACKING_ID] = 0;
ui_dev.absmax[ABS_MT_TRACKING_ID] = 65535;
ui_dev.absmin[ABS_MT_PRESSURE] = 0;
ui_dev.absmax[ABS_MT_PRESSURE] = 30;
ui_dev.absmin[ABS_MT_TOOL_TYPE] = 0;
ui_dev.absmax[ABS_MT_TOOL_TYPE] = 1;

//enable direct
ioctl(uinp_fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT);
//enable mouse event
ioctl(uinp_fd, UI_SET_EVBIT, EV_REL);
ioctl(uinp_fd, UI_SET_RELBIT, REL_X);
ioctl(uinp_fd, UI_SET_RELBIT, REL_Y);
//enable touch event
ioctl(uinp_fd, UI_SET_EVBIT, EV_ABS);
for (i = 0; i <= ABS_CNT; i++) {
    ioctl(uinp_fd, UI_SET_ABSBIT, i);
}

ioctl(uinp_fd, UI_SET_EVBIT, EV_SYN);
ioctl(uinp_fd, UI_SET_EVBIT, EV_KEY);
for (i = 0; i < 256; i++) {
    ioctl(uinp_fd, UI_SET_KEYBIT, i);
}
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_MOUSE);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_TOUCH);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_MOUSE);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_LEFT);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_MIDDLE);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_RIGHT);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_FORWARD);
ioctl(uinp_fd, UI_SET_KEYBIT, BTN_BACK);

write(uinp_fd, &ui_dev, sizeof(ui_dev));
if (ioctl(uinp_fd, UI_DEV_CREATE)) {
    debug("Unable to create UINPUT device.");
    return -1;
}
return 0;

}

然后在uinput_fd中写入一些事件,代码段如下:

 int len;
// Move pointer to (100,100) location
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, NULL);
event.type = type;
event.code = code;
event.value = value;
len = write(uinp_fd, &event, sizeof(event));
debug("SendEventToUinput done:%d %d %d",type, code, value);

我可以通过输入命令“getevent -l”在终端的 /dev/input/event7 上看到事件,如下所示:

/dev/input/event7: EV_KEY       BTN_TOUCH            DOWN                
/dev/input/event7: EV_ABS       ABS_MT_TRACKING_ID   00000027            
/dev/input/event7: EV_ABS       ABS_MT_TOUCH_MAJOR   0000005d            
/dev/input/event7: EV_ABS       ABS_MT_POSITION_X    00000251            
/dev/input/event7: EV_ABS       ABS_MT_POSITION_Y    0000048f            
/dev/input/event7: EV_SYN       SYN_REPORT           00000000            
/dev/input/event7: EV_ABS       ABS_MT_TOUCH_MAJOR   00000045            
/dev/input/event7: EV_SYN       SYN_REPORT           00000000            
/dev/input/event7: EV_ABS       ABS_MT_TRACKING_ID   ffffffff            
/dev/input/event7: EV_SYN       SYN_REPORT           00000000            
/dev/input/event7: EV_KEY       BTN_TOUCH            UP                  
/dev/input/event7: EV_SYN       SYN_REPORT           00000000 

但是屏幕上什么也没有显示,如果我在“dev/input/event4”上发送相同的事件,它可以工作吗?为什么“dev/uinput”无效?

请有人帮助我。

4

5 回答 5

1

当您执行此部分时:

ioctl(uinp_fd, UI_SET_EVBIT, EV_ABS);
for (i = 0; i <= ABS_CNT; i++) {
    ioctl(uinp_fd, UI_SET_ABSBIT, i);
}

您还可以设置 ABS_X 和 ABS_Y 位。ABS_X 和 ABS_Y 位不得与 ABS_MT_POSITION_X 和 ABS_MT_POSITION_Y 位一起设置。

我建议只设置您将使用的 ABS 位。

于 2016-05-19T07:39:58.963 回答
0

查看 adb shell 输入的实现: https://android.googlesource.com/platform/frameworks/base/+/HEAD/cmds/input/src/com/android/commands/input/Input.java 有类型转换该坐标。可能这就是为什么发送到输入事件的完全相同的坐标在使用 adb shell getevent 捕获相同的坐标时会转换为不同的坐标的原因。我仍然没有解决方案,但您可能会发现此信息很有用 - 要不翻译坐标,需要在 AOSP 级别以浮点形式注入它。-- 巴西拉

于 2020-07-04T08:41:36.847 回答
0

您的 ui_dev.name 已经存在,使用另一个,它将正常工作。

于 2016-05-12T03:37:33.150 回答
-1

在我的 pionion 中,您应该像这样使用 adb 命令行:

adb shell sendevent /dev/input/event[event_number_here] input_value_here

前任:

adb shell sendevent /dev/input/event2 1 315 1
adb shell sendevent /dev/input/event2 0 0 0

或者你可以试试这个命令:

adb shell input tap x y

例如:adb shell 输入点击 150 150

于 2016-03-14T07:49:58.513 回答
-2

尝试更改分配参数的顺序:

strncpy(ui_dev.name, "RemoteTV Event", UINPUT_MAX_NAME_SIZE);

做了:

strncpy(ui_dev.name,  UINPUT_MAX_NAME_SIZE, "RemoteTV Event");
于 2016-11-30T11:32:19.367 回答