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