blob: 02e4658d2b87345e0464df0a9d3928cdc58c4ed9 [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 Pelly22048ef2009-05-07 12:48:03 -070094 " the given serial number. Overrides ANDROID_SERIAL\n"
95 " envivornment 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 Onorato8071a4b2010-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"
129 " adb install [-l] [-r] <file> - push this package file to the device and install it\n"
130 " ('-l' means forward-lock the app)\n"
131 " ('-r' means reinstall the app, keeping its data)\n"
132 " adb uninstall [-k] <package> - remove this app package from the device\n"
133 " ('-k' means keep the data and cache directories)\n"
134 " adb bugreport - return all information from the device\n"
135 " that should be included in a bug report.\n"
136 "\n"
137 " adb help - show this help message\n"
138 " adb version - show version num\n"
139 "\n"
140 "DATAOPTS:\n"
141 " (no option) - don't touch the data partition\n"
142 " -w - wipe the data partition\n"
143 " -d - flash the data partition\n"
144 "\n"
145 "scripting:\n"
146 " adb wait-for-device - block until device is online\n"
147 " adb start-server - ensure that there is a server running\n"
148 " adb kill-server - kill the server if it is running\n"
149 " adb get-state - prints: offline | bootloader | device\n"
150 " adb get-serialno - prints: <serial-number>\n"
151 " adb status-window - continuously print device status for a specified device\n"
152 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwood5f4b0512009-08-04 20:37:51 -0400153 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guya48d43a2009-12-14 14:42:17 -0800154 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwood2f38b692009-08-24 15:58:40 -0700155 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guya48d43a2009-12-14 14:42:17 -0800156 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwood2f38b692009-08-24 15:58:40 -0700157 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800158 "\n"
159 "networking:\n"
160 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Root417a3232009-06-08 14:40:30 -0500161 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800162 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
163 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
164 "\n"
165 "adb sync notes: adb sync [ <directory> ]\n"
166 " <localdir> can be interpreted in several ways:\n"
167 "\n"
168 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
169 "\n"
170 " - If it is \"system\" or \"data\", only the corresponding partition\n"
171 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000172 "\n"
173 "environmental variables:\n"
174 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
175 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
176 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
177 " 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 -0800178 );
179}
180
181int usage()
182{
183 help();
184 return 1;
185}
186
187#ifdef HAVE_TERMIO_H
188static struct termios tio_save;
189
190static void stdin_raw_init(int fd)
191{
192 struct termios tio;
193
194 if(tcgetattr(fd, &tio)) return;
195 if(tcgetattr(fd, &tio_save)) return;
196
197 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
198
199 /* no timeout but request at least one character per read */
200 tio.c_cc[VTIME] = 0;
201 tio.c_cc[VMIN] = 1;
202
203 tcsetattr(fd, TCSANOW, &tio);
204 tcflush(fd, TCIFLUSH);
205}
206
207static void stdin_raw_restore(int fd)
208{
209 tcsetattr(fd, TCSANOW, &tio_save);
210 tcflush(fd, TCIFLUSH);
211}
212#endif
213
214static void read_and_dump(int fd)
215{
216 char buf[4096];
217 int len;
218
219 while(fd >= 0) {
220 len = adb_read(fd, buf, 4096);
221 if(len == 0) {
222 break;
223 }
224
225 if(len < 0) {
226 if(errno == EINTR) continue;
227 break;
228 }
Mike Lockwoodc519c002009-09-22 01:18:40 -0400229 fwrite(buf, 1, len, stdout);
230 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800231 }
232}
233
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800234static void *stdin_read_thread(void *x)
235{
236 int fd, fdi;
237 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800238 int r, n;
239 int state = 0;
240
241 int *fds = (int*) x;
242 fd = fds[0];
243 fdi = fds[1];
244 free(fds);
245
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800246 for(;;) {
247 /* fdi is really the client's stdin, so use read, not adb_read here */
248 r = unix_read(fdi, buf, 1024);
249 if(r == 0) break;
250 if(r < 0) {
251 if(errno == EINTR) continue;
252 break;
253 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400254 for(n = 0; n < r; n++){
255 switch(buf[n]) {
256 case '\n':
257 state = 1;
258 break;
259 case '\r':
260 state = 1;
261 break;
262 case '~':
263 if(state == 1) state++;
264 break;
265 case '.':
266 if(state == 2) {
267 fprintf(stderr,"\n* disconnect *\n");
268#ifdef HAVE_TERMIO_H
269 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800270#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400271 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800272 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400273 default:
274 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800275 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800276 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800277 r = adb_write(fd, buf, r);
278 if(r <= 0) {
279 break;
280 }
281 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800282 return 0;
283}
284
285int interactive_shell(void)
286{
287 adb_thread_t thr;
288 int fdi, fd;
289 int *fds;
290
291 fd = adb_connect("shell:");
292 if(fd < 0) {
293 fprintf(stderr,"error: %s\n", adb_error());
294 return 1;
295 }
296 fdi = 0; //dup(0);
297
298 fds = malloc(sizeof(int) * 2);
299 fds[0] = fd;
300 fds[1] = fdi;
301
302#ifdef HAVE_TERMIO_H
303 stdin_raw_init(fdi);
304#endif
305 adb_thread_create(&thr, stdin_read_thread, fds);
306 read_and_dump(fd);
307#ifdef HAVE_TERMIO_H
308 stdin_raw_restore(fdi);
309#endif
310 return 0;
311}
312
313
314static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
315{
316 if (serial) {
317 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
318 } else {
319 const char* prefix = "host";
320 if (ttype == kTransportUsb)
321 prefix = "host-usb";
322 else if (ttype == kTransportLocal)
323 prefix = "host-local";
324
325 snprintf(buffer, buflen, "%s:%s", prefix, command);
326 }
327}
328
329static void status_window(transport_type ttype, const char* serial)
330{
331 char command[4096];
332 char *state = 0;
333 char *laststate = 0;
334
335 /* silence stderr */
336#ifdef _WIN32
337 /* XXX: TODO */
338#else
339 int fd;
340 fd = unix_open("/dev/null", O_WRONLY);
341 dup2(fd, 2);
342 adb_close(fd);
343#endif
344
345 format_host_command(command, sizeof command, "get-state", ttype, serial);
346
347 for(;;) {
348 adb_sleep_ms(250);
349
350 if(state) {
351 free(state);
352 state = 0;
353 }
354
355 state = adb_query(command);
356
357 if(state) {
358 if(laststate && !strcmp(state,laststate)){
359 continue;
360 } else {
361 if(laststate) free(laststate);
362 laststate = strdup(state);
363 }
364 }
365
366 printf("%c[2J%c[2H", 27, 27);
367 printf("Android Debug Bridge\n");
368 printf("State: %s\n", state ? state : "offline");
369 fflush(stdout);
370 }
371}
372
373/** duplicate string and quote all \ " ( ) chars + space character. */
374static char *
375dupAndQuote(const char *s)
376{
377 const char *ts;
378 size_t alloc_len;
379 char *ret;
380 char *dest;
381
382 ts = s;
383
384 alloc_len = 0;
385
386 for( ;*ts != '\0'; ts++) {
387 alloc_len++;
388 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
389 alloc_len++;
390 }
391 }
392
393 ret = (char *)malloc(alloc_len + 1);
394
395 ts = s;
396 dest = ret;
397
398 for ( ;*ts != '\0'; ts++) {
399 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
400 *dest++ = '\\';
401 }
402
403 *dest++ = *ts;
404 }
405
406 *dest++ = '\0';
407
408 return ret;
409}
410
411/**
412 * Run ppp in "notty" mode against a resource listed as the first parameter
413 * eg:
414 *
415 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
416 *
417 */
418int ppp(int argc, char **argv)
419{
420#ifdef HAVE_WIN32_PROC
421 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
422 return -1;
423#else
424 char *adb_service_name;
425 pid_t pid;
426 int fd;
427
428 if (argc < 2) {
429 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
430 argv[0]);
431
432 return 1;
433 }
434
435 adb_service_name = argv[1];
436
437 fd = adb_connect(adb_service_name);
438
439 if(fd < 0) {
440 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
441 adb_service_name, adb_error());
442 return 1;
443 }
444
445 pid = fork();
446
447 if (pid < 0) {
448 perror("from fork()");
449 return 1;
450 } else if (pid == 0) {
451 int err;
452 int i;
453 const char **ppp_args;
454
455 // copy args
456 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
457 ppp_args[0] = "pppd";
458 for (i = 2 ; i < argc ; i++) {
459 //argv[2] and beyond become ppp_args[1] and beyond
460 ppp_args[i - 1] = argv[i];
461 }
462 ppp_args[i-1] = NULL;
463
464 // child side
465
466 dup2(fd, STDIN_FILENO);
467 dup2(fd, STDOUT_FILENO);
468 adb_close(STDERR_FILENO);
469 adb_close(fd);
470
471 err = execvp("pppd", (char * const *)ppp_args);
472
473 if (err < 0) {
474 perror("execing pppd");
475 }
476 exit(-1);
477 } else {
478 // parent side
479
480 adb_close(fd);
481 return 0;
482 }
483#endif /* !HAVE_WIN32_PROC */
484}
485
486static int send_shellcommand(transport_type transport, char* serial, char* buf)
487{
488 int fd, ret;
489
490 for(;;) {
491 fd = adb_connect(buf);
492 if(fd >= 0)
493 break;
494 fprintf(stderr,"- waiting for device -\n");
495 adb_sleep_ms(1000);
496 do_cmd(transport, serial, "wait-for-device", 0);
497 }
498
499 read_and_dump(fd);
500 ret = adb_close(fd);
501 if (ret)
502 perror("close");
503
504 return ret;
505}
506
507static int logcat(transport_type transport, char* serial, int argc, char **argv)
508{
509 char buf[4096];
510
511 char *log_tags;
512 char *quoted_log_tags;
513
514 log_tags = getenv("ANDROID_LOG_TAGS");
515 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
516
517 snprintf(buf, sizeof(buf),
518 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
519 quoted_log_tags);
520
521 free(quoted_log_tags);
522
523 argc -= 1;
524 argv += 1;
525 while(argc-- > 0) {
526 char *quoted;
527
528 quoted = dupAndQuote (*argv++);
529
530 strncat(buf, " ", sizeof(buf)-1);
531 strncat(buf, quoted, sizeof(buf)-1);
532 free(quoted);
533 }
534
535 send_shellcommand(transport, serial, buf);
536 return 0;
537}
538
539#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
540static int top_works(const char *top)
541{
542 if (top != NULL && adb_is_absolute_host_path(top)) {
543 char path_buf[PATH_MAX];
544 snprintf(path_buf, sizeof(path_buf),
545 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
546 return access(path_buf, F_OK) == 0;
547 }
548 return 0;
549}
550
551static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
552{
553 strcpy(path_buf, indir);
554 while (1) {
555 if (top_works(path_buf)) {
556 return path_buf;
557 }
558 char *s = adb_dirstop(path_buf);
559 if (s != NULL) {
560 *s = '\0';
561 } else {
562 path_buf[0] = '\0';
563 return NULL;
564 }
565 }
566}
567
568static char *find_top(char path_buf[PATH_MAX])
569{
570 char *top = getenv("ANDROID_BUILD_TOP");
571 if (top != NULL && top[0] != '\0') {
572 if (!top_works(top)) {
573 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
574 return NULL;
575 }
576 } else {
577 top = getenv("TOP");
578 if (top != NULL && top[0] != '\0') {
579 if (!top_works(top)) {
580 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
581 return NULL;
582 }
583 } else {
584 top = NULL;
585 }
586 }
587
588 if (top != NULL) {
589 /* The environment pointed to a top directory that works.
590 */
591 strcpy(path_buf, top);
592 return path_buf;
593 }
594
595 /* The environment didn't help. Walk up the tree from the CWD
596 * to see if we can find the top.
597 */
598 char dir[PATH_MAX];
599 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
600 if (top == NULL) {
601 /* If the CWD isn't under a good-looking top, see if the
602 * executable is.
603 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100604 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800605 top = find_top_from(dir, path_buf);
606 }
607 return top;
608}
609
610/* <hint> may be:
611 * - A simple product name
612 * e.g., "sooner"
613TODO: debug? sooner-debug, sooner:debug?
614 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
615 * e.g., "out/target/product/sooner"
616 * - An absolute path to the PRODUCT_OUT dir
617 * e.g., "/src/device/out/target/product/sooner"
618 *
619 * Given <hint>, try to construct an absolute path to the
620 * ANDROID_PRODUCT_OUT dir.
621 */
622static const char *find_product_out_path(const char *hint)
623{
624 static char path_buf[PATH_MAX];
625
626 if (hint == NULL || hint[0] == '\0') {
627 return NULL;
628 }
629
630 /* If it's already absolute, don't bother doing any work.
631 */
632 if (adb_is_absolute_host_path(hint)) {
633 strcpy(path_buf, hint);
634 return path_buf;
635 }
636
637 /* If there are any slashes in it, assume it's a relative path;
638 * make it absolute.
639 */
640 if (adb_dirstart(hint) != NULL) {
641 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
642 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
643 return NULL;
644 }
645 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
646 fprintf(stderr, "adb: Couldn't assemble path\n");
647 return NULL;
648 }
649 strcat(path_buf, OS_PATH_SEPARATOR_STR);
650 strcat(path_buf, hint);
651 return path_buf;
652 }
653
654 /* It's a string without any slashes. Try to do something with it.
655 *
656 * Try to find the root of the build tree, and build a PRODUCT_OUT
657 * path from there.
658 */
659 char top_buf[PATH_MAX];
660 const char *top = find_top(top_buf);
661 if (top == NULL) {
662 fprintf(stderr, "adb: Couldn't find top of build tree\n");
663 return NULL;
664 }
665//TODO: if we have a way to indicate debug, look in out/debug/target/...
666 snprintf(path_buf, sizeof(path_buf),
667 "%s" OS_PATH_SEPARATOR_STR
668 "out" OS_PATH_SEPARATOR_STR
669 "target" OS_PATH_SEPARATOR_STR
670 "product" OS_PATH_SEPARATOR_STR
671 "%s", top_buf, hint);
672 if (access(path_buf, F_OK) < 0) {
673 fprintf(stderr, "adb: Couldn't find a product dir "
674 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
675 return NULL;
676 }
677 return path_buf;
678}
679
680int adb_commandline(int argc, char **argv)
681{
682 char buf[4096];
683 int no_daemon = 0;
684 int is_daemon = 0;
685 int persist = 0;
686 int r;
687 int quote;
688 transport_type ttype = kTransportAny;
689 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100690 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800691
692 /* If defined, this should be an absolute path to
693 * the directory containing all of the various system images
694 * for a particular product. If not defined, and the adb
695 * command requires this information, then the user must
696 * specify the path using "-p".
697 */
698 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
699 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
700 gProductOutPath = NULL;
701 }
702 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
703
Nick Pelly22048ef2009-05-07 12:48:03 -0700704 serial = getenv("ANDROID_SERIAL");
705
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100706 /* Validate and assign the server port */
707 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
708 int server_port = DEFAULT_ADB_PORT;
709 if (server_port_str && strlen(server_port_str) > 0) {
710 server_port = (int) strtol(server_port_str, NULL, 0);
711 if (server_port <= 0) {
712 fprintf(stderr,
713 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
714 server_port_str);
715 return usage();
716 }
717 }
718
719 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800720 while(argc > 0) {
721 if(!strcmp(argv[0],"nodaemon")) {
722 no_daemon = 1;
723 } else if (!strcmp(argv[0], "fork-server")) {
724 /* this is a special flag used only when the ADB client launches the ADB Server */
725 is_daemon = 1;
726 } else if(!strcmp(argv[0],"persist")) {
727 persist = 1;
728 } else if(!strncmp(argv[0], "-p", 2)) {
729 const char *product = NULL;
730 if (argv[0][2] == '\0') {
731 if (argc < 2) return usage();
732 product = argv[1];
733 argc--;
734 argv++;
735 } else {
736 product = argv[1] + 2;
737 }
738 gProductOutPath = find_product_out_path(product);
739 if (gProductOutPath == NULL) {
740 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
741 product);
742 return usage();
743 }
744 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
745 if (isdigit(argv[0][2])) {
746 serial = argv[0] + 2;
747 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100748 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800749 serial = argv[1];
750 argc--;
751 argv++;
752 }
753 } else if (!strcmp(argv[0],"-d")) {
754 ttype = kTransportUsb;
755 } else if (!strcmp(argv[0],"-e")) {
756 ttype = kTransportLocal;
757 } else {
758 /* out of recognized modifiers and flags */
759 break;
760 }
761 argc--;
762 argv++;
763 }
764
765 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100766 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800767
768 if ((argc > 0) && (!strcmp(argv[0],"server"))) {
769 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100770 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800771 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100772 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800773 }
774 if(r) {
775 fprintf(stderr,"* could not start server *\n");
776 }
777 return r;
778 }
779
780top:
781 if(argc == 0) {
782 return usage();
783 }
784
785 /* adb_connect() commands */
786
787 if(!strcmp(argv[0], "devices")) {
788 char *tmp;
789 snprintf(buf, sizeof buf, "host:%s", argv[0]);
790 tmp = adb_query(buf);
791 if(tmp) {
792 printf("List of devices attached \n");
793 printf("%s\n", tmp);
794 return 0;
795 } else {
796 return 1;
797 }
798 }
799
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400800 if(!strcmp(argv[0], "connect")) {
Mike Lockwood2f38b692009-08-24 15:58:40 -0700801 char *tmp;
802 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400803 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwood2f38b692009-08-24 15:58:40 -0700804 return 1;
805 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400806 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
807 tmp = adb_query(buf);
808 if(tmp) {
809 printf("%s\n", tmp);
810 return 0;
811 } else {
812 return 1;
813 }
814 }
815
816 if(!strcmp(argv[0], "disconnect")) {
817 char *tmp;
818 if (argc > 2) {
819 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
820 return 1;
821 }
822 if (argc == 2) {
823 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
824 } else {
825 snprintf(buf, sizeof buf, "host:disconnect:");
826 }
Mike Lockwood2f38b692009-08-24 15:58:40 -0700827 tmp = adb_query(buf);
828 if(tmp) {
829 printf("%s\n", tmp);
830 return 0;
831 } else {
832 return 1;
833 }
834 }
835
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800836 if (!strcmp(argv[0], "emu")) {
837 return adb_send_emulator_command(argc, argv);
838 }
839
840 if(!strcmp(argv[0], "shell")) {
841 int r;
842 int fd;
843
844 if(argc < 2) {
845 return interactive_shell();
846 }
847
848 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
849 argc -= 2;
850 argv += 2;
851 while(argc-- > 0) {
852 strcat(buf, " ");
853
854 /* quote empty strings and strings with spaces */
855 quote = (**argv == 0 || strchr(*argv, ' '));
856 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100857 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800858 strcat(buf, *argv++);
859 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100860 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800861 }
862
863 for(;;) {
864 fd = adb_connect(buf);
865 if(fd >= 0) {
866 read_and_dump(fd);
867 adb_close(fd);
868 r = 0;
869 } else {
870 fprintf(stderr,"error: %s\n", adb_error());
871 r = -1;
872 }
873
874 if(persist) {
875 fprintf(stderr,"\n- waiting for device -\n");
876 adb_sleep_ms(1000);
877 do_cmd(ttype, serial, "wait-for-device", 0);
878 } else {
879 return r;
880 }
881 }
882 }
883
884 if(!strcmp(argv[0], "kill-server")) {
885 int fd;
886 fd = _adb_connect("host:kill");
887 if(fd == -1) {
888 fprintf(stderr,"* server not running *\n");
889 return 1;
890 }
891 return 0;
892 }
893
Mike Lockwood2f38b692009-08-24 15:58:40 -0700894 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guya48d43a2009-12-14 14:42:17 -0800895 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwood2f38b692009-08-24 15:58:40 -0700896 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Xavier Ducrohetf71c7112009-08-25 20:16:14 -0700897 || !strcmp(argv[0], "root")) {
Mike Lockwood2f38b692009-08-24 15:58:40 -0700898 char command[100];
Romain Guya48d43a2009-12-14 14:42:17 -0800899 if (!strcmp(argv[0], "reboot-bootloader"))
900 snprintf(command, sizeof(command), "reboot:bootloader");
901 else if (argc > 1)
Mike Lockwood2f38b692009-08-24 15:58:40 -0700902 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwood5f4b0512009-08-04 20:37:51 -0400903 else
Mike Lockwood2f38b692009-08-24 15:58:40 -0700904 snprintf(command, sizeof(command), "%s:", argv[0]);
905 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -0700906 if(fd >= 0) {
907 read_and_dump(fd);
908 adb_close(fd);
909 return 0;
910 }
911 fprintf(stderr,"error: %s\n", adb_error());
912 return 1;
913 }
914
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800915 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor7eced2b2010-01-20 13:50:36 -0800916 if (argc != 1) return usage();
917 do_cmd(ttype, serial, "shell", "bugreport", 0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800918 return 0;
919 }
920
921 /* adb_command() wrapper commands */
922
923 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
924 char* service = argv[0];
925 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
926 if (ttype == kTransportUsb) {
927 service = "wait-for-usb";
928 } else if (ttype == kTransportLocal) {
929 service = "wait-for-local";
930 } else {
931 service = "wait-for-any";
932 }
933 }
934
935 format_host_command(buf, sizeof buf, service, ttype, serial);
936
937 if (adb_command(buf)) {
938 D("failure: %s *\n",adb_error());
939 fprintf(stderr,"error: %s\n", adb_error());
940 return 1;
941 }
942
943 /* Allow a command to be run after wait-for-device,
944 * e.g. 'adb wait-for-device shell'.
945 */
946 if(argc > 1) {
947 argc--;
948 argv++;
949 goto top;
950 }
951 return 0;
952 }
953
954 if(!strcmp(argv[0], "forward")) {
955 if(argc != 3) return usage();
956 if (serial) {
Mike Lockwooda59387b2009-11-28 12:46:13 -0500957 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
958 } else if (ttype == kTransportUsb) {
959 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
960 } else if (ttype == kTransportLocal) {
961 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800962 } else {
Mike Lockwooda59387b2009-11-28 12:46:13 -0500963 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800964 }
965 if(adb_command(buf)) {
966 fprintf(stderr,"error: %s\n", adb_error());
967 return 1;
968 }
969 return 0;
970 }
971
972 /* do_sync_*() commands */
973
974 if(!strcmp(argv[0], "ls")) {
975 if(argc != 2) return usage();
976 return do_sync_ls(argv[1]);
977 }
978
979 if(!strcmp(argv[0], "push")) {
980 if(argc != 3) return usage();
981 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
982 }
983
984 if(!strcmp(argv[0], "pull")) {
Joe Onorato8071a4b2010-01-05 13:42:25 -0800985 if (argc == 2) {
986 return do_sync_pull(argv[1], ".");
987 } else if (argc == 3) {
988 return do_sync_pull(argv[1], argv[2]);
989 } else {
990 return usage();
991 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800992 }
993
994 if(!strcmp(argv[0], "install")) {
995 if (argc < 2) return usage();
996 return install_app(ttype, serial, argc, argv);
997 }
998
999 if(!strcmp(argv[0], "uninstall")) {
1000 if (argc < 2) return usage();
1001 return uninstall_app(ttype, serial, argc, argv);
1002 }
1003
1004 if(!strcmp(argv[0], "sync")) {
1005 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001006 int listonly = 0;
1007
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001008 int ret;
1009 if(argc < 2) {
1010 /* No local path was specified. */
1011 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001012 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1013 listonly = 1;
1014 if (argc == 3) {
1015 srcarg = argv[2];
1016 } else {
1017 srcarg = NULL;
1018 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001019 } else if(argc == 2) {
1020 /* A local path or "android"/"data" arg was specified. */
1021 srcarg = argv[1];
1022 } else {
1023 return usage();
1024 }
1025 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1026 if(ret != 0) return usage();
1027
1028 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001029 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001030 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001031 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001032
1033 free(android_srcpath);
1034 free(data_srcpath);
1035 return ret;
1036 }
1037
1038 /* passthrough commands */
1039
1040 if(!strcmp(argv[0],"get-state") ||
1041 !strcmp(argv[0],"get-serialno"))
1042 {
1043 char *tmp;
1044
1045 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1046 tmp = adb_query(buf);
1047 if(tmp) {
1048 printf("%s\n", tmp);
1049 return 0;
1050 } else {
1051 return 1;
1052 }
1053 }
1054
1055 /* other commands */
1056
1057 if(!strcmp(argv[0],"status-window")) {
1058 status_window(ttype, serial);
1059 return 0;
1060 }
1061
1062 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) {
1063 return logcat(ttype, serial, argc, argv);
1064 }
1065
1066 if(!strcmp(argv[0],"ppp")) {
1067 return ppp(argc, argv);
1068 }
1069
1070 if (!strcmp(argv[0], "start-server")) {
1071 return adb_connect("host:start-server");
1072 }
1073
1074 if (!strcmp(argv[0], "jdwp")) {
1075 int fd = adb_connect("jdwp");
1076 if (fd >= 0) {
1077 read_and_dump(fd);
1078 adb_close(fd);
1079 return 0;
1080 } else {
1081 fprintf(stderr, "error: %s\n", adb_error());
1082 return -1;
1083 }
1084 }
1085
1086 /* "adb /?" is a common idiom under Windows */
1087 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1088 help();
1089 return 0;
1090 }
1091
1092 if(!strcmp(argv[0], "version")) {
1093 version(stdout);
1094 return 0;
1095 }
1096
1097 usage();
1098 return 1;
1099}
1100
1101static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1102{
1103 char *argv[16];
1104 int argc;
1105 va_list ap;
1106
1107 va_start(ap, cmd);
1108 argc = 0;
1109
1110 if (serial) {
1111 argv[argc++] = "-s";
1112 argv[argc++] = serial;
1113 } else if (ttype == kTransportUsb) {
1114 argv[argc++] = "-d";
1115 } else if (ttype == kTransportLocal) {
1116 argv[argc++] = "-e";
1117 }
1118
1119 argv[argc++] = cmd;
1120 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1121 va_end(ap);
1122
1123#if 0
1124 int n;
1125 fprintf(stderr,"argc = %d\n",argc);
1126 for(n = 0; n < argc; n++) {
1127 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1128 }
1129#endif
1130
1131 return adb_commandline(argc, argv);
1132}
1133
1134int find_sync_dirs(const char *srcarg,
1135 char **android_srcdir_out, char **data_srcdir_out)
1136{
1137 char *android_srcdir, *data_srcdir;
1138
1139 if(srcarg == NULL) {
1140 android_srcdir = product_file("system");
1141 data_srcdir = product_file("data");
1142 } else {
1143 /* srcarg may be "data", "system" or NULL.
1144 * if srcarg is NULL, then both data and system are synced
1145 */
1146 if(strcmp(srcarg, "system") == 0) {
1147 android_srcdir = product_file("system");
1148 data_srcdir = NULL;
1149 } else if(strcmp(srcarg, "data") == 0) {
1150 android_srcdir = NULL;
1151 data_srcdir = product_file("data");
1152 } else {
1153 /* It's not "system" or "data".
1154 */
1155 return 1;
1156 }
1157 }
1158
1159 if(android_srcdir_out != NULL)
1160 *android_srcdir_out = android_srcdir;
1161 else
1162 free(android_srcdir);
1163
1164 if(data_srcdir_out != NULL)
1165 *data_srcdir_out = data_srcdir;
1166 else
1167 free(data_srcdir);
1168
1169 return 0;
1170}
1171
1172static int pm_command(transport_type transport, char* serial,
1173 int argc, char** argv)
1174{
1175 char buf[4096];
1176
1177 snprintf(buf, sizeof(buf), "shell:pm");
1178
1179 while(argc-- > 0) {
1180 char *quoted;
1181
1182 quoted = dupAndQuote(*argv++);
1183
1184 strncat(buf, " ", sizeof(buf)-1);
1185 strncat(buf, quoted, sizeof(buf)-1);
1186 free(quoted);
1187 }
1188
1189 send_shellcommand(transport, serial, buf);
1190 return 0;
1191}
1192
1193int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1194{
1195 /* if the user choose the -k option, we refuse to do it until devices are
1196 out with the option to uninstall the remaining data somehow (adb/ui) */
1197 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1198 {
1199 printf(
1200 "The -k option uninstalls the application while retaining the data/cache.\n"
1201 "At the moment, there is no way to remove the remaining data.\n"
1202 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1203 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1204 return -1;
1205 }
1206
1207 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1208 return pm_command(transport, serial, argc, argv);
1209}
1210
1211static int delete_file(transport_type transport, char* serial, char* filename)
1212{
1213 char buf[4096];
1214 char* quoted;
1215
1216 snprintf(buf, sizeof(buf), "shell:rm ");
1217 quoted = dupAndQuote(filename);
1218 strncat(buf, quoted, sizeof(buf)-1);
1219 free(quoted);
1220
1221 send_shellcommand(transport, serial, buf);
1222 return 0;
1223}
1224
1225int install_app(transport_type transport, char* serial, int argc, char** argv)
1226{
1227 struct stat st;
1228 int err;
1229 const char *const WHERE = "/data/local/tmp/%s";
1230 char to[PATH_MAX];
1231 char* filename = argv[argc - 1];
1232 const char* p;
1233
1234 p = adb_dirstop(filename);
1235 if (p) {
1236 p++;
1237 snprintf(to, sizeof to, WHERE, p);
1238 } else {
1239 snprintf(to, sizeof to, WHERE, filename);
1240 }
1241 if (p[0] == '\0') {
1242 }
1243
1244 err = stat(filename, &st);
1245 if (err != 0) {
1246 fprintf(stderr, "can't find '%s' to install\n", filename);
1247 return 1;
1248 }
1249 if (!S_ISREG(st.st_mode)) {
1250 fprintf(stderr, "can't install '%s' because it's not a file\n",
1251 filename);
1252 return 1;
1253 }
1254
1255 if (!(err = do_sync_push(filename, to, 1 /* verify APK */))) {
1256 /* file in place; tell the Package Manager to install it */
1257 argv[argc - 1] = to; /* destination name, not source location */
1258 pm_command(transport, serial, argc, argv);
1259 delete_file(transport, serial, to);
1260 }
1261
1262 return err;
1263}