Loading cmds/dumpstate/dumpstate.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -1236,7 +1236,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(Dumpsys::Type::DUMP, 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; Loading Loading @@ -1315,7 +1315,7 @@ static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priori path.append("_HIGH"); } path.append(kProtoExt); status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, 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); Loading cmds/dumpsys/dumpsys.cpp +43 −31 Original line number Diff line number Diff line Loading @@ -62,13 +62,14 @@ static void usage() { "usage: dumpsys\n" " To dump all services.\n" "or:\n" " dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--thread] [--help | -l | " "--skip SERVICES " " dumpsys [-t TIMEOUT] [--priority LEVEL] [--dump] [--pid] [--thread] [--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" " --dump: ask the service to dump itself (this is the default)\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" Loading Loading @@ -127,10 +128,11 @@ int Dumpsys::main(int argc, char* const argv[]) { bool showListOnly = false; bool skipServices = false; bool asProto = false; Type type = Type::DUMP; int dumpTypeFlags = 0; int timeoutArgMs = 10000; int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL; static struct option longOptions[] = {{"help", no_argument, 0, 0}, {"dump", no_argument, 0, 0}, {"pid", no_argument, 0, 0}, {"priority", required_argument, 0, 0}, {"proto", no_argument, 0, 0}, Loading Loading @@ -168,12 +170,14 @@ int Dumpsys::main(int argc, char* const argv[]) { usage(); return -1; } } else if (!strcmp(longOptions[optionIndex].name, "dump")) { dumpTypeFlags |= TYPE_DUMP; } else if (!strcmp(longOptions[optionIndex].name, "pid")) { type = Type::PID; dumpTypeFlags |= TYPE_PID; } else if (!strcmp(longOptions[optionIndex].name, "stability")) { type = Type::STABILITY; dumpTypeFlags |= TYPE_STABILITY; } else if (!strcmp(longOptions[optionIndex].name, "thread")) { type = Type::THREAD; dumpTypeFlags |= TYPE_THREAD; } break; Loading Loading @@ -211,6 +215,10 @@ int Dumpsys::main(int argc, char* const argv[]) { } } if (dumpTypeFlags == 0) { dumpTypeFlags = TYPE_DUMP; } for (int i = optind; i < argc; i++) { if (skipServices) { skippedServices.add(String16(argv[i])); Loading Loading @@ -263,7 +271,7 @@ int Dumpsys::main(int argc, char* const argv[]) { const String16& serviceName = services[i]; if (IsSkipped(skippedServices, serviceName)) continue; if (startDumpThread(type, serviceName, args) == OK) { if (startDumpThread(dumpTypeFlags, serviceName, args) == OK) { bool addSeparator = (N > 1); if (addSeparator) { writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags); Loading Loading @@ -330,18 +338,21 @@ void Dumpsys::setServiceArgs(Vector<String16>& args, bool asProto, int priorityF } } static status_t dumpPidToFd(const sp<IBinder>& service, const unique_fd& fd) { static status_t dumpPidToFd(const sp<IBinder>& service, const unique_fd& fd, bool exclusive) { pid_t pid; status_t status = service->getDebugPid(&pid); if (status != OK) { return status; } if (!exclusive) { WriteStringToFd("Service host process PID: ", fd.get()); } WriteStringToFd(std::to_string(pid) + "\n", fd.get()); return OK; } static status_t dumpStabilityToFd(const sp<IBinder>& service, const unique_fd& fd) { WriteStringToFd(internal::Stability::debugToString(service) + "\n", fd); WriteStringToFd("Stability: " + internal::Stability::debugToString(service) + "\n", fd); return OK; } Loading @@ -362,7 +373,14 @@ static status_t dumpThreadsToFd(const sp<IBinder>& service, const unique_fd& fd) return OK; } status_t Dumpsys::startDumpThread(Type type, const String16& serviceName, static void reportDumpError(const String16& serviceName, status_t error, const char* context) { if (error == OK) return; std::cerr << "Error with service '" << serviceName << "' while " << context << ": " << statusToString(error) << std::endl; } status_t Dumpsys::startDumpThread(int dumpTypeFlags, const String16& serviceName, const Vector<String16>& args) { sp<IBinder> service = sm_->checkService(serviceName); if (service == nullptr) { Loading @@ -383,29 +401,23 @@ status_t Dumpsys::startDumpThread(Type type, const String16& serviceName, // dump blocks until completion, so spawn a thread.. activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable { 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; case Type::STABILITY: err = dumpStabilityToFd(service, remote_end); break; case Type::THREAD: err = dumpThreadsToFd(service, remote_end); break; default: std::cerr << "Unknown dump type" << static_cast<int>(type) << std::endl; return; if (dumpTypeFlags & TYPE_PID) { status_t err = dumpPidToFd(service, remote_end, dumpTypeFlags == TYPE_PID); reportDumpError(serviceName, err, "dumping PID"); } if (dumpTypeFlags & TYPE_STABILITY) { status_t err = dumpStabilityToFd(service, remote_end); reportDumpError(serviceName, err, "dumping stability"); } if (dumpTypeFlags & TYPE_THREAD) { status_t err = dumpThreadsToFd(service, remote_end); reportDumpError(serviceName, err, "dumping thread info"); } if (err != OK) { std::cerr << "Error dumping service info status_t: " << statusToString(err) << " " << serviceName << std::endl; // other types always act as a header, this is usually longer if (dumpTypeFlags & TYPE_DUMP) { status_t err = service->dump(remote_end.get(), args); reportDumpError(serviceName, err, "dumping"); } }); return OK; Loading cmds/dumpsys/dumpsys.h +7 −6 Original line number Diff line number Diff line Loading @@ -51,24 +51,25 @@ 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 STABILITY, // dump stability information of server THREAD, // dump thread usage of server only enum Type { TYPE_DUMP = 0x1, // dump using `dump` function TYPE_PID = 0x2, // dump pid of server only TYPE_STABILITY = 0x4, // dump stability information of server TYPE_THREAD = 0x8, // dump thread usage 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 call to {@code * stopDumpThread}. * @param dumpTypeFlags operations to perform * @param serviceName * @param args list of arguments to pass to service dump method. * @return {@code OK} thread is started successfully. * {@code NAME_NOT_FOUND} service could not be found. * {@code != OK} error */ status_t startDumpThread(Type type, const String16& serviceName, status_t startDumpThread(int dumpTypeFlags, const String16& serviceName, const Vector<String16>& args); /** Loading cmds/dumpsys/tests/dumpsys_test.cpp +23 −1 Original line number Diff line number Diff line Loading @@ -200,7 +200,7 @@ class DumpsysTest : public Test { CaptureStdout(); CaptureStderr(); dump_.setServiceArgs(args, supportsProto, priorityFlags); status_t status = dump_.startDumpThread(Dumpsys::Type::DUMP, 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); Loading Loading @@ -627,6 +627,28 @@ TEST_F(DumpsysTest, ListServiceWithThread) { AssertOutputFormat(format); } // Tests 'dumpsys --thread --stability' TEST_F(DumpsysTest, ListAllServicesWithMultipleOptions) { ExpectListServices({"Locksmith", "Valet"}); ExpectCheckService("Locksmith"); ExpectCheckService("Valet"); CallMain({"--pid", "--stability"}); AssertRunningServices({"Locksmith", "Valet"}); AssertOutputContains(std::to_string(getpid())); AssertOutputContains("stability"); } // Tests 'dumpsys --pid --stability service_name' TEST_F(DumpsysTest, ListServiceWithMultipleOptions) { ExpectCheckService("Locksmith"); CallMain({"--pid", "--stability", "Locksmith"}); AssertOutputContains(std::to_string(getpid())); AssertOutputContains("stability"); } TEST_F(DumpsysTest, GetBytesWritten) { const char* serviceName = "service2"; const char* dumpContents = "dump1"; Loading Loading
cmds/dumpstate/dumpstate.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -1236,7 +1236,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(Dumpsys::Type::DUMP, 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; Loading Loading @@ -1315,7 +1315,7 @@ static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priori path.append("_HIGH"); } path.append(kProtoExt); status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, 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); Loading
cmds/dumpsys/dumpsys.cpp +43 −31 Original line number Diff line number Diff line Loading @@ -62,13 +62,14 @@ static void usage() { "usage: dumpsys\n" " To dump all services.\n" "or:\n" " dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--thread] [--help | -l | " "--skip SERVICES " " dumpsys [-t TIMEOUT] [--priority LEVEL] [--dump] [--pid] [--thread] [--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" " --dump: ask the service to dump itself (this is the default)\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" Loading Loading @@ -127,10 +128,11 @@ int Dumpsys::main(int argc, char* const argv[]) { bool showListOnly = false; bool skipServices = false; bool asProto = false; Type type = Type::DUMP; int dumpTypeFlags = 0; int timeoutArgMs = 10000; int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL; static struct option longOptions[] = {{"help", no_argument, 0, 0}, {"dump", no_argument, 0, 0}, {"pid", no_argument, 0, 0}, {"priority", required_argument, 0, 0}, {"proto", no_argument, 0, 0}, Loading Loading @@ -168,12 +170,14 @@ int Dumpsys::main(int argc, char* const argv[]) { usage(); return -1; } } else if (!strcmp(longOptions[optionIndex].name, "dump")) { dumpTypeFlags |= TYPE_DUMP; } else if (!strcmp(longOptions[optionIndex].name, "pid")) { type = Type::PID; dumpTypeFlags |= TYPE_PID; } else if (!strcmp(longOptions[optionIndex].name, "stability")) { type = Type::STABILITY; dumpTypeFlags |= TYPE_STABILITY; } else if (!strcmp(longOptions[optionIndex].name, "thread")) { type = Type::THREAD; dumpTypeFlags |= TYPE_THREAD; } break; Loading Loading @@ -211,6 +215,10 @@ int Dumpsys::main(int argc, char* const argv[]) { } } if (dumpTypeFlags == 0) { dumpTypeFlags = TYPE_DUMP; } for (int i = optind; i < argc; i++) { if (skipServices) { skippedServices.add(String16(argv[i])); Loading Loading @@ -263,7 +271,7 @@ int Dumpsys::main(int argc, char* const argv[]) { const String16& serviceName = services[i]; if (IsSkipped(skippedServices, serviceName)) continue; if (startDumpThread(type, serviceName, args) == OK) { if (startDumpThread(dumpTypeFlags, serviceName, args) == OK) { bool addSeparator = (N > 1); if (addSeparator) { writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags); Loading Loading @@ -330,18 +338,21 @@ void Dumpsys::setServiceArgs(Vector<String16>& args, bool asProto, int priorityF } } static status_t dumpPidToFd(const sp<IBinder>& service, const unique_fd& fd) { static status_t dumpPidToFd(const sp<IBinder>& service, const unique_fd& fd, bool exclusive) { pid_t pid; status_t status = service->getDebugPid(&pid); if (status != OK) { return status; } if (!exclusive) { WriteStringToFd("Service host process PID: ", fd.get()); } WriteStringToFd(std::to_string(pid) + "\n", fd.get()); return OK; } static status_t dumpStabilityToFd(const sp<IBinder>& service, const unique_fd& fd) { WriteStringToFd(internal::Stability::debugToString(service) + "\n", fd); WriteStringToFd("Stability: " + internal::Stability::debugToString(service) + "\n", fd); return OK; } Loading @@ -362,7 +373,14 @@ static status_t dumpThreadsToFd(const sp<IBinder>& service, const unique_fd& fd) return OK; } status_t Dumpsys::startDumpThread(Type type, const String16& serviceName, static void reportDumpError(const String16& serviceName, status_t error, const char* context) { if (error == OK) return; std::cerr << "Error with service '" << serviceName << "' while " << context << ": " << statusToString(error) << std::endl; } status_t Dumpsys::startDumpThread(int dumpTypeFlags, const String16& serviceName, const Vector<String16>& args) { sp<IBinder> service = sm_->checkService(serviceName); if (service == nullptr) { Loading @@ -383,29 +401,23 @@ status_t Dumpsys::startDumpThread(Type type, const String16& serviceName, // dump blocks until completion, so spawn a thread.. activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable { 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; case Type::STABILITY: err = dumpStabilityToFd(service, remote_end); break; case Type::THREAD: err = dumpThreadsToFd(service, remote_end); break; default: std::cerr << "Unknown dump type" << static_cast<int>(type) << std::endl; return; if (dumpTypeFlags & TYPE_PID) { status_t err = dumpPidToFd(service, remote_end, dumpTypeFlags == TYPE_PID); reportDumpError(serviceName, err, "dumping PID"); } if (dumpTypeFlags & TYPE_STABILITY) { status_t err = dumpStabilityToFd(service, remote_end); reportDumpError(serviceName, err, "dumping stability"); } if (dumpTypeFlags & TYPE_THREAD) { status_t err = dumpThreadsToFd(service, remote_end); reportDumpError(serviceName, err, "dumping thread info"); } if (err != OK) { std::cerr << "Error dumping service info status_t: " << statusToString(err) << " " << serviceName << std::endl; // other types always act as a header, this is usually longer if (dumpTypeFlags & TYPE_DUMP) { status_t err = service->dump(remote_end.get(), args); reportDumpError(serviceName, err, "dumping"); } }); return OK; Loading
cmds/dumpsys/dumpsys.h +7 −6 Original line number Diff line number Diff line Loading @@ -51,24 +51,25 @@ 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 STABILITY, // dump stability information of server THREAD, // dump thread usage of server only enum Type { TYPE_DUMP = 0x1, // dump using `dump` function TYPE_PID = 0x2, // dump pid of server only TYPE_STABILITY = 0x4, // dump stability information of server TYPE_THREAD = 0x8, // dump thread usage 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 call to {@code * stopDumpThread}. * @param dumpTypeFlags operations to perform * @param serviceName * @param args list of arguments to pass to service dump method. * @return {@code OK} thread is started successfully. * {@code NAME_NOT_FOUND} service could not be found. * {@code != OK} error */ status_t startDumpThread(Type type, const String16& serviceName, status_t startDumpThread(int dumpTypeFlags, const String16& serviceName, const Vector<String16>& args); /** Loading
cmds/dumpsys/tests/dumpsys_test.cpp +23 −1 Original line number Diff line number Diff line Loading @@ -200,7 +200,7 @@ class DumpsysTest : public Test { CaptureStdout(); CaptureStderr(); dump_.setServiceArgs(args, supportsProto, priorityFlags); status_t status = dump_.startDumpThread(Dumpsys::Type::DUMP, 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); Loading Loading @@ -627,6 +627,28 @@ TEST_F(DumpsysTest, ListServiceWithThread) { AssertOutputFormat(format); } // Tests 'dumpsys --thread --stability' TEST_F(DumpsysTest, ListAllServicesWithMultipleOptions) { ExpectListServices({"Locksmith", "Valet"}); ExpectCheckService("Locksmith"); ExpectCheckService("Valet"); CallMain({"--pid", "--stability"}); AssertRunningServices({"Locksmith", "Valet"}); AssertOutputContains(std::to_string(getpid())); AssertOutputContains("stability"); } // Tests 'dumpsys --pid --stability service_name' TEST_F(DumpsysTest, ListServiceWithMultipleOptions) { ExpectCheckService("Locksmith"); CallMain({"--pid", "--stability", "Locksmith"}); AssertOutputContains(std::to_string(getpid())); AssertOutputContains("stability"); } TEST_F(DumpsysTest, GetBytesWritten) { const char* serviceName = "service2"; const char* dumpContents = "dump1"; Loading