blob: 8003a644eb835f1201882a143d463a1b1790f9d2 [file] [log] [blame]
The Android Open Source Project9ca14dc2009-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
40#ifdef SH_HISTORY
41#include "shlist.h"
42#include "history.h"
43#endif
44
45enum {
46 IGNORE_DATA,
47 WIPE_DATA,
48 FLASH_DATA
49};
50
51static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
52
Alexey Tarasov857f17a2009-10-22 02:55:00 +110053void get_my_path(char *s, size_t maxLen);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080054int find_sync_dirs(const char *srcarg,
55 char **android_srcdir_out, char **data_srcdir_out);
56int install_app(transport_type transport, char* serial, int argc, char** argv);
57int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
58
59static const char *gProductOutPath = NULL;
60
61static char *product_file(const char *extra)
62{
63 int n;
64 char *x;
65
66 if (gProductOutPath == NULL) {
67 fprintf(stderr, "adb: Product directory not specified; "
68 "use -p or define ANDROID_PRODUCT_OUT\n");
69 exit(1);
70 }
71
72 n = strlen(gProductOutPath) + strlen(extra) + 2;
73 x = malloc(n);
74 if (x == 0) {
75 fprintf(stderr, "adb: Out of memory (product_file())\n");
76 exit(1);
77 }
78
79 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
80 return x;
81}
82
83void version(FILE * out) {
84 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
85 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
86}
87
88void help()
89{
90 version(stderr);
91
92 fprintf(stderr,
93 "\n"
94 " -d - directs command to the only connected USB device\n"
95 " returns an error if more than one USB device is present.\n"
96 " -e - directs command to the only running emulator.\n"
97 " returns an error if more than one emulator is running.\n"
98 " -s <serial number> - directs command to the USB device or emulator with\n"
Nick Pelly2a05d0d2009-05-07 12:48:03 -070099 " the given serial number. Overrides ANDROID_SERIAL\n"
100 " envivornment variable.\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800101 " -p <product name or path> - simple product name like 'sooner', or\n"
102 " a relative/absolute path to a product\n"
103 " out directory like 'out/target/product/sooner'.\n"
104 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
105 " environment variable is used, which must\n"
106 " be an absolute path.\n"
107 " devices - list all connected devices\n"
Brian Carlstrom812613c2010-03-01 22:54:12 -0800108 " connect <host>:<port> - connect to a device via TCP/IP\n"
109 " disconnect <host>:<port> - disconnect from a TCP/IP device\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800110 "\n"
111 "device commands:\n"
112 " adb push <local> <remote> - copy file/dir to device\n"
Joe Onoratod0263702010-01-05 13:42:25 -0800113 " adb pull <remote> [<local>] - copy file/dir from device\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800114 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnamdd2db142010-02-22 08:36:49 -0600115 " (-l means list but don't copy)\n"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800116 " (see 'adb help all')\n"
117 " adb shell - run remote shell interactively\n"
118 " adb shell <command> - run remote shell command\n"
119 " adb emu <command> - run emulator console command\n"
120 " adb logcat [ <filter-spec> ] - View device log\n"
121 " adb forward <local> <remote> - forward socket connections\n"
122 " forward specs are one of: \n"
123 " tcp:<port>\n"
124 " localabstract:<unix domain socket name>\n"
125 " localreserved:<unix domain socket name>\n"
126 " localfilesystem:<unix domain socket name>\n"
127 " dev:<character device name>\n"
128 " jdwp:<process pid> (remote only)\n"
129 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
130 " adb install [-l] [-r] <file> - push this package file to the device and install it\n"
131 " ('-l' means forward-lock the app)\n"
132 " ('-r' means reinstall the app, keeping its data)\n"
133 " 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 Lockwooda91f54c2009-08-04 20:37:51 -0400154 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy5a984e62009-12-14 14:42:17 -0800155 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700156 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy5a984e62009-12-14 14:42:17 -0800157 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700158 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800159 "\n"
160 "networking:\n"
161 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootd102bf02009-06-08 14:40:30 -0500162 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Project9ca14dc2009-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"
Tim1b29ed32010-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 Project9ca14dc2009-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 Lockwood9eb799e2009-09-22 01:18:40 -0400230 fwrite(buf, 1, len, stdout);
231 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800232 }
233}
234
235#ifdef SH_HISTORY
236int shItemCmp( void *val, void *idata )
237{
238 return( (strcmp( val, idata ) == 0) );
239}
240#endif
241
242static void *stdin_read_thread(void *x)
243{
244 int fd, fdi;
245 unsigned char buf[1024];
246#ifdef SH_HISTORY
247 unsigned char realbuf[1024], *buf_ptr;
248 SHLIST history;
249 SHLIST *item = &history;
250 int cmdlen = 0, ins_flag = 0;
251#endif
252 int r, n;
253 int state = 0;
254
255 int *fds = (int*) x;
256 fd = fds[0];
257 fdi = fds[1];
258 free(fds);
259
260#ifdef SH_HISTORY
261 shListInitList( &history );
262#endif
263 for(;;) {
264 /* fdi is really the client's stdin, so use read, not adb_read here */
265 r = unix_read(fdi, buf, 1024);
266 if(r == 0) break;
267 if(r < 0) {
268 if(errno == EINTR) continue;
269 break;
270 }
271#ifdef SH_HISTORY
272 if( (r == 3) && /* Arrow processing */
273 (memcmp( (void *)buf, SH_ARROW_ANY, 2 ) == 0) ) {
274 switch( buf[2] ) {
275 case SH_ARROW_UP:
276 item = shListGetNextItem( &history, item );
277 break;
278 case SH_ARROW_DOWN:
279 item = shListGetPrevItem( &history, item );
280 break;
281 default:
282 item = NULL;
283 break;
284 }
285 memset( buf, SH_DEL_CHAR, cmdlen );
286 if( item != NULL ) {
287 n = snprintf( (char *)(&buf[cmdlen]), sizeof buf - cmdlen, "%s", (char *)(item->data) );
288 memcpy( realbuf, item->data, n );
289 }
290 else { /* Clean buffer */
291 item = &history;
292 n = 0;
293 }
294 r = n + cmdlen;
295 cmdlen = n;
296 ins_flag = 0;
297 if( r == 0 )
298 continue;
299 }
300 else {
301#endif
302 for(n = 0; n < r; n++){
303 switch(buf[n]) {
304 case '\n':
305#ifdef SH_HISTORY
306 if( ins_flag && (SH_BLANK_CHAR <= realbuf[0]) ) {
307 buf_ptr = malloc(cmdlen + 1);
308 if( buf_ptr != NULL ) {
309 memcpy( buf_ptr, realbuf, cmdlen );
310 buf_ptr[cmdlen] = '\0';
311 if( (item = shListFindItem( &history, (void *)buf_ptr, shItemCmp )) == NULL ) {
312 shListInsFirstItem( &history, (void *)buf_ptr );
313 item = &history;
314 }
315 }
316 }
317 cmdlen = 0;
318 ins_flag = 0;
319#endif
320 state = 1;
321 break;
322 case '\r':
323 state = 1;
324 break;
325 case '~':
326 if(state == 1) state++;
327 break;
328 case '.':
329 if(state == 2) {
330 fprintf(stderr,"\n* disconnect *\n");
331 #ifdef HAVE_TERMIO_H
332 stdin_raw_restore(fdi);
333 #endif
334 exit(0);
335 }
336 default:
337#ifdef SH_HISTORY
338 if( buf[n] == SH_DEL_CHAR ) {
339 if( cmdlen > 0 )
340 cmdlen--;
341 }
342 else {
343 realbuf[cmdlen] = buf[n];
344 cmdlen++;
345 }
346 ins_flag = 1;
347#endif
348 state = 0;
349 }
350 }
351#ifdef SH_HISTORY
352 }
353#endif
354 r = adb_write(fd, buf, r);
355 if(r <= 0) {
356 break;
357 }
358 }
359#ifdef SH_HISTORY
360 shListDelAllItems( &history, (shListFree)free );
361#endif
362 return 0;
363}
364
365int interactive_shell(void)
366{
367 adb_thread_t thr;
368 int fdi, fd;
369 int *fds;
370
371 fd = adb_connect("shell:");
372 if(fd < 0) {
373 fprintf(stderr,"error: %s\n", adb_error());
374 return 1;
375 }
376 fdi = 0; //dup(0);
377
378 fds = malloc(sizeof(int) * 2);
379 fds[0] = fd;
380 fds[1] = fdi;
381
382#ifdef HAVE_TERMIO_H
383 stdin_raw_init(fdi);
384#endif
385 adb_thread_create(&thr, stdin_read_thread, fds);
386 read_and_dump(fd);
387#ifdef HAVE_TERMIO_H
388 stdin_raw_restore(fdi);
389#endif
390 return 0;
391}
392
393
394static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
395{
396 if (serial) {
397 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
398 } else {
399 const char* prefix = "host";
400 if (ttype == kTransportUsb)
401 prefix = "host-usb";
402 else if (ttype == kTransportLocal)
403 prefix = "host-local";
404
405 snprintf(buffer, buflen, "%s:%s", prefix, command);
406 }
407}
408
409static void status_window(transport_type ttype, const char* serial)
410{
411 char command[4096];
412 char *state = 0;
413 char *laststate = 0;
414
415 /* silence stderr */
416#ifdef _WIN32
417 /* XXX: TODO */
418#else
419 int fd;
420 fd = unix_open("/dev/null", O_WRONLY);
421 dup2(fd, 2);
422 adb_close(fd);
423#endif
424
425 format_host_command(command, sizeof command, "get-state", ttype, serial);
426
427 for(;;) {
428 adb_sleep_ms(250);
429
430 if(state) {
431 free(state);
432 state = 0;
433 }
434
435 state = adb_query(command);
436
437 if(state) {
438 if(laststate && !strcmp(state,laststate)){
439 continue;
440 } else {
441 if(laststate) free(laststate);
442 laststate = strdup(state);
443 }
444 }
445
446 printf("%c[2J%c[2H", 27, 27);
447 printf("Android Debug Bridge\n");
448 printf("State: %s\n", state ? state : "offline");
449 fflush(stdout);
450 }
451}
452
453/** duplicate string and quote all \ " ( ) chars + space character. */
454static char *
455dupAndQuote(const char *s)
456{
457 const char *ts;
458 size_t alloc_len;
459 char *ret;
460 char *dest;
461
462 ts = s;
463
464 alloc_len = 0;
465
466 for( ;*ts != '\0'; ts++) {
467 alloc_len++;
468 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
469 alloc_len++;
470 }
471 }
472
473 ret = (char *)malloc(alloc_len + 1);
474
475 ts = s;
476 dest = ret;
477
478 for ( ;*ts != '\0'; ts++) {
479 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
480 *dest++ = '\\';
481 }
482
483 *dest++ = *ts;
484 }
485
486 *dest++ = '\0';
487
488 return ret;
489}
490
491/**
492 * Run ppp in "notty" mode against a resource listed as the first parameter
493 * eg:
494 *
495 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
496 *
497 */
498int ppp(int argc, char **argv)
499{
500#ifdef HAVE_WIN32_PROC
501 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
502 return -1;
503#else
504 char *adb_service_name;
505 pid_t pid;
506 int fd;
507
508 if (argc < 2) {
509 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
510 argv[0]);
511
512 return 1;
513 }
514
515 adb_service_name = argv[1];
516
517 fd = adb_connect(adb_service_name);
518
519 if(fd < 0) {
520 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
521 adb_service_name, adb_error());
522 return 1;
523 }
524
525 pid = fork();
526
527 if (pid < 0) {
528 perror("from fork()");
529 return 1;
530 } else if (pid == 0) {
531 int err;
532 int i;
533 const char **ppp_args;
534
535 // copy args
536 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
537 ppp_args[0] = "pppd";
538 for (i = 2 ; i < argc ; i++) {
539 //argv[2] and beyond become ppp_args[1] and beyond
540 ppp_args[i - 1] = argv[i];
541 }
542 ppp_args[i-1] = NULL;
543
544 // child side
545
546 dup2(fd, STDIN_FILENO);
547 dup2(fd, STDOUT_FILENO);
548 adb_close(STDERR_FILENO);
549 adb_close(fd);
550
551 err = execvp("pppd", (char * const *)ppp_args);
552
553 if (err < 0) {
554 perror("execing pppd");
555 }
556 exit(-1);
557 } else {
558 // parent side
559
560 adb_close(fd);
561 return 0;
562 }
563#endif /* !HAVE_WIN32_PROC */
564}
565
566static int send_shellcommand(transport_type transport, char* serial, char* buf)
567{
568 int fd, ret;
569
570 for(;;) {
571 fd = adb_connect(buf);
572 if(fd >= 0)
573 break;
574 fprintf(stderr,"- waiting for device -\n");
575 adb_sleep_ms(1000);
576 do_cmd(transport, serial, "wait-for-device", 0);
577 }
578
579 read_and_dump(fd);
580 ret = adb_close(fd);
581 if (ret)
582 perror("close");
583
584 return ret;
585}
586
587static int logcat(transport_type transport, char* serial, int argc, char **argv)
588{
589 char buf[4096];
590
591 char *log_tags;
592 char *quoted_log_tags;
593
594 log_tags = getenv("ANDROID_LOG_TAGS");
595 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
596
597 snprintf(buf, sizeof(buf),
598 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
599 quoted_log_tags);
600
601 free(quoted_log_tags);
602
603 argc -= 1;
604 argv += 1;
605 while(argc-- > 0) {
606 char *quoted;
607
608 quoted = dupAndQuote (*argv++);
609
610 strncat(buf, " ", sizeof(buf)-1);
611 strncat(buf, quoted, sizeof(buf)-1);
612 free(quoted);
613 }
614
615 send_shellcommand(transport, serial, buf);
616 return 0;
617}
618
619#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
620static int top_works(const char *top)
621{
622 if (top != NULL && adb_is_absolute_host_path(top)) {
623 char path_buf[PATH_MAX];
624 snprintf(path_buf, sizeof(path_buf),
625 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
626 return access(path_buf, F_OK) == 0;
627 }
628 return 0;
629}
630
631static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
632{
633 strcpy(path_buf, indir);
634 while (1) {
635 if (top_works(path_buf)) {
636 return path_buf;
637 }
638 char *s = adb_dirstop(path_buf);
639 if (s != NULL) {
640 *s = '\0';
641 } else {
642 path_buf[0] = '\0';
643 return NULL;
644 }
645 }
646}
647
648static char *find_top(char path_buf[PATH_MAX])
649{
650 char *top = getenv("ANDROID_BUILD_TOP");
651 if (top != NULL && top[0] != '\0') {
652 if (!top_works(top)) {
653 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
654 return NULL;
655 }
656 } else {
657 top = getenv("TOP");
658 if (top != NULL && top[0] != '\0') {
659 if (!top_works(top)) {
660 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
661 return NULL;
662 }
663 } else {
664 top = NULL;
665 }
666 }
667
668 if (top != NULL) {
669 /* The environment pointed to a top directory that works.
670 */
671 strcpy(path_buf, top);
672 return path_buf;
673 }
674
675 /* The environment didn't help. Walk up the tree from the CWD
676 * to see if we can find the top.
677 */
678 char dir[PATH_MAX];
679 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
680 if (top == NULL) {
681 /* If the CWD isn't under a good-looking top, see if the
682 * executable is.
683 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100684 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800685 top = find_top_from(dir, path_buf);
686 }
687 return top;
688}
689
690/* <hint> may be:
691 * - A simple product name
692 * e.g., "sooner"
693TODO: debug? sooner-debug, sooner:debug?
694 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
695 * e.g., "out/target/product/sooner"
696 * - An absolute path to the PRODUCT_OUT dir
697 * e.g., "/src/device/out/target/product/sooner"
698 *
699 * Given <hint>, try to construct an absolute path to the
700 * ANDROID_PRODUCT_OUT dir.
701 */
702static const char *find_product_out_path(const char *hint)
703{
704 static char path_buf[PATH_MAX];
705
706 if (hint == NULL || hint[0] == '\0') {
707 return NULL;
708 }
709
710 /* If it's already absolute, don't bother doing any work.
711 */
712 if (adb_is_absolute_host_path(hint)) {
713 strcpy(path_buf, hint);
714 return path_buf;
715 }
716
717 /* If there are any slashes in it, assume it's a relative path;
718 * make it absolute.
719 */
720 if (adb_dirstart(hint) != NULL) {
721 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
722 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
723 return NULL;
724 }
725 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
726 fprintf(stderr, "adb: Couldn't assemble path\n");
727 return NULL;
728 }
729 strcat(path_buf, OS_PATH_SEPARATOR_STR);
730 strcat(path_buf, hint);
731 return path_buf;
732 }
733
734 /* It's a string without any slashes. Try to do something with it.
735 *
736 * Try to find the root of the build tree, and build a PRODUCT_OUT
737 * path from there.
738 */
739 char top_buf[PATH_MAX];
740 const char *top = find_top(top_buf);
741 if (top == NULL) {
742 fprintf(stderr, "adb: Couldn't find top of build tree\n");
743 return NULL;
744 }
745//TODO: if we have a way to indicate debug, look in out/debug/target/...
746 snprintf(path_buf, sizeof(path_buf),
747 "%s" OS_PATH_SEPARATOR_STR
748 "out" OS_PATH_SEPARATOR_STR
749 "target" OS_PATH_SEPARATOR_STR
750 "product" OS_PATH_SEPARATOR_STR
751 "%s", top_buf, hint);
752 if (access(path_buf, F_OK) < 0) {
753 fprintf(stderr, "adb: Couldn't find a product dir "
754 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
755 return NULL;
756 }
757 return path_buf;
758}
759
760int adb_commandline(int argc, char **argv)
761{
762 char buf[4096];
763 int no_daemon = 0;
764 int is_daemon = 0;
765 int persist = 0;
766 int r;
767 int quote;
768 transport_type ttype = kTransportAny;
769 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100770 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800771
772 /* If defined, this should be an absolute path to
773 * the directory containing all of the various system images
774 * for a particular product. If not defined, and the adb
775 * command requires this information, then the user must
776 * specify the path using "-p".
777 */
778 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
779 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
780 gProductOutPath = NULL;
781 }
782 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
783
Nick Pelly2a05d0d2009-05-07 12:48:03 -0700784 serial = getenv("ANDROID_SERIAL");
785
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100786 /* Validate and assign the server port */
787 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
788 int server_port = DEFAULT_ADB_PORT;
789 if (server_port_str && strlen(server_port_str) > 0) {
790 server_port = (int) strtol(server_port_str, NULL, 0);
791 if (server_port <= 0) {
792 fprintf(stderr,
793 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
794 server_port_str);
795 return usage();
796 }
797 }
798
799 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800800 while(argc > 0) {
801 if(!strcmp(argv[0],"nodaemon")) {
802 no_daemon = 1;
803 } else if (!strcmp(argv[0], "fork-server")) {
804 /* this is a special flag used only when the ADB client launches the ADB Server */
805 is_daemon = 1;
806 } else if(!strcmp(argv[0],"persist")) {
807 persist = 1;
808 } else if(!strncmp(argv[0], "-p", 2)) {
809 const char *product = NULL;
810 if (argv[0][2] == '\0') {
811 if (argc < 2) return usage();
812 product = argv[1];
813 argc--;
814 argv++;
815 } else {
816 product = argv[1] + 2;
817 }
818 gProductOutPath = find_product_out_path(product);
819 if (gProductOutPath == NULL) {
820 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
821 product);
822 return usage();
823 }
824 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
825 if (isdigit(argv[0][2])) {
826 serial = argv[0] + 2;
827 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100828 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800829 serial = argv[1];
830 argc--;
831 argv++;
832 }
833 } else if (!strcmp(argv[0],"-d")) {
834 ttype = kTransportUsb;
835 } else if (!strcmp(argv[0],"-e")) {
836 ttype = kTransportLocal;
837 } else {
838 /* out of recognized modifiers and flags */
839 break;
840 }
841 argc--;
842 argv++;
843 }
844
845 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100846 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800847
848 if ((argc > 0) && (!strcmp(argv[0],"server"))) {
849 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100850 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800851 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100852 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800853 }
854 if(r) {
855 fprintf(stderr,"* could not start server *\n");
856 }
857 return r;
858 }
859
860top:
861 if(argc == 0) {
862 return usage();
863 }
864
865 /* adb_connect() commands */
866
867 if(!strcmp(argv[0], "devices")) {
868 char *tmp;
869 snprintf(buf, sizeof buf, "host:%s", argv[0]);
870 tmp = adb_query(buf);
871 if(tmp) {
872 printf("List of devices attached \n");
873 printf("%s\n", tmp);
874 return 0;
875 } else {
876 return 1;
877 }
878 }
879
Mike Lockwood5f2c4a12009-10-11 23:04:18 -0400880 if(!strcmp(argv[0], "connect") || !strcmp(argv[0], "disconnect")) {
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700881 char *tmp;
882 if (argc != 2) {
Mike Lockwood5f2c4a12009-10-11 23:04:18 -0400883 fprintf(stderr, "Usage: adb %s <host>:<port>\n", argv[0]);
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700884 return 1;
885 }
886 snprintf(buf, sizeof buf, "host:%s:%s", argv[0], argv[1]);
887 tmp = adb_query(buf);
888 if(tmp) {
889 printf("%s\n", tmp);
890 return 0;
891 } else {
892 return 1;
893 }
894 }
895
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800896 if (!strcmp(argv[0], "emu")) {
897 return adb_send_emulator_command(argc, argv);
898 }
899
900 if(!strcmp(argv[0], "shell")) {
901 int r;
902 int fd;
903
904 if(argc < 2) {
905 return interactive_shell();
906 }
907
908 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
909 argc -= 2;
910 argv += 2;
911 while(argc-- > 0) {
912 strcat(buf, " ");
913
914 /* quote empty strings and strings with spaces */
915 quote = (**argv == 0 || strchr(*argv, ' '));
916 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100917 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800918 strcat(buf, *argv++);
919 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100920 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800921 }
922
923 for(;;) {
924 fd = adb_connect(buf);
925 if(fd >= 0) {
926 read_and_dump(fd);
927 adb_close(fd);
928 r = 0;
929 } else {
930 fprintf(stderr,"error: %s\n", adb_error());
931 r = -1;
932 }
933
934 if(persist) {
935 fprintf(stderr,"\n- waiting for device -\n");
936 adb_sleep_ms(1000);
937 do_cmd(ttype, serial, "wait-for-device", 0);
938 } else {
939 return r;
940 }
941 }
942 }
943
944 if(!strcmp(argv[0], "kill-server")) {
945 int fd;
946 fd = _adb_connect("host:kill");
947 if(fd == -1) {
948 fprintf(stderr,"* server not running *\n");
949 return 1;
950 }
951 return 0;
952 }
953
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700954 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy5a984e62009-12-14 14:42:17 -0800955 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700956 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Xavier Ducrohet75d550a2009-08-25 20:16:14 -0700957 || !strcmp(argv[0], "root")) {
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700958 char command[100];
Romain Guy5a984e62009-12-14 14:42:17 -0800959 if (!strcmp(argv[0], "reboot-bootloader"))
960 snprintf(command, sizeof(command), "reboot:bootloader");
961 else if (argc > 1)
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700962 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwooda91f54c2009-08-04 20:37:51 -0400963 else
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700964 snprintf(command, sizeof(command), "%s:", argv[0]);
965 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -0700966 if(fd >= 0) {
967 read_and_dump(fd);
968 adb_close(fd);
969 return 0;
970 }
971 fprintf(stderr,"error: %s\n", adb_error());
972 return 1;
973 }
974
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800975 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor680b10c2010-01-20 13:50:36 -0800976 if (argc != 1) return usage();
977 do_cmd(ttype, serial, "shell", "bugreport", 0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800978 return 0;
979 }
980
981 /* adb_command() wrapper commands */
982
983 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
984 char* service = argv[0];
985 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
986 if (ttype == kTransportUsb) {
987 service = "wait-for-usb";
988 } else if (ttype == kTransportLocal) {
989 service = "wait-for-local";
990 } else {
991 service = "wait-for-any";
992 }
993 }
994
995 format_host_command(buf, sizeof buf, service, ttype, serial);
996
997 if (adb_command(buf)) {
998 D("failure: %s *\n",adb_error());
999 fprintf(stderr,"error: %s\n", adb_error());
1000 return 1;
1001 }
1002
1003 /* Allow a command to be run after wait-for-device,
1004 * e.g. 'adb wait-for-device shell'.
1005 */
1006 if(argc > 1) {
1007 argc--;
1008 argv++;
1009 goto top;
1010 }
1011 return 0;
1012 }
1013
1014 if(!strcmp(argv[0], "forward")) {
1015 if(argc != 3) return usage();
1016 if (serial) {
Mike Lockwooda12befc2009-11-28 12:46:13 -05001017 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1018 } else if (ttype == kTransportUsb) {
1019 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1020 } else if (ttype == kTransportLocal) {
1021 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001022 } else {
Mike Lockwooda12befc2009-11-28 12:46:13 -05001023 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001024 }
1025 if(adb_command(buf)) {
1026 fprintf(stderr,"error: %s\n", adb_error());
1027 return 1;
1028 }
1029 return 0;
1030 }
1031
1032 /* do_sync_*() commands */
1033
1034 if(!strcmp(argv[0], "ls")) {
1035 if(argc != 2) return usage();
1036 return do_sync_ls(argv[1]);
1037 }
1038
1039 if(!strcmp(argv[0], "push")) {
1040 if(argc != 3) return usage();
1041 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1042 }
1043
1044 if(!strcmp(argv[0], "pull")) {
Joe Onoratod0263702010-01-05 13:42:25 -08001045 if (argc == 2) {
1046 return do_sync_pull(argv[1], ".");
1047 } else if (argc == 3) {
1048 return do_sync_pull(argv[1], argv[2]);
1049 } else {
1050 return usage();
1051 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001052 }
1053
1054 if(!strcmp(argv[0], "install")) {
1055 if (argc < 2) return usage();
1056 return install_app(ttype, serial, argc, argv);
1057 }
1058
1059 if(!strcmp(argv[0], "uninstall")) {
1060 if (argc < 2) return usage();
1061 return uninstall_app(ttype, serial, argc, argv);
1062 }
1063
1064 if(!strcmp(argv[0], "sync")) {
1065 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001066 int listonly = 0;
1067
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001068 int ret;
1069 if(argc < 2) {
1070 /* No local path was specified. */
1071 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001072 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1073 listonly = 1;
1074 if (argc == 3) {
1075 srcarg = argv[2];
1076 } else {
1077 srcarg = NULL;
1078 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001079 } else if(argc == 2) {
1080 /* A local path or "android"/"data" arg was specified. */
1081 srcarg = argv[1];
1082 } else {
1083 return usage();
1084 }
1085 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1086 if(ret != 0) return usage();
1087
1088 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001089 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001090 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001091 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001092
1093 free(android_srcpath);
1094 free(data_srcpath);
1095 return ret;
1096 }
1097
1098 /* passthrough commands */
1099
1100 if(!strcmp(argv[0],"get-state") ||
1101 !strcmp(argv[0],"get-serialno"))
1102 {
1103 char *tmp;
1104
1105 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1106 tmp = adb_query(buf);
1107 if(tmp) {
1108 printf("%s\n", tmp);
1109 return 0;
1110 } else {
1111 return 1;
1112 }
1113 }
1114
1115 /* other commands */
1116
1117 if(!strcmp(argv[0],"status-window")) {
1118 status_window(ttype, serial);
1119 return 0;
1120 }
1121
1122 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) {
1123 return logcat(ttype, serial, argc, argv);
1124 }
1125
1126 if(!strcmp(argv[0],"ppp")) {
1127 return ppp(argc, argv);
1128 }
1129
1130 if (!strcmp(argv[0], "start-server")) {
1131 return adb_connect("host:start-server");
1132 }
1133
1134 if (!strcmp(argv[0], "jdwp")) {
1135 int fd = adb_connect("jdwp");
1136 if (fd >= 0) {
1137 read_and_dump(fd);
1138 adb_close(fd);
1139 return 0;
1140 } else {
1141 fprintf(stderr, "error: %s\n", adb_error());
1142 return -1;
1143 }
1144 }
1145
1146 /* "adb /?" is a common idiom under Windows */
1147 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1148 help();
1149 return 0;
1150 }
1151
1152 if(!strcmp(argv[0], "version")) {
1153 version(stdout);
1154 return 0;
1155 }
1156
1157 usage();
1158 return 1;
1159}
1160
1161static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1162{
1163 char *argv[16];
1164 int argc;
1165 va_list ap;
1166
1167 va_start(ap, cmd);
1168 argc = 0;
1169
1170 if (serial) {
1171 argv[argc++] = "-s";
1172 argv[argc++] = serial;
1173 } else if (ttype == kTransportUsb) {
1174 argv[argc++] = "-d";
1175 } else if (ttype == kTransportLocal) {
1176 argv[argc++] = "-e";
1177 }
1178
1179 argv[argc++] = cmd;
1180 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1181 va_end(ap);
1182
1183#if 0
1184 int n;
1185 fprintf(stderr,"argc = %d\n",argc);
1186 for(n = 0; n < argc; n++) {
1187 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1188 }
1189#endif
1190
1191 return adb_commandline(argc, argv);
1192}
1193
1194int find_sync_dirs(const char *srcarg,
1195 char **android_srcdir_out, char **data_srcdir_out)
1196{
1197 char *android_srcdir, *data_srcdir;
1198
1199 if(srcarg == NULL) {
1200 android_srcdir = product_file("system");
1201 data_srcdir = product_file("data");
1202 } else {
1203 /* srcarg may be "data", "system" or NULL.
1204 * if srcarg is NULL, then both data and system are synced
1205 */
1206 if(strcmp(srcarg, "system") == 0) {
1207 android_srcdir = product_file("system");
1208 data_srcdir = NULL;
1209 } else if(strcmp(srcarg, "data") == 0) {
1210 android_srcdir = NULL;
1211 data_srcdir = product_file("data");
1212 } else {
1213 /* It's not "system" or "data".
1214 */
1215 return 1;
1216 }
1217 }
1218
1219 if(android_srcdir_out != NULL)
1220 *android_srcdir_out = android_srcdir;
1221 else
1222 free(android_srcdir);
1223
1224 if(data_srcdir_out != NULL)
1225 *data_srcdir_out = data_srcdir;
1226 else
1227 free(data_srcdir);
1228
1229 return 0;
1230}
1231
1232static int pm_command(transport_type transport, char* serial,
1233 int argc, char** argv)
1234{
1235 char buf[4096];
1236
1237 snprintf(buf, sizeof(buf), "shell:pm");
1238
1239 while(argc-- > 0) {
1240 char *quoted;
1241
1242 quoted = dupAndQuote(*argv++);
1243
1244 strncat(buf, " ", sizeof(buf)-1);
1245 strncat(buf, quoted, sizeof(buf)-1);
1246 free(quoted);
1247 }
1248
1249 send_shellcommand(transport, serial, buf);
1250 return 0;
1251}
1252
1253int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1254{
1255 /* if the user choose the -k option, we refuse to do it until devices are
1256 out with the option to uninstall the remaining data somehow (adb/ui) */
1257 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1258 {
1259 printf(
1260 "The -k option uninstalls the application while retaining the data/cache.\n"
1261 "At the moment, there is no way to remove the remaining data.\n"
1262 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1263 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1264 return -1;
1265 }
1266
1267 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1268 return pm_command(transport, serial, argc, argv);
1269}
1270
1271static int delete_file(transport_type transport, char* serial, char* filename)
1272{
1273 char buf[4096];
1274 char* quoted;
1275
1276 snprintf(buf, sizeof(buf), "shell:rm ");
1277 quoted = dupAndQuote(filename);
1278 strncat(buf, quoted, sizeof(buf)-1);
1279 free(quoted);
1280
1281 send_shellcommand(transport, serial, buf);
1282 return 0;
1283}
1284
1285int install_app(transport_type transport, char* serial, int argc, char** argv)
1286{
1287 struct stat st;
1288 int err;
1289 const char *const WHERE = "/data/local/tmp/%s";
1290 char to[PATH_MAX];
1291 char* filename = argv[argc - 1];
1292 const char* p;
1293
1294 p = adb_dirstop(filename);
1295 if (p) {
1296 p++;
1297 snprintf(to, sizeof to, WHERE, p);
1298 } else {
1299 snprintf(to, sizeof to, WHERE, filename);
1300 }
1301 if (p[0] == '\0') {
1302 }
1303
1304 err = stat(filename, &st);
1305 if (err != 0) {
1306 fprintf(stderr, "can't find '%s' to install\n", filename);
1307 return 1;
1308 }
1309 if (!S_ISREG(st.st_mode)) {
1310 fprintf(stderr, "can't install '%s' because it's not a file\n",
1311 filename);
1312 return 1;
1313 }
1314
1315 if (!(err = do_sync_push(filename, to, 1 /* verify APK */))) {
1316 /* file in place; tell the Package Manager to install it */
1317 argv[argc - 1] = to; /* destination name, not source location */
1318 pm_command(transport, serial, argc, argv);
1319 delete_file(transport, serial, to);
1320 }
1321
1322 return err;
1323}