Loading cmds/dumpstate/dumpstate.cpp +2 −2 Original line number Original line Diff line number Diff line Loading @@ -1082,7 +1082,7 @@ static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, i std::string path(title); std::string path(title); path.append(" - ").append(String8(service).c_str()); path.append(" - ").append(String8(service).c_str()); size_t bytes_written = 0; 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) { if (status == OK) { dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority); dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority); std::chrono::duration<double> elapsed_seconds; std::chrono::duration<double> elapsed_seconds; Loading Loading @@ -1154,7 +1154,7 @@ static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priori path.append("_HIGH"); path.append("_HIGH"); } } path.append(kProtoExt); path.append(kProtoExt); status_t status = dumpsys.startDumpThread(service, args); status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args); if (status == OK) { if (status == OK) { status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout); status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout); bool dumpTerminated = (status == OK); bool dumpTerminated = (status == OK); Loading cmds/dumpsys/dumpsys.cpp +35 −13 Original line number Original line Diff line number Diff line Loading @@ -59,12 +59,13 @@ static void usage() { "usage: dumpsys\n" "usage: dumpsys\n" " To dump all services.\n" " To dump all services.\n" "or:\n" "or:\n" " dumpsys [-t TIMEOUT] [--priority LEVEL] [--help | -l | --skip SERVICES | " " dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--help | -l | --skip SERVICES " "SERVICE [ARGS]]\n" "| SERVICE [ARGS]]\n" " --help: shows this help\n" " --help: shows this help\n" " -l: only list services, do not dump them\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_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" " -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" " --proto: filter services that support dumping data in proto format. Dumps\n" " will be in proto format.\n" " will be in proto format.\n" " --priority LEVEL: filter services based on specified priority\n" " --priority LEVEL: filter services based on specified priority\n" Loading Loading @@ -120,9 +121,11 @@ int Dumpsys::main(int argc, char* const argv[]) { bool showListOnly = false; bool showListOnly = false; bool skipServices = false; bool skipServices = false; bool asProto = false; bool asProto = false; Type type = Type::DUMP; int timeoutArgMs = 10000; int timeoutArgMs = 10000; int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL; 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}, {"proto", no_argument, 0, 0}, {"skip", no_argument, 0, 0}, {"skip", no_argument, 0, 0}, {"help", no_argument, 0, 0}, {"help", no_argument, 0, 0}, Loading Loading @@ -157,6 +160,8 @@ int Dumpsys::main(int argc, char* const argv[]) { usage(); usage(); return -1; return -1; } } } else if (!strcmp(longOptions[optionIndex].name, "pid")) { type = Type::PID; } } break; break; Loading Loading @@ -246,7 +251,7 @@ int Dumpsys::main(int argc, char* const argv[]) { const String16& serviceName = services[i]; const String16& serviceName = services[i]; if (IsSkipped(skippedServices, serviceName)) continue; if (IsSkipped(skippedServices, serviceName)) continue; if (startDumpThread(serviceName, args) == OK) { if (startDumpThread(type, serviceName, args) == OK) { bool addSeparator = (N > 1); bool addSeparator = (N > 1); if (addSeparator) { if (addSeparator) { writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags); writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags); Loading Loading @@ -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); sp<IBinder> service = sm_->checkService(serviceName); if (service == nullptr) { if (service == nullptr) { aerr << "Can't find service: " << serviceName << endl; aerr << "Can't find service: " << serviceName << endl; Loading @@ -333,16 +349,22 @@ status_t Dumpsys::startDumpThread(const String16& serviceName, const Vector<Stri // dump blocks until completion, so spawn a thread.. // dump blocks until completion, so spawn a thread.. activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable { activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable { int err = service->dump(remote_end.get(), args); status_t err = 0; // It'd be nice to be able to close the remote end of the socketpair before the dump switch (type) { // call returns, to terminate our reads if the other end closes their copy of the case Type::DUMP: // file descriptor, but then hangs for some reason. There doesn't seem to be a good err = service->dump(remote_end.get(), args); // way to do this, though. break; remote_end.reset(); case Type::PID: err = dumpPidToFd(service, remote_end); break; default: aerr << "Unknown dump type" << static_cast<int>(type) << endl; return; } if (err != 0) { if (err != OK) { aerr << "Error dumping service info: (" << strerror(err) << ") " aerr << "Error dumping service info status_t: (" << err << ") " << serviceName << endl; << serviceName << endl; } } }); }); Loading cmds/dumpsys/dumpsys.h +7 −1 Original line number Original line Diff line number Diff line Loading @@ -51,6 +51,11 @@ class Dumpsys { */ */ static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags); 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 * 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 * the output to a pipe. Thread must be stopped by a subsequent callto {@code Loading @@ -61,7 +66,8 @@ class Dumpsys { * {@code NAME_NOT_FOUND} service could not be found. * {@code NAME_NOT_FOUND} service could not be found. * {@code != OK} error * {@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. * Writes a section header to a file descriptor. Loading cmds/dumpsys/tests/dumpsys_test.cpp +23 −2 Original line number Original line Diff line number Diff line Loading @@ -194,7 +194,7 @@ class DumpsysTest : public Test { CaptureStdout(); CaptureStdout(); CaptureStderr(); CaptureStderr(); dump_.setServiceArgs(args, supportsProto, priorityFlags); 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)); EXPECT_THAT(status, Eq(0)); status = dump_.writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(500), false, status = dump_.writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(500), false, elapsedDuration, bytesWritten); elapsedDuration, bytesWritten); Loading Loading @@ -539,6 +539,27 @@ TEST_F(DumpsysTest, DumpWithPriorityHighAndProto) { AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH); 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) { TEST_F(DumpsysTest, GetBytesWritten) { const char* serviceName = "service2"; const char* serviceName = "service2"; const char* dumpContents = "dump1"; const char* dumpContents = "dump1"; Loading Loading
cmds/dumpstate/dumpstate.cpp +2 −2 Original line number Original line Diff line number Diff line Loading @@ -1082,7 +1082,7 @@ static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, i std::string path(title); std::string path(title); path.append(" - ").append(String8(service).c_str()); path.append(" - ").append(String8(service).c_str()); size_t bytes_written = 0; 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) { if (status == OK) { dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority); dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority); std::chrono::duration<double> elapsed_seconds; std::chrono::duration<double> elapsed_seconds; Loading Loading @@ -1154,7 +1154,7 @@ static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priori path.append("_HIGH"); path.append("_HIGH"); } } path.append(kProtoExt); path.append(kProtoExt); status_t status = dumpsys.startDumpThread(service, args); status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args); if (status == OK) { if (status == OK) { status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout); status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout); bool dumpTerminated = (status == OK); bool dumpTerminated = (status == OK); Loading
cmds/dumpsys/dumpsys.cpp +35 −13 Original line number Original line Diff line number Diff line Loading @@ -59,12 +59,13 @@ static void usage() { "usage: dumpsys\n" "usage: dumpsys\n" " To dump all services.\n" " To dump all services.\n" "or:\n" "or:\n" " dumpsys [-t TIMEOUT] [--priority LEVEL] [--help | -l | --skip SERVICES | " " dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--help | -l | --skip SERVICES " "SERVICE [ARGS]]\n" "| SERVICE [ARGS]]\n" " --help: shows this help\n" " --help: shows this help\n" " -l: only list services, do not dump them\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_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" " -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" " --proto: filter services that support dumping data in proto format. Dumps\n" " will be in proto format.\n" " will be in proto format.\n" " --priority LEVEL: filter services based on specified priority\n" " --priority LEVEL: filter services based on specified priority\n" Loading Loading @@ -120,9 +121,11 @@ int Dumpsys::main(int argc, char* const argv[]) { bool showListOnly = false; bool showListOnly = false; bool skipServices = false; bool skipServices = false; bool asProto = false; bool asProto = false; Type type = Type::DUMP; int timeoutArgMs = 10000; int timeoutArgMs = 10000; int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL; 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}, {"proto", no_argument, 0, 0}, {"skip", no_argument, 0, 0}, {"skip", no_argument, 0, 0}, {"help", no_argument, 0, 0}, {"help", no_argument, 0, 0}, Loading Loading @@ -157,6 +160,8 @@ int Dumpsys::main(int argc, char* const argv[]) { usage(); usage(); return -1; return -1; } } } else if (!strcmp(longOptions[optionIndex].name, "pid")) { type = Type::PID; } } break; break; Loading Loading @@ -246,7 +251,7 @@ int Dumpsys::main(int argc, char* const argv[]) { const String16& serviceName = services[i]; const String16& serviceName = services[i]; if (IsSkipped(skippedServices, serviceName)) continue; if (IsSkipped(skippedServices, serviceName)) continue; if (startDumpThread(serviceName, args) == OK) { if (startDumpThread(type, serviceName, args) == OK) { bool addSeparator = (N > 1); bool addSeparator = (N > 1); if (addSeparator) { if (addSeparator) { writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags); writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags); Loading Loading @@ -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); sp<IBinder> service = sm_->checkService(serviceName); if (service == nullptr) { if (service == nullptr) { aerr << "Can't find service: " << serviceName << endl; aerr << "Can't find service: " << serviceName << endl; Loading @@ -333,16 +349,22 @@ status_t Dumpsys::startDumpThread(const String16& serviceName, const Vector<Stri // dump blocks until completion, so spawn a thread.. // dump blocks until completion, so spawn a thread.. activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable { activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable { int err = service->dump(remote_end.get(), args); status_t err = 0; // It'd be nice to be able to close the remote end of the socketpair before the dump switch (type) { // call returns, to terminate our reads if the other end closes their copy of the case Type::DUMP: // file descriptor, but then hangs for some reason. There doesn't seem to be a good err = service->dump(remote_end.get(), args); // way to do this, though. break; remote_end.reset(); case Type::PID: err = dumpPidToFd(service, remote_end); break; default: aerr << "Unknown dump type" << static_cast<int>(type) << endl; return; } if (err != 0) { if (err != OK) { aerr << "Error dumping service info: (" << strerror(err) << ") " aerr << "Error dumping service info status_t: (" << err << ") " << serviceName << endl; << serviceName << endl; } } }); }); Loading
cmds/dumpsys/dumpsys.h +7 −1 Original line number Original line Diff line number Diff line Loading @@ -51,6 +51,11 @@ class Dumpsys { */ */ static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags); 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 * 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 * the output to a pipe. Thread must be stopped by a subsequent callto {@code Loading @@ -61,7 +66,8 @@ class Dumpsys { * {@code NAME_NOT_FOUND} service could not be found. * {@code NAME_NOT_FOUND} service could not be found. * {@code != OK} error * {@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. * Writes a section header to a file descriptor. Loading
cmds/dumpsys/tests/dumpsys_test.cpp +23 −2 Original line number Original line Diff line number Diff line Loading @@ -194,7 +194,7 @@ class DumpsysTest : public Test { CaptureStdout(); CaptureStdout(); CaptureStderr(); CaptureStderr(); dump_.setServiceArgs(args, supportsProto, priorityFlags); 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)); EXPECT_THAT(status, Eq(0)); status = dump_.writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(500), false, status = dump_.writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(500), false, elapsedDuration, bytesWritten); elapsedDuration, bytesWritten); Loading Loading @@ -539,6 +539,27 @@ TEST_F(DumpsysTest, DumpWithPriorityHighAndProto) { AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH); 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) { TEST_F(DumpsysTest, GetBytesWritten) { const char* serviceName = "service2"; const char* serviceName = "service2"; const char* dumpContents = "dump1"; const char* dumpContents = "dump1"; Loading