diff options
author | 2020-07-09 16:38:18 -0700 | |
---|---|---|
committer | 2020-07-10 11:36:16 -0700 | |
commit | 6884b87a376d69fa873d71dd52563c7d5d4d6385 (patch) | |
tree | 6f446db2dfa9c53ed5548e309462679f42a520e8 | |
parent | 5cceea8d0b9fe851fcefb827623a2251a896aaba (diff) |
lshal: --debug omits info on parent objects.
Instead, print a short message that contains the information
on the row that it should look up.
Test: lshal --debug
Test: lshal debug -E android.hardware.health@2.0::IHealth/default
Test: lshal_test
Fixes: 160745145
Change-Id: I7d5ab9fba097c0fb0b080ec52682084c65ba9f50
-rw-r--r-- | cmds/lshal/DebugCommand.cpp | 4 | ||||
-rw-r--r-- | cmds/lshal/DebugCommand.h | 6 | ||||
-rw-r--r-- | cmds/lshal/ListCommand.cpp | 2 | ||||
-rw-r--r-- | cmds/lshal/Lshal.cpp | 7 | ||||
-rw-r--r-- | cmds/lshal/Lshal.h | 3 | ||||
-rw-r--r-- | cmds/lshal/ParentDebugInfoLevel.h | 34 | ||||
-rw-r--r-- | cmds/lshal/test.cpp | 85 |
7 files changed, 132 insertions, 9 deletions
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp index af22ac9b3d..72958bd2a9 100644 --- a/cmds/lshal/DebugCommand.cpp +++ b/cmds/lshal/DebugCommand.cpp @@ -39,7 +39,7 @@ Status DebugCommand::parseArgs(const Arg &arg) { // Optargs cannnot be used because the flag should not be considered set // if it should really be contained in mOptions. if (std::string(arg.argv[optind]) == "-E") { - mExcludesParentInstances = true; + mParentDebugInfoLevel = ParentDebugInfoLevel::NOTHING; optind++; } @@ -67,7 +67,7 @@ Status DebugCommand::main(const Arg &arg) { return mLshal.emitDebugInfo( pair.first, pair.second.empty() ? "default" : pair.second, mOptions, - mExcludesParentInstances, + mParentDebugInfoLevel, mLshal.out().buf(), mLshal.err()); } diff --git a/cmds/lshal/DebugCommand.h b/cmds/lshal/DebugCommand.h index cd57e31bfc..317cc2821c 100644 --- a/cmds/lshal/DebugCommand.h +++ b/cmds/lshal/DebugCommand.h @@ -21,6 +21,7 @@ #include <android-base/macros.h> #include "Command.h" +#include "ParentDebugInfoLevel.h" #include "utils.h" namespace android { @@ -42,9 +43,8 @@ private: std::string mInterfaceName; std::vector<std::string> mOptions; - // Outputs the actual descriptor of a hal instead of the debug output - // if the arguments provided are a superclass of the actual hal impl. - bool mExcludesParentInstances; + // See comment on ParentDebugInfoLevel. + ParentDebugInfoLevel mParentDebugInfoLevel = ParentDebugInfoLevel::FULL; DISALLOW_COPY_AND_ASSIGN(DebugCommand); }; diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp index fb11cee33e..a805a4844a 100644 --- a/cmds/lshal/ListCommand.cpp +++ b/cmds/lshal/ListCommand.cpp @@ -555,7 +555,7 @@ void ListCommand::dumpTable(const NullableOStream<std::ostream>& out) const { std::stringstream ss; auto pair = splitFirst(iName, '/'); mLshal.emitDebugInfo(pair.first, pair.second, {}, - false /* excludesParentInstances */, ss, + ParentDebugInfoLevel::FQNAME_ONLY, ss, NullableOStream<std::ostream>(nullptr)); return ss.str(); }; diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp index 132b31ebc3..2c3efe524e 100644 --- a/cmds/lshal/Lshal.cpp +++ b/cmds/lshal/Lshal.cpp @@ -101,7 +101,7 @@ Status Lshal::emitDebugInfo( const std::string &interfaceName, const std::string &instanceName, const std::vector<std::string> &options, - bool excludesParentInstances, + ParentDebugInfoLevel parentDebugInfoLevel, std::ostream &out, NullableOStream<std::ostream> err) const { using android::hidl::base::V1_0::IBase; @@ -126,7 +126,7 @@ Status Lshal::emitDebugInfo( return NO_INTERFACE; } - if (excludesParentInstances) { + if (parentDebugInfoLevel != ParentDebugInfoLevel::FULL) { const std::string descriptor = getDescriptor(base.get()); if (descriptor.empty()) { std::string msg = interfaceName + "/" + instanceName + " getDescriptor failed"; @@ -134,6 +134,9 @@ Status Lshal::emitDebugInfo( LOG(ERROR) << msg; } if (descriptor != interfaceName) { + if (parentDebugInfoLevel == ParentDebugInfoLevel::FQNAME_ONLY) { + out << "[See " << descriptor << "/" << instanceName << "]"; + } return OK; } } diff --git a/cmds/lshal/Lshal.h b/cmds/lshal/Lshal.h index 830bd872ff..50279d4d7a 100644 --- a/cmds/lshal/Lshal.h +++ b/cmds/lshal/Lshal.h @@ -25,6 +25,7 @@ #include "Command.h" #include "NullableOStream.h" +#include "ParentDebugInfoLevel.h" #include "utils.h" namespace android { @@ -49,7 +50,7 @@ public: const std::string &interfaceName, const std::string &instanceName, const std::vector<std::string> &options, - bool excludesParentInstances, + ParentDebugInfoLevel parentDebugInfoLevel, std::ostream &out, NullableOStream<std::ostream> err) const; diff --git a/cmds/lshal/ParentDebugInfoLevel.h b/cmds/lshal/ParentDebugInfoLevel.h new file mode 100644 index 0000000000..12ac9c8648 --- /dev/null +++ b/cmds/lshal/ParentDebugInfoLevel.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2020 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. + */ +#pragma once + +namespace android { +namespace lshal { + +// Describe verbosity when dumping debug information on a HAL service by +// referring to a parent HAL interface FQName (for example, when dumping debug information +// on foo@1.0::IFoo but the HAL implementation is foo@1.1::IFoo). +enum class ParentDebugInfoLevel { + // Write nothing. + NOTHING, + // Write a short description that includes the FQName of the real implementation. + FQNAME_ONLY, + // Write full debug info. + FULL, +}; + +} // namespace lshal +} // namespace android diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp index fd94392b16..afe5d63575 100644 --- a/cmds/lshal/test.cpp +++ b/cmds/lshal/test.cpp @@ -793,6 +793,91 @@ TEST_F(ListTest, Vintf) { EXPECT_EQ("", err.str()); } +// Fake service returned by mocked IServiceManager::get for DumpDebug. +// The interfaceChain and getHashChain functions returns +// foo(id - 1) -> foo(id - 2) -> ... foo1 -> IBase. +class InheritingService : public IBase { +public: + explicit InheritingService(pid_t id) : mId(id) {} + android::hardware::Return<void> interfaceDescriptor(interfaceDescriptor_cb cb) override { + cb(getInterfaceName(mId)); + return hardware::Void(); + } + android::hardware::Return<void> interfaceChain(interfaceChain_cb cb) override { + std::vector<hidl_string> ret; + for (auto i = mId; i > 0; --i) { + ret.push_back(getInterfaceName(i)); + } + ret.push_back(IBase::descriptor); + cb(ret); + return hardware::Void(); + } + android::hardware::Return<void> getHashChain(getHashChain_cb cb) override { + std::vector<hidl_hash> ret; + for (auto i = mId; i > 0; --i) { + ret.push_back(getHashFromId(i)); + } + ret.push_back(getHashFromId(0xff)); + cb(ret); + return hardware::Void(); + } + android::hardware::Return<void> debug(const hidl_handle& hh, + const hidl_vec<hidl_string>&) override { + const native_handle_t* handle = hh.getNativeHandle(); + if (handle->numFds < 1) { + return Void(); + } + int fd = handle->data[0]; + std::string content = "debug info for "; + content += getInterfaceName(mId); + ssize_t written = write(fd, content.c_str(), content.size()); + if (written != (ssize_t)content.size()) { + LOG(WARNING) << "SERVER(" << descriptor << ") debug writes " << written << " bytes < " + << content.size() << " bytes, errno = " << errno; + } + return Void(); + } + +private: + pid_t mId; +}; + +TEST_F(ListTest, DumpDebug) { + size_t inheritanceLevel = 3; + sp<IBase> service = new InheritingService(inheritanceLevel); + + EXPECT_CALL(*serviceManager, list(_)).WillRepeatedly(Invoke([&](IServiceManager::list_cb cb) { + std::vector<hidl_string> ret; + for (auto i = 1; i <= inheritanceLevel; ++i) { + ret.push_back(getInterfaceName(i) + "/default"); + } + cb(ret); + return hardware::Void(); + })); + EXPECT_CALL(*serviceManager, get(_, _)) + .WillRepeatedly( + Invoke([&](const hidl_string&, const hidl_string& instance) -> sp<IBase> { + int id = getIdFromInstanceName(instance); + if (id > inheritanceLevel) return nullptr; + return sp<IBase>(service); + })); + + const std::string expected = "[fake description 0]\n" + "Interface\n" + "a.h.foo1@1.0::IFoo/default\n" + "[See a.h.foo3@3.0::IFoo/default]\n" + "a.h.foo2@2.0::IFoo/default\n" + "[See a.h.foo3@3.0::IFoo/default]\n" + "a.h.foo3@3.0::IFoo/default\n" + "debug info for a.h.foo3@3.0::IFoo\n" + "\n"; + + optind = 1; // mimic Lshal::parseArg() + EXPECT_EQ(0u, mockList->main(createArg({"lshal", "--types=b", "-id"}))); + EXPECT_EQ(expected, out.str()); + EXPECT_EQ("", err.str()); +} + class ListVintfTest : public ListTest { public: virtual void SetUp() override { |