getevent 脚本测试

本文介绍如何将adb shell脚本转换为设备支持的脚本语言,并通过自定义脚本来执行摄像头活动,包括启动应用、进行多次摄像头切换等操作。


1.adb shell getevent -t  > camera.sh

2.操作Device 录入event,ctrl + V 结束

3.将camera.sh 转换成device 支持的脚本语言(java 代码 如下)

编写执行 camera.sh 的脚本 stress.sh

# stress.sh shell

#!/system/bin/sh
# Test Result
echo "***************start camera activity ***************"
#am start -e FactoryTest true -e camera-id 0 -a android.media.action.IMAGE_CAPTURE
am start -n com.android.camera/com.android.camera.Camera
sleep 6
TIMES=2
mtime=1

while true
do
echo "********************This is the $mtime camera switch stress*************"

. /data/bin/camera.sh
sleep 8
mtime=$(($mtime+1))
done
echo "result is $TEST_RESULT"

//Java 转换代码

package com.event;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;

public class Event{
public static void parseEvent(String inFile,String outFile){
        BufferedReader reader = null;
        FileWriter fw = null;
        BufferedWriter bw = null;
        try {
            System.out.println("start:" + inFile);
            reader = new BufferedReader(new FileReader(inFile));
            fw = new FileWriter(outFile);
            bw = new BufferedWriter(fw);
            String tempString = null;
            int line = 1;    
        String separator = " ";
            // 一次读入一行,直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
            if (tempString.isEmpty() || tempString.contains("add")
            || tempString.contains("name:"))
            continue;
            String newLine = "sendevent";
            String arrs[] = tempString.split(separator);
            for (int i = 1;i < arrs.length;i++){
            if (arrs[i].endsWith(":")){
            newLine += separator;
            newLine += arrs[i].substring(0, arrs[i].length()-1);
            }else{
            String hex  = arrs[i];
            //int vaule = Long.parseLong(hex, 16);
            newLine += separator;
            newLine +=  Long.toString(Long.parseLong(hex, 16));
            }
            }
            // 显示行号
                //System.out.println("line " + line + ": " + newLine);
                line++;
                               
            bw.write(newLine);
            bw.newLine();
            bw.flush();
                
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
            if (reader != null)
            reader.close();
            if (fw != null)
            fw.close();
            if (bw != null)
            bw.close();
                } catch (IOException e1) {
                }
            }        
}
public static void main(String [] args){

String fileInArr[] = {
"E:/temp_data/shell/camera.sh",
};
String fileOutArr[] = {
"E:/temp_data/shell/out/camera.sh",
};
for (int i = 0;i<fileInArr.length;i++){
parseEvent(fileInArr[i],fileOutArr[i]);
}

}
}

