blob: 5a485e4b991f28d5695ad46395e3efb9e16c3726 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21#include <sys/stat.h>
22#include <limits.h>
San Mehat30b9f572009-09-01 13:27:20 -070023#include <errno.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024#include <fcntl.h>
25#include <sys/time.h>
26#include <sys/resource.h>
27
Mike Lockwood8d533732009-09-02 18:01:05 -040028#include <cutils/sockets.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029#include "private/android_filesystem_config.h"
30
Mike Lockwoodbb6fa172009-10-05 23:23:40 -040031#define LOG_NDEBUG 0
32#define LOG_TAG "dumpstate"
33#include <utils/Log.h>
34
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035#include "dumpstate.h"
36
37static char* const gzip_args[] = { "gzip", "-6", 0 };
38static int start_pattern[] = { 150, 0 };
39static int end_pattern[] = { 75, 50, 75, 50, 75, 0 };
40
41static struct tm now;
42
San Mehat30b9f572009-09-01 13:27:20 -070043static void dump_kernel_log(const char *path, const char *title) ;
44
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045/* dumps the current system state to stdout */
46static void dumpstate(int full) {
47 if (full) {
48 PRINT("========================================================");
49 PRINT("== dumpstate");
50 PRINT("========================================================");
51 PRINT("------ MEMORY INFO ------");
52 DUMP("/proc/meminfo");
53 PRINT("------ CPU INFO ------");
54 EXEC7("top", "-n", "1", "-d", "1", "-m", "30", "-t");
55 PRINT("------ PROCRANK ------");
56 EXEC_XBIN("procrank");
57 PRINT("------ VIRTUAL MEMORY STATS ------");
58 DUMP("/proc/vmstat");
Dianne Hackbornb80b8d52009-10-08 10:49:12 -070059 PRINT("------ VMALLOC INFO ------");
60 DUMP("/proc/vmallocinfo");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 PRINT("------ SLAB INFO ------");
62 DUMP("/proc/slabinfo");
63 PRINT("------ ZONEINFO ------");
64 DUMP("/proc/zoneinfo");
65 PRINT("------ SYSTEM LOG ------");
66 EXEC4("logcat", "-v", "time", "-d", "*:v");
67 PRINT("------ VM TRACES ------");
68 DUMP("/data/anr/traces.txt");
69 PRINT("------ EVENT LOG TAGS ------");
70 DUMP("/etc/event-log-tags");
71 PRINT("------ EVENT LOG ------");
72 EXEC6("logcat", "-b", "events", "-v", "time", "-d", "*:v");
73 PRINT("------ RADIO LOG ------");
74 EXEC6("logcat", "-b", "radio", "-v", "time", "-d", "*:v");
75 PRINT("------ NETWORK STATE ------");
76 PRINT("Interfaces:");
77 EXEC("netcfg");
78 PRINT("");
79 PRINT("Routes:");
80 DUMP("/proc/net/route");
81 PRINT("------ SYSTEM PROPERTIES ------");
82 print_properties();
83 PRINT("------ KERNEL LOG ------");
84 EXEC("dmesg");
85 PRINT("------ KERNEL WAKELOCKS ------");
86 DUMP("/proc/wakelocks");
Mike Chanc6b406f2009-11-19 16:01:05 -080087 PRINT("------ KERNEL CPUFREQ ------");
88 DUMP("/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089 PRINT("");
90 PRINT("------ PROCESSES ------");
Evan Millar26a2d822009-10-29 12:41:39 -070091 EXEC1("ps", "-P");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 PRINT("------ PROCESSES AND THREADS ------");
Evan Millar26a2d822009-10-29 12:41:39 -070093 EXEC3("ps", "-t", "-p", "-P");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 PRINT("------ LIBRANK ------");
95 EXEC_XBIN("librank");
96 PRINT("------ BINDER FAILED TRANSACTION LOG ------");
97 DUMP("/proc/binder/failed_transaction_log");
98 PRINT("");
99 PRINT("------ BINDER TRANSACTION LOG ------");
100 DUMP("/proc/binder/transaction_log");
101 PRINT("");
102 PRINT("------ BINDER TRANSACTIONS ------");
103 DUMP("/proc/binder/transactions");
104 PRINT("");
105 PRINT("------ BINDER STATS ------");
106 DUMP("/proc/binder/stats");
107 PRINT("");
108 PRINT("------ BINDER PROCESS STATE: $i ------");
109 DUMP_FILES("/proc/binder/proc");
110 PRINT("------ FILESYSTEMS ------");
111 EXEC("df");
112 PRINT("------ PACKAGE SETTINGS ------");
113 DUMP("/data/system/packages.xml");
114 PRINT("------ PACKAGE UID ERRORS ------");
115 DUMP("/data/system/uiderrors.txt");
San Mehat30b9f572009-09-01 13:27:20 -0700116
Dima Zavinf8172182009-11-25 23:31:48 -0800117 dump_kernel_log("/proc/last_kmsg", "LAST KMSG");
Iliyan Malchev326e3e22009-11-15 18:28:06 -0800118
119 PRINT("------ LAST RADIO LOG ------");
120 EXEC1("parse_radio_log", "/proc/last_radio_log");
121
San Mehat30b9f572009-09-01 13:27:20 -0700122 dump_kernel_log("/data/dontpanic/apanic_console",
123 "PANIC CONSOLE");
124 dump_kernel_log("/data/dontpanic/apanic_threads",
125 "PANIC THREADS");
Mike Lockwood2ecf3f5e02009-10-04 17:21:05 -0400126
127 PRINT("------ BACKLIGHTS ------");
128 DUMP_PROMPT("LCD brightness=", "/sys/class/leds/lcd-backlight/brightness");
129 DUMP_PROMPT("Button brightness=", "/sys/class/leds/button-backlight/brightness");
130 DUMP_PROMPT("Keyboard brightness=", "/sys/class/leds/keyboard-backlight/brightness");
131 DUMP_PROMPT("ALS mode=", "/sys/class/leds/lcd-backlight/als");
132 DUMP_PROMPT("LCD driver registers:\n", "/sys/class/leds/lcd-backlight/registers");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 }
134 PRINT("========================================================");
135 PRINT("== build.prop");
136 PRINT("========================================================");
137
138 /* the crash server parses key-value pairs between the VERSION INFO and
139 * END lines so we can aggregate crash reports based on this data.
140 */
141 PRINT("------ VERSION INFO ------");
142 print_date("currenttime=", &now);
143 DUMP_PROMPT("kernel.version=", "/proc/version");
144 DUMP_PROMPT("kernel.cmdline=", "/proc/cmdline");
145 DUMP("/system/build.prop");
146 PROPERTY("gsm.version.ril-impl");
147 PROPERTY("gsm.version.baseband");
148 PROPERTY("gsm.imei");
149 PROPERTY("gsm.sim.operator.numeric");
150 PROPERTY("gsm.operator.alpha");
151 PRINT("------ END ------");
152
153 if (full) {
154 PRINT("========================================================");
155 PRINT("== dumpsys");
156 PRINT("========================================================");
The Android Open Source Project4df24232009-03-05 14:34:35 -0800157 /* the full dumpsys is starting to take a long time, so we need
158 to increase its timeout. we really need to do the timeouts in
159 dumpsys itself... */
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700160 EXEC_TIMEOUT("dumpsys", 60);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 }
162}
163
164/* used to check the file name passed via argv[0] */
165static int check_command_name(const char* name, const char* test) {
166 int name_length, test_length;
167
168 if (!strcmp(name, test))
169 return 1;
170
171 name_length = strlen(name);
172 test_length = strlen(test);
173
174 if (name_length > test_length + 2) {
175 name += (name_length - test_length);
176 if (name[-1] != '/')
177 return 0;
178 if (!strcmp(name, test))
179 return 1;
180 }
181
182 return 0;
183}
184
185int main(int argc, char *argv[]) {
186 int dumpcrash = check_command_name(argv[0], "dumpcrash");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 int add_date = 0;
188 char* outfile = 0;
189 int vibrate = 0;
190 int compress = 0;
Mike Lockwood8d533732009-09-02 18:01:05 -0400191 int socket = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 int c, fd, vibrate_fd, fds[2];
193 char path[PATH_MAX];
194 pid_t pid;
Mike Lockwood472be482009-05-22 13:31:42 -0400195 gid_t groups[] = { AID_LOG, AID_SDCARD_RW };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196
Mike Lockwoodbb6fa172009-10-05 23:23:40 -0400197 LOGI("begin\n");
198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 /* set as high priority, and protect from OOM killer */
200 setpriority(PRIO_PROCESS, 0, -20);
201 protect_from_oom_killer();
202
203 get_time(&now);
204
Mike Lockwood8d533732009-09-02 18:01:05 -0400205 do {
206 c = getopt(argc, argv, "do:svz");
207 if (c == EOF)
208 break;
209 switch (c) {
210 case 'd':
211 add_date = 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 break;
Mike Lockwood8d533732009-09-02 18:01:05 -0400213 case 'o':
214 outfile = optarg;
215 break;
216 case 'v':
217 vibrate = 1;
218 break;
219 case 'z':
220 compress = 1;
221 break;
222 case 's':
223 socket = 1;
224 break;
225 case '?':
226 fprintf(stderr, "%s: invalid option -%c\n",
227 argv[0], optopt);
228 exit(1);
229 }
230 } while (1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231
232 /* open vibrator before switching user */
233 if (vibrate) {
234 vibrate_fd = open("/sys/class/timed_output/vibrator/enable", O_WRONLY);
235 if (vibrate_fd > 0)
236 fcntl(vibrate_fd, F_SETFD, FD_CLOEXEC);
237 } else
238 vibrate_fd = -1;
239
240 /* switch to non-root user and group */
Mike Lockwood472be482009-05-22 13:31:42 -0400241 setgroups(sizeof(groups)/sizeof(groups[0]), groups);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 setuid(AID_SHELL);
243
244 /* make it safe to use both printf and STDOUT_FILENO */
245 setvbuf(stdout, 0, _IONBF, 0);
246
Mike Lockwood8d533732009-09-02 18:01:05 -0400247 if (socket) {
248 struct sockaddr addr;
249 socklen_t alen;
250
251 int s = android_get_control_socket("dumpstate");
252 if (s < 0) {
253 fprintf(stderr, "could not open dumpstate socket\n");
254 exit(1);
255 }
256 if (listen(s, 4) < 0) {
257 fprintf(stderr, "could not listen on dumpstate socket\n");
258 exit(1);
259 }
260
261 alen = sizeof(addr);
262 fd = accept(s, &addr, &alen);
263 if (fd < 0) {
264 fprintf(stderr, "could not accept dumpstate socket\n");
265 exit(1);
266 }
267
268 /* redirect stdout to the socket */
269 dup2(fd, STDOUT_FILENO);
270 close(fd);
271 } else if (outfile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 if (strlen(outfile) > sizeof(path) - 100)
273 exit(1);
274
275 strcpy(path, outfile);
276 if (add_date) {
277 char date[260];
278 strftime(date, sizeof(date),
279 "-%Y-%m-%d-%H-%M-%S",
280 &now);
281 strcat(path, date);
282 }
283 if (compress)
284 strcat(path, ".gz");
285 else
286 strcat(path, ".txt");
287
288 /* ensure that all directories in the path exist */
289 create_directories(path);
290 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
291 if (fd < 0)
292 return fd;
293
294 if (compress) {
295 pipe(fds);
296
297 /* redirect our stdout to the pipe */
298 dup2(fds[1], STDOUT_FILENO);
299 close(fds[1]);
300
301 if ((pid = fork()) < 0)
302 {
303 fprintf(stderr, "fork error\n");
304 exit(1);
305 }
306
307 if (pid) {
308 /* parent case */
309
310 /* close our copy of the input to gzip */
311 close(fds[0]);
312 /* close our copy of the output file */
313 close(fd);
314 } else {
315 /* child case */
316
317 /* redirect our input pipe to stdin */
318 dup2(fds[0], STDIN_FILENO);
319 close(fds[0]);
320
321 /* redirect stdout to the output file */
322 dup2(fd, STDOUT_FILENO);
323 close(fd);
324
325 /* run gzip to postprocess our output */
326 execv("/system/bin/gzip", gzip_args);
327 fprintf(stderr, "execv returned\n");
328 }
329 } else {
330 /* redirect stdout to the output file */
331 dup2(fd, STDOUT_FILENO);
332 close(fd);
333 }
334 }
335 /* else everything will print to stdout */
336
337 if (vibrate) {
338 vibrate_pattern(vibrate_fd, start_pattern);
339 }
340 dumpstate(!dumpcrash);
341 if (vibrate) {
342 vibrate_pattern(vibrate_fd, end_pattern);
343 close(vibrate_fd);
344 }
345
346 /* so gzip will terminate */
347 close(STDOUT_FILENO);
348
Mike Lockwoodbb6fa172009-10-05 23:23:40 -0400349 LOGI("done\n");
350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 return 0;
352}
353
San Mehat30b9f572009-09-01 13:27:20 -0700354static void dump_kernel_log(const char *path, const char *title)
355
356{
San Mehata4eb91d2009-09-05 15:20:20 -0700357 printf("------ KERNEL %s LOG ------\n", title);
358 if (access(path, R_OK) < 0)
359 printf("%s: %s\n", path, strerror(errno));
360 else {
361 struct stat sbuf;
362
363 if (stat(path, &sbuf) < 0)
364 printf("%s: stat failed (%s)\n", path, strerror(errno));
365 else
San Mehataf686342009-10-02 13:15:53 -0700366 printf("Harvested %s", ctime(&sbuf.st_mtime));
San Mehata4eb91d2009-09-05 15:20:20 -0700367
368 DUMP(path);
369 }
San Mehat30b9f572009-09-01 13:27:20 -0700370}