diff options
author | Yifan Hong <elsk@google.com> | 2017-05-09 19:33:08 -0700 |
---|---|---|
committer | Yifan Hong <elsk@google.com> | 2017-05-12 12:47:43 -0700 |
commit | 48dc9f8586c288e152bdd5e14423281764f8db5f (patch) | |
tree | fd168878fff560b5b8d4e3cd69408cf91ebea743 | |
parent | 443df7932cedd88d523164ac7175fa19ec553c7b (diff) | |
download | native-48dc9f8586c288e152bdd5e14423281764f8db5f.tar.gz |
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: 37954458
Change-Id: Ia2f4c9c0d3fb0a7bb26e76f01d02f49dc426e7f8
-rw-r--r-- | cmds/lshal/Android.bp | 1 | ||||
-rw-r--r-- | cmds/lshal/DebugCommand.cpp | 54 | ||||
-rw-r--r-- | cmds/lshal/DebugCommand.h | 49 | ||||
-rw-r--r-- | cmds/lshal/ListCommand.cpp | 18 | ||||
-rw-r--r-- | cmds/lshal/Lshal.cpp | 54 | ||||
-rw-r--r-- | cmds/lshal/Lshal.h | 6 | ||||
-rw-r--r-- | cmds/lshal/utils.h | 2 |
7 files changed, 152 insertions, 32 deletions
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp index 6489ea0415..74f78650a8 100644 --- a/cmds/lshal/Android.bp +++ b/cmds/lshal/Android.bp @@ -24,6 +24,7 @@ cc_binary { "libvintf", ], srcs: [ + "DebugCommand.cpp", "Lshal.cpp", "ListCommand.cpp", "PipeRelay.cpp", diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp new file mode 100644 index 0000000000..672cad67cb --- /dev/null +++ b/cmds/lshal/DebugCommand.cpp @@ -0,0 +1,54 @@ +/* + * 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 + diff --git a/cmds/lshal/DebugCommand.h b/cmds/lshal/DebugCommand.h new file mode 100644 index 0000000000..fa0f0faafb --- /dev/null +++ b/cmds/lshal/DebugCommand.h @@ -0,0 +1,49 @@ +/* + * 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_ diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp index 5696843336..a0ed7a346f 100644 --- a/cmds/lshal/ListCommand.cpp +++ b/cmds/lshal/ListCommand.cpp @@ -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; diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp index 43108b7925..bf4ba2c2d6 100644 --- a/cmds/lshal/Lshal.cpp +++ b/cmds/lshal/Lshal.cpp @@ -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); + + 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; - if (!retBase.isOk() || (base = retBase) == nullptr) { - mErr << interfaceName << "/" << instanceName << " does not exist." << std::endl; - return; + 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; diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h index cabf50399c..cf77b6ba53 100644 --- a/cmds/lshal/Lshal.h +++ b/cmds/lshal/Lshal.h @@ -38,12 +38,12 @@ public: NullableOStream<std::ostream> err() const; NullableOStream<std::ostream> out() const; - static void emitDebugInfo( - const sp<hidl::manager::V1_0::IServiceManager> &serviceManager, + Status 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; private: Status parseArgs(const Arg &arg); std::string mCommand; diff --git a/cmds/lshal/utils.h b/cmds/lshal/utils.h index 972009453f..45b922cc03 100644 --- a/cmds/lshal/utils.h +++ b/cmds/lshal/utils.h @@ -36,6 +36,8 @@ enum : unsigned int { DUMP_PASSTHROUGH_ERROR = 1 << 4, DUMP_ALL_LIBS_ERROR = 1 << 5, IO_ERROR = 1 << 6, + NO_INTERFACE = 1 << 7, + TRANSACTION_ERROR = 1 << 8, }; using Status = unsigned int; |