blob: 5ed1b522b40e507ed742d20b50a153f882c3b13e [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 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 <errno.h>
21#include <unistd.h>
22#include <limits.h>
23#include <stdarg.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <ctype.h>
27#include <assert.h>
28
29#include "sysdeps.h"
30
31#ifdef HAVE_TERMIO_H
32#include <termios.h>
33#endif
34
35#define TRACE_TAG TRACE_ADB
36#include "adb.h"
37#include "adb_client.h"
38#include "file_sync_service.h"
39
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080040enum {
41 IGNORE_DATA,
42 WIPE_DATA,
43 FLASH_DATA
44};
45
46static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
47
Alexey Tarasov31664102009-10-22 02:55:00 +110048void get_my_path(char *s, size_t maxLen);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080049int find_sync_dirs(const char *srcarg,
50 char **android_srcdir_out, char **data_srcdir_out);
51int install_app(transport_type transport, char* serial, int argc, char** argv);
52int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
53
54static const char *gProductOutPath = NULL;
55
56static char *product_file(const char *extra)
57{
58 int n;
59 char *x;
60
61 if (gProductOutPath == NULL) {
62 fprintf(stderr, "adb: Product directory not specified; "
63 "use -p or define ANDROID_PRODUCT_OUT\n");
64 exit(1);
65 }
66
67 n = strlen(gProductOutPath) + strlen(extra) + 2;
68 x = malloc(n);
69 if (x == 0) {
70 fprintf(stderr, "adb: Out of memory (product_file())\n");
71 exit(1);
72 }
73
74 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
75 return x;
76}
77
78void version(FILE * out) {
79 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
80 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
81}
82
83void help()
84{
85 version(stderr);
86
87 fprintf(stderr,
88 "\n"
89 " -d - directs command to the only connected USB device\n"
90 " returns an error if more than one USB device is present.\n"
91 " -e - directs command to the only running emulator.\n"
92 " returns an error if more than one emulator is running.\n"
93 " -s <serial number> - directs command to the USB device or emulator with\n"
Nick Pellydb449262009-05-07 12:48:03 -070094 " the given serial number. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070095 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080096 " -p <product name or path> - simple product name like 'sooner', or\n"
97 " a relative/absolute path to a product\n"
98 " out directory like 'out/target/product/sooner'.\n"
99 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
100 " environment variable is used, which must\n"
101 " be an absolute path.\n"
102 " devices - list all connected devices\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400103 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
104 " Port 5555 is used by default if no port number is specified.\n"
105 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
106 " Port 5555 is used by default if no port number is specified.\n"
107 " Using this ocmmand with no additional arguments\n"
108 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800109 "\n"
110 "device commands:\n"
111 " adb push <local> <remote> - copy file/dir to device\n"
Joe Onorato00c0eea2010-01-05 13:42:25 -0800112 " adb pull <remote> [<local>] - copy file/dir from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800113 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600114 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800115 " (see 'adb help all')\n"
116 " adb shell - run remote shell interactively\n"
117 " adb shell <command> - run remote shell command\n"
118 " adb emu <command> - run emulator console command\n"
119 " adb logcat [ <filter-spec> ] - View device log\n"
120 " adb forward <local> <remote> - forward socket connections\n"
121 " forward specs are one of: \n"
122 " tcp:<port>\n"
123 " localabstract:<unix domain socket name>\n"
124 " localreserved:<unix domain socket name>\n"
125 " localfilesystem:<unix domain socket name>\n"
126 " dev:<character device name>\n"
127 " jdwp:<process pid> (remote only)\n"
128 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Mike Lockwood0ef3fd02010-02-19 17:53:27 -0500129 " adb install [-l] [-r] [-s] <file> - push this package file to the device and install it\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800130 " ('-l' means forward-lock the app)\n"
131 " ('-r' means reinstall the app, keeping its data)\n"
Mike Lockwood0ef3fd02010-02-19 17:53:27 -0500132 " ('-s' means install on SD card instead of internal storage)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800133 " adb uninstall [-k] <package> - remove this app package from the device\n"
134 " ('-k' means keep the data and cache directories)\n"
135 " adb bugreport - return all information from the device\n"
136 " that should be included in a bug report.\n"
137 "\n"
138 " adb help - show this help message\n"
139 " adb version - show version num\n"
140 "\n"
141 "DATAOPTS:\n"
142 " (no option) - don't touch the data partition\n"
143 " -w - wipe the data partition\n"
144 " -d - flash the data partition\n"
145 "\n"
146 "scripting:\n"
147 " adb wait-for-device - block until device is online\n"
148 " adb start-server - ensure that there is a server running\n"
149 " adb kill-server - kill the server if it is running\n"
150 " adb get-state - prints: offline | bootloader | device\n"
151 " adb get-serialno - prints: <serial-number>\n"
152 " adb status-window - continuously print device status for a specified device\n"
153 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400154 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800155 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700156 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800157 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700158 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800159 "\n"
160 "networking:\n"
161 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500162 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800163 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
164 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
165 "\n"
166 "adb sync notes: adb sync [ <directory> ]\n"
167 " <localdir> can be interpreted in several ways:\n"
168 "\n"
169 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
170 "\n"
171 " - If it is \"system\" or \"data\", only the corresponding partition\n"
172 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000173 "\n"
174 "environmental variables:\n"
175 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
176 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
177 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
178 " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800179 );
180}
181
182int usage()
183{
184 help();
185 return 1;
186}
187
188#ifdef HAVE_TERMIO_H
189static struct termios tio_save;
190
191static void stdin_raw_init(int fd)
192{
193 struct termios tio;
194
195 if(tcgetattr(fd, &tio)) return;
196 if(tcgetattr(fd, &tio_save)) return;
197
198 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
199
200 /* no timeout but request at least one character per read */
201 tio.c_cc[VTIME] = 0;
202 tio.c_cc[VMIN] = 1;
203
204 tcsetattr(fd, TCSANOW, &tio);
205 tcflush(fd, TCIFLUSH);
206}
207
208static void stdin_raw_restore(int fd)
209{
210 tcsetattr(fd, TCSANOW, &tio_save);
211 tcflush(fd, TCIFLUSH);
212}
213#endif
214
215static void read_and_dump(int fd)
216{
217 char buf[4096];
218 int len;
219
220 while(fd >= 0) {
221 len = adb_read(fd, buf, 4096);
222 if(len == 0) {
223 break;
224 }
225
226 if(len < 0) {
227 if(errno == EINTR) continue;
228 break;
229 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400230 fwrite(buf, 1, len, stdout);
231 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800232 }
233}
234
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800235static void *stdin_read_thread(void *x)
236{
237 int fd, fdi;
238 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800239 int r, n;
240 int state = 0;
241
242 int *fds = (int*) x;
243 fd = fds[0];
244 fdi = fds[1];
245 free(fds);
246
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800247 for(;;) {
248 /* fdi is really the client's stdin, so use read, not adb_read here */
249 r = unix_read(fdi, buf, 1024);
250 if(r == 0) break;
251 if(r < 0) {
252 if(errno == EINTR) continue;
253 break;
254 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400255 for(n = 0; n < r; n++){
256 switch(buf[n]) {
257 case '\n':
258 state = 1;
259 break;
260 case '\r':
261 state = 1;
262 break;
263 case '~':
264 if(state == 1) state++;
265 break;
266 case '.':
267 if(state == 2) {
268 fprintf(stderr,"\n* disconnect *\n");
269#ifdef HAVE_TERMIO_H
270 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800271#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400272 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800273 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400274 default:
275 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800276 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800277 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800278 r = adb_write(fd, buf, r);
279 if(r <= 0) {
280 break;
281 }
282 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800283 return 0;
284}
285
286int interactive_shell(void)
287{
288 adb_thread_t thr;
289 int fdi, fd;
290 int *fds;
291
292 fd = adb_connect("shell:");
293 if(fd < 0) {
294 fprintf(stderr,"error: %s\n", adb_error());
295 return 1;
296 }
297 fdi = 0; //dup(0);
298
299 fds = malloc(sizeof(int) * 2);
300 fds[0] = fd;
301 fds[1] = fdi;
302
303#ifdef HAVE_TERMIO_H
304 stdin_raw_init(fdi);
305#endif
306 adb_thread_create(&thr, stdin_read_thread, fds);
307 read_and_dump(fd);
308#ifdef HAVE_TERMIO_H
309 stdin_raw_restore(fdi);
310#endif
311 return 0;
312}
313
314
315static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
316{
317 if (serial) {
318 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
319 } else {
320 const char* prefix = "host";
321 if (ttype == kTransportUsb)
322 prefix = "host-usb";
323 else if (ttype == kTransportLocal)
324 prefix = "host-local";
325
326 snprintf(buffer, buflen, "%s:%s", prefix, command);
327 }
328}
329
330static void status_window(transport_type ttype, const char* serial)
331{
332 char command[4096];
333 char *state = 0;
334 char *laststate = 0;
335
336 /* silence stderr */
337#ifdef _WIN32
338 /* XXX: TODO */
339#else
340 int fd;
341 fd = unix_open("/dev/null", O_WRONLY);
342 dup2(fd, 2);
343 adb_close(fd);
344#endif
345
346 format_host_command(command, sizeof command, "get-state", ttype, serial);
347
348 for(;;) {
349 adb_sleep_ms(250);
350
351 if(state) {
352 free(state);
353 state = 0;
354 }
355
356 state = adb_query(command);
357
358 if(state) {
359 if(laststate && !strcmp(state,laststate)){
360 continue;
361 } else {
362 if(laststate) free(laststate);
363 laststate = strdup(state);
364 }
365 }
366
367 printf("%c[2J%c[2H", 27, 27);
368 printf("Android Debug Bridge\n");
369 printf("State: %s\n", state ? state : "offline");
370 fflush(stdout);
371 }
372}
373
374/** duplicate string and quote all \ " ( ) chars + space character. */
375static char *
376dupAndQuote(const char *s)
377{
378 const char *ts;
379 size_t alloc_len;
380 char *ret;
381 char *dest;
382
383 ts = s;
384
385 alloc_len = 0;
386
387 for( ;*ts != '\0'; ts++) {
388 alloc_len++;
389 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
390 alloc_len++;
391 }
392 }
393
394 ret = (char *)malloc(alloc_len + 1);
395
396 ts = s;
397 dest = ret;
398
399 for ( ;*ts != '\0'; ts++) {
400 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
401 *dest++ = '\\';
402 }
403
404 *dest++ = *ts;
405 }
406
407 *dest++ = '\0';
408
409 return ret;
410}
411
412/**
413 * Run ppp in "notty" mode against a resource listed as the first parameter
414 * eg:
415 *
416 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
417 *
418 */
419int ppp(int argc, char **argv)
420{
421#ifdef HAVE_WIN32_PROC
422 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
423 return -1;
424#else
425 char *adb_service_name;
426 pid_t pid;
427 int fd;
428
429 if (argc < 2) {
430 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
431 argv[0]);
432
433 return 1;
434 }
435
436 adb_service_name = argv[1];
437
438 fd = adb_connect(adb_service_name);
439
440 if(fd < 0) {
441 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
442 adb_service_name, adb_error());
443 return 1;
444 }
445
446 pid = fork();
447
448 if (pid < 0) {
449 perror("from fork()");
450 return 1;
451 } else if (pid == 0) {
452 int err;
453 int i;
454 const char **ppp_args;
455
456 // copy args
457 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
458 ppp_args[0] = "pppd";
459 for (i = 2 ; i < argc ; i++) {
460 //argv[2] and beyond become ppp_args[1] and beyond
461 ppp_args[i - 1] = argv[i];
462 }
463 ppp_args[i-1] = NULL;
464
465 // child side
466
467 dup2(fd, STDIN_FILENO);
468 dup2(fd, STDOUT_FILENO);
469 adb_close(STDERR_FILENO);
470 adb_close(fd);
471
472 err = execvp("pppd", (char * const *)ppp_args);
473
474 if (err < 0) {
475 perror("execing pppd");
476 }
477 exit(-1);
478 } else {
479 // parent side
480
481 adb_close(fd);
482 return 0;
483 }
484#endif /* !HAVE_WIN32_PROC */
485}
486
487static int send_shellcommand(transport_type transport, char* serial, char* buf)
488{
489 int fd, ret;
490
491 for(;;) {
492 fd = adb_connect(buf);
493 if(fd >= 0)
494 break;
495 fprintf(stderr,"- waiting for device -\n");
496 adb_sleep_ms(1000);
497 do_cmd(transport, serial, "wait-for-device", 0);
498 }
499
500 read_and_dump(fd);
501 ret = adb_close(fd);
502 if (ret)
503 perror("close");
504
505 return ret;
506}
507
508static int logcat(transport_type transport, char* serial, int argc, char **argv)
509{
510 char buf[4096];
511
512 char *log_tags;
513 char *quoted_log_tags;
514
515 log_tags = getenv("ANDROID_LOG_TAGS");
516 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
517
518 snprintf(buf, sizeof(buf),
519 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
520 quoted_log_tags);
521
522 free(quoted_log_tags);
523
524 argc -= 1;
525 argv += 1;
526 while(argc-- > 0) {
527 char *quoted;
528
529 quoted = dupAndQuote (*argv++);
530
531 strncat(buf, " ", sizeof(buf)-1);
532 strncat(buf, quoted, sizeof(buf)-1);
533 free(quoted);
534 }
535
536 send_shellcommand(transport, serial, buf);
537 return 0;
538}
539
540#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
541static int top_works(const char *top)
542{
543 if (top != NULL && adb_is_absolute_host_path(top)) {
544 char path_buf[PATH_MAX];
545 snprintf(path_buf, sizeof(path_buf),
546 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
547 return access(path_buf, F_OK) == 0;
548 }
549 return 0;
550}
551
552static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
553{
554 strcpy(path_buf, indir);
555 while (1) {
556 if (top_works(path_buf)) {
557 return path_buf;
558 }
559 char *s = adb_dirstop(path_buf);
560 if (s != NULL) {
561 *s = '\0';
562 } else {
563 path_buf[0] = '\0';
564 return NULL;
565 }
566 }
567}
568
569static char *find_top(char path_buf[PATH_MAX])
570{
571 char *top = getenv("ANDROID_BUILD_TOP");
572 if (top != NULL && top[0] != '\0') {
573 if (!top_works(top)) {
574 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
575 return NULL;
576 }
577 } else {
578 top = getenv("TOP");
579 if (top != NULL && top[0] != '\0') {
580 if (!top_works(top)) {
581 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
582 return NULL;
583 }
584 } else {
585 top = NULL;
586 }
587 }
588
589 if (top != NULL) {
590 /* The environment pointed to a top directory that works.
591 */
592 strcpy(path_buf, top);
593 return path_buf;
594 }
595
596 /* The environment didn't help. Walk up the tree from the CWD
597 * to see if we can find the top.
598 */
599 char dir[PATH_MAX];
600 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
601 if (top == NULL) {
602 /* If the CWD isn't under a good-looking top, see if the
603 * executable is.
604 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100605 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800606 top = find_top_from(dir, path_buf);
607 }
608 return top;
609}
610
611/* <hint> may be:
612 * - A simple product name
613 * e.g., "sooner"
614TODO: debug? sooner-debug, sooner:debug?
615 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
616 * e.g., "out/target/product/sooner"
617 * - An absolute path to the PRODUCT_OUT dir
618 * e.g., "/src/device/out/target/product/sooner"
619 *
620 * Given <hint>, try to construct an absolute path to the
621 * ANDROID_PRODUCT_OUT dir.
622 */
623static const char *find_product_out_path(const char *hint)
624{
625 static char path_buf[PATH_MAX];
626
627 if (hint == NULL || hint[0] == '\0') {
628 return NULL;
629 }
630
631 /* If it's already absolute, don't bother doing any work.
632 */
633 if (adb_is_absolute_host_path(hint)) {
634 strcpy(path_buf, hint);
635 return path_buf;
636 }
637
638 /* If there are any slashes in it, assume it's a relative path;
639 * make it absolute.
640 */
641 if (adb_dirstart(hint) != NULL) {
642 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
643 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
644 return NULL;
645 }
646 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
647 fprintf(stderr, "adb: Couldn't assemble path\n");
648 return NULL;
649 }
650 strcat(path_buf, OS_PATH_SEPARATOR_STR);
651 strcat(path_buf, hint);
652 return path_buf;
653 }
654
655 /* It's a string without any slashes. Try to do something with it.
656 *
657 * Try to find the root of the build tree, and build a PRODUCT_OUT
658 * path from there.
659 */
660 char top_buf[PATH_MAX];
661 const char *top = find_top(top_buf);
662 if (top == NULL) {
663 fprintf(stderr, "adb: Couldn't find top of build tree\n");
664 return NULL;
665 }
666//TODO: if we have a way to indicate debug, look in out/debug/target/...
667 snprintf(path_buf, sizeof(path_buf),
668 "%s" OS_PATH_SEPARATOR_STR
669 "out" OS_PATH_SEPARATOR_STR
670 "target" OS_PATH_SEPARATOR_STR
671 "product" OS_PATH_SEPARATOR_STR
672 "%s", top_buf, hint);
673 if (access(path_buf, F_OK) < 0) {
674 fprintf(stderr, "adb: Couldn't find a product dir "
675 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
676 return NULL;
677 }
678 return path_buf;
679}
680
681int adb_commandline(int argc, char **argv)
682{
683 char buf[4096];
684 int no_daemon = 0;
685 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100686 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800687 int persist = 0;
688 int r;
689 int quote;
690 transport_type ttype = kTransportAny;
691 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100692 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800693
694 /* If defined, this should be an absolute path to
695 * the directory containing all of the various system images
696 * for a particular product. If not defined, and the adb
697 * command requires this information, then the user must
698 * specify the path using "-p".
699 */
700 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
701 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
702 gProductOutPath = NULL;
703 }
704 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
705
Nick Pellydb449262009-05-07 12:48:03 -0700706 serial = getenv("ANDROID_SERIAL");
707
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100708 /* Validate and assign the server port */
709 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
710 int server_port = DEFAULT_ADB_PORT;
711 if (server_port_str && strlen(server_port_str) > 0) {
712 server_port = (int) strtol(server_port_str, NULL, 0);
713 if (server_port <= 0) {
714 fprintf(stderr,
715 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
716 server_port_str);
717 return usage();
718 }
719 }
720
721 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800722 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100723 if(!strcmp(argv[0],"server")) {
724 is_server = 1;
725 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800726 no_daemon = 1;
727 } else if (!strcmp(argv[0], "fork-server")) {
728 /* this is a special flag used only when the ADB client launches the ADB Server */
729 is_daemon = 1;
730 } else if(!strcmp(argv[0],"persist")) {
731 persist = 1;
732 } else if(!strncmp(argv[0], "-p", 2)) {
733 const char *product = NULL;
734 if (argv[0][2] == '\0') {
735 if (argc < 2) return usage();
736 product = argv[1];
737 argc--;
738 argv++;
739 } else {
740 product = argv[1] + 2;
741 }
742 gProductOutPath = find_product_out_path(product);
743 if (gProductOutPath == NULL) {
744 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
745 product);
746 return usage();
747 }
748 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
749 if (isdigit(argv[0][2])) {
750 serial = argv[0] + 2;
751 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100752 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800753 serial = argv[1];
754 argc--;
755 argv++;
756 }
757 } else if (!strcmp(argv[0],"-d")) {
758 ttype = kTransportUsb;
759 } else if (!strcmp(argv[0],"-e")) {
760 ttype = kTransportLocal;
761 } else {
762 /* out of recognized modifiers and flags */
763 break;
764 }
765 argc--;
766 argv++;
767 }
768
769 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100770 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800771
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100772 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800773 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100774 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800775 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100776 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800777 }
778 if(r) {
779 fprintf(stderr,"* could not start server *\n");
780 }
781 return r;
782 }
783
784top:
785 if(argc == 0) {
786 return usage();
787 }
788
789 /* adb_connect() commands */
790
791 if(!strcmp(argv[0], "devices")) {
792 char *tmp;
793 snprintf(buf, sizeof buf, "host:%s", argv[0]);
794 tmp = adb_query(buf);
795 if(tmp) {
796 printf("List of devices attached \n");
797 printf("%s\n", tmp);
798 return 0;
799 } else {
800 return 1;
801 }
802 }
803
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400804 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -0700805 char *tmp;
806 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400807 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -0700808 return 1;
809 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400810 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
811 tmp = adb_query(buf);
812 if(tmp) {
813 printf("%s\n", tmp);
814 return 0;
815 } else {
816 return 1;
817 }
818 }
819
820 if(!strcmp(argv[0], "disconnect")) {
821 char *tmp;
822 if (argc > 2) {
823 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
824 return 1;
825 }
826 if (argc == 2) {
827 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
828 } else {
829 snprintf(buf, sizeof buf, "host:disconnect:");
830 }
Mike Lockwoodff196702009-08-24 15:58:40 -0700831 tmp = adb_query(buf);
832 if(tmp) {
833 printf("%s\n", tmp);
834 return 0;
835 } else {
836 return 1;
837 }
838 }
839
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800840 if (!strcmp(argv[0], "emu")) {
841 return adb_send_emulator_command(argc, argv);
842 }
843
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400844 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800845 int r;
846 int fd;
847
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400848 char h = (argv[0][0] == 'h');
849
850 if (h) {
851 printf("\x1b[41;33m");
852 fflush(stdout);
853 }
854
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800855 if(argc < 2) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400856 r = interactive_shell();
857 if (h) {
858 printf("\x1b[0m");
859 fflush(stdout);
860 }
861 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800862 }
863
864 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
865 argc -= 2;
866 argv += 2;
867 while(argc-- > 0) {
868 strcat(buf, " ");
869
870 /* quote empty strings and strings with spaces */
871 quote = (**argv == 0 || strchr(*argv, ' '));
872 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100873 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800874 strcat(buf, *argv++);
875 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100876 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800877 }
878
879 for(;;) {
880 fd = adb_connect(buf);
881 if(fd >= 0) {
882 read_and_dump(fd);
883 adb_close(fd);
884 r = 0;
885 } else {
886 fprintf(stderr,"error: %s\n", adb_error());
887 r = -1;
888 }
889
890 if(persist) {
891 fprintf(stderr,"\n- waiting for device -\n");
892 adb_sleep_ms(1000);
893 do_cmd(ttype, serial, "wait-for-device", 0);
894 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -0400895 if (h) {
896 printf("\x1b[0m");
897 fflush(stdout);
898 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800899 return r;
900 }
901 }
902 }
903
904 if(!strcmp(argv[0], "kill-server")) {
905 int fd;
906 fd = _adb_connect("host:kill");
907 if(fd == -1) {
908 fprintf(stderr,"* server not running *\n");
909 return 1;
910 }
911 return 0;
912 }
913
Mike Lockwoodff196702009-08-24 15:58:40 -0700914 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -0800915 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -0700916 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -0400917 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -0700918 char command[100];
Romain Guy311add42009-12-14 14:42:17 -0800919 if (!strcmp(argv[0], "reboot-bootloader"))
920 snprintf(command, sizeof(command), "reboot:bootloader");
921 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -0700922 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -0400923 else
Mike Lockwoodff196702009-08-24 15:58:40 -0700924 snprintf(command, sizeof(command), "%s:", argv[0]);
925 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -0700926 if(fd >= 0) {
927 read_and_dump(fd);
928 adb_close(fd);
929 return 0;
930 }
931 fprintf(stderr,"error: %s\n", adb_error());
932 return 1;
933 }
934
Mike Lockwoodf56d1b52009-09-03 14:54:58 -0400935 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -0800936 if (argc != 1) return usage();
937 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -0400938 return 0;
939 }
940
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800941 /* adb_command() wrapper commands */
942
943 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
944 char* service = argv[0];
945 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
946 if (ttype == kTransportUsb) {
947 service = "wait-for-usb";
948 } else if (ttype == kTransportLocal) {
949 service = "wait-for-local";
950 } else {
951 service = "wait-for-any";
952 }
953 }
954
955 format_host_command(buf, sizeof buf, service, ttype, serial);
956
957 if (adb_command(buf)) {
958 D("failure: %s *\n",adb_error());
959 fprintf(stderr,"error: %s\n", adb_error());
960 return 1;
961 }
962
963 /* Allow a command to be run after wait-for-device,
964 * e.g. 'adb wait-for-device shell'.
965 */
966 if(argc > 1) {
967 argc--;
968 argv++;
969 goto top;
970 }
971 return 0;
972 }
973
974 if(!strcmp(argv[0], "forward")) {
975 if(argc != 3) return usage();
976 if (serial) {
Mike Lockwood64e99542009-11-28 12:46:13 -0500977 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
978 } else if (ttype == kTransportUsb) {
979 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
980 } else if (ttype == kTransportLocal) {
981 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800982 } else {
Mike Lockwood64e99542009-11-28 12:46:13 -0500983 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800984 }
985 if(adb_command(buf)) {
986 fprintf(stderr,"error: %s\n", adb_error());
987 return 1;
988 }
989 return 0;
990 }
991
992 /* do_sync_*() commands */
993
994 if(!strcmp(argv[0], "ls")) {
995 if(argc != 2) return usage();
996 return do_sync_ls(argv[1]);
997 }
998
999 if(!strcmp(argv[0], "push")) {
1000 if(argc != 3) return usage();
1001 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1002 }
1003
1004 if(!strcmp(argv[0], "pull")) {
Joe Onorato00c0eea2010-01-05 13:42:25 -08001005 if (argc == 2) {
1006 return do_sync_pull(argv[1], ".");
1007 } else if (argc == 3) {
1008 return do_sync_pull(argv[1], argv[2]);
1009 } else {
1010 return usage();
1011 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001012 }
1013
1014 if(!strcmp(argv[0], "install")) {
1015 if (argc < 2) return usage();
1016 return install_app(ttype, serial, argc, argv);
1017 }
1018
1019 if(!strcmp(argv[0], "uninstall")) {
1020 if (argc < 2) return usage();
1021 return uninstall_app(ttype, serial, argc, argv);
1022 }
1023
1024 if(!strcmp(argv[0], "sync")) {
1025 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001026 int listonly = 0;
1027
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001028 int ret;
1029 if(argc < 2) {
1030 /* No local path was specified. */
1031 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001032 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1033 listonly = 1;
1034 if (argc == 3) {
1035 srcarg = argv[2];
1036 } else {
1037 srcarg = NULL;
1038 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001039 } else if(argc == 2) {
1040 /* A local path or "android"/"data" arg was specified. */
1041 srcarg = argv[1];
1042 } else {
1043 return usage();
1044 }
1045 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1046 if(ret != 0) return usage();
1047
1048 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001049 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001050 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001051 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001052
1053 free(android_srcpath);
1054 free(data_srcpath);
1055 return ret;
1056 }
1057
1058 /* passthrough commands */
1059
1060 if(!strcmp(argv[0],"get-state") ||
1061 !strcmp(argv[0],"get-serialno"))
1062 {
1063 char *tmp;
1064
1065 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1066 tmp = adb_query(buf);
1067 if(tmp) {
1068 printf("%s\n", tmp);
1069 return 0;
1070 } else {
1071 return 1;
1072 }
1073 }
1074
1075 /* other commands */
1076
1077 if(!strcmp(argv[0],"status-window")) {
1078 status_window(ttype, serial);
1079 return 0;
1080 }
1081
1082 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) {
1083 return logcat(ttype, serial, argc, argv);
1084 }
1085
1086 if(!strcmp(argv[0],"ppp")) {
1087 return ppp(argc, argv);
1088 }
1089
1090 if (!strcmp(argv[0], "start-server")) {
1091 return adb_connect("host:start-server");
1092 }
1093
1094 if (!strcmp(argv[0], "jdwp")) {
1095 int fd = adb_connect("jdwp");
1096 if (fd >= 0) {
1097 read_and_dump(fd);
1098 adb_close(fd);
1099 return 0;
1100 } else {
1101 fprintf(stderr, "error: %s\n", adb_error());
1102 return -1;
1103 }
1104 }
1105
1106 /* "adb /?" is a common idiom under Windows */
1107 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1108 help();
1109 return 0;
1110 }
1111
1112 if(!strcmp(argv[0], "version")) {
1113 version(stdout);
1114 return 0;
1115 }
1116
1117 usage();
1118 return 1;
1119}
1120
1121static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1122{
1123 char *argv[16];
1124 int argc;
1125 va_list ap;
1126
1127 va_start(ap, cmd);
1128 argc = 0;
1129
1130 if (serial) {
1131 argv[argc++] = "-s";
1132 argv[argc++] = serial;
1133 } else if (ttype == kTransportUsb) {
1134 argv[argc++] = "-d";
1135 } else if (ttype == kTransportLocal) {
1136 argv[argc++] = "-e";
1137 }
1138
1139 argv[argc++] = cmd;
1140 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1141 va_end(ap);
1142
1143#if 0
1144 int n;
1145 fprintf(stderr,"argc = %d\n",argc);
1146 for(n = 0; n < argc; n++) {
1147 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1148 }
1149#endif
1150
1151 return adb_commandline(argc, argv);
1152}
1153
1154int find_sync_dirs(const char *srcarg,
1155 char **android_srcdir_out, char **data_srcdir_out)
1156{
1157 char *android_srcdir, *data_srcdir;
1158
1159 if(srcarg == NULL) {
1160 android_srcdir = product_file("system");
1161 data_srcdir = product_file("data");
1162 } else {
1163 /* srcarg may be "data", "system" or NULL.
1164 * if srcarg is NULL, then both data and system are synced
1165 */
1166 if(strcmp(srcarg, "system") == 0) {
1167 android_srcdir = product_file("system");
1168 data_srcdir = NULL;
1169 } else if(strcmp(srcarg, "data") == 0) {
1170 android_srcdir = NULL;
1171 data_srcdir = product_file("data");
1172 } else {
1173 /* It's not "system" or "data".
1174 */
1175 return 1;
1176 }
1177 }
1178
1179 if(android_srcdir_out != NULL)
1180 *android_srcdir_out = android_srcdir;
1181 else
1182 free(android_srcdir);
1183
1184 if(data_srcdir_out != NULL)
1185 *data_srcdir_out = data_srcdir;
1186 else
1187 free(data_srcdir);
1188
1189 return 0;
1190}
1191
1192static int pm_command(transport_type transport, char* serial,
1193 int argc, char** argv)
1194{
1195 char buf[4096];
1196
1197 snprintf(buf, sizeof(buf), "shell:pm");
1198
1199 while(argc-- > 0) {
1200 char *quoted;
1201
1202 quoted = dupAndQuote(*argv++);
1203
1204 strncat(buf, " ", sizeof(buf)-1);
1205 strncat(buf, quoted, sizeof(buf)-1);
1206 free(quoted);
1207 }
1208
1209 send_shellcommand(transport, serial, buf);
1210 return 0;
1211}
1212
1213int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1214{
1215 /* if the user choose the -k option, we refuse to do it until devices are
1216 out with the option to uninstall the remaining data somehow (adb/ui) */
1217 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1218 {
1219 printf(
1220 "The -k option uninstalls the application while retaining the data/cache.\n"
1221 "At the moment, there is no way to remove the remaining data.\n"
1222 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1223 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1224 return -1;
1225 }
1226
1227 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1228 return pm_command(transport, serial, argc, argv);
1229}
1230
1231static int delete_file(transport_type transport, char* serial, char* filename)
1232{
1233 char buf[4096];
1234 char* quoted;
1235
1236 snprintf(buf, sizeof(buf), "shell:rm ");
1237 quoted = dupAndQuote(filename);
1238 strncat(buf, quoted, sizeof(buf)-1);
1239 free(quoted);
1240
1241 send_shellcommand(transport, serial, buf);
1242 return 0;
1243}
1244
1245int install_app(transport_type transport, char* serial, int argc, char** argv)
1246{
1247 struct stat st;
1248 int err;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001249 const char *const DATA_DEST = "/data/local/tmp/%s";
1250 const char *const SD_DEST = "/sdcard/tmp/%s";
1251 const char* where = DATA_DEST;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001252 char to[PATH_MAX];
1253 char* filename = argv[argc - 1];
1254 const char* p;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001255 int i;
1256
1257 for (i = 0; i < argc; i++) {
1258 if (!strcmp(argv[i], "-s"))
1259 where = SD_DEST;
1260 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001261
1262 p = adb_dirstop(filename);
1263 if (p) {
1264 p++;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001265 snprintf(to, sizeof to, where, p);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001266 } else {
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001267 snprintf(to, sizeof to, where, filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001268 }
1269 if (p[0] == '\0') {
1270 }
1271
1272 err = stat(filename, &st);
1273 if (err != 0) {
1274 fprintf(stderr, "can't find '%s' to install\n", filename);
1275 return 1;
1276 }
1277 if (!S_ISREG(st.st_mode)) {
1278 fprintf(stderr, "can't install '%s' because it's not a file\n",
1279 filename);
1280 return 1;
1281 }
1282
1283 if (!(err = do_sync_push(filename, to, 1 /* verify APK */))) {
1284 /* file in place; tell the Package Manager to install it */
1285 argv[argc - 1] = to; /* destination name, not source location */
1286 pm_command(transport, serial, argc, argv);
1287 delete_file(transport, serial, to);
1288 }
1289
1290 return err;
1291}