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