模拟触摸、按键等操作,直接在命令行输入对应命令即可。命令行如何识别并操作此命令,执行操作的是shell程序,还是java程序?是不是可以添加自定义的命令?
以下在Android13的代码中分析input命令
Android系统中使用了一款叫mksh的shell程序,用于交互式的命令解释器。
mksh
mksh是一款开源的命令解释器(shell),aosp中的源码路径是external/mksh,编译后会在/system/bin下生成 "sh"可执行程序,init.rc中配置了开机启动这个二进制程序。当"sh"启动后,终端工具上就会出现我们常知的命令解释器,可以输入shell命令进行操作。
init.rc中定义了名为"console"的service,service对应的可执行程序是sh这个二进制,这个二进制程序由 exteranl/mksh/Android.bp定义。
bash
service console /system/bin/sh
class core
console
disabled
user shell
group shell log readproc
seclabel u:r:shell:s0
src/main.c中定义一些指令
cpp
static const char *initcoms[] = {
Ttypeset, Tdr, initvsn, NULL,
Ttypeset, Tdx, "HOME", TPATH, TSHELL, NULL,
Ttypeset, "-i10", "COLUMNS", "LINES", "SECONDS", "TMOUT", NULL,
Talias,
"integer=\\\\builtin typeset -i",
"local=\\\\builtin typeset",
/* not "alias -t --": hash -r needs to work */
"hash=\\\\builtin alias -t",
"type=\\\\builtin whence -v",
"autoload=\\\\builtin typeset -fu",
"functions=\\\\builtin typeset -f",
"history=\\\\builtin fc -l",
"nameref=\\\\builtin typeset -n",
"nohup=nohup ",
"r=\\\\builtin fc -e -",
"login=\\\\builtin exec login",
"ll=\\ls -all",
NULL,
/* this is what AT&T ksh seems to track, with the addition of emacs */
Talias, "-tU",
Tcat, "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls",
"make", "mv", "pr", "rm", "sed", Tsh, "vi", "who", NULL,
NULL
};
可在此处添加命令。如:ll=ls -all
cmd命令的入口在frameworks/native/cmds/cmd,在cmd.cpp的cmdMain方法中,根据命令获取对应service
cpp
int cmdMain(const std::vector<std::string_view>& argv, TextOutput& outputLog, TextOutput& errorLog, int in, int out, int err, RunMode runMode) {
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();
......
sp<IServiceManager> sm = defaultServiceManager();
if (sm == nullptr) {
ALOGW("Unable to get default service manager!");
errorLog << "cmd: Unable to get default service manager!" << endl;
return 20;
}
int argc = argv.size();
if (argc == 0) {
errorLog << "cmd: No service specified; use -l to list all running services. Use -w to start and wait for a service." << endl;
return 20;
}
......
const auto cmd = argv[serviceIdx];
Vector<String16> args;
String16 serviceName = String16(cmd.data(), cmd.size());
......
sp<IBinder> service;
if(waitForService) {
service = sm->waitForService(serviceName);
} else {
service = sm->checkService(serviceName);
}
......
status_t error = IBinder::shellCommand(service, in, out, err, args, cb, result);
首先获取ServiceManage,根据命令获取对应的service,sm->checkService(serviceName);
通过service执行命令IBinder::shellCommand(service, in, out, err, args, cb, result);
因此执行cmd命令的是Java程序,如果执行input命令,需要一个service,系统中InputManagerService处理cmd命令
java
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
new InputShellCommand().exec(this, in, out, err, args, callback, resultReceiver);
}
最终InputShellCommand执行命令。
此时命令行还不能识别input命令。需要要添加命令入口
frameworks/base/cmds/input,
bash
#!/system/bin/sh
cmd input "$@"
添加自定义shell命令步骤:
1.创建service,添加到servicemanager中
2.创建命令执行类ShellCommand
3.添加cmd入口脚本