diff options
author | 2019-10-08 13:53:28 -0700 | |
---|---|---|
committer | 2019-10-11 12:52:19 -0700 | |
commit | 5a30d34320a60cc81da28a544233419b011c6f45 (patch) | |
tree | 44ec8f5ce240e2ae705845f0cf3b30ac209b807a | |
parent | 3f6764362eae1126f0c86d28f2489ef9116ce40d (diff) |
dumpsys: add --pid option
We can't change the output format of dumpsys since too many places rely
on it, so introducing a separate option to dump the PID of a service.
Fixes: 141187318
Test: dumpsys_test, bugreport, also:
$ adb shell dumpsys --pid
...
-------------------------------------------------------------------------------
DUMP OF SERVICE package_native:
1165
--------- 0.001s was the duration of dumpsys package_native, ending at: 2019-10-08 20:35:32
...
(dumps pids of all services)
or with specific service name only:
$ dumpsys --pid package_native
1165
Change-Id: Iaa2478568245ca7d10d2e3f8ebafe43d2d26df2c
-rw-r--r-- | cmds/dumpstate/dumpstate.cpp | 4 | ||||
-rw-r--r-- | cmds/dumpsys/dumpsys.cpp | 44 | ||||
-rw-r--r-- | cmds/dumpsys/dumpsys.h | 8 | ||||
-rw-r--r-- | cmds/dumpsys/tests/dumpsys_test.cpp | 25 |
4 files changed, 68 insertions, 13 deletions
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 739f9ca8e3..67f12e8efe 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -1082,7 +1082,7 @@ static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, i std::string path(title); path.append(" - ").append(String8(service).c_str()); size_t bytes_written = 0; - status_t status = dumpsys.startDumpThread(service, args); + status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args); if (status == OK) { dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority); std::chrono::duration<double> elapsed_seconds; @@ -1154,7 +1154,7 @@ static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priori path.append("_HIGH"); } path.append(kProtoExt); - status_t status = dumpsys.startDumpThread(service, args); + status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args); if (status == OK) { status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout); bool dumpTerminated = (status == OK); diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp index 232dcec166..abdf168233 100644 --- a/cmds/dumpsys/dumpsys.cpp +++ b/cmds/dumpsys/dumpsys.cpp @@ -59,12 +59,13 @@ static void usage() { "usage: dumpsys\n" " To dump all services.\n" "or:\n" - " dumpsys [-t TIMEOUT] [--priority LEVEL] [--help | -l | --skip SERVICES | " - "SERVICE [ARGS]]\n" + " dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--help | -l | --skip SERVICES " + "| SERVICE [ARGS]]\n" " --help: shows this help\n" " -l: only list services, do not dump them\n" " -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n" " -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n" + " --pid: dump PID instead of usual dump\n" " --proto: filter services that support dumping data in proto format. Dumps\n" " will be in proto format.\n" " --priority LEVEL: filter services based on specified priority\n" @@ -120,9 +121,11 @@ int Dumpsys::main(int argc, char* const argv[]) { bool showListOnly = false; bool skipServices = false; bool asProto = false; + Type type = Type::DUMP; int timeoutArgMs = 10000; int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL; - static struct option longOptions[] = {{"priority", required_argument, 0, 0}, + static struct option longOptions[] = {{"pid", no_argument, 0, 0}, + {"priority", required_argument, 0, 0}, {"proto", no_argument, 0, 0}, {"skip", no_argument, 0, 0}, {"help", no_argument, 0, 0}, @@ -157,6 +160,8 @@ int Dumpsys::main(int argc, char* const argv[]) { usage(); return -1; } + } else if (!strcmp(longOptions[optionIndex].name, "pid")) { + type = Type::PID; } break; @@ -246,7 +251,7 @@ int Dumpsys::main(int argc, char* const argv[]) { const String16& serviceName = services[i]; if (IsSkipped(skippedServices, serviceName)) continue; - if (startDumpThread(serviceName, args) == OK) { + if (startDumpThread(type, serviceName, args) == OK) { bool addSeparator = (N > 1); if (addSeparator) { writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags); @@ -313,7 +318,18 @@ void Dumpsys::setServiceArgs(Vector<String16>& args, bool asProto, int priorityF } } -status_t Dumpsys::startDumpThread(const String16& serviceName, const Vector<String16>& args) { +static status_t dumpPidToFd(const sp<IBinder>& service, const unique_fd& fd) { + pid_t pid; + status_t status = service->getDebugPid(&pid); + if (status != OK) { + return status; + } + WriteStringToFd(std::to_string(pid) + "\n", fd.get()); + return OK; +} + +status_t Dumpsys::startDumpThread(Type type, const String16& serviceName, + const Vector<String16>& args) { sp<IBinder> service = sm_->checkService(serviceName); if (service == nullptr) { aerr << "Can't find service: " << serviceName << endl; @@ -333,10 +349,22 @@ status_t Dumpsys::startDumpThread(const String16& serviceName, const Vector<Stri // dump blocks until completion, so spawn a thread.. activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable { - int err = service->dump(remote_end.get(), args); + status_t err = 0; + + switch (type) { + case Type::DUMP: + err = service->dump(remote_end.get(), args); + break; + case Type::PID: + err = dumpPidToFd(service, remote_end); + break; + default: + aerr << "Unknown dump type" << static_cast<int>(type) << endl; + return; + } - if (err != 0) { - aerr << "Error dumping service info: (" << strerror(err) << ") " + if (err != OK) { + aerr << "Error dumping service info status_t: (" << err << ") " << serviceName << endl; } }); diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h index c48a1e959b..929c55c364 100644 --- a/cmds/dumpsys/dumpsys.h +++ b/cmds/dumpsys/dumpsys.h @@ -51,6 +51,11 @@ class Dumpsys { */ static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags); + enum class Type { + DUMP, // dump using `dump` function + PID, // dump pid of server only + }; + /** * Starts a thread to connect to a service and get its dump output. The thread redirects * the output to a pipe. Thread must be stopped by a subsequent callto {@code @@ -61,7 +66,8 @@ class Dumpsys { * {@code NAME_NOT_FOUND} service could not be found. * {@code != OK} error */ - status_t startDumpThread(const String16& serviceName, const Vector<String16>& args); + status_t startDumpThread(Type type, const String16& serviceName, + const Vector<String16>& args); /** * Writes a section header to a file descriptor. diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp index cbac839e6f..cf4e0b5a4c 100644 --- a/cmds/dumpsys/tests/dumpsys_test.cpp +++ b/cmds/dumpsys/tests/dumpsys_test.cpp @@ -194,7 +194,7 @@ class DumpsysTest : public Test { CaptureStdout(); CaptureStderr(); dump_.setServiceArgs(args, supportsProto, priorityFlags); - status_t status = dump_.startDumpThread(serviceName, args); + status_t status = dump_.startDumpThread(Dumpsys::Type::DUMP, serviceName, args); EXPECT_THAT(status, Eq(0)); status = dump_.writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(500), false, elapsedDuration, bytesWritten); @@ -539,6 +539,27 @@ TEST_F(DumpsysTest, DumpWithPriorityHighAndProto) { AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH); } +// Tests 'dumpsys --pid' +TEST_F(DumpsysTest, ListAllServicesWithPid) { + ExpectListServices({"Locksmith", "Valet"}); + ExpectCheckService("Locksmith"); + ExpectCheckService("Valet"); + + CallMain({"--pid"}); + + AssertRunningServices({"Locksmith", "Valet"}); + AssertOutputContains(std::to_string(getpid())); +} + +// Tests 'dumpsys --pid service_name' +TEST_F(DumpsysTest, ListServiceWithPid) { + ExpectCheckService("Locksmith"); + + CallMain({"--pid", "Locksmith"}); + + AssertOutput(std::to_string(getpid()) + "\n"); +} + TEST_F(DumpsysTest, GetBytesWritten) { const char* serviceName = "service2"; const char* dumpContents = "dump1"; @@ -563,4 +584,4 @@ TEST_F(DumpsysTest, WriteDumpWithoutThreadStart) { dump_.writeDump(STDOUT_FILENO, String16("service"), std::chrono::milliseconds(500), /* as_proto = */ false, elapsedDuration, bytesWritten); EXPECT_THAT(status, Eq(INVALID_OPERATION)); -}
\ No newline at end of file +} |