【Android cmd命令的执行流程】

代码路径

/frameworks/native/cmds/cmd/

执行逻辑

main.cpp 将参数转化为c++格式

int main(int argc, char* const argv[]) {
    signal(SIGPIPE, SIG_IGN);

    std::vector<std::string_view> arguments;
    arguments.reserve(argc - 1);
    // 0th argument is a program name, skipping.
    for (int i = 1; i < argc; ++i) {
        arguments.emplace_back(argv[i]);
    }

    return cmdMain(arguments, android::aout, android::aerr, STDIN_FILENO, STDOUT_FILENO,
                   STDERR_FILENO, RunMode::kStandalone);
}

cmd.cpp 查找对应的服务,并调用IBinder::shellCommand命令


int cmdMain(const std::vector<std::string_view>& argv, TextOutput& outputLog, TextOutput& errorLog,
            int in, int out, int err, RunMode runMode) {
 
    ...
    sp<IServiceManager> sm = defaultServiceManager();
    ...
    int argc = argv.size();
// 通过 -l 列出 支持的服务
    if ((argc == 1) && (argv[0] == "-l")) {
        Vector<String16> services = sm->listServices();
        services.sort(sort_func);
        outputLog << "Currently running services:" << endl;

        for (size_t i=0; i<services.size(); i++) {
            sp<IBinder> service = sm->checkService(services[i]);
            if (service != nullptr) {
                outputLog << "  " << services[i] << endl;
            }
        }
        return 0;
    }
// 通过使用 -w 等待服务启动
    bool waitForService = ((argc > 1) && (argv[0] == "-w"));
    int serviceIdx = (waitForService) ? 1 : 0;
    const auto cmd = argv[serviceIdx];

    Vector<String16> args;
// 获得服务名称
    String16 serviceName = String16(cmd.data(), cmd.size());
    for (int i = serviceIdx + 1; i < argc; i++) {
        args.add(String16(argv[i].data(), argv[i].size()));
    }
    sp<IBinder> service;
    if(waitForService) {
        service = sm->waitForService(serviceName);
    } else {
        service = sm->checkService(serviceName);
    }
		...
// 发送agras到对应的服务
    // TODO: block until a result is returned to MyResultReceiver.
    status_t error = IBinder::shellCommand(service, in, out, err, args, cb, result);

    ...
    status_t res = result->waitForResult();
    return res;
}

Binder.cpp 发送服务到对应的服务

status_t IBinder::shellCommand(const sp<IBinder>& target, int in, int out, int err,
    Vector<String16>& args, const sp<IShellCallback>& callback,
    const sp<IResultReceiver>& resultReceiver)
{
    Parcel send;
    Parcel reply;
    send.writeFileDescriptor(in);
    send.writeFileDescriptor(out);
    send.writeFileDescriptor(err);
    const size_t numArgs = args.size();
    send.writeInt32(numArgs);
    for (size_t i = 0; i < numArgs; i++) {
        send.writeString16(args[i]);
    }
    send.writeStrongBinder(callback != nullptr ? IInterface::asBinder(callback) : nullptr);
    send.writeStrongBinder(resultReceiver != nullptr ? IInterface::asBinder(resultReceiver) : nullptr);
    // 发送到对应的服务
    return target->transact(SHELL_COMMAND_TRANSACTION, send, &reply);
}

每个service会有一个接口,如PackageManagerShellCommand.java , 其Handler会继承自BasicShellCommandHandler.java中的基类, 而上面的transact会调用到基类中的exec函数, 代码路径aosp/frameworks/libs/modules-utils/java/com/android/modules/utils;

    public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
            String[] args) {
        String cmd;
        int start;
        if (args != null && args.length > 0) {
            cmd = args[0];
            start = 1;
        } else {
            cmd = null;
            start = 0;
        }
        init(target, in, out, err, args, start);
        mCmd = cmd;

        int res = -1;
        res = onCommand(mCmd);
        return res;
    }

其中onCommand是抽象函数,每个继承自该类的类会重写函数;

举例调用

以adb shell cmd package compile -m speed-profile -f com.tencent.mm 为例
当调用到该命令之后, 会调用到PackageManagerShellCommand.java中的onCommand函数, 从而会调用到各个函数
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值