blob: bb77c4fcd852a3fa5054442617cab29ec0848f0b [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"
173 );
174}
175
176int usage()
177{
178 help();
179 return 1;
180}
181
182#ifdef HAVE_TERMIO_H
183static struct termios tio_save;
184
185static void stdin_raw_init(int fd)
186{
187 struct termios tio;
188
189 if(tcgetattr(fd, &tio)) return;
190 if(tcgetattr(fd, &tio_save)) return;
191
192 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
193
194 /* no timeout but request at least one character per read */
195 tio.c_cc[VTIME] = 0;
196 tio.c_cc[VMIN] = 1;
197
198 tcsetattr(fd, TCSANOW, &tio);
199 tcflush(fd, TCIFLUSH);
200}
201
202static void stdin_raw_restore(int fd)
203{
204 tcsetattr(fd, TCSANOW, &tio_save);
205 tcflush(fd, TCIFLUSH);
206}
207#endif
208
209static void read_and_dump(int fd)
210{
211 char buf[4096];
212 int len;
213
214 while(fd >= 0) {
215 len = adb_read(fd, buf, 4096);
216 if(len == 0) {
217 break;
218 }
219
220 if(len < 0) {
221 if(errno == EINTR) continue;
222 break;
223 }
Mike Lockwood9eb799e2009-09-22 01:18:40 -0400224 fwrite(buf, 1, len, stdout);
225 fflush(stdout);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800226 }
227}
228
229#ifdef SH_HISTORY
230int shItemCmp( void *val, void *idata )
231{
232 return( (strcmp( val, idata ) == 0) );
233}
234#endif
235
236static void *stdin_read_thread(void *x)
237{
238 int fd, fdi;
239 unsigned char buf[1024];
240#ifdef SH_HISTORY
241 unsigned char realbuf[1024], *buf_ptr;
242 SHLIST history;
243 SHLIST *item = &history;
244 int cmdlen = 0, ins_flag = 0;
245#endif
246 int r, n;
247 int state = 0;
248
249 int *fds = (int*) x;
250 fd = fds[0];
251 fdi = fds[1];
252 free(fds);
253
254#ifdef SH_HISTORY
255 shListInitList( &history );
256#endif
257 for(;;) {
258 /* fdi is really the client's stdin, so use read, not adb_read here */
259 r = unix_read(fdi, buf, 1024);
260 if(r == 0) break;
261 if(r < 0) {
262 if(errno == EINTR) continue;
263 break;
264 }
265#ifdef SH_HISTORY
266 if( (r == 3) && /* Arrow processing */
267 (memcmp( (void *)buf, SH_ARROW_ANY, 2 ) == 0) ) {
268 switch( buf[2] ) {
269 case SH_ARROW_UP:
270 item = shListGetNextItem( &history, item );
271 break;
272 case SH_ARROW_DOWN:
273 item = shListGetPrevItem( &history, item );
274 break;
275 default:
276 item = NULL;
277 break;
278 }
279 memset( buf, SH_DEL_CHAR, cmdlen );
280 if( item != NULL ) {
281 n = snprintf( (char *)(&buf[cmdlen]), sizeof buf - cmdlen, "%s", (char *)(item->data) );
282 memcpy( realbuf, item->data, n );
283 }
284 else { /* Clean buffer */
285 item = &history;
286 n = 0;
287 }
288 r = n + cmdlen;
289 cmdlen = n;
290 ins_flag = 0;
291 if( r == 0 )
292 continue;
293 }
294 else {
295#endif
296 for(n = 0; n < r; n++){
297 switch(buf[n]) {
298 case '\n':
299#ifdef SH_HISTORY
300 if( ins_flag && (SH_BLANK_CHAR <= realbuf[0]) ) {
301 buf_ptr = malloc(cmdlen + 1);
302 if( buf_ptr != NULL ) {
303 memcpy( buf_ptr, realbuf, cmdlen );
304 buf_ptr[cmdlen] = '\0';
305 if( (item = shListFindItem( &history, (void *)buf_ptr, shItemCmp )) == NULL ) {
306 shListInsFirstItem( &history, (void *)buf_ptr );
307 item = &history;
308 }
309 }
310 }
311 cmdlen = 0;
312 ins_flag = 0;
313#endif
314 state = 1;
315 break;
316 case '\r':
317 state = 1;
318 break;
319 case '~':
320 if(state == 1) state++;
321 break;
322 case '.':
323 if(state == 2) {
324 fprintf(stderr,"\n* disconnect *\n");
325 #ifdef HAVE_TERMIO_H
326 stdin_raw_restore(fdi);
327 #endif
328 exit(0);
329 }
330 default:
331#ifdef SH_HISTORY
332 if( buf[n] == SH_DEL_CHAR ) {
333 if( cmdlen > 0 )
334 cmdlen--;
335 }
336 else {
337 realbuf[cmdlen] = buf[n];
338 cmdlen++;
339 }
340 ins_flag = 1;
341#endif
342 state = 0;
343 }
344 }
345#ifdef SH_HISTORY
346 }
347#endif
348 r = adb_write(fd, buf, r);
349 if(r <= 0) {
350 break;
351 }
352 }
353#ifdef SH_HISTORY
354 shListDelAllItems( &history, (shListFree)free );
355#endif
356 return 0;
357}
358
359int interactive_shell(void)
360{
361 adb_thread_t thr;
362 int fdi, fd;
363 int *fds;
364
365 fd = adb_connect("shell:");
366 if(fd < 0) {
367 fprintf(stderr,"error: %s\n", adb_error());
368 return 1;
369 }
370 fdi = 0; //dup(0);
371
372 fds = malloc(sizeof(int) * 2);
373 fds[0] = fd;
374 fds[1] = fdi;
375
376#ifdef HAVE_TERMIO_H
377 stdin_raw_init(fdi);
378#endif
379 adb_thread_create(&thr, stdin_read_thread, fds);
380 read_and_dump(fd);
381#ifdef HAVE_TERMIO_H
382 stdin_raw_restore(fdi);
383#endif
384 return 0;
385}
386
387
388static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
389{
390 if (serial) {
391 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
392 } else {
393 const char* prefix = "host";
394 if (ttype == kTransportUsb)
395 prefix = "host-usb";
396 else if (ttype == kTransportLocal)
397 prefix = "host-local";
398
399 snprintf(buffer, buflen, "%s:%s", prefix, command);
400 }
401}
402
403static void status_window(transport_type ttype, const char* serial)
404{
405 char command[4096];
406 char *state = 0;
407 char *laststate = 0;
408
409 /* silence stderr */
410#ifdef _WIN32
411 /* XXX: TODO */
412#else
413 int fd;
414 fd = unix_open("/dev/null", O_WRONLY);
415 dup2(fd, 2);
416 adb_close(fd);
417#endif
418
419 format_host_command(command, sizeof command, "get-state", ttype, serial);
420
421 for(;;) {
422 adb_sleep_ms(250);
423
424 if(state) {
425 free(state);
426 state = 0;
427 }
428
429 state = adb_query(command);
430
431 if(state) {
432 if(laststate && !strcmp(state,laststate)){
433 continue;
434 } else {
435 if(laststate) free(laststate);
436 laststate = strdup(state);
437 }
438 }
439
440 printf("%c[2J%c[2H", 27, 27);
441 printf("Android Debug Bridge\n");
442 printf("State: %s\n", state ? state : "offline");
443 fflush(stdout);
444 }
445}
446
447/** duplicate string and quote all \ " ( ) chars + space character. */
448static char *
449dupAndQuote(const char *s)
450{
451 const char *ts;
452 size_t alloc_len;
453 char *ret;
454 char *dest;
455
456 ts = s;
457
458 alloc_len = 0;
459
460 for( ;*ts != '\0'; ts++) {
461 alloc_len++;
462 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
463 alloc_len++;
464 }
465 }
466
467 ret = (char *)malloc(alloc_len + 1);
468
469 ts = s;
470 dest = ret;
471
472 for ( ;*ts != '\0'; ts++) {
473 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
474 *dest++ = '\\';
475 }
476
477 *dest++ = *ts;
478 }
479
480 *dest++ = '\0';
481
482 return ret;
483}
484
485/**
486 * Run ppp in "notty" mode against a resource listed as the first parameter
487 * eg:
488 *
489 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
490 *
491 */
492int ppp(int argc, char **argv)
493{
494#ifdef HAVE_WIN32_PROC
495 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
496 return -1;
497#else
498 char *adb_service_name;
499 pid_t pid;
500 int fd;
501
502 if (argc < 2) {
503 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
504 argv[0]);
505
506 return 1;
507 }
508
509 adb_service_name = argv[1];
510
511 fd = adb_connect(adb_service_name);
512
513 if(fd < 0) {
514 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
515 adb_service_name, adb_error());
516 return 1;
517 }
518
519 pid = fork();
520
521 if (pid < 0) {
522 perror("from fork()");
523 return 1;
524 } else if (pid == 0) {
525 int err;
526 int i;
527 const char **ppp_args;
528
529 // copy args
530 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
531 ppp_args[0] = "pppd";
532 for (i = 2 ; i < argc ; i++) {
533 //argv[2] and beyond become ppp_args[1] and beyond
534 ppp_args[i - 1] = argv[i];
535 }
536 ppp_args[i-1] = NULL;
537
538 // child side
539
540 dup2(fd, STDIN_FILENO);
541 dup2(fd, STDOUT_FILENO);
542 adb_close(STDERR_FILENO);
543 adb_close(fd);
544
545 err = execvp("pppd", (char * const *)ppp_args);
546
547 if (err < 0) {
548 perror("execing pppd");
549 }
550 exit(-1);
551 } else {
552 // parent side
553
554 adb_close(fd);
555 return 0;
556 }
557#endif /* !HAVE_WIN32_PROC */
558}
559
560static int send_shellcommand(transport_type transport, char* serial, char* buf)
561{
562 int fd, ret;
563
564 for(;;) {
565 fd = adb_connect(buf);
566 if(fd >= 0)
567 break;
568 fprintf(stderr,"- waiting for device -\n");
569 adb_sleep_ms(1000);
570 do_cmd(transport, serial, "wait-for-device", 0);
571 }
572
573 read_and_dump(fd);
574 ret = adb_close(fd);
575 if (ret)
576 perror("close");
577
578 return ret;
579}
580
581static int logcat(transport_type transport, char* serial, int argc, char **argv)
582{
583 char buf[4096];
584
585 char *log_tags;
586 char *quoted_log_tags;
587
588 log_tags = getenv("ANDROID_LOG_TAGS");
589 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
590
591 snprintf(buf, sizeof(buf),
592 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
593 quoted_log_tags);
594
595 free(quoted_log_tags);
596
597 argc -= 1;
598 argv += 1;
599 while(argc-- > 0) {
600 char *quoted;
601
602 quoted = dupAndQuote (*argv++);
603
604 strncat(buf, " ", sizeof(buf)-1);
605 strncat(buf, quoted, sizeof(buf)-1);
606 free(quoted);
607 }
608
609 send_shellcommand(transport, serial, buf);
610 return 0;
611}
612
613#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
614static int top_works(const char *top)
615{
616 if (top != NULL && adb_is_absolute_host_path(top)) {
617 char path_buf[PATH_MAX];
618 snprintf(path_buf, sizeof(path_buf),
619 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
620 return access(path_buf, F_OK) == 0;
621 }
622 return 0;
623}
624
625static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
626{
627 strcpy(path_buf, indir);
628 while (1) {
629 if (top_works(path_buf)) {
630 return path_buf;
631 }
632 char *s = adb_dirstop(path_buf);
633 if (s != NULL) {
634 *s = '\0';
635 } else {
636 path_buf[0] = '\0';
637 return NULL;
638 }
639 }
640}
641
642static char *find_top(char path_buf[PATH_MAX])
643{
644 char *top = getenv("ANDROID_BUILD_TOP");
645 if (top != NULL && top[0] != '\0') {
646 if (!top_works(top)) {
647 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
648 return NULL;
649 }
650 } else {
651 top = getenv("TOP");
652 if (top != NULL && top[0] != '\0') {
653 if (!top_works(top)) {
654 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
655 return NULL;
656 }
657 } else {
658 top = NULL;
659 }
660 }
661
662 if (top != NULL) {
663 /* The environment pointed to a top directory that works.
664 */
665 strcpy(path_buf, top);
666 return path_buf;
667 }
668
669 /* The environment didn't help. Walk up the tree from the CWD
670 * to see if we can find the top.
671 */
672 char dir[PATH_MAX];
673 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
674 if (top == NULL) {
675 /* If the CWD isn't under a good-looking top, see if the
676 * executable is.
677 */
Alexey Tarasov857f17a2009-10-22 02:55:00 +1100678 get_my_path(dir, PATH_MAX);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800679 top = find_top_from(dir, path_buf);
680 }
681 return top;
682}
683
684/* <hint> may be:
685 * - A simple product name
686 * e.g., "sooner"
687TODO: debug? sooner-debug, sooner:debug?
688 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
689 * e.g., "out/target/product/sooner"
690 * - An absolute path to the PRODUCT_OUT dir
691 * e.g., "/src/device/out/target/product/sooner"
692 *
693 * Given <hint>, try to construct an absolute path to the
694 * ANDROID_PRODUCT_OUT dir.
695 */
696static const char *find_product_out_path(const char *hint)
697{
698 static char path_buf[PATH_MAX];
699
700 if (hint == NULL || hint[0] == '\0') {
701 return NULL;
702 }
703
704 /* If it's already absolute, don't bother doing any work.
705 */
706 if (adb_is_absolute_host_path(hint)) {
707 strcpy(path_buf, hint);
708 return path_buf;
709 }
710
711 /* If there are any slashes in it, assume it's a relative path;
712 * make it absolute.
713 */
714 if (adb_dirstart(hint) != NULL) {
715 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
716 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
717 return NULL;
718 }
719 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
720 fprintf(stderr, "adb: Couldn't assemble path\n");
721 return NULL;
722 }
723 strcat(path_buf, OS_PATH_SEPARATOR_STR);
724 strcat(path_buf, hint);
725 return path_buf;
726 }
727
728 /* It's a string without any slashes. Try to do something with it.
729 *
730 * Try to find the root of the build tree, and build a PRODUCT_OUT
731 * path from there.
732 */
733 char top_buf[PATH_MAX];
734 const char *top = find_top(top_buf);
735 if (top == NULL) {
736 fprintf(stderr, "adb: Couldn't find top of build tree\n");
737 return NULL;
738 }
739//TODO: if we have a way to indicate debug, look in out/debug/target/...
740 snprintf(path_buf, sizeof(path_buf),
741 "%s" OS_PATH_SEPARATOR_STR
742 "out" OS_PATH_SEPARATOR_STR
743 "target" OS_PATH_SEPARATOR_STR
744 "product" OS_PATH_SEPARATOR_STR
745 "%s", top_buf, hint);
746 if (access(path_buf, F_OK) < 0) {
747 fprintf(stderr, "adb: Couldn't find a product dir "
748 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
749 return NULL;
750 }
751 return path_buf;
752}
753
754int adb_commandline(int argc, char **argv)
755{
756 char buf[4096];
757 int no_daemon = 0;
758 int is_daemon = 0;
759 int persist = 0;
760 int r;
761 int quote;
762 transport_type ttype = kTransportAny;
763 char* serial = NULL;
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100764 char* server_port_str = NULL;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800765
766 /* If defined, this should be an absolute path to
767 * the directory containing all of the various system images
768 * for a particular product. If not defined, and the adb
769 * command requires this information, then the user must
770 * specify the path using "-p".
771 */
772 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
773 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
774 gProductOutPath = NULL;
775 }
776 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
777
Nick Pelly2a05d0d2009-05-07 12:48:03 -0700778 serial = getenv("ANDROID_SERIAL");
779
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100780 /* Validate and assign the server port */
781 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
782 int server_port = DEFAULT_ADB_PORT;
783 if (server_port_str && strlen(server_port_str) > 0) {
784 server_port = (int) strtol(server_port_str, NULL, 0);
785 if (server_port <= 0) {
786 fprintf(stderr,
787 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number. Got \"%s\"\n",
788 server_port_str);
789 return usage();
790 }
791 }
792
793 /* modifiers and flags */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800794 while(argc > 0) {
795 if(!strcmp(argv[0],"nodaemon")) {
796 no_daemon = 1;
797 } else if (!strcmp(argv[0], "fork-server")) {
798 /* this is a special flag used only when the ADB client launches the ADB Server */
799 is_daemon = 1;
800 } else if(!strcmp(argv[0],"persist")) {
801 persist = 1;
802 } else if(!strncmp(argv[0], "-p", 2)) {
803 const char *product = NULL;
804 if (argv[0][2] == '\0') {
805 if (argc < 2) return usage();
806 product = argv[1];
807 argc--;
808 argv++;
809 } else {
810 product = argv[1] + 2;
811 }
812 gProductOutPath = find_product_out_path(product);
813 if (gProductOutPath == NULL) {
814 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
815 product);
816 return usage();
817 }
818 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
819 if (isdigit(argv[0][2])) {
820 serial = argv[0] + 2;
821 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100822 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800823 serial = argv[1];
824 argc--;
825 argv++;
826 }
827 } else if (!strcmp(argv[0],"-d")) {
828 ttype = kTransportUsb;
829 } else if (!strcmp(argv[0],"-e")) {
830 ttype = kTransportLocal;
831 } else {
832 /* out of recognized modifiers and flags */
833 break;
834 }
835 argc--;
836 argv++;
837 }
838
839 adb_set_transport(ttype, serial);
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100840 adb_set_tcp_specifics(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800841
842 if ((argc > 0) && (!strcmp(argv[0],"server"))) {
843 if (no_daemon || is_daemon) {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100844 r = adb_main(is_daemon, server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800845 } else {
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100846 r = launch_server(server_port);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800847 }
848 if(r) {
849 fprintf(stderr,"* could not start server *\n");
850 }
851 return r;
852 }
853
854top:
855 if(argc == 0) {
856 return usage();
857 }
858
859 /* adb_connect() commands */
860
861 if(!strcmp(argv[0], "devices")) {
862 char *tmp;
863 snprintf(buf, sizeof buf, "host:%s", argv[0]);
864 tmp = adb_query(buf);
865 if(tmp) {
866 printf("List of devices attached \n");
867 printf("%s\n", tmp);
868 return 0;
869 } else {
870 return 1;
871 }
872 }
873
Mike Lockwood5f2c4a12009-10-11 23:04:18 -0400874 if(!strcmp(argv[0], "connect") || !strcmp(argv[0], "disconnect")) {
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700875 char *tmp;
876 if (argc != 2) {
Mike Lockwood5f2c4a12009-10-11 23:04:18 -0400877 fprintf(stderr, "Usage: adb %s <host>:<port>\n", argv[0]);
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700878 return 1;
879 }
880 snprintf(buf, sizeof buf, "host:%s:%s", argv[0], argv[1]);
881 tmp = adb_query(buf);
882 if(tmp) {
883 printf("%s\n", tmp);
884 return 0;
885 } else {
886 return 1;
887 }
888 }
889
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800890 if (!strcmp(argv[0], "emu")) {
891 return adb_send_emulator_command(argc, argv);
892 }
893
894 if(!strcmp(argv[0], "shell")) {
895 int r;
896 int fd;
897
898 if(argc < 2) {
899 return interactive_shell();
900 }
901
902 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
903 argc -= 2;
904 argv += 2;
905 while(argc-- > 0) {
906 strcat(buf, " ");
907
908 /* quote empty strings and strings with spaces */
909 quote = (**argv == 0 || strchr(*argv, ' '));
910 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100911 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800912 strcat(buf, *argv++);
913 if (quote)
Stefan Hilzinger92ca4fa2010-04-19 12:21:12 +0100914 strcat(buf, "\"");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800915 }
916
917 for(;;) {
918 fd = adb_connect(buf);
919 if(fd >= 0) {
920 read_and_dump(fd);
921 adb_close(fd);
922 r = 0;
923 } else {
924 fprintf(stderr,"error: %s\n", adb_error());
925 r = -1;
926 }
927
928 if(persist) {
929 fprintf(stderr,"\n- waiting for device -\n");
930 adb_sleep_ms(1000);
931 do_cmd(ttype, serial, "wait-for-device", 0);
932 } else {
933 return r;
934 }
935 }
936 }
937
938 if(!strcmp(argv[0], "kill-server")) {
939 int fd;
940 fd = _adb_connect("host:kill");
941 if(fd == -1) {
942 fprintf(stderr,"* server not running *\n");
943 return 1;
944 }
945 return 0;
946 }
947
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700948 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy5a984e62009-12-14 14:42:17 -0800949 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700950 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Xavier Ducrohet75d550a2009-08-25 20:16:14 -0700951 || !strcmp(argv[0], "root")) {
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700952 char command[100];
Romain Guy5a984e62009-12-14 14:42:17 -0800953 if (!strcmp(argv[0], "reboot-bootloader"))
954 snprintf(command, sizeof(command), "reboot:bootloader");
955 else if (argc > 1)
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700956 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwooda91f54c2009-08-04 20:37:51 -0400957 else
Mike Lockwoodb51ae572009-08-24 15:58:40 -0700958 snprintf(command, sizeof(command), "%s:", argv[0]);
959 int fd = adb_connect(command);
The Android Open Source Project9c753402009-03-13 13:04:37 -0700960 if(fd >= 0) {
961 read_and_dump(fd);
962 adb_close(fd);
963 return 0;
964 }
965 fprintf(stderr,"error: %s\n", adb_error());
966 return 1;
967 }
968
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800969 if(!strcmp(argv[0], "bugreport")) {
Dan Egnor680b10c2010-01-20 13:50:36 -0800970 if (argc != 1) return usage();
971 do_cmd(ttype, serial, "shell", "bugreport", 0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800972 return 0;
973 }
974
975 /* adb_command() wrapper commands */
976
977 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
978 char* service = argv[0];
979 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
980 if (ttype == kTransportUsb) {
981 service = "wait-for-usb";
982 } else if (ttype == kTransportLocal) {
983 service = "wait-for-local";
984 } else {
985 service = "wait-for-any";
986 }
987 }
988
989 format_host_command(buf, sizeof buf, service, ttype, serial);
990
991 if (adb_command(buf)) {
992 D("failure: %s *\n",adb_error());
993 fprintf(stderr,"error: %s\n", adb_error());
994 return 1;
995 }
996
997 /* Allow a command to be run after wait-for-device,
998 * e.g. 'adb wait-for-device shell'.
999 */
1000 if(argc > 1) {
1001 argc--;
1002 argv++;
1003 goto top;
1004 }
1005 return 0;
1006 }
1007
1008 if(!strcmp(argv[0], "forward")) {
1009 if(argc != 3) return usage();
1010 if (serial) {
Mike Lockwooda12befc2009-11-28 12:46:13 -05001011 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
1012 } else if (ttype == kTransportUsb) {
1013 snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
1014 } else if (ttype == kTransportLocal) {
1015 snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001016 } else {
Mike Lockwooda12befc2009-11-28 12:46:13 -05001017 snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001018 }
1019 if(adb_command(buf)) {
1020 fprintf(stderr,"error: %s\n", adb_error());
1021 return 1;
1022 }
1023 return 0;
1024 }
1025
1026 /* do_sync_*() commands */
1027
1028 if(!strcmp(argv[0], "ls")) {
1029 if(argc != 2) return usage();
1030 return do_sync_ls(argv[1]);
1031 }
1032
1033 if(!strcmp(argv[0], "push")) {
1034 if(argc != 3) return usage();
1035 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
1036 }
1037
1038 if(!strcmp(argv[0], "pull")) {
Joe Onoratod0263702010-01-05 13:42:25 -08001039 if (argc == 2) {
1040 return do_sync_pull(argv[1], ".");
1041 } else if (argc == 3) {
1042 return do_sync_pull(argv[1], argv[2]);
1043 } else {
1044 return usage();
1045 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001046 }
1047
1048 if(!strcmp(argv[0], "install")) {
1049 if (argc < 2) return usage();
1050 return install_app(ttype, serial, argc, argv);
1051 }
1052
1053 if(!strcmp(argv[0], "uninstall")) {
1054 if (argc < 2) return usage();
1055 return uninstall_app(ttype, serial, argc, argv);
1056 }
1057
1058 if(!strcmp(argv[0], "sync")) {
1059 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001060 int listonly = 0;
1061
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001062 int ret;
1063 if(argc < 2) {
1064 /* No local path was specified. */
1065 srcarg = NULL;
Anthony Newnamdd2db142010-02-22 08:36:49 -06001066 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1067 listonly = 1;
1068 if (argc == 3) {
1069 srcarg = argv[2];
1070 } else {
1071 srcarg = NULL;
1072 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001073 } else if(argc == 2) {
1074 /* A local path or "android"/"data" arg was specified. */
1075 srcarg = argv[1];
1076 } else {
1077 return usage();
1078 }
1079 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1080 if(ret != 0) return usage();
1081
1082 if(android_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001083 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001084 if(ret == 0 && data_srcpath != NULL)
Anthony Newnamdd2db142010-02-22 08:36:49 -06001085 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001086
1087 free(android_srcpath);
1088 free(data_srcpath);
1089 return ret;
1090 }
1091
1092 /* passthrough commands */
1093
1094 if(!strcmp(argv[0],"get-state") ||
1095 !strcmp(argv[0],"get-serialno"))
1096 {
1097 char *tmp;
1098
1099 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1100 tmp = adb_query(buf);
1101 if(tmp) {
1102 printf("%s\n", tmp);
1103 return 0;
1104 } else {
1105 return 1;
1106 }
1107 }
1108
1109 /* other commands */
1110
1111 if(!strcmp(argv[0],"status-window")) {
1112 status_window(ttype, serial);
1113 return 0;
1114 }
1115
1116 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) {
1117 return logcat(ttype, serial, argc, argv);
1118 }
1119
1120 if(!strcmp(argv[0],"ppp")) {
1121 return ppp(argc, argv);
1122 }
1123
1124 if (!strcmp(argv[0], "start-server")) {
1125 return adb_connect("host:start-server");
1126 }
1127
1128 if (!strcmp(argv[0], "jdwp")) {
1129 int fd = adb_connect("jdwp");
1130 if (fd >= 0) {
1131 read_and_dump(fd);
1132 adb_close(fd);
1133 return 0;
1134 } else {
1135 fprintf(stderr, "error: %s\n", adb_error());
1136 return -1;
1137 }
1138 }
1139
1140 /* "adb /?" is a common idiom under Windows */
1141 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1142 help();
1143 return 0;
1144 }
1145
1146 if(!strcmp(argv[0], "version")) {
1147 version(stdout);
1148 return 0;
1149 }
1150
1151 usage();
1152 return 1;
1153}
1154
1155static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1156{
1157 char *argv[16];
1158 int argc;
1159 va_list ap;
1160
1161 va_start(ap, cmd);
1162 argc = 0;
1163
1164 if (serial) {
1165 argv[argc++] = "-s";
1166 argv[argc++] = serial;
1167 } else if (ttype == kTransportUsb) {
1168 argv[argc++] = "-d";
1169 } else if (ttype == kTransportLocal) {
1170 argv[argc++] = "-e";
1171 }
1172
1173 argv[argc++] = cmd;
1174 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1175 va_end(ap);
1176
1177#if 0
1178 int n;
1179 fprintf(stderr,"argc = %d\n",argc);
1180 for(n = 0; n < argc; n++) {
1181 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1182 }
1183#endif
1184
1185 return adb_commandline(argc, argv);
1186}
1187
1188int find_sync_dirs(const char *srcarg,
1189 char **android_srcdir_out, char **data_srcdir_out)
1190{
1191 char *android_srcdir, *data_srcdir;
1192
1193 if(srcarg == NULL) {
1194 android_srcdir = product_file("system");
1195 data_srcdir = product_file("data");
1196 } else {
1197 /* srcarg may be "data", "system" or NULL.
1198 * if srcarg is NULL, then both data and system are synced
1199 */
1200 if(strcmp(srcarg, "system") == 0) {
1201 android_srcdir = product_file("system");
1202 data_srcdir = NULL;
1203 } else if(strcmp(srcarg, "data") == 0) {
1204 android_srcdir = NULL;
1205 data_srcdir = product_file("data");
1206 } else {
1207 /* It's not "system" or "data".
1208 */
1209 return 1;
1210 }
1211 }
1212
1213 if(android_srcdir_out != NULL)
1214 *android_srcdir_out = android_srcdir;
1215 else
1216 free(android_srcdir);
1217
1218 if(data_srcdir_out != NULL)
1219 *data_srcdir_out = data_srcdir;
1220 else
1221 free(data_srcdir);
1222
1223 return 0;
1224}
1225
1226static int pm_command(transport_type transport, char* serial,
1227 int argc, char** argv)
1228{
1229 char buf[4096];
1230
1231 snprintf(buf, sizeof(buf), "shell:pm");
1232
1233 while(argc-- > 0) {
1234 char *quoted;
1235
1236 quoted = dupAndQuote(*argv++);
1237
1238 strncat(buf, " ", sizeof(buf)-1);
1239 strncat(buf, quoted, sizeof(buf)-1);
1240 free(quoted);
1241 }
1242
1243 send_shellcommand(transport, serial, buf);
1244 return 0;
1245}
1246
1247int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1248{
1249 /* if the user choose the -k option, we refuse to do it until devices are
1250 out with the option to uninstall the remaining data somehow (adb/ui) */
1251 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1252 {
1253 printf(
1254 "The -k option uninstalls the application while retaining the data/cache.\n"
1255 "At the moment, there is no way to remove the remaining data.\n"
1256 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1257 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1258 return -1;
1259 }
1260
1261 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1262 return pm_command(transport, serial, argc, argv);
1263}
1264
1265static int delete_file(transport_type transport, char* serial, char* filename)
1266{
1267 char buf[4096];
1268 char* quoted;
1269
1270 snprintf(buf, sizeof(buf), "shell:rm ");
1271 quoted = dupAndQuote(filename);
1272 strncat(buf, quoted, sizeof(buf)-1);
1273 free(quoted);
1274
1275 send_shellcommand(transport, serial, buf);
1276 return 0;
1277}
1278
1279int install_app(transport_type transport, char* serial, int argc, char** argv)
1280{
1281 struct stat st;
1282 int err;
1283 const char *const WHERE = "/data/local/tmp/%s";
1284 char to[PATH_MAX];
1285 char* filename = argv[argc - 1];
1286 const char* p;
1287
1288 p = adb_dirstop(filename);
1289 if (p) {
1290 p++;
1291 snprintf(to, sizeof to, WHERE, p);
1292 } else {
1293 snprintf(to, sizeof to, WHERE, filename);
1294 }
1295 if (p[0] == '\0') {
1296 }
1297
1298 err = stat(filename, &st);
1299 if (err != 0) {
1300 fprintf(stderr, "can't find '%s' to install\n", filename);
1301 return 1;
1302 }
1303 if (!S_ISREG(st.st_mode)) {
1304 fprintf(stderr, "can't install '%s' because it's not a file\n",
1305 filename);
1306 return 1;
1307 }
1308
1309 if (!(err = do_sync_push(filename, to, 1 /* verify APK */))) {
1310 /* file in place; tell the Package Manager to install it */
1311 argv[argc - 1] = to; /* destination name, not source location */
1312 pm_command(transport, serial, argc, argv);
1313 delete_file(transport, serial, to);
1314 }
1315
1316 return err;
1317}