blob: 83b568d962af8dc8b785f0c7bef82ba8974ede9c [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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080040static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
41
Alexey Tarasov31664102009-10-22 02:55:00 +110042void get_my_path(char *s, size_t maxLen);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043int find_sync_dirs(const char *srcarg,
44 char **android_srcdir_out, char **data_srcdir_out);
45int install_app(transport_type transport, char* serial, int argc, char** argv);
46int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
47
48static const char *gProductOutPath = NULL;
Matt Gumbeld7b33082012-11-14 10:16:17 -080049extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050
51static char *product_file(const char *extra)
52{
53 int n;
54 char *x;
55
56 if (gProductOutPath == NULL) {
57 fprintf(stderr, "adb: Product directory not specified; "
58 "use -p or define ANDROID_PRODUCT_OUT\n");
59 exit(1);
60 }
61
62 n = strlen(gProductOutPath) + strlen(extra) + 2;
63 x = malloc(n);
64 if (x == 0) {
65 fprintf(stderr, "adb: Out of memory (product_file())\n");
66 exit(1);
67 }
68
69 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
70 return x;
71}
72
73void version(FILE * out) {
74 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
75 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
76}
77
78void help()
79{
80 version(stderr);
81
82 fprintf(stderr,
83 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080084 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080085 " -d - directs command to the only connected USB device\n"
86 " returns an error if more than one USB device is present.\n"
87 " -e - directs command to the only running emulator.\n"
88 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070089 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070090 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070091 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080092 " -p <product name or path> - simple product name like 'sooner', or\n"
93 " a relative/absolute path to a product\n"
94 " out directory like 'out/target/product/sooner'.\n"
95 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
96 " environment variable is used, which must\n"
97 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080098 " -H - Name of adb server host (default: localhost)\n"
99 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -0700100 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700101 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400102 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
103 " Port 5555 is used by default if no port number is specified.\n"
104 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
105 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200106 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400107 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800108 "\n"
109 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700110 " adb push [-p] <local> <remote>\n"
111 " - copy file/dir to device\n"
112 " ('-p' to display the transfer progress)\n"
113 " adb pull [-p] <remote> [<local>]\n"
114 " - copy file/dir from device\n"
115 " ('-p' to display the transfer progress)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800116 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600117 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800118 " (see 'adb help all')\n"
119 " adb shell - run remote shell interactively\n"
120 " adb shell <command> - run remote shell command\n"
121 " adb emu <command> - run emulator console command\n"
122 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100123 " adb forward --list - list all forward socket connections.\n"
124 " the format is a list of lines with the following format:\n"
125 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800126 " adb forward <local> <remote> - forward socket connections\n"
127 " forward specs are one of: \n"
128 " tcp:<port>\n"
129 " localabstract:<unix domain socket name>\n"
130 " localreserved:<unix domain socket name>\n"
131 " localfilesystem:<unix domain socket name>\n"
132 " dev:<character device name>\n"
133 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100134 " adb forward --no-rebind <local> <remote>\n"
135 " - same as 'adb forward <local> <remote>' but fails\n"
136 " if <local> is already forwarded\n"
137 " adb forward --remove <local> - remove a specific forward socket connection\n"
138 " adb forward --remove-all - remove all forward socket connections\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800139 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700140 " adb install [-l] [-r] [-s] [--algo <algorithm name> --key <hex-encoded key> --iv <hex-encoded iv>] <file>\n"
141 " - push this package file to the device and install it\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800142 " ('-l' means forward-lock the app)\n"
143 " ('-r' means reinstall the app, keeping its data)\n"
Mike Lockwood0ef3fd02010-02-19 17:53:27 -0500144 " ('-s' means install on SD card instead of internal storage)\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700145 " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800146 " adb uninstall [-k] <package> - remove this app package from the device\n"
147 " ('-k' means keep the data and cache directories)\n"
148 " adb bugreport - return all information from the device\n"
149 " that should be included in a bug report.\n"
150 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800151 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700152 " - write an archive of the device's data to <file>.\n"
153 " If no -f option is supplied then the data is written\n"
154 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700155 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700156 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800157 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
158 " (aka .obb) files associated with each application; the default\n"
159 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700160 " (-shared|-noshared enable/disable backup of the device's\n"
161 " shared storage / SD card contents; the default is noshared.)\n"
162 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700163 " (-system|-nosystem toggles whether -all automatically includes\n"
164 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700165 " (<packages...> is the list of applications to be backed up. If\n"
166 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700167 " list is optional. Applications explicitly given on the\n"
168 " command line will be included even if -nosystem would\n"
169 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700170 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700171 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700172 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800173 " adb help - show this help message\n"
174 " adb version - show version num\n"
175 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800176 "scripting:\n"
177 " adb wait-for-device - block until device is online\n"
178 " adb start-server - ensure that there is a server running\n"
179 " adb kill-server - kill the server if it is running\n"
180 " adb get-state - prints: offline | bootloader | device\n"
181 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700182 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800183 " adb status-window - continuously print device status for a specified device\n"
184 " adb remount - remounts the /system partition on the device read-write\n"
Mike Lockwoodee156622009-08-04 20:37:51 -0400185 " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n"
Romain Guy311add42009-12-14 14:42:17 -0800186 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700187 " adb root - restarts the adbd daemon with root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800188 " adb usb - restarts the adbd daemon listening on USB\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700189 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800190 "\n"
191 "networking:\n"
192 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500193 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800194 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
195 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
196 "\n"
197 "adb sync notes: adb sync [ <directory> ]\n"
198 " <localdir> can be interpreted in several ways:\n"
199 "\n"
200 " - If <directory> is not specified, both /system and /data partitions will be updated.\n"
201 "\n"
202 " - If it is \"system\" or \"data\", only the corresponding partition\n"
203 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000204 "\n"
205 "environmental variables:\n"
206 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
207 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
208 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
209 " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800210 );
211}
212
213int usage()
214{
215 help();
216 return 1;
217}
218
219#ifdef HAVE_TERMIO_H
220static struct termios tio_save;
221
222static void stdin_raw_init(int fd)
223{
224 struct termios tio;
225
226 if(tcgetattr(fd, &tio)) return;
227 if(tcgetattr(fd, &tio_save)) return;
228
229 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */
230
231 /* no timeout but request at least one character per read */
232 tio.c_cc[VTIME] = 0;
233 tio.c_cc[VMIN] = 1;
234
235 tcsetattr(fd, TCSANOW, &tio);
236 tcflush(fd, TCIFLUSH);
237}
238
239static void stdin_raw_restore(int fd)
240{
241 tcsetattr(fd, TCSANOW, &tio_save);
242 tcflush(fd, TCIFLUSH);
243}
244#endif
245
246static void read_and_dump(int fd)
247{
248 char buf[4096];
249 int len;
250
251 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700252 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800253 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700254 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800255 if(len == 0) {
256 break;
257 }
258
259 if(len < 0) {
260 if(errno == EINTR) continue;
261 break;
262 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400263 fwrite(buf, 1, len, stdout);
264 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800265 }
266}
267
Christopher Tated2f54152011-04-21 12:53:28 -0700268static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700269 const size_t BUFSIZE = 32 * 1024;
270 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700271 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700272 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700273
274 D("copy_to_file(%d -> %d)\n", inFd, outFd);
275 for (;;) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700276 len = adb_read(inFd, buf, BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700277 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700278 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700279 break;
280 }
281 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700282 if (errno == EINTR) {
283 D("copy_to_file() : EINTR, retrying\n");
284 continue;
285 }
Christopher Tated2f54152011-04-21 12:53:28 -0700286 D("copy_to_file() : error %d\n", errno);
287 break;
288 }
289 adb_write(outFd, buf, len);
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700290 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700291 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700292 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700293 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700294}
295
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800296static void *stdin_read_thread(void *x)
297{
298 int fd, fdi;
299 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800300 int r, n;
301 int state = 0;
302
303 int *fds = (int*) x;
304 fd = fds[0];
305 fdi = fds[1];
306 free(fds);
307
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800308 for(;;) {
309 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700310 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800311 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700312 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800313 if(r == 0) break;
314 if(r < 0) {
315 if(errno == EINTR) continue;
316 break;
317 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400318 for(n = 0; n < r; n++){
319 switch(buf[n]) {
320 case '\n':
321 state = 1;
322 break;
323 case '\r':
324 state = 1;
325 break;
326 case '~':
327 if(state == 1) state++;
328 break;
329 case '.':
330 if(state == 2) {
331 fprintf(stderr,"\n* disconnect *\n");
332#ifdef HAVE_TERMIO_H
333 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800334#endif
Mike Lockwood67d53582010-05-25 13:40:15 -0400335 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800336 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400337 default:
338 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800339 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800340 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800341 r = adb_write(fd, buf, r);
342 if(r <= 0) {
343 break;
344 }
345 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800346 return 0;
347}
348
349int interactive_shell(void)
350{
351 adb_thread_t thr;
352 int fdi, fd;
353 int *fds;
354
355 fd = adb_connect("shell:");
356 if(fd < 0) {
357 fprintf(stderr,"error: %s\n", adb_error());
358 return 1;
359 }
360 fdi = 0; //dup(0);
361
362 fds = malloc(sizeof(int) * 2);
363 fds[0] = fd;
364 fds[1] = fdi;
365
366#ifdef HAVE_TERMIO_H
367 stdin_raw_init(fdi);
368#endif
369 adb_thread_create(&thr, stdin_read_thread, fds);
370 read_and_dump(fd);
371#ifdef HAVE_TERMIO_H
372 stdin_raw_restore(fdi);
373#endif
374 return 0;
375}
376
377
378static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
379{
380 if (serial) {
381 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
382 } else {
383 const char* prefix = "host";
384 if (ttype == kTransportUsb)
385 prefix = "host-usb";
386 else if (ttype == kTransportLocal)
387 prefix = "host-local";
388
389 snprintf(buffer, buflen, "%s:%s", prefix, command);
390 }
391}
392
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100393int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800394 unsigned progress)
395{
396 char buf[4096];
397 unsigned total;
398 int fd;
399 const unsigned char *ptr;
400
401 sprintf(buf,"%s:%d", service, sz);
402 fd = adb_connect(buf);
403 if(fd < 0) {
404 fprintf(stderr,"error: %s\n", adb_error());
405 return -1;
406 }
407
408 int opt = CHUNK_SIZE;
409 opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
410
411 total = sz;
412 ptr = data;
413
414 if(progress) {
415 char *x = strrchr(service, ':');
416 if(x) service = x + 1;
417 }
418
419 while(sz > 0) {
420 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
421 if(writex(fd, ptr, xfer)) {
422 adb_status(fd);
423 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
424 return -1;
425 }
426 sz -= xfer;
427 ptr += xfer;
428 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100429 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800430 fflush(stdout);
431 }
432 }
433 if(progress) {
434 printf("\n");
435 }
436
437 if(readx(fd, buf, 4)){
438 fprintf(stderr,"* error reading response *\n");
439 adb_close(fd);
440 return -1;
441 }
442 if(memcmp(buf, "OKAY", 4)) {
443 buf[4] = 0;
444 fprintf(stderr,"* error response '%s' *\n", buf);
445 adb_close(fd);
446 return -1;
447 }
448
449 adb_close(fd);
450 return 0;
451}
452
453
454int adb_download(const char *service, const char *fn, unsigned progress)
455{
456 void *data;
457 unsigned sz;
458
459 data = load_file(fn, &sz);
460 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100461 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800462 return -1;
463 }
464
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100465 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800466 free(data);
467 return status;
468}
469
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800470static void status_window(transport_type ttype, const char* serial)
471{
472 char command[4096];
473 char *state = 0;
474 char *laststate = 0;
475
476 /* silence stderr */
477#ifdef _WIN32
478 /* XXX: TODO */
479#else
480 int fd;
481 fd = unix_open("/dev/null", O_WRONLY);
482 dup2(fd, 2);
483 adb_close(fd);
484#endif
485
486 format_host_command(command, sizeof command, "get-state", ttype, serial);
487
488 for(;;) {
489 adb_sleep_ms(250);
490
491 if(state) {
492 free(state);
493 state = 0;
494 }
495
496 state = adb_query(command);
497
498 if(state) {
499 if(laststate && !strcmp(state,laststate)){
500 continue;
501 } else {
502 if(laststate) free(laststate);
503 laststate = strdup(state);
504 }
505 }
506
507 printf("%c[2J%c[2H", 27, 27);
508 printf("Android Debug Bridge\n");
509 printf("State: %s\n", state ? state : "offline");
510 fflush(stdout);
511 }
512}
513
514/** duplicate string and quote all \ " ( ) chars + space character. */
515static char *
516dupAndQuote(const char *s)
517{
518 const char *ts;
519 size_t alloc_len;
520 char *ret;
521 char *dest;
522
523 ts = s;
524
525 alloc_len = 0;
526
527 for( ;*ts != '\0'; ts++) {
528 alloc_len++;
529 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
530 alloc_len++;
531 }
532 }
533
534 ret = (char *)malloc(alloc_len + 1);
535
536 ts = s;
537 dest = ret;
538
539 for ( ;*ts != '\0'; ts++) {
540 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
541 *dest++ = '\\';
542 }
543
544 *dest++ = *ts;
545 }
546
547 *dest++ = '\0';
548
549 return ret;
550}
551
552/**
553 * Run ppp in "notty" mode against a resource listed as the first parameter
554 * eg:
555 *
556 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
557 *
558 */
559int ppp(int argc, char **argv)
560{
561#ifdef HAVE_WIN32_PROC
562 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
563 return -1;
564#else
565 char *adb_service_name;
566 pid_t pid;
567 int fd;
568
569 if (argc < 2) {
570 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
571 argv[0]);
572
573 return 1;
574 }
575
576 adb_service_name = argv[1];
577
578 fd = adb_connect(adb_service_name);
579
580 if(fd < 0) {
581 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
582 adb_service_name, adb_error());
583 return 1;
584 }
585
586 pid = fork();
587
588 if (pid < 0) {
589 perror("from fork()");
590 return 1;
591 } else if (pid == 0) {
592 int err;
593 int i;
594 const char **ppp_args;
595
596 // copy args
597 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
598 ppp_args[0] = "pppd";
599 for (i = 2 ; i < argc ; i++) {
600 //argv[2] and beyond become ppp_args[1] and beyond
601 ppp_args[i - 1] = argv[i];
602 }
603 ppp_args[i-1] = NULL;
604
605 // child side
606
607 dup2(fd, STDIN_FILENO);
608 dup2(fd, STDOUT_FILENO);
609 adb_close(STDERR_FILENO);
610 adb_close(fd);
611
612 err = execvp("pppd", (char * const *)ppp_args);
613
614 if (err < 0) {
615 perror("execing pppd");
616 }
617 exit(-1);
618 } else {
619 // parent side
620
621 adb_close(fd);
622 return 0;
623 }
624#endif /* !HAVE_WIN32_PROC */
625}
626
627static int send_shellcommand(transport_type transport, char* serial, char* buf)
628{
629 int fd, ret;
630
631 for(;;) {
632 fd = adb_connect(buf);
633 if(fd >= 0)
634 break;
635 fprintf(stderr,"- waiting for device -\n");
636 adb_sleep_ms(1000);
637 do_cmd(transport, serial, "wait-for-device", 0);
638 }
639
640 read_and_dump(fd);
641 ret = adb_close(fd);
642 if (ret)
643 perror("close");
644
645 return ret;
646}
647
648static int logcat(transport_type transport, char* serial, int argc, char **argv)
649{
650 char buf[4096];
651
652 char *log_tags;
653 char *quoted_log_tags;
654
655 log_tags = getenv("ANDROID_LOG_TAGS");
656 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags);
657
658 snprintf(buf, sizeof(buf),
659 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat",
660 quoted_log_tags);
661
662 free(quoted_log_tags);
663
Christopher Tatedb0a8802011-11-30 13:00:33 -0800664 if (!strcmp(argv[0],"longcat")) {
665 strncat(buf, " -v long", sizeof(buf)-1);
666 }
667
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800668 argc -= 1;
669 argv += 1;
670 while(argc-- > 0) {
671 char *quoted;
672
673 quoted = dupAndQuote (*argv++);
674
675 strncat(buf, " ", sizeof(buf)-1);
676 strncat(buf, quoted, sizeof(buf)-1);
677 free(quoted);
678 }
679
680 send_shellcommand(transport, serial, buf);
681 return 0;
682}
683
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800684static int mkdirs(char *path)
685{
686 int ret;
687 char *x = path + 1;
688
689 for(;;) {
690 x = adb_dirstart(x);
691 if(x == 0) return 0;
692 *x = 0;
693 ret = adb_mkdir(path, 0775);
694 *x = OS_PATH_SEPARATOR;
695 if((ret < 0) && (errno != EEXIST)) {
696 return ret;
697 }
698 x++;
699 }
700 return 0;
701}
702
Christopher Tated2f54152011-04-21 12:53:28 -0700703static int backup(int argc, char** argv) {
704 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800705 char default_name[32];
706 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700707 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700708 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700709
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700710 /* find, extract, and use any -f argument */
711 for (i = 1; i < argc; i++) {
712 if (!strcmp("-f", argv[i])) {
713 if (i == argc-1) {
714 fprintf(stderr, "adb: -f passed with no filename\n");
715 return usage();
716 }
717 filename = argv[i+1];
718 for (j = i+2; j <= argc; ) {
719 argv[i++] = argv[j++];
720 }
721 argc -= 2;
722 argv[argc] = NULL;
723 }
Christopher Tated2f54152011-04-21 12:53:28 -0700724 }
725
Christopher Tatebb86bc52011-08-22 17:12:08 -0700726 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
727 if (argc < 2) return usage();
728
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800729 adb_unlink(filename);
730 mkdirs((char *)filename);
731 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700732 if (outFd < 0) {
733 fprintf(stderr, "adb: unable to open file %s\n", filename);
734 return -1;
735 }
736
737 snprintf(buf, sizeof(buf), "backup");
738 for (argc--, argv++; argc; argc--, argv++) {
739 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
740 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
741 }
742
743 D("backup. filename=%s buf=%s\n", filename, buf);
744 fd = adb_connect(buf);
745 if (fd < 0) {
746 fprintf(stderr, "adb: unable to connect for backup\n");
747 adb_close(outFd);
748 return -1;
749 }
750
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800751 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700752 copy_to_file(fd, outFd);
753
754 adb_close(fd);
755 adb_close(outFd);
756 return 0;
757}
758
Christopher Tate702967a2011-05-17 15:52:54 -0700759static int restore(int argc, char** argv) {
760 const char* filename;
761 int fd, tarFd;
762
763 if (argc != 2) return usage();
764
765 filename = argv[1];
766 tarFd = adb_open(filename, O_RDONLY);
767 if (tarFd < 0) {
768 fprintf(stderr, "adb: unable to open file %s\n", filename);
769 return -1;
770 }
771
772 fd = adb_connect("restore:");
773 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700774 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700775 adb_close(tarFd);
776 return -1;
777 }
778
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800779 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700780 copy_to_file(tarFd, fd);
781
782 adb_close(fd);
783 adb_close(tarFd);
784 return 0;
785}
786
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800787#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
788static int top_works(const char *top)
789{
790 if (top != NULL && adb_is_absolute_host_path(top)) {
791 char path_buf[PATH_MAX];
792 snprintf(path_buf, sizeof(path_buf),
793 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
794 return access(path_buf, F_OK) == 0;
795 }
796 return 0;
797}
798
799static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
800{
801 strcpy(path_buf, indir);
802 while (1) {
803 if (top_works(path_buf)) {
804 return path_buf;
805 }
806 char *s = adb_dirstop(path_buf);
807 if (s != NULL) {
808 *s = '\0';
809 } else {
810 path_buf[0] = '\0';
811 return NULL;
812 }
813 }
814}
815
816static char *find_top(char path_buf[PATH_MAX])
817{
818 char *top = getenv("ANDROID_BUILD_TOP");
819 if (top != NULL && top[0] != '\0') {
820 if (!top_works(top)) {
821 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
822 return NULL;
823 }
824 } else {
825 top = getenv("TOP");
826 if (top != NULL && top[0] != '\0') {
827 if (!top_works(top)) {
828 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
829 return NULL;
830 }
831 } else {
832 top = NULL;
833 }
834 }
835
836 if (top != NULL) {
837 /* The environment pointed to a top directory that works.
838 */
839 strcpy(path_buf, top);
840 return path_buf;
841 }
842
843 /* The environment didn't help. Walk up the tree from the CWD
844 * to see if we can find the top.
845 */
846 char dir[PATH_MAX];
847 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
848 if (top == NULL) {
849 /* If the CWD isn't under a good-looking top, see if the
850 * executable is.
851 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100852 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800853 top = find_top_from(dir, path_buf);
854 }
855 return top;
856}
857
858/* <hint> may be:
859 * - A simple product name
860 * e.g., "sooner"
861TODO: debug? sooner-debug, sooner:debug?
862 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
863 * e.g., "out/target/product/sooner"
864 * - An absolute path to the PRODUCT_OUT dir
865 * e.g., "/src/device/out/target/product/sooner"
866 *
867 * Given <hint>, try to construct an absolute path to the
868 * ANDROID_PRODUCT_OUT dir.
869 */
870static const char *find_product_out_path(const char *hint)
871{
872 static char path_buf[PATH_MAX];
873
874 if (hint == NULL || hint[0] == '\0') {
875 return NULL;
876 }
877
878 /* If it's already absolute, don't bother doing any work.
879 */
880 if (adb_is_absolute_host_path(hint)) {
881 strcpy(path_buf, hint);
882 return path_buf;
883 }
884
885 /* If there are any slashes in it, assume it's a relative path;
886 * make it absolute.
887 */
888 if (adb_dirstart(hint) != NULL) {
889 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
890 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
891 return NULL;
892 }
893 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
894 fprintf(stderr, "adb: Couldn't assemble path\n");
895 return NULL;
896 }
897 strcat(path_buf, OS_PATH_SEPARATOR_STR);
898 strcat(path_buf, hint);
899 return path_buf;
900 }
901
902 /* It's a string without any slashes. Try to do something with it.
903 *
904 * Try to find the root of the build tree, and build a PRODUCT_OUT
905 * path from there.
906 */
907 char top_buf[PATH_MAX];
908 const char *top = find_top(top_buf);
909 if (top == NULL) {
910 fprintf(stderr, "adb: Couldn't find top of build tree\n");
911 return NULL;
912 }
913//TODO: if we have a way to indicate debug, look in out/debug/target/...
914 snprintf(path_buf, sizeof(path_buf),
915 "%s" OS_PATH_SEPARATOR_STR
916 "out" OS_PATH_SEPARATOR_STR
917 "target" OS_PATH_SEPARATOR_STR
918 "product" OS_PATH_SEPARATOR_STR
919 "%s", top_buf, hint);
920 if (access(path_buf, F_OK) < 0) {
921 fprintf(stderr, "adb: Couldn't find a product dir "
922 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
923 return NULL;
924 }
925 return path_buf;
926}
927
Mark Lindner76f2a932014-03-11 17:55:59 -0700928
929static void parse_push_pull_args(char** arg, int narg, char const** path1, char const** path2,
930 int* show_progress) {
931 *show_progress = 0;
932
933 if ((narg > 0) && !strcmp(*arg, "-p")) {
934 *show_progress = 1;
935 ++arg;
936 --narg;
937 }
938
939 if (narg > 0) {
940 *path1 = *arg;
941 ++arg;
942 --narg;
943 }
944
945 if (narg > 0) {
946 *path2 = *arg;
947 }
948}
949
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800950int adb_commandline(int argc, char **argv)
951{
952 char buf[4096];
953 int no_daemon = 0;
954 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100955 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800956 int persist = 0;
957 int r;
958 int quote;
959 transport_type ttype = kTransportAny;
960 char* serial = NULL;
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100961 char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800962
963 /* If defined, this should be an absolute path to
964 * the directory containing all of the various system images
965 * for a particular product. If not defined, and the adb
966 * command requires this information, then the user must
967 * specify the path using "-p".
968 */
969 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
970 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
971 gProductOutPath = NULL;
972 }
973 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
974
Nick Pellydb449262009-05-07 12:48:03 -0700975 serial = getenv("ANDROID_SERIAL");
976
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100977 /* Validate and assign the server port */
978 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
979 int server_port = DEFAULT_ADB_PORT;
980 if (server_port_str && strlen(server_port_str) > 0) {
981 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -0800982 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100983 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -0800984 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100985 server_port_str);
986 return usage();
987 }
988 }
989
990 /* modifiers and flags */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800991 while(argc > 0) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100992 if(!strcmp(argv[0],"server")) {
993 is_server = 1;
994 } else if(!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800995 no_daemon = 1;
996 } else if (!strcmp(argv[0], "fork-server")) {
997 /* this is a special flag used only when the ADB client launches the ADB Server */
998 is_daemon = 1;
999 } else if(!strcmp(argv[0],"persist")) {
1000 persist = 1;
1001 } else if(!strncmp(argv[0], "-p", 2)) {
1002 const char *product = NULL;
1003 if (argv[0][2] == '\0') {
1004 if (argc < 2) return usage();
1005 product = argv[1];
1006 argc--;
1007 argv++;
1008 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001009 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001010 }
1011 gProductOutPath = find_product_out_path(product);
1012 if (gProductOutPath == NULL) {
1013 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1014 product);
1015 return usage();
1016 }
1017 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1018 if (isdigit(argv[0][2])) {
1019 serial = argv[0] + 2;
1020 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001021 if(argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001022 serial = argv[1];
1023 argc--;
1024 argv++;
1025 }
1026 } else if (!strcmp(argv[0],"-d")) {
1027 ttype = kTransportUsb;
1028 } else if (!strcmp(argv[0],"-e")) {
1029 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001030 } else if (!strcmp(argv[0],"-a")) {
1031 gListenAll = 1;
1032 } else if(!strncmp(argv[0], "-H", 2)) {
1033 const char *hostname = NULL;
1034 if (argv[0][2] == '\0') {
1035 if (argc < 2) return usage();
1036 hostname = argv[1];
1037 argc--;
1038 argv++;
1039 } else {
1040 hostname = argv[0] + 2;
1041 }
1042 adb_set_tcp_name(hostname);
1043
1044 } else if(!strncmp(argv[0], "-P", 2)) {
1045 if (argv[0][2] == '\0') {
1046 if (argc < 2) return usage();
1047 server_port_str = argv[1];
1048 argc--;
1049 argv++;
1050 } else {
1051 server_port_str = argv[0] + 2;
1052 }
1053 if (strlen(server_port_str) > 0) {
1054 server_port = (int) strtol(server_port_str, NULL, 0);
1055 if (server_port <= 0 || server_port > 65535) {
1056 fprintf(stderr,
1057 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1058 server_port_str);
1059 return usage();
1060 }
1061 } else {
1062 fprintf(stderr,
1063 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1064 return usage();
1065 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001066 } else {
1067 /* out of recognized modifiers and flags */
1068 break;
1069 }
1070 argc--;
1071 argv++;
1072 }
1073
1074 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001075 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001076
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001077 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001078 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001079 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001080 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001081 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001082 }
1083 if(r) {
1084 fprintf(stderr,"* could not start server *\n");
1085 }
1086 return r;
1087 }
1088
1089top:
1090 if(argc == 0) {
1091 return usage();
1092 }
1093
1094 /* adb_connect() commands */
1095
1096 if(!strcmp(argv[0], "devices")) {
1097 char *tmp;
Scott Andersone109d262012-04-20 11:21:14 -07001098 char *listopt;
1099 if (argc < 2)
1100 listopt = "";
1101 else if (argc == 2 && !strcmp(argv[1], "-l"))
1102 listopt = argv[1];
1103 else {
1104 fprintf(stderr, "Usage: adb devices [-l]\n");
1105 return 1;
1106 }
1107 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001108 tmp = adb_query(buf);
1109 if(tmp) {
1110 printf("List of devices attached \n");
1111 printf("%s\n", tmp);
1112 return 0;
1113 } else {
1114 return 1;
1115 }
1116 }
1117
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001118 if(!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001119 char *tmp;
1120 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001121 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001122 return 1;
1123 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001124 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1125 tmp = adb_query(buf);
1126 if(tmp) {
1127 printf("%s\n", tmp);
1128 return 0;
1129 } else {
1130 return 1;
1131 }
1132 }
1133
1134 if(!strcmp(argv[0], "disconnect")) {
1135 char *tmp;
1136 if (argc > 2) {
1137 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1138 return 1;
1139 }
1140 if (argc == 2) {
1141 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1142 } else {
1143 snprintf(buf, sizeof buf, "host:disconnect:");
1144 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001145 tmp = adb_query(buf);
1146 if(tmp) {
1147 printf("%s\n", tmp);
1148 return 0;
1149 } else {
1150 return 1;
1151 }
1152 }
1153
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001154 if (!strcmp(argv[0], "emu")) {
1155 return adb_send_emulator_command(argc, argv);
1156 }
1157
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001158 if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001159 int r;
1160 int fd;
1161
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001162 char h = (argv[0][0] == 'h');
1163
1164 if (h) {
1165 printf("\x1b[41;33m");
1166 fflush(stdout);
1167 }
1168
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001169 if(argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001170 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001171 r = interactive_shell();
1172 if (h) {
1173 printf("\x1b[0m");
1174 fflush(stdout);
1175 }
1176 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001177 }
1178
1179 snprintf(buf, sizeof buf, "shell:%s", argv[1]);
1180 argc -= 2;
1181 argv += 2;
1182 while(argc-- > 0) {
1183 strcat(buf, " ");
1184
1185 /* quote empty strings and strings with spaces */
1186 quote = (**argv == 0 || strchr(*argv, ' '));
1187 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001188 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001189 strcat(buf, *argv++);
1190 if (quote)
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001191 strcat(buf, "\"");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001192 }
1193
1194 for(;;) {
JP Abgrall408fa572011-03-16 15:57:42 -07001195 D("interactive shell loop. buff=%s\n", buf);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001196 fd = adb_connect(buf);
1197 if(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001198 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001199 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001200 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001201 adb_close(fd);
1202 r = 0;
1203 } else {
1204 fprintf(stderr,"error: %s\n", adb_error());
1205 r = -1;
1206 }
1207
1208 if(persist) {
1209 fprintf(stderr,"\n- waiting for device -\n");
1210 adb_sleep_ms(1000);
1211 do_cmd(ttype, serial, "wait-for-device", 0);
1212 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001213 if (h) {
1214 printf("\x1b[0m");
1215 fflush(stdout);
1216 }
JP Abgrall408fa572011-03-16 15:57:42 -07001217 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001218 return r;
1219 }
1220 }
1221 }
1222
1223 if(!strcmp(argv[0], "kill-server")) {
1224 int fd;
1225 fd = _adb_connect("host:kill");
1226 if(fd == -1) {
1227 fprintf(stderr,"* server not running *\n");
1228 return 1;
1229 }
1230 return 0;
1231 }
1232
Doug Zongker447f0612012-01-09 14:54:53 -08001233 if(!strcmp(argv[0], "sideload")) {
1234 if(argc != 2) return usage();
1235 if(adb_download("sideload", argv[1], 1)) {
1236 return 1;
1237 } else {
1238 return 0;
1239 }
1240 }
1241
Mike Lockwoodff196702009-08-24 15:58:40 -07001242 if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
Romain Guy311add42009-12-14 14:42:17 -08001243 || !strcmp(argv[0], "reboot-bootloader")
Mike Lockwoodff196702009-08-24 15:58:40 -07001244 || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001245 || !strcmp(argv[0], "root")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001246 char command[100];
Romain Guy311add42009-12-14 14:42:17 -08001247 if (!strcmp(argv[0], "reboot-bootloader"))
1248 snprintf(command, sizeof(command), "reboot:bootloader");
1249 else if (argc > 1)
Mike Lockwoodff196702009-08-24 15:58:40 -07001250 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Mike Lockwoodee156622009-08-04 20:37:51 -04001251 else
Mike Lockwoodff196702009-08-24 15:58:40 -07001252 snprintf(command, sizeof(command), "%s:", argv[0]);
1253 int fd = adb_connect(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001254 if(fd >= 0) {
1255 read_and_dump(fd);
1256 adb_close(fd);
1257 return 0;
1258 }
1259 fprintf(stderr,"error: %s\n", adb_error());
1260 return 1;
1261 }
1262
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001263 if(!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001264 if (argc != 1) return usage();
1265 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001266 return 0;
1267 }
1268
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001269 /* adb_command() wrapper commands */
1270
1271 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
1272 char* service = argv[0];
1273 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1274 if (ttype == kTransportUsb) {
1275 service = "wait-for-usb";
1276 } else if (ttype == kTransportLocal) {
1277 service = "wait-for-local";
1278 } else {
1279 service = "wait-for-any";
1280 }
1281 }
1282
1283 format_host_command(buf, sizeof buf, service, ttype, serial);
1284
1285 if (adb_command(buf)) {
1286 D("failure: %s *\n",adb_error());
1287 fprintf(stderr,"error: %s\n", adb_error());
1288 return 1;
1289 }
1290
1291 /* Allow a command to be run after wait-for-device,
1292 * e.g. 'adb wait-for-device shell'.
1293 */
1294 if(argc > 1) {
1295 argc--;
1296 argv++;
1297 goto top;
1298 }
1299 return 0;
1300 }
1301
1302 if(!strcmp(argv[0], "forward")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001303 char host_prefix[64];
1304 char remove = 0;
1305 char remove_all = 0;
1306 char list = 0;
1307 char no_rebind = 0;
1308
1309 // Parse options here.
1310 while (argc > 1 && argv[1][0] == '-') {
1311 if (!strcmp(argv[1], "--list"))
1312 list = 1;
1313 else if (!strcmp(argv[1], "--remove"))
1314 remove = 1;
1315 else if (!strcmp(argv[1], "--remove-all"))
1316 remove_all = 1;
1317 else if (!strcmp(argv[1], "--no-rebind"))
1318 no_rebind = 1;
1319 else {
1320 return usage();
1321 }
1322 argc--;
1323 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001324 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001325
1326 // Ensure we can only use one option at a time.
1327 if (list + remove + remove_all + no_rebind > 1) {
1328 return usage();
1329 }
1330
1331 // Determine the <host-prefix> for this command.
1332 if (serial) {
1333 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1334 serial);
1335 } else if (ttype == kTransportUsb) {
1336 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1337 } else if (ttype == kTransportLocal) {
1338 snprintf(host_prefix, sizeof host_prefix, "host-local");
1339 } else {
1340 snprintf(host_prefix, sizeof host_prefix, "host");
1341 }
1342
1343 // Implement forward --list
1344 if (list) {
1345 if (argc != 1)
1346 return usage();
1347 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1348 char* forwards = adb_query(buf);
1349 if (forwards == NULL) {
1350 fprintf(stderr, "error: %s\n", adb_error());
1351 return 1;
1352 }
1353 printf("%s", forwards);
1354 free(forwards);
1355 return 0;
1356 }
1357
1358 // Implement forward --remove-all
1359 else if (remove_all) {
1360 if (argc != 1)
1361 return usage();
1362 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1363 }
1364
1365 // Implement forward --remove <local>
1366 else if (remove) {
1367 if (argc != 2)
1368 return usage();
1369 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1370 }
1371 // Or implement one of:
1372 // forward <local> <remote>
1373 // forward --no-rebind <local> <remote>
1374 else
1375 {
1376 if (argc != 3)
1377 return usage();
1378 const char* command = no_rebind ? "forward:norebind:" : "forward";
1379 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1380 }
1381
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001382 if(adb_command(buf)) {
1383 fprintf(stderr,"error: %s\n", adb_error());
1384 return 1;
1385 }
1386 return 0;
1387 }
1388
1389 /* do_sync_*() commands */
1390
1391 if(!strcmp(argv[0], "ls")) {
1392 if(argc != 2) return usage();
1393 return do_sync_ls(argv[1]);
1394 }
1395
1396 if(!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001397 int show_progress = 0;
1398 const char* lpath = NULL, *rpath = NULL;
1399
1400 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress);
1401
1402 if ((lpath != NULL) && (rpath != NULL)) {
1403 return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
1404 }
1405
1406 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001407 }
1408
1409 if(!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001410 int show_progress = 0;
1411 const char* rpath = NULL, *lpath = ".";
1412
1413 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress);
1414
1415 if (rpath != NULL) {
1416 return do_sync_pull(rpath, lpath, show_progress);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001417 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001418
1419 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001420 }
1421
1422 if(!strcmp(argv[0], "install")) {
1423 if (argc < 2) return usage();
1424 return install_app(ttype, serial, argc, argv);
1425 }
1426
1427 if(!strcmp(argv[0], "uninstall")) {
1428 if (argc < 2) return usage();
1429 return uninstall_app(ttype, serial, argc, argv);
1430 }
1431
1432 if(!strcmp(argv[0], "sync")) {
1433 char *srcarg, *android_srcpath, *data_srcpath;
Anthony Newnam705c9442010-02-22 08:36:49 -06001434 int listonly = 0;
1435
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001436 int ret;
1437 if(argc < 2) {
1438 /* No local path was specified. */
1439 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001440 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1441 listonly = 1;
1442 if (argc == 3) {
1443 srcarg = argv[2];
1444 } else {
1445 srcarg = NULL;
1446 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001447 } else if(argc == 2) {
1448 /* A local path or "android"/"data" arg was specified. */
1449 srcarg = argv[1];
1450 } else {
1451 return usage();
1452 }
1453 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1454 if(ret != 0) return usage();
1455
1456 if(android_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001457 ret = do_sync_sync(android_srcpath, "/system", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001458 if(ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001459 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001460
1461 free(android_srcpath);
1462 free(data_srcpath);
1463 return ret;
1464 }
1465
1466 /* passthrough commands */
1467
1468 if(!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001469 !strcmp(argv[0],"get-serialno") ||
1470 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001471 {
1472 char *tmp;
1473
1474 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1475 tmp = adb_query(buf);
1476 if(tmp) {
1477 printf("%s\n", tmp);
1478 return 0;
1479 } else {
1480 return 1;
1481 }
1482 }
1483
1484 /* other commands */
1485
1486 if(!strcmp(argv[0],"status-window")) {
1487 status_window(ttype, serial);
1488 return 0;
1489 }
1490
Christopher Tatedb0a8802011-11-30 13:00:33 -08001491 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001492 return logcat(ttype, serial, argc, argv);
1493 }
1494
1495 if(!strcmp(argv[0],"ppp")) {
1496 return ppp(argc, argv);
1497 }
1498
1499 if (!strcmp(argv[0], "start-server")) {
1500 return adb_connect("host:start-server");
1501 }
1502
Christopher Tated2f54152011-04-21 12:53:28 -07001503 if (!strcmp(argv[0], "backup")) {
1504 return backup(argc, argv);
1505 }
1506
Christopher Tate702967a2011-05-17 15:52:54 -07001507 if (!strcmp(argv[0], "restore")) {
1508 return restore(argc, argv);
1509 }
1510
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001511 if (!strcmp(argv[0], "jdwp")) {
1512 int fd = adb_connect("jdwp");
1513 if (fd >= 0) {
1514 read_and_dump(fd);
1515 adb_close(fd);
1516 return 0;
1517 } else {
1518 fprintf(stderr, "error: %s\n", adb_error());
1519 return -1;
1520 }
1521 }
1522
1523 /* "adb /?" is a common idiom under Windows */
1524 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1525 help();
1526 return 0;
1527 }
1528
1529 if(!strcmp(argv[0], "version")) {
1530 version(stdout);
1531 return 0;
1532 }
1533
1534 usage();
1535 return 1;
1536}
1537
1538static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1539{
1540 char *argv[16];
1541 int argc;
1542 va_list ap;
1543
1544 va_start(ap, cmd);
1545 argc = 0;
1546
1547 if (serial) {
1548 argv[argc++] = "-s";
1549 argv[argc++] = serial;
1550 } else if (ttype == kTransportUsb) {
1551 argv[argc++] = "-d";
1552 } else if (ttype == kTransportLocal) {
1553 argv[argc++] = "-e";
1554 }
1555
1556 argv[argc++] = cmd;
1557 while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1558 va_end(ap);
1559
1560#if 0
1561 int n;
1562 fprintf(stderr,"argc = %d\n",argc);
1563 for(n = 0; n < argc; n++) {
1564 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1565 }
1566#endif
1567
1568 return adb_commandline(argc, argv);
1569}
1570
1571int find_sync_dirs(const char *srcarg,
1572 char **android_srcdir_out, char **data_srcdir_out)
1573{
1574 char *android_srcdir, *data_srcdir;
1575
1576 if(srcarg == NULL) {
1577 android_srcdir = product_file("system");
1578 data_srcdir = product_file("data");
1579 } else {
1580 /* srcarg may be "data", "system" or NULL.
1581 * if srcarg is NULL, then both data and system are synced
1582 */
1583 if(strcmp(srcarg, "system") == 0) {
1584 android_srcdir = product_file("system");
1585 data_srcdir = NULL;
1586 } else if(strcmp(srcarg, "data") == 0) {
1587 android_srcdir = NULL;
1588 data_srcdir = product_file("data");
1589 } else {
1590 /* It's not "system" or "data".
1591 */
1592 return 1;
1593 }
1594 }
1595
1596 if(android_srcdir_out != NULL)
1597 *android_srcdir_out = android_srcdir;
1598 else
1599 free(android_srcdir);
1600
1601 if(data_srcdir_out != NULL)
1602 *data_srcdir_out = data_srcdir;
1603 else
1604 free(data_srcdir);
1605
1606 return 0;
1607}
1608
1609static int pm_command(transport_type transport, char* serial,
1610 int argc, char** argv)
1611{
1612 char buf[4096];
1613
1614 snprintf(buf, sizeof(buf), "shell:pm");
1615
1616 while(argc-- > 0) {
1617 char *quoted;
1618
1619 quoted = dupAndQuote(*argv++);
1620
1621 strncat(buf, " ", sizeof(buf)-1);
1622 strncat(buf, quoted, sizeof(buf)-1);
1623 free(quoted);
1624 }
1625
1626 send_shellcommand(transport, serial, buf);
1627 return 0;
1628}
1629
1630int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1631{
1632 /* if the user choose the -k option, we refuse to do it until devices are
1633 out with the option to uninstall the remaining data somehow (adb/ui) */
1634 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1635 {
1636 printf(
1637 "The -k option uninstalls the application while retaining the data/cache.\n"
1638 "At the moment, there is no way to remove the remaining data.\n"
1639 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1640 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1641 return -1;
1642 }
1643
1644 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1645 return pm_command(transport, serial, argc, argv);
1646}
1647
1648static int delete_file(transport_type transport, char* serial, char* filename)
1649{
1650 char buf[4096];
1651 char* quoted;
1652
1653 snprintf(buf, sizeof(buf), "shell:rm ");
1654 quoted = dupAndQuote(filename);
1655 strncat(buf, quoted, sizeof(buf)-1);
1656 free(quoted);
1657
1658 send_shellcommand(transport, serial, buf);
1659 return 0;
1660}
1661
Kenny Root597ea5b2011-08-05 11:19:45 -07001662static const char* get_basename(const char* filename)
1663{
1664 const char* basename = adb_dirstop(filename);
1665 if (basename) {
1666 basename++;
1667 return basename;
1668 } else {
1669 return filename;
1670 }
1671}
1672
1673static int check_file(const char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001674{
1675 struct stat st;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001676
Kenny Root597ea5b2011-08-05 11:19:45 -07001677 if (filename == NULL) {
1678 return 0;
Mike Lockwood0ef3fd02010-02-19 17:53:27 -05001679 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001680
Kenny Root597ea5b2011-08-05 11:19:45 -07001681 if (stat(filename, &st) != 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001682 fprintf(stderr, "can't find '%s' to install\n", filename);
1683 return 1;
1684 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001685
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001686 if (!S_ISREG(st.st_mode)) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001687 fprintf(stderr, "can't install '%s' because it's not a file\n", filename);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001688 return 1;
1689 }
1690
Kenny Root597ea5b2011-08-05 11:19:45 -07001691 return 0;
1692}
1693
1694int install_app(transport_type transport, char* serial, int argc, char** argv)
1695{
1696 static const char *const DATA_DEST = "/data/local/tmp/%s";
1697 static const char *const SD_DEST = "/sdcard/tmp/%s";
1698 const char* where = DATA_DEST;
1699 char apk_dest[PATH_MAX];
1700 char verification_dest[PATH_MAX];
1701 char* apk_file;
1702 char* verification_file = NULL;
1703 int file_arg = -1;
1704 int err;
1705 int i;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001706 int verify_apk = 1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001707
1708 for (i = 1; i < argc; i++) {
1709 if (*argv[i] != '-') {
1710 file_arg = i;
1711 break;
Kenny Roota031a912011-09-23 12:46:39 -07001712 } else if (!strcmp(argv[i], "-i")) {
1713 // Skip the installer package name.
1714 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001715 } else if (!strcmp(argv[i], "-s")) {
1716 where = SD_DEST;
Anonymous Coward4474ac42012-04-24 10:43:41 -07001717 } else if (!strcmp(argv[i], "--algo")) {
1718 verify_apk = 0;
1719 i++;
1720 } else if (!strcmp(argv[i], "--iv")) {
1721 verify_apk = 0;
1722 i++;
1723 } else if (!strcmp(argv[i], "--key")) {
1724 verify_apk = 0;
1725 i++;
Kenny Root597ea5b2011-08-05 11:19:45 -07001726 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001727 }
1728
Kenny Root597ea5b2011-08-05 11:19:45 -07001729 if (file_arg < 0) {
Kenny Roota031a912011-09-23 12:46:39 -07001730 fprintf(stderr, "can't find filename in arguments\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001731 return 1;
1732 } else if (file_arg + 2 < argc) {
Kenny Roota031a912011-09-23 12:46:39 -07001733 fprintf(stderr, "too many files specified; only takes APK file and verifier file\n");
Kenny Root597ea5b2011-08-05 11:19:45 -07001734 return 1;
1735 }
1736
1737 apk_file = argv[file_arg];
1738
1739 if (file_arg != argc - 1) {
1740 verification_file = argv[file_arg + 1];
1741 }
1742
1743 if (check_file(apk_file) || check_file(verification_file)) {
1744 return 1;
1745 }
1746
1747 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
1748 if (verification_file != NULL) {
1749 snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file));
1750
1751 if (!strcmp(apk_dest, verification_dest)) {
1752 fprintf(stderr, "APK and verification file can't have the same name\n");
1753 return 1;
1754 }
1755 }
1756
Mark Lindner76f2a932014-03-11 17:55:59 -07001757 err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001758 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001759 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001760 } else {
1761 argv[file_arg] = apk_dest; /* destination name, not source location */
1762 }
1763
1764 if (verification_file != NULL) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001765 err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
1766 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001767 if (err) {
1768 goto cleanup_apk;
1769 } else {
1770 argv[file_arg + 1] = verification_dest; /* destination name, not source location */
1771 }
1772 }
1773
1774 pm_command(transport, serial, argc, argv);
1775
Kenny Root60733e92012-03-26 16:14:02 -07001776cleanup_apk:
Kenny Root597ea5b2011-08-05 11:19:45 -07001777 if (verification_file != NULL) {
1778 delete_file(transport, serial, verification_dest);
1779 }
1780
Kenny Root597ea5b2011-08-05 11:19:45 -07001781 delete_file(transport, serial, apk_dest);
1782
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001783 return err;
1784}