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