android input命令 模拟按键

我们可以在手机adb shell中,使用input来模拟按键,和之前的sm类似,input也是一个进程,在framework/base/cmds目录下。
一、Input源码

下面我们先看下input的源码:
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
private void run(String[] args) {
if (args.length < 1) {
showUsage();
return;
}

   int index = 0;  
   String command = args[index];  
   int inputSource = InputDevice.SOURCE_UNKNOWN;  
   if (SOURCES.containsKey(command)) {  
       inputSource = SOURCES.get(command);  
       index++;  
       command = args[index];  
   }  
   final int length = args.length - index;  

   try {  
       if (command.equals("text")) {  
           if (length == 2) {  
               inputSource = getSource(inputSource, InputDevice.SOURCE_KEYBOARD);  
               sendText(inputSource, args[index+1]);  
               return;  
           }  
       } else if (command.equals("keyevent")) {  
           if (length >= 2) {  
               final boolean longpress = "--longpress".equals(args[index + 1]);  
               final int start = longpress ? index + 2 : index + 1;  
               inputSource = getSource(inputSource, InputDevice.SOURCE_KEYBOARD);  
               if (length > start) {  
                   for (int i = start; i < length; i++) {  
                       int keyCode = KeyEvent.keyCodeFromString(args[i]);  
                       if (keyCode == KeyEvent.KEYCODE_UNKNOWN) {  
                           keyCode = KeyEvent.keyCodeFromString("KEYCODE_" + args[i]);  
                       }  
                       sendKeyEvent(inputSource, keyCode, longpress);  
                   }  
                   return;  
               }  
           }  
       }.............  

我们再来看看sendKeyEvent函数
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
private void sendKeyEvent(int inputSource, int keyCode, boolean longpress) {
long now = SystemClock.uptimeMillis();
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
if (longpress) {
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 1, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_LONG_PRESS,
inputSource));
}
injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, inputSource));
}
最后再来看看injectKeyEvent函数,其主要还是调用了,InputManager中的injectInputEvent函数。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
private void injectKeyEvent(KeyEvent event) {
Log.i(TAG, “injectKeyEvent: ” + event);
InputManager.getInstance().injectInputEvent(event,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}

二、InputManager相关代码

我们再来看看InputManager的injectInputEvent函数,最后还是调用了InputManagerService的injectInputEvent函数。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
public boolean injectInputEvent(InputEvent event, int mode) {
if (event == null) {
throw new IllegalArgumentException(“event must not be null”);
}
if (mode != INJECT_INPUT_EVENT_MODE_ASYNC
&& mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
&& mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
throw new IllegalArgumentException(“mode is invalid”);
}

try {  
    return mIm.injectInputEvent(event, mode);//调用了InputManagerService的injectInputEvent函数  
} catch (RemoteException ex) {  
    return false;  
}  

}
我们再来看看InputManagerService的injectInputEvent函数
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
@Override // Binder call
public boolean injectInputEvent(InputEvent event, int mode) {
return injectInputEventInternal(event, Display.DEFAULT_DISPLAY, mode);
}
我们再来看injectInputEventInternal函数
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
private boolean injectInputEventInternal(InputEvent event, int displayId, int mode) {
if (event == null) {
throw new IllegalArgumentException(“event must not be null”);
}
if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC
&& mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
&& mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
throw new IllegalArgumentException(“mode is invalid”);
}

final int pid = Binder.getCallingPid();  
final int uid = Binder.getCallingUid();  
final long ident = Binder.clearCallingIdentity();  
final int result;  
try {  
    result = nativeInjectInputEvent(mPtr, event, displayId, pid, uid, mode,//主要看这个jni函数  
            INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);  
} finally {  
    Binder.restoreCallingIdentity(ident);  
}  
switch (result) {  
    case INPUT_EVENT_INJECTION_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 INPUT_EVENT_INJECTION_SUCCEEDED:  
        return true;  
    case INPUT_EVENT_INJECTION_TIMED_OUT:  
        Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");  
        return false;  
    case INPUT_EVENT_INJECTION_FAILED:  
    default:  
        Slog.w(TAG, "Input event injection from pid " + pid + " failed.");  
        return false;  
}  

}

三、native层代码

上面这个函数主要调用了nativeInjectInputEvent这个native函数。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */,
jlong ptr, jobject inputEventObj, jint displayId, jint injectorPid, jint injectorUid,
jint syncMode, jint timeoutMillis, jint policyFlags) {
NativeInputManager* im = reinterpret_cast

Abaqus和LS-DYNA是计算力学与仿真领域广泛应用的有限元分析软件。Abaqus以强大的非线性求解能力著称,LS-DYNA则擅长高效处理瞬态动力学问题。用户有时需要在两者间转换数据以利用各自优势。本文介绍如何使用Python脚本实现Abaqus关键字输入文件(.inp)到LS-DYNA关键字输入文件(.k)的转换。Abaqus的.inp文件包含模型几何、材料属性、边界条件及求解设置等信息;LS-DYNA的.k文件有类似定义,但格式与语法不同。“abaqus2dyna”是一个Python脚本项目,通过解析Abaqus的.inp文件,依据LS-DYNA语法生成对应的.k文件。用户可下载并运行相关代码包,其中通常包含转换脚本、示例输入文件及其他辅助文件。转换过程主要包括以下步骤:1. **解析Abaqus文件**:读取.inp文件,识别如*Solid Section、*Node、*Element等部分,并存储相关信息。2. **映射数据**:将Abaqus的单元类型、材料模型等转换为LS-DYNA认可的格式。3. **生成LS-DYNA文件**:基于解析与映射结果,生成包含几何定义、材料属性、边界条件及求解设置的.k文件。4. **验证与调试**:通过对比分析结果确保转换后模型与原始Abaqus模型尽可能一致。实际应用中,用户可能需要根据具体模型对脚本进行调整或扩展。Python的灵活性使定制化相对简便。由于LS-DYNA支持更多物理现象(如流体动力学、热力耦合等),转换后的模型可提供更广泛的分析选项。总之,“abaqus2dyna”是一个用Python编写的工具,简化了Abaqus与LS-DYNA间输入文件的转换过程。理解两软件的关键字文件格式及Python脚本运行机制,有助于用户有效利用该工具,提升工作效率,并拓展在两个软件间进行复杂模拟的可能性。资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值