<think>我们正在讨论`adb shell getevent`命令的实现方式。根据引用内容,特别是引用[2]和引用[3],我们可以了解到`getevent`命令是一个用于监听并输出Linux输入设备事件的工具。它通常位于Android设备的`/system/bin`目录下,是一个可执行程序。 ### 📌 实现原理 `getevent`命令的实现基于Linux内核的输入子系统(Input Subsystem)。在Linux中,输入设备(如触摸屏、按键、传感器等)通过输入子系统将事件上报给用户空间。用户空间应用程序可以通过读取设备节点(如`/dev/input/eventX`)来获取这些事件。 #### 内核事件上报流程 1. **输入设备驱动**:当输入设备有事件发生时(如触摸屏被按下),驱动会调用`input_event`函数上报事件。 2. **输入核心层**:负责将事件传递给用户空间。 3. **用户空间**:通过读取`/dev/input/eventX`设备文件获取事件。 #### getevent的工作流程 1. **打开设备节点**:`getevent`命令通过`open`系统调用打开指定的输入设备节点(如`/dev/input/event3`)。 2. **读取事件**:使用`read`系统调用读取输入事件,事件的数据结构为`struct input_event`,定义如下(在Linux内核头文件中): ```c struct input_event { struct timeval time; // 时间戳 __u16 type; // 事件类型(如EV_ABS, EV_KEY等) __u16 code; // 事件代码(如ABS_MT_POSITION_X, BTN_TOUCH等) __s32 value; // 事件值 }; ``` 3. **解析并输出**:将读取到的二进制数据解析成可读的格式并输出到终端。 ### 🔧 代码示例(简化版) 以下是一个简化版的`getevent`实现(C语言): ```c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <linux/input.h> int main(int argc, char **argv) { const char *dev = "/dev/input/event3"; // 默认设备 int fd = open(dev, O_RDONLY); if (fd < 0) { perror("open device failed"); exit(1); } struct input_event ev; while (1) { if (read(fd, &ev, sizeof(ev)) != sizeof(ev)) { perror("read error"); break; } // 输出事件:设备节点 事件类型 事件代码 事件值 printf("%s: %04x %04x %08x\n", dev, ev.type, ev.code, ev.value); } close(fd); return 0; } ``` 此程序持续读取指定输入设备的事件,并按照`设备名: 类型 代码 值`的格式输出。 ### 📝 输出解读 根据引用[3]的示例输出: ``` /dev/input/event3: 0003 0039 0000011c /dev/input/event3: 0003 0035 000001e1 /dev/input/event3: 0003 0036 00000212 ... ``` - `0003`:事件类型,对应`EV_ABS`(绝对坐标事件)。 - `0035`:事件代码,对应`ABS_MT_POSITION_X`(触摸点X坐标)。 - `000001e1`:事件值,十进制为481,表示X坐标为481像素。 ### ️ 高级功能 引用[2]中提到的命令行参数(如`-t`显示时间戳)是通过解析`struct input_event`中的`time`成员实现的: ```c if (show_timestamp) { printf("[%ld.%06ld] ", ev.time.tv_sec, ev.time.tv_usec); } ``` ### 💡 应用场景 1. **调试输入设备**:如触摸屏、按键等。 2. **自动化测试**:结合`sendevent`模拟用户输入(引用[2][^2])。 3. **坐标捕获**:如引用[4]中通过Python脚本解析触摸坐标[^4]。 ### ❓ 相关问题 §§相关问题§§ 1. 如何通过`sendevent`命令模拟触摸屏点击事件? 2. 如何确定设备的输入事件节点(如`event3`)对应哪个物理设备? 3. `getevent`与`dumpsys input`命令有何区别? 4. 在Android高版本中,`getevent`命令的使用有哪些权限限制? [^2]: adb shell getevent/sendevent命令语法 [^3]: adb shell getevent输出示例 [^4]: 解析getevent坐标的Python示例 </think>### 🔍 `adb shell getevent` 命令的实现原理 `adb shell getevent` 是 Android 调试桥(ADB)中的底层输入设备事件监控工具,其实现涉及 Linux 内核输入子系统和用户空间交互机制: #### 🧠 核心实现机制 1. **内核层事件捕获** - 通过 `/dev/input/eventX` 设备节点监听输入设备原始数据流 - 使用 `ioctl` 系统调用获取设备能力信息(如 `EVIOCGBIT`) - 循环执行 `read()` 系统调用读取 `struct input_event` 结构体: ```c struct input_event { struct timeval time; // 时间戳 __u16 type; // 事件类型 (EV_KEY, EV_ABS等) __u16 code; // 事件代码 (如 ABS_MT_POSITION_X) __s32 value; // 事件值 }; ``` 2. **事件解析与格式化** - 将二进制事件转换为可读字符串: `printf("[%ld.%06ld] %s %04x %04x %d\n", event.time.tv_sec, event.time.tv_usec, device_name, event.type, event.code, event.value);` - 支持多种输出格式(如 `-t` 时间戳、`-l` 标签化输出) 3. **设备枚举逻辑** - 扫描 `/dev/input/` 目录检测可用设备 - 通过 `EVIOCGNAME` 获取设备友好名称 - 根据参数过滤特定设备事件 4. **多路复用处理** 采用 `poll()` 或 `select()` 系统调用同时监控多个输入设备: ```c struct pollfd fds[MAX_DEVICES]; while (poll(fds, num_devices, -1) > 0) { for (int i=0; i<num_devices; i++) { if (fds[i].revents & POLLIN) { read_and_print_event(fds[i].fd); } } } ``` #### 📊 坐标获取示例(引用[4]) 触摸事件的 ABS_MT_POSITION_X (0035) 和 ABS_MT_POSITION_Y (0036) 值对应: $$ x = \text{0035\_value} \times \frac{\text{屏幕宽度}}{\text{设备X最大值}} $$ $$ y = \text{0036\_value} \times \frac{\text{屏幕高度}}{\text{设备Y最大值}} $$ 具体转换需结合 `adb shell getevent -p` 获取设备范围参数[^3][^4]。 #### ️ 权限与限制 - 需要 `SELinux` 权限:`u:r:shell:s0` 上下文 - Android 10+ 需要 `adb root` 访问完整事件流 - 部分安全设备可能限制原始事件访问 ### 🛠 实现参考 官方实现位于 AOSP 源码: ```bash aosp/system/core/toolbox/getevent.c aosp/system/core/libcutils/input.c ``` 关键函数:`monitor_devices()`, `print_event()`, `parse_options()`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值