Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d71d291 authored by Yifan Hong's avatar Yifan Hong
Browse files

Add `lshal debug` command.

Supported command:
    lshal debug android.hardware.foo@1.0::IFoo option option

Test: adb unroot && lshal --debug ; echo $?
Test: adb unroot && lshal debug android.hardware.nfc@1.0::INfc ; echo $?
Test: adb root && lshal --debug ; echo $?
Test: adb root && lshal debug android.hardware.nfc@1.0::INfc ; echo $?

Bug: 37725279
Change-Id: Ia2f4c9c0d3fb0a7bb26e76f01d02f49dc426e7f8
Merged-In: Ia2f4c9c0d3fb0a7bb26e76f01d02f49dc426e7f8
parent 8388ba3e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ cc_binary {
        "android.hidl.manager@1.0",
    ],
    srcs: [
        "DebugCommand.cpp",
        "Lshal.cpp",
        "ListCommand.cpp",
        "PipeRelay.cpp",
+54 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "DebugCommand.h"

#include "Lshal.h"

namespace android {
namespace lshal {

DebugCommand::DebugCommand(Lshal &lshal) : mLshal(lshal) {
}

Status DebugCommand::parseArgs(const std::string &command, const Arg &arg) {
    if (optind >= arg.argc) {
        mLshal.usage(command);
        return USAGE;
    }
    mInterfaceName = arg.argv[optind];
    ++optind;
    for (; optind < arg.argc; ++optind) {
        mOptions.push_back(arg.argv[optind]);
    }
    return OK;
}

Status DebugCommand::main(const std::string &command, const Arg &arg) {
    Status status = parseArgs(command, arg);
    if (status != OK) {
        return status;
    }
    auto pair = splitFirst(mInterfaceName, '/');
    return mLshal.emitDebugInfo(
            pair.first, pair.second.empty() ? "default" : pair.second, mOptions,
            mLshal.out().buf(),
            mLshal.err());
}

}  // namespace lshal
}  // namespace android
+49 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
#define FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_

#include <string>

#include <android-base/macros.h>

#include "utils.h"

namespace android {
namespace lshal {

class Lshal;

class DebugCommand {
public:
    DebugCommand(Lshal &lshal);
    Status main(const std::string &command, const Arg &arg);
private:
    Status parseArgs(const std::string &command, const Arg &arg);

    Lshal &mLshal;
    std::string mInterfaceName;
    std::vector<std::string> mOptions;

    DISALLOW_COPY_AND_ASSIGN(DebugCommand);
};


}  // namespace lshal
}  // namespace android

#endif  // FRAMEWORK_NATIVE_CMDS_LSHAL_DEBUG_COMMAND_H_
+7 −11
Original line number Diff line number Diff line
@@ -350,15 +350,6 @@ void ListCommand::dumpTable() {
        printLine("Interface", "Transport", "Arch", "Server", "Server CMD",
                  "PTR", "Clients", "Clients CMD");

        // We're only interested in dumping debug info for already
        // instantiated services. There's little value in dumping the
        // debug info for a service we create on the fly, so we only operate
        // on the "mServicesTable".
        sp<IServiceManager> serviceManager;
        if (mEmitDebugInfo && &table == &mServicesTable) {
            serviceManager = ::android::hardware::defaultServiceManager();
        }

        for (const auto &entry : table) {
            printLine(entry.interfaceName,
                    entry.transport,
@@ -369,9 +360,14 @@ void ListCommand::dumpTable() {
                    join(entry.clientPids, " "),
                    join(entry.clientCmdlines, ";"));

            if (serviceManager != nullptr) {
            // We're only interested in dumping debug info for already
            // instantiated services. There's little value in dumping the
            // debug info for a service we create on the fly, so we only operate
            // on the "mServicesTable".
            if (mEmitDebugInfo && &table == &mServicesTable) {
                auto pair = splitFirst(entry.interfaceName, '/');
                mLshal.emitDebugInfo(serviceManager, pair.first, pair.second, {}, mOut.buf());
                mLshal.emitDebugInfo(pair.first, pair.second, {}, mOut.buf(),
                        NullableOStream<std::ostream>(nullptr));
            }
        }
        mOut << std::endl;
+36 −18
Original line number Diff line number Diff line
@@ -14,11 +14,17 @@
 * limitations under the License.
 */

#define LOG_TAG "lshal"
#include <android-base/logging.h>

#include "Lshal.h"

#include <set>
#include <string>

#include <hidl/ServiceManagement.h>

#include "DebugCommand.h"
#include "ListCommand.h"
#include "PipeRelay.h"

@@ -111,29 +117,41 @@ static hardware::hidl_vec<hardware::hidl_string> convert(const std::vector<std::
    return hv;
}

// static
void Lshal::emitDebugInfo(
        const sp<IServiceManager> &serviceManager,
Status Lshal::emitDebugInfo(
        const std::string &interfaceName,
        const std::string &instanceName,
        const std::vector<std::string> &options,
        std::ostream &out) {
        std::ostream &out,
        NullableOStream<std::ostream> err) const {
    using android::hidl::base::V1_0::IBase;

    hardware::Return<sp<IBase>> retBase =
        serviceManager->get(interfaceName, instanceName);
        ::android::hardware::defaultServiceManager()->get(interfaceName, instanceName);

    sp<IBase> base;
    if (!retBase.isOk() || (base = retBase) == nullptr) {
        mErr << interfaceName << "/" << instanceName << " does not exist." << std::endl;
        return;
    if (!retBase.isOk()) {
        std::string msg = "Cannot get " + interfaceName + "/" + instanceName + ": "
                + retBase.description();
        err << msg << std::endl;
        LOG(ERROR) << msg;
        return TRANSACTION_ERROR;
    }

    sp<IBase> base = retBase;
    if (base == nullptr) {
        std::string msg = interfaceName + "/" + instanceName + " does not exist, or "
                + "no permission to connect.";
        err << msg << std::endl;
        LOG(ERROR) << msg;
        return NO_INTERFACE;
    }

    PipeRelay relay(out);

    if (relay.initCheck() != OK) {
        mErr << "PipeRelay::initCheck() FAILED w/ " << relay.initCheck() << std::endl;
        return;
        std::string msg = "PipeRelay::initCheck() FAILED w/ " + std::to_string(relay.initCheck());
        err << msg << std::endl;
        LOG(ERROR) << msg;
        return IO_ERROR;
    }

    deleted_unique_ptr<native_handle_t> fdHandle(
@@ -145,12 +163,13 @@ void Lshal::emitDebugInfo(
    hardware::Return<void> ret = base->debug(fdHandle.get(), convert(options));

    if (!ret.isOk()) {
        LOG(ERROR)
            << interfaceName
            << "::debug(...) FAILED. (instance "
            << instanceName
            << ")";
        std::string msg = "debug() FAILED on " + interfaceName + "/" + instanceName + ": "
                + ret.description();
        err << msg << std::endl;
        LOG(ERROR) << msg;
        return TRANSACTION_ERROR;
    }
    return OK;
}

Status Lshal::parseArgs(const Arg &arg) {
@@ -191,8 +210,7 @@ Status Lshal::main(const Arg &arg) {
        return ListCommand{*this}.main(mCommand, arg);
    }
    if (mCommand == "debug") {
        // TODO(b/37725279) implement this
        return OK;
        return DebugCommand{*this}.main(mCommand, arg);
    }
    usage();
    return USAGE;
Loading