2 * Command that dumps interesting system state to the log.
6 #define LOG_TAG "dumpsys"
12 #include <android-base/file.h>
13 #include <android-base/stringprintf.h>
14 #include <android-base/unique_fd.h>
15 #include <binder/IServiceManager.h>
16 #include <binder/Parcel.h>
17 #include <binder/ProcessState.h>
18 #include <binder/TextOutput.h>
19 #include <utils/Log.h>
20 #include <utils/Vector.h>
28 #include <sys/socket.h>
30 #include <sys/types.h>
33 using namespace android;
34 using android::base::StringPrintf;
35 using android::base::unique_fd;
36 using android::base::WriteFully;
38 static int sort_func(const String16* lhs, const String16* rhs)
40 return lhs->compare(*rhs);
46 " To dump all services.\n"
48 " dumpsys [-t TIMEOUT] [--help | -l | --skip SERVICES | SERVICE [ARGS]]\n"
49 " --help: shows this help\n"
50 " -l: only list services, do not dump them\n"
51 " -t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds\n"
52 " --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
53 " SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
56 bool IsSkipped(const Vector<String16>& skipped, const String16& service) {
57 for (const auto& candidate : skipped) {
58 if (candidate == service) {
65 int main(int argc, char* const argv[])
67 signal(SIGPIPE, SIG_IGN);
68 sp<IServiceManager> sm = defaultServiceManager();
71 ALOGE("Unable to get default service manager!");
72 aerr << "dumpsys: Unable to get default service manager!" << endl;
76 Vector<String16> services;
77 Vector<String16> args;
78 Vector<String16> skippedServices;
79 bool showListOnly = false;
80 bool skipServices = false;
82 static struct option longOptions[] = {
83 {"skip", no_argument, 0, 0 },
84 {"help", no_argument, 0, 0 },
92 c = getopt_long(argc, argv, "+t:l", longOptions, &optionIndex);
100 if (!strcmp(longOptions[optionIndex].name, "skip")) {
102 } else if (!strcmp(longOptions[optionIndex].name, "help")) {
111 timeoutArg = strtol(optarg, &endptr, 10);
112 if (*endptr != '\0' || timeoutArg <= 0) {
113 fprintf(stderr, "Error: invalid timeout number: '%s'\n", optarg);
124 fprintf(stderr, "\n");
130 for (int i = optind; i < argc; i++) {
132 skippedServices.add(String16(argv[i]));
135 services.add(String16(argv[i]));
137 args.add(String16(argv[i]));
142 if ((skipServices && skippedServices.empty()) ||
143 (showListOnly && (!services.empty() || !skippedServices.empty()))) {
148 if (services.empty() || showListOnly) {
150 services = sm->listServices();
151 services.sort(sort_func);
152 args.add(String16("-a"));
155 const size_t N = services.size();
158 // first print a list of the current services
159 aout << "Currently running services:" << endl;
161 for (size_t i=0; i<N; i++) {
162 sp<IBinder> service = sm->checkService(services[i]);
163 if (service != NULL) {
164 bool skipped = IsSkipped(skippedServices, services[i]);
165 aout << " " << services[i] << (skipped ? " (skipped)" : "") << endl;
174 for (size_t i = 0; i < N; i++) {
175 String16 service_name = std::move(services[i]);
176 if (IsSkipped(skippedServices, service_name)) continue;
178 sp<IBinder> service = sm->checkService(service_name);
179 if (service != NULL) {
182 if (pipe(sfd) != 0) {
183 aerr << "Failed to create pipe to dump service info for " << service_name
184 << ": " << strerror(errno) << endl;
188 unique_fd local_end(sfd[0]);
189 unique_fd remote_end(sfd[1]);
190 sfd[0] = sfd[1] = -1;
193 aout << "------------------------------------------------------------"
194 "-------------------" << endl;
195 aout << "DUMP OF SERVICE " << service_name << ":" << endl;
198 // dump blocks until completion, so spawn a thread..
199 std::thread dump_thread([=, remote_end { std::move(remote_end) }]() mutable {
200 int err = service->dump(remote_end.get(), args);
202 // It'd be nice to be able to close the remote end of the socketpair before the dump
203 // call returns, to terminate our reads if the other end closes their copy of the
204 // file descriptor, but then hangs for some reason. There doesn't seem to be a good
205 // way to do this, though.
209 aerr << "Error dumping service info: (" << strerror(err) << ") " << service_name
214 auto timeout = std::chrono::seconds(timeoutArg);
215 auto start = std::chrono::steady_clock::now();
216 auto end = start + timeout;
218 struct pollfd pfd = {
219 .fd = local_end.get(),
223 bool timed_out = false;
226 // Wrap this in a lambda so that TEMP_FAILURE_RETRY recalculates the timeout.
227 auto time_left_ms = [end]() {
228 auto now = std::chrono::steady_clock::now();
229 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
230 return std::max(diff.count(), 0ll);
233 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
235 aerr << "Error in poll while dumping service " << service_name << " : "
236 << strerror(errno) << endl;
239 } else if (rc == 0) {
245 rc = TEMP_FAILURE_RETRY(read(local_end.get(), buf, sizeof(buf)));
247 aerr << "Failed to read while dumping service " << service_name << ": "
248 << strerror(errno) << endl;
251 } else if (rc == 0) {
256 if (!WriteFully(STDOUT_FILENO, buf, rc)) {
257 aerr << "Failed to write while dumping service " << service_name << ": "
258 << strerror(errno) << endl;
265 aout << endl << "*** SERVICE DUMP TIMEOUT EXPIRED ***" << endl << endl;
268 if (timed_out || error) {
269 dump_thread.detach();
275 std::chrono::duration<double> elapsed_seconds =
276 std::chrono::steady_clock::now() - start;
277 aout << StringPrintf("--------- %.3fs ", elapsed_seconds.count()).c_str()
278 << "was the duration of dumpsys " << service_name << endl;
281 aerr << "Can't find service: " << service_name << endl;