blob: 58e1adefc8fac92db3daa1ac3f9bc775e63187b4 [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
Dan Albert33134262015-03-19 15:21:08 -070017#define TRACE_TAG TRACE_ADB
18
19#include "sysdeps.h"
20
Dan Albert76649012015-02-24 15:51:19 -080021#include <assert.h>
22#include <ctype.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023#include <errno.h>
Elliott Hughes2940ccf2015-04-17 14:07:52 -070024#include <inttypes.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080025#include <limits.h>
26#include <stdarg.h>
Dan Albert76649012015-02-24 15:51:19 -080027#include <stdint.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080031#include <sys/stat.h>
Dan Albert76649012015-02-24 15:51:19 -080032#include <sys/types.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080033
Elliott Hughes2baae3a2015-04-17 10:59:34 -070034#include <string>
35
36#include <base/stringprintf.h>
37
Yabin Cuid325e862014-11-17 14:48:25 -080038#if !defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080039#include <termios.h>
Dan Albert76649012015-02-24 15:51:19 -080040#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080041#endif
42
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043#include "adb.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080044#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080045#include "adb_client.h"
46#include "adb_io.h"
Elliott Hughes58305772015-04-17 13:57:15 -070047#include "adb_utils.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048#include "file_sync_service.h"
49
Dan Albertbac34742015-02-25 17:51:28 -080050static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080051
Elliott Hughes58305772015-04-17 13:57:15 -070052static int install_app(transport_type transport, const char* serial, int argc,
53 const char** argv);
54static int install_multiple_app(transport_type transport, const char* serial, int argc,
55 const char** argv);
56static int uninstall_app(transport_type transport, const char* serial, int argc,
Dan Albertbac34742015-02-25 17:51:28 -080057 const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080058
Elliott Hughes58305772015-04-17 13:57:15 -070059static std::string gProductOutPath;
Matt Gumbeld7b33082012-11-14 10:16:17 -080060extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080061
Elliott Hughes58305772015-04-17 13:57:15 -070062static std::string product_file(const char *extra) {
63 if (gProductOutPath.empty()) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080064 fprintf(stderr, "adb: Product directory not specified; "
65 "use -p or define ANDROID_PRODUCT_OUT\n");
66 exit(1);
67 }
68
Elliott Hughes58305772015-04-17 13:57:15 -070069 return android::base::StringPrintf("%s%s%s",
70 gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080071}
72
Elliott Hughes58305772015-04-17 13:57:15 -070073static void version(FILE* out) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080074 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
Elliott Hughes58305772015-04-17 13:57:15 -070075 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080076}
77
Elliott Hughes58305772015-04-17 13:57:15 -070078static void help() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080079 version(stderr);
80
81 fprintf(stderr,
82 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080083 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080084 " -d - directs command to the only connected USB device\n"
85 " returns an error if more than one USB device is present.\n"
86 " -e - directs command to the only running emulator.\n"
87 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070088 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070089 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070090 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080091 " -p <product name or path> - simple product name like 'sooner', or\n"
92 " a relative/absolute path to a product\n"
93 " out directory like 'out/target/product/sooner'.\n"
94 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
95 " environment variable is used, which must\n"
96 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080097 " -H - Name of adb server host (default: localhost)\n"
98 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -070099 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700100 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -0400101 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
102 " Port 5555 is used by default if no port number is specified.\n"
103 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
104 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200105 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -0400106 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800107 "\n"
108 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700109 " adb push [-p] <local> <remote>\n"
110 " - copy file/dir to device\n"
111 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700112 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700113 " - copy file/dir from device\n"
114 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700115 " ('-a' means copy timestamp and mode)\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"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100139 " adb reverse --list - list all reverse socket connections from device\n"
140 " adb reverse <remote> <local> - reverse socket connections\n"
141 " reverse specs are one of:\n"
142 " tcp:<port>\n"
143 " localabstract:<unix domain socket name>\n"
144 " localreserved:<unix domain socket name>\n"
145 " localfilesystem:<unix domain socket name>\n"
146 " adb reverse --norebind <remote> <local>\n"
147 " - same as 'adb reverse <remote> <local>' but fails\n"
148 " if <remote> is already reversed.\n"
149 " adb reverse --remove <remote>\n"
150 " - remove a specific reversed socket connection\n"
151 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800152 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700153 " adb install [-lrtsd] <file>\n"
154 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700155 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700156 " (-l: forward lock application)\n"
157 " (-r: replace existing application)\n"
158 " (-t: allow test packages)\n"
159 " (-s: install application on sdcard)\n"
160 " (-d: allow version code downgrade)\n"
161 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800162 " adb uninstall [-k] <package> - remove this app package from the device\n"
163 " ('-k' means keep the data and cache directories)\n"
164 " adb bugreport - return all information from the device\n"
165 " that should be included in a bug report.\n"
166 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800167 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700168 " - write an archive of the device's data to <file>.\n"
169 " If no -f option is supplied then the data is written\n"
170 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700171 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700172 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800173 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
174 " (aka .obb) files associated with each application; the default\n"
175 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700176 " (-shared|-noshared enable/disable backup of the device's\n"
177 " shared storage / SD card contents; the default is noshared.)\n"
178 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700179 " (-system|-nosystem toggles whether -all automatically includes\n"
180 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700181 " (<packages...> is the list of applications to be backed up. If\n"
182 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700183 " list is optional. Applications explicitly given on the\n"
184 " command line will be included even if -nosystem would\n"
185 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700186 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700187 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700188 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800189 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
190 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800191 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
192 " and the public key is stored in <file>.pub. Any existing files\n"
193 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800194 " adb help - show this help message\n"
195 " adb version - show version num\n"
196 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800197 "scripting:\n"
198 " adb wait-for-device - block until device is online\n"
199 " adb start-server - ensure that there is a server running\n"
200 " adb kill-server - kill the server if it is running\n"
201 " adb get-state - prints: offline | bootloader | device\n"
202 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700203 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800204 " adb status-window - continuously print device status for a specified device\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000205 " adb remount - remounts the /system, /vendor (if present) and /oem (if present) partitions on the device read-write\n"
Tao Bao175b7bb2015-03-29 11:22:34 -0700206 " adb reboot [bootloader|recovery]\n"
207 " - reboots the device, optionally into the bootloader or recovery program.\n"
208 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
209 " adb reboot sideload-auto-reboot\n"
210 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Romain Guy311add42009-12-14 14:42:17 -0800211 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700212 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500213 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800214 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000215 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800216 "networking:\n"
217 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500218 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800219 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
220 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
221 "\n"
222 "adb sync notes: adb sync [ <directory> ]\n"
223 " <localdir> can be interpreted in several ways:\n"
224 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000225 " - If <directory> is not specified, /system, /vendor (if present), /oem (if present) and /data partitions will be updated.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800226 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000227 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800228 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000229 "\n"
230 "environmental variables:\n"
231 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
232 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
233 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
234 " 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 -0800235 );
236}
237
Elliott Hughes58305772015-04-17 13:57:15 -0700238static int usage() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800239 help();
240 return 1;
241}
242
Yabin Cuid325e862014-11-17 14:48:25 -0800243#if defined(_WIN32)
244
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700245// Implemented in sysdeps_win32.cpp.
Spencer Low50184062015-03-01 15:06:21 -0800246void stdin_raw_init(int fd);
247void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800248
249#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100250static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800251
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100252static void stdin_raw_init(int fd) {
253 if (tcgetattr(fd, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800254
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100255 termios tio;
256 if (tcgetattr(fd, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800257
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100258 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800259
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100260 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800261 tio.c_cc[VTIME] = 0;
262 tio.c_cc[VMIN] = 1;
263
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100264 tcsetattr(fd, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800265}
266
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100267static void stdin_raw_restore(int fd) {
268 tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800269}
270#endif
271
272static void read_and_dump(int fd)
273{
274 char buf[4096];
275 int len;
276
277 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700278 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800279 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700280 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800281 if(len == 0) {
282 break;
283 }
284
285 if(len < 0) {
286 if(errno == EINTR) continue;
287 break;
288 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400289 fwrite(buf, 1, len, stdout);
290 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800291 }
292}
293
Jeff Sharkey960df972014-06-09 17:30:57 -0700294static void read_status_line(int fd, char* buf, size_t count)
295{
296 count--;
297 while (count > 0) {
298 int len = adb_read(fd, buf, count);
299 if (len == 0) {
300 break;
301 } else if (len < 0) {
302 if (errno == EINTR) continue;
303 break;
304 }
305
306 buf += len;
307 count -= len;
308 }
309 *buf = '\0';
310}
311
Christopher Tated2f54152011-04-21 12:53:28 -0700312static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700313 const size_t BUFSIZE = 32 * 1024;
314 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700315 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700316 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700317
318 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800319
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700320 if (inFd == STDIN_FILENO) {
321 stdin_raw_init(STDIN_FILENO);
322 }
Yabin Cuid325e862014-11-17 14:48:25 -0800323
Elliott Hughesa7090b92015-04-17 17:03:59 -0700324 while (true) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700325 if (inFd == STDIN_FILENO) {
326 len = unix_read(inFd, buf, BUFSIZE);
327 } else {
328 len = adb_read(inFd, buf, BUFSIZE);
329 }
Christopher Tated2f54152011-04-21 12:53:28 -0700330 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700331 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700332 break;
333 }
334 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700335 if (errno == EINTR) {
336 D("copy_to_file() : EINTR, retrying\n");
337 continue;
338 }
Christopher Tated2f54152011-04-21 12:53:28 -0700339 D("copy_to_file() : error %d\n", errno);
340 break;
341 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700342 if (outFd == STDOUT_FILENO) {
343 fwrite(buf, 1, len, stdout);
344 fflush(stdout);
345 } else {
346 adb_write(outFd, buf, len);
347 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700348 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700349 }
Yabin Cuid325e862014-11-17 14:48:25 -0800350
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700351 if (inFd == STDIN_FILENO) {
352 stdin_raw_restore(STDIN_FILENO);
353 }
Yabin Cuid325e862014-11-17 14:48:25 -0800354
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700355 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700356 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700357}
358
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800359static void *stdin_read_thread(void *x)
360{
361 int fd, fdi;
362 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800363 int r, n;
364 int state = 0;
365
366 int *fds = (int*) x;
367 fd = fds[0];
368 fdi = fds[1];
369 free(fds);
370
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800371 for(;;) {
372 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700373 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800374 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700375 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800376 if(r == 0) break;
377 if(r < 0) {
378 if(errno == EINTR) continue;
379 break;
380 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400381 for(n = 0; n < r; n++){
382 switch(buf[n]) {
383 case '\n':
384 state = 1;
385 break;
386 case '\r':
387 state = 1;
388 break;
389 case '~':
390 if(state == 1) state++;
391 break;
392 case '.':
393 if(state == 2) {
394 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400395 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400396 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800397 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400398 default:
399 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800400 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800401 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800402 r = adb_write(fd, buf, r);
403 if(r <= 0) {
404 break;
405 }
406 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800407 return 0;
408}
409
Elliott Hughes58305772015-04-17 13:57:15 -0700410static int interactive_shell() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800411 adb_thread_t thr;
412 int fdi, fd;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800413
414 fd = adb_connect("shell:");
415 if(fd < 0) {
416 fprintf(stderr,"error: %s\n", adb_error());
417 return 1;
418 }
419 fdi = 0; //dup(0);
420
Dan Albertbac34742015-02-25 17:51:28 -0800421 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800422 fds[0] = fd;
423 fds[1] = fdi;
424
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800425 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800426 adb_thread_create(&thr, stdin_read_thread, fds);
427 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800428 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800429 return 0;
430}
431
432
433static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
434{
435 if (serial) {
436 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
437 } else {
438 const char* prefix = "host";
439 if (ttype == kTransportUsb)
440 prefix = "host-usb";
441 else if (ttype == kTransportLocal)
442 prefix = "host-local";
443
444 snprintf(buffer, buflen, "%s:%s", prefix, command);
445 }
446}
447
Elliott Hughes58305772015-04-17 13:57:15 -0700448static int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
449 unsigned progress)
Doug Zongker447f0612012-01-09 14:54:53 -0800450{
451 char buf[4096];
452 unsigned total;
453 int fd;
Doug Zongker447f0612012-01-09 14:54:53 -0800454
455 sprintf(buf,"%s:%d", service, sz);
456 fd = adb_connect(buf);
457 if(fd < 0) {
458 fprintf(stderr,"error: %s\n", adb_error());
459 return -1;
460 }
461
462 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800463 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800464
465 total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800466 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800467
468 if(progress) {
469 char *x = strrchr(service, ':');
470 if(x) service = x + 1;
471 }
472
473 while(sz > 0) {
474 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800475 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800476 adb_status(fd);
477 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
478 return -1;
479 }
480 sz -= xfer;
481 ptr += xfer;
482 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100483 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800484 fflush(stdout);
485 }
486 }
487 if(progress) {
488 printf("\n");
489 }
490
Dan Albertcc731cc2015-02-24 21:26:58 -0800491 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800492 fprintf(stderr,"* error reading response *\n");
493 adb_close(fd);
494 return -1;
495 }
496 if(memcmp(buf, "OKAY", 4)) {
497 buf[4] = 0;
498 fprintf(stderr,"* error response '%s' *\n", buf);
499 adb_close(fd);
500 return -1;
501 }
502
503 adb_close(fd);
504 return 0;
505}
506
Doug Zongker71fe5842014-06-26 15:35:36 -0700507#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
508
509/*
510 * The sideload-host protocol serves the data in a file (given on the
511 * command line) to the client, using a simple protocol:
512 *
513 * - The connect message includes the total number of bytes in the
514 * file and a block size chosen by us.
515 *
516 * - The other side sends the desired block number as eight decimal
517 * digits (eg "00000023" for block 23). Blocks are numbered from
518 * zero.
519 *
520 * - We send back the data of the requested block. The last block is
521 * likely to be partial; when the last block is requested we only
522 * send the part of the block that exists, it's not padded up to the
523 * block size.
524 *
525 * - When the other side sends "DONEDONE" instead of a block number,
526 * we hang up.
527 */
Elliott Hughes58305772015-04-17 13:57:15 -0700528static int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700529 unsigned sz;
530 size_t xfer = 0;
531 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800532 int last_percent = -1;
533 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700534
535 printf("loading: '%s'", fn);
536 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800537 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700538 if (data == 0) {
539 printf("\n");
540 fprintf(stderr, "* cannot read '%s' *\n", fn);
541 return -1;
542 }
543
544 char buf[100];
545 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
546 int fd = adb_connect(buf);
547 if (fd < 0) {
548 // Try falling back to the older sideload method. Maybe this
549 // is an older device that doesn't support sideload-host.
550 printf("\n");
551 status = adb_download_buffer("sideload", fn, data, sz, 1);
552 goto done;
553 }
554
Spencer Lowf055c192015-01-25 14:40:16 -0800555 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700556
Elliott Hughesa7090b92015-04-17 17:03:59 -0700557 while (true) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800558 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700559 fprintf(stderr, "* failed to read command: %s\n", adb_error());
560 status = -1;
561 goto done;
562 }
563
564 if (strncmp("DONEDONE", buf, 8) == 0) {
565 status = 0;
566 break;
567 }
568
569 buf[8] = '\0';
570 int block = strtol(buf, NULL, 10);
571
572 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
573 if (offset >= sz) {
574 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
575 status = -1;
576 goto done;
577 }
578 uint8_t* start = data + offset;
579 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
580 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
581 if (offset_end > sz) {
582 to_write = sz - offset;
583 }
584
Dan Albertcc731cc2015-02-24 21:26:58 -0800585 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700586 adb_status(fd);
587 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
588 status = -1;
589 goto done;
590 }
591 xfer += to_write;
592
593 // For normal OTA packages, we expect to transfer every byte
594 // twice, plus a bit of overhead (one read during
595 // verification, one read of each byte for installation, plus
596 // extra access to things like the zip central directory).
597 // This estimate of the completion becomes 100% when we've
598 // transferred ~2.13 (=100/47) times the package size.
599 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
600 if (percent != last_percent) {
601 printf("\rserving: '%s' (~%d%%) ", fn, percent);
602 fflush(stdout);
603 last_percent = percent;
604 }
605 }
606
Colin Cross6d6a8982014-07-07 14:12:41 -0700607 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700608
609 done:
610 if (fd >= 0) adb_close(fd);
611 free(data);
612 return status;
613}
614
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800615static void status_window(transport_type ttype, const char* serial)
616{
617 char command[4096];
618 char *state = 0;
619 char *laststate = 0;
620
621 /* silence stderr */
622#ifdef _WIN32
623 /* XXX: TODO */
624#else
625 int fd;
626 fd = unix_open("/dev/null", O_WRONLY);
627 dup2(fd, 2);
628 adb_close(fd);
629#endif
630
631 format_host_command(command, sizeof command, "get-state", ttype, serial);
632
633 for(;;) {
634 adb_sleep_ms(250);
635
636 if(state) {
637 free(state);
638 state = 0;
639 }
640
641 state = adb_query(command);
642
643 if(state) {
644 if(laststate && !strcmp(state,laststate)){
645 continue;
646 } else {
647 if(laststate) free(laststate);
648 laststate = strdup(state);
649 }
650 }
651
652 printf("%c[2J%c[2H", 27, 27);
653 printf("Android Debug Bridge\n");
654 printf("State: %s\n", state ? state : "offline");
655 fflush(stdout);
656 }
657}
658
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800659/**
660 * Run ppp in "notty" mode against a resource listed as the first parameter
661 * eg:
662 *
663 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
664 *
665 */
Elliott Hughes58305772015-04-17 13:57:15 -0700666static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800667#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800668 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
669 return -1;
670#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800671 pid_t pid;
672 int fd;
673
674 if (argc < 2) {
675 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
676 argv[0]);
677
678 return 1;
679 }
680
Dan Albertbac34742015-02-25 17:51:28 -0800681 const char* adb_service_name = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800682 fd = adb_connect(adb_service_name);
683
684 if(fd < 0) {
685 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
686 adb_service_name, adb_error());
687 return 1;
688 }
689
690 pid = fork();
691
692 if (pid < 0) {
693 perror("from fork()");
694 return 1;
695 } else if (pid == 0) {
696 int err;
697 int i;
698 const char **ppp_args;
699
700 // copy args
701 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
702 ppp_args[0] = "pppd";
703 for (i = 2 ; i < argc ; i++) {
704 //argv[2] and beyond become ppp_args[1] and beyond
705 ppp_args[i - 1] = argv[i];
706 }
707 ppp_args[i-1] = NULL;
708
709 // child side
710
711 dup2(fd, STDIN_FILENO);
712 dup2(fd, STDOUT_FILENO);
713 adb_close(STDERR_FILENO);
714 adb_close(fd);
715
716 err = execvp("pppd", (char * const *)ppp_args);
717
718 if (err < 0) {
719 perror("execing pppd");
720 }
721 exit(-1);
722 } else {
723 // parent side
724
725 adb_close(fd);
726 return 0;
727 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800728#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800729}
730
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700731static int send_shell_command(transport_type transport, const char* serial,
732 const std::string& command) {
733 int fd;
734 while (true) {
735 fd = adb_connect(command.c_str());
736 if (fd >= 0)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800737 break;
738 fprintf(stderr,"- waiting for device -\n");
739 adb_sleep_ms(1000);
740 do_cmd(transport, serial, "wait-for-device", 0);
741 }
742
743 read_and_dump(fd);
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700744 int rc = adb_close(fd);
745 if (rc) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800746 perror("close");
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700747 }
748 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800749}
750
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700751static int logcat(transport_type transport, const char* serial, int argc, const char** argv) {
752 char* log_tags = getenv("ANDROID_LOG_TAGS");
753 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800754
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700755 std::string cmd = "shell:export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800756
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700757 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700758 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -0800759 }
760
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700761 --argc;
762 ++argv;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700763 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700764 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800765 }
766
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700767 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800768 return 0;
769}
770
Mark Salyzyn60299df2014-04-30 09:10:31 -0700771static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800772{
773 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700774 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800775
776 for(;;) {
777 x = adb_dirstart(x);
778 if(x == 0) return 0;
779 *x = 0;
780 ret = adb_mkdir(path, 0775);
781 *x = OS_PATH_SEPARATOR;
782 if((ret < 0) && (errno != EEXIST)) {
783 return ret;
784 }
785 x++;
786 }
787 return 0;
788}
789
Dan Albertbac34742015-02-25 17:51:28 -0800790static int backup(int argc, const char** argv) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700791 const char* filename = "./backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -0700792
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700793 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700794 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700795 if (!strcmp("-f", argv[i])) {
796 if (i == argc-1) {
797 fprintf(stderr, "adb: -f passed with no filename\n");
798 return usage();
799 }
800 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700801 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700802 argv[i++] = argv[j++];
803 }
804 argc -= 2;
805 argv[argc] = NULL;
806 }
Christopher Tated2f54152011-04-21 12:53:28 -0700807 }
808
Christopher Tatebb86bc52011-08-22 17:12:08 -0700809 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
810 if (argc < 2) return usage();
811
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800812 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700813 mkdirs(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700814 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700815 if (outFd < 0) {
816 fprintf(stderr, "adb: unable to open file %s\n", filename);
817 return -1;
818 }
819
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700820 std::string cmd = "backup:";
821 --argc;
822 ++argv;
823 while (argc-- > 0) {
824 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -0700825 }
826
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700827 D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
828 int fd = adb_connect(cmd.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -0700829 if (fd < 0) {
830 fprintf(stderr, "adb: unable to connect for backup\n");
831 adb_close(outFd);
832 return -1;
833 }
834
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800835 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700836 copy_to_file(fd, outFd);
837
838 adb_close(fd);
839 adb_close(outFd);
840 return 0;
841}
842
Dan Albertbac34742015-02-25 17:51:28 -0800843static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700844 const char* filename;
845 int fd, tarFd;
846
847 if (argc != 2) return usage();
848
849 filename = argv[1];
850 tarFd = adb_open(filename, O_RDONLY);
851 if (tarFd < 0) {
852 fprintf(stderr, "adb: unable to open file %s\n", filename);
853 return -1;
854 }
855
856 fd = adb_connect("restore:");
857 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700858 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700859 adb_close(tarFd);
860 return -1;
861 }
862
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800863 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700864 copy_to_file(tarFd, fd);
865
866 adb_close(fd);
867 adb_close(tarFd);
868 return 0;
869}
870
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800871/* <hint> may be:
872 * - A simple product name
873 * e.g., "sooner"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800874 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
875 * e.g., "out/target/product/sooner"
876 * - An absolute path to the PRODUCT_OUT dir
877 * e.g., "/src/device/out/target/product/sooner"
878 *
879 * Given <hint>, try to construct an absolute path to the
880 * ANDROID_PRODUCT_OUT dir.
881 */
Elliott Hughes58305772015-04-17 13:57:15 -0700882static std::string find_product_out_path(const char* hint) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800883 if (hint == NULL || hint[0] == '\0') {
Elliott Hughes58305772015-04-17 13:57:15 -0700884 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800885 }
886
Elliott Hughes58305772015-04-17 13:57:15 -0700887 // If it's already absolute, don't bother doing any work.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800888 if (adb_is_absolute_host_path(hint)) {
Elliott Hughes58305772015-04-17 13:57:15 -0700889 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800890 }
891
Elliott Hughes58305772015-04-17 13:57:15 -0700892 // If there are any slashes in it, assume it's a relative path;
893 // make it absolute.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700894 if (adb_dirstart(hint) != nullptr) {
895 std::string cwd;
896 if (!getcwd(&cwd)) {
897 fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -0700898 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800899 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700900 return android::base::StringPrintf("%s%s%s", cwd.c_str(), OS_PATH_SEPARATOR_STR, hint);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800901 }
902
Elliott Hughes58305772015-04-17 13:57:15 -0700903 // It's a string without any slashes. Try to do something with it.
904 //
905 // Try to find the root of the build tree, and build a PRODUCT_OUT
906 // path from there.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700907 char* top = getenv("ANDROID_BUILD_TOP");
Elliott Hughes58305772015-04-17 13:57:15 -0700908 if (top == nullptr) {
Elliott Hughesa7090b92015-04-17 17:03:59 -0700909 fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
Elliott Hughes58305772015-04-17 13:57:15 -0700910 return "";
911 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700912
913 std::string path = top;
Elliott Hughes58305772015-04-17 13:57:15 -0700914 path += OS_PATH_SEPARATOR_STR;
915 path += "out";
916 path += OS_PATH_SEPARATOR_STR;
917 path += "target";
918 path += OS_PATH_SEPARATOR_STR;
919 path += "product";
920 path += OS_PATH_SEPARATOR_STR;
921 path += hint;
922 if (!directory_exists(path)) {
923 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
924 "\"%s\" doesn't exist\n", hint, path.c_str());
Elliott Hughesa7090b92015-04-17 17:03:59 -0700925 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800926 }
Elliott Hughes58305772015-04-17 13:57:15 -0700927 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800928}
929
Dan Albertbac34742015-02-25 17:51:28 -0800930static void parse_push_pull_args(const char **arg, int narg, char const **path1,
931 char const **path2, int *show_progress,
932 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -0700933 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700934 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -0700935
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700936 while (narg > 0) {
937 if (!strcmp(*arg, "-p")) {
938 *show_progress = 1;
939 } else if (!strcmp(*arg, "-a")) {
940 *copy_attrs = 1;
941 } else {
942 break;
943 }
Mark Lindner76f2a932014-03-11 17:55:59 -0700944 ++arg;
945 --narg;
946 }
947
948 if (narg > 0) {
949 *path1 = *arg;
950 ++arg;
951 --narg;
952 }
953
954 if (narg > 0) {
955 *path2 = *arg;
956 }
957}
958
Tao Bao175b7bb2015-03-29 11:22:34 -0700959static int adb_connect_command(const char* command) {
960 int fd = adb_connect(command);
961 if (fd != -1) {
962 read_and_dump(fd);
963 adb_close(fd);
964 return 0;
965 }
966 fprintf(stderr, "Error: %s\n", adb_error());
967 return 1;
968}
969
Dan Albertbac34742015-02-25 17:51:28 -0800970int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800971{
972 char buf[4096];
973 int no_daemon = 0;
974 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100975 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800976 int persist = 0;
977 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800978 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -0800979 const char* serial = NULL;
980 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800981
Elliott Hughes58305772015-04-17 13:57:15 -0700982 // If defined, this should be an absolute path to
983 // the directory containing all of the various system images
984 // for a particular product. If not defined, and the adb
985 // command requires this information, then the user must
986 // specify the path using "-p".
987 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
988 if (ANDROID_PRODUCT_OUT != nullptr) {
989 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800990 }
991 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
992
Nick Pellydb449262009-05-07 12:48:03 -0700993 serial = getenv("ANDROID_SERIAL");
994
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100995 /* Validate and assign the server port */
996 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
997 int server_port = DEFAULT_ADB_PORT;
998 if (server_port_str && strlen(server_port_str) > 0) {
999 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001000 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001001 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001002 "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 +01001003 server_port_str);
1004 return usage();
1005 }
1006 }
1007
1008 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001009 while (argc > 0) {
1010 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001011 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001012 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001013 no_daemon = 1;
1014 } else if (!strcmp(argv[0], "fork-server")) {
1015 /* this is a special flag used only when the ADB client launches the ADB Server */
1016 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001017 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001018 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001019 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001020 const char *product = NULL;
1021 if (argv[0][2] == '\0') {
1022 if (argc < 2) return usage();
1023 product = argv[1];
1024 argc--;
1025 argv++;
1026 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001027 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001028 }
1029 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -07001030 if (gProductOutPath.empty()) {
1031 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001032 return usage();
1033 }
1034 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1035 if (isdigit(argv[0][2])) {
1036 serial = argv[0] + 2;
1037 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001038 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001039 serial = argv[1];
1040 argc--;
1041 argv++;
1042 }
1043 } else if (!strcmp(argv[0],"-d")) {
1044 ttype = kTransportUsb;
1045 } else if (!strcmp(argv[0],"-e")) {
1046 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001047 } else if (!strcmp(argv[0],"-a")) {
1048 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001049 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001050 const char *hostname = NULL;
1051 if (argv[0][2] == '\0') {
1052 if (argc < 2) return usage();
1053 hostname = argv[1];
1054 argc--;
1055 argv++;
1056 } else {
1057 hostname = argv[0] + 2;
1058 }
1059 adb_set_tcp_name(hostname);
1060
Riley Andrews98f58e82014-12-05 17:37:24 -08001061 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001062 if (argv[0][2] == '\0') {
1063 if (argc < 2) return usage();
1064 server_port_str = argv[1];
1065 argc--;
1066 argv++;
1067 } else {
1068 server_port_str = argv[0] + 2;
1069 }
1070 if (strlen(server_port_str) > 0) {
1071 server_port = (int) strtol(server_port_str, NULL, 0);
1072 if (server_port <= 0 || server_port > 65535) {
1073 fprintf(stderr,
1074 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1075 server_port_str);
1076 return usage();
1077 }
1078 } else {
1079 fprintf(stderr,
1080 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1081 return usage();
1082 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001083 } else {
1084 /* out of recognized modifiers and flags */
1085 break;
1086 }
1087 argc--;
1088 argv++;
1089 }
1090
1091 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001092 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001093
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001094 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001095 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001096 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001097 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001098 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001099 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001100 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001101 fprintf(stderr,"* could not start server *\n");
1102 }
1103 return r;
1104 }
1105
Riley Andrews98f58e82014-12-05 17:37:24 -08001106 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001107 return usage();
1108 }
1109
Riley Andrewsc8514c82014-12-05 17:32:46 -08001110 /* handle wait-for-* prefix */
1111 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001112 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001113 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1114 if (ttype == kTransportUsb) {
1115 service = "wait-for-usb";
1116 } else if (ttype == kTransportLocal) {
1117 service = "wait-for-local";
1118 } else {
1119 service = "wait-for-any";
1120 }
1121 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001122
Riley Andrewsc8514c82014-12-05 17:32:46 -08001123 format_host_command(buf, sizeof buf, service, ttype, serial);
1124
1125 if (adb_command(buf)) {
1126 D("failure: %s *\n",adb_error());
1127 fprintf(stderr,"error: %s\n", adb_error());
1128 return 1;
1129 }
1130
1131 /* Allow a command to be run after wait-for-device,
1132 * e.g. 'adb wait-for-device shell'.
1133 */
1134 if (argc == 1) {
1135 return 0;
1136 }
1137
1138 /* Fall through */
1139 argc--;
1140 argv++;
1141 }
1142
1143 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001144 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001145 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001146 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001147 if (argc < 2)
1148 listopt = "";
1149 else if (argc == 2 && !strcmp(argv[1], "-l"))
1150 listopt = argv[1];
1151 else {
1152 fprintf(stderr, "Usage: adb devices [-l]\n");
1153 return 1;
1154 }
1155 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001156 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001157 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001158 printf("List of devices attached \n");
1159 printf("%s\n", tmp);
1160 return 0;
1161 } else {
1162 return 1;
1163 }
1164 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001165 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001166 char *tmp;
1167 if (argc != 2) {
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001168 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001169 return 1;
1170 }
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001171 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1172 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001173 if (tmp) {
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001174 printf("%s\n", tmp);
1175 return 0;
1176 } else {
1177 return 1;
1178 }
1179 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001180 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001181 char *tmp;
1182 if (argc > 2) {
1183 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1184 return 1;
1185 }
1186 if (argc == 2) {
1187 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1188 } else {
1189 snprintf(buf, sizeof buf, "host:disconnect:");
1190 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001191 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001192 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001193 printf("%s\n", tmp);
1194 return 0;
1195 } else {
1196 return 1;
1197 }
1198 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001199 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001200 return adb_send_emulator_command(argc, argv);
1201 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001202 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001203 char h = (argv[0][0] == 'h');
1204
1205 if (h) {
1206 printf("\x1b[41;33m");
1207 fflush(stdout);
1208 }
1209
Riley Andrews98f58e82014-12-05 17:37:24 -08001210 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001211 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001212 r = interactive_shell();
1213 if (h) {
1214 printf("\x1b[0m");
1215 fflush(stdout);
1216 }
1217 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001218 }
1219
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001220 std::string cmd = "shell:";
1221 cmd += argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001222 argc -= 2;
1223 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001224 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001225 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001226 }
1227
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001228 while (true) {
1229 D("interactive shell loop. cmd=%s\n", cmd.c_str());
1230 int fd = adb_connect(cmd.c_str());
1231 int r;
Riley Andrews98f58e82014-12-05 17:37:24 -08001232 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001233 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001234 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001235 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001236 adb_close(fd);
1237 r = 0;
1238 } else {
1239 fprintf(stderr,"error: %s\n", adb_error());
1240 r = -1;
1241 }
1242
Riley Andrews98f58e82014-12-05 17:37:24 -08001243 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001244 fprintf(stderr,"\n- waiting for device -\n");
1245 adb_sleep_ms(1000);
1246 do_cmd(ttype, serial, "wait-for-device", 0);
1247 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001248 if (h) {
1249 printf("\x1b[0m");
1250 fflush(stdout);
1251 }
JP Abgrall408fa572011-03-16 15:57:42 -07001252 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001253 return r;
1254 }
1255 }
1256 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001257 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001258 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001259
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001260 std::string cmd = "exec:";
1261 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001262 argc -= 2;
1263 argv += 2;
1264 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001265 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001266 }
1267
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001268 int fd = adb_connect(cmd.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001269 if (fd < 0) {
1270 fprintf(stderr, "error: %s\n", adb_error());
1271 return -1;
1272 }
1273
1274 if (exec_in) {
1275 copy_to_file(STDIN_FILENO, fd);
1276 } else {
1277 copy_to_file(fd, STDOUT_FILENO);
1278 }
1279
1280 adb_close(fd);
1281 return 0;
1282 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001283 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001284 int fd;
1285 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001286 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001287 fprintf(stderr,"* server not running *\n");
1288 return 1;
1289 }
1290 return 0;
1291 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001292 else if (!strcmp(argv[0], "sideload")) {
1293 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001294 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001295 return 1;
1296 } else {
1297 return 0;
1298 }
1299 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001300 else if (!strcmp(argv[0], "remount") ||
1301 !strcmp(argv[0], "reboot") ||
1302 !strcmp(argv[0], "reboot-bootloader") ||
1303 !strcmp(argv[0], "tcpip") ||
1304 !strcmp(argv[0], "usb") ||
1305 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001306 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001307 !strcmp(argv[0], "disable-verity") ||
1308 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001309 char command[100];
Tao Bao175b7bb2015-03-29 11:22:34 -07001310 if (!strcmp(argv[0], "reboot-bootloader")) {
Romain Guy311add42009-12-14 14:42:17 -08001311 snprintf(command, sizeof(command), "reboot:bootloader");
Tao Bao175b7bb2015-03-29 11:22:34 -07001312 } else if (argc > 1) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001313 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001314 } else {
Mike Lockwoodff196702009-08-24 15:58:40 -07001315 snprintf(command, sizeof(command), "%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001316 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001317 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001318 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001319 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001320 if (argc != 1) return usage();
1321 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001322 return 0;
1323 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001324 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001325 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001326 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001327 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001328 char remove = 0;
1329 char remove_all = 0;
1330 char list = 0;
1331 char no_rebind = 0;
1332
1333 // Parse options here.
1334 while (argc > 1 && argv[1][0] == '-') {
1335 if (!strcmp(argv[1], "--list"))
1336 list = 1;
1337 else if (!strcmp(argv[1], "--remove"))
1338 remove = 1;
1339 else if (!strcmp(argv[1], "--remove-all"))
1340 remove_all = 1;
1341 else if (!strcmp(argv[1], "--no-rebind"))
1342 no_rebind = 1;
1343 else {
1344 return usage();
1345 }
1346 argc--;
1347 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001348 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001349
1350 // Ensure we can only use one option at a time.
1351 if (list + remove + remove_all + no_rebind > 1) {
1352 return usage();
1353 }
1354
1355 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001356 if (reverse) {
1357 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001358 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001359 if (serial) {
1360 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1361 serial);
1362 } else if (ttype == kTransportUsb) {
1363 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1364 } else if (ttype == kTransportLocal) {
1365 snprintf(host_prefix, sizeof host_prefix, "host-local");
1366 } else {
1367 snprintf(host_prefix, sizeof host_prefix, "host");
1368 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001369 }
1370
1371 // Implement forward --list
1372 if (list) {
1373 if (argc != 1)
1374 return usage();
1375 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1376 char* forwards = adb_query(buf);
1377 if (forwards == NULL) {
1378 fprintf(stderr, "error: %s\n", adb_error());
1379 return 1;
1380 }
1381 printf("%s", forwards);
1382 free(forwards);
1383 return 0;
1384 }
1385
1386 // Implement forward --remove-all
1387 else if (remove_all) {
1388 if (argc != 1)
1389 return usage();
1390 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1391 }
1392
1393 // Implement forward --remove <local>
1394 else if (remove) {
1395 if (argc != 2)
1396 return usage();
1397 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1398 }
1399 // Or implement one of:
1400 // forward <local> <remote>
1401 // forward --no-rebind <local> <remote>
1402 else
1403 {
1404 if (argc != 3)
1405 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001406 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001407 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1408 }
1409
Riley Andrews98f58e82014-12-05 17:37:24 -08001410 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001411 fprintf(stderr,"error: %s\n", adb_error());
1412 return 1;
1413 }
1414 return 0;
1415 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001416 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001417 else if (!strcmp(argv[0], "ls")) {
1418 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001419 return do_sync_ls(argv[1]);
1420 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001421 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001422 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001423 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001424 const char* lpath = NULL, *rpath = NULL;
1425
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001426 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001427
1428 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001429 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001430 }
1431
1432 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001433 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001434 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001435 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001436 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001437 const char* rpath = NULL, *lpath = ".";
1438
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001439 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001440
1441 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001442 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001443 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001444
1445 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001446 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001447 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001448 if (argc < 2) return usage();
1449 return install_app(ttype, serial, argc, argv);
1450 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001451 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001452 if (argc < 2) return usage();
1453 return install_multiple_app(ttype, serial, argc, argv);
1454 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001455 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001456 if (argc < 2) return usage();
1457 return uninstall_app(ttype, serial, argc, argv);
1458 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001459 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001460 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001461 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001462 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001463 // No local path was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001464 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001465 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001466 list_only = true;
Anthony Newnam705c9442010-02-22 08:36:49 -06001467 if (argc == 3) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001468 src = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001469 } else {
Elliott Hughesd236d072015-04-21 10:17:07 -07001470 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001471 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001472 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001473 // A local path or "android"/"data" arg was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001474 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001475 } else {
1476 return usage();
1477 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001478
Elliott Hughesd236d072015-04-21 10:17:07 -07001479 if (src != "" &&
1480 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes58305772015-04-17 13:57:15 -07001481 return usage();
1482 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001483
Elliott Hughes58305772015-04-17 13:57:15 -07001484 std::string system_src_path = product_file("system");
1485 std::string data_src_path = product_file("data");
1486 std::string vendor_src_path = product_file("vendor");
1487 std::string oem_src_path = product_file("oem");
Elliott Hughes58305772015-04-17 13:57:15 -07001488
1489 int rc = 0;
Elliott Hughesd236d072015-04-21 10:17:07 -07001490 if (rc == 0 && (src.empty() || src == "system")) {
1491 rc = do_sync_sync(system_src_path, "/system", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001492 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001493 if (rc == 0 && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
1494 rc = do_sync_sync(vendor_src_path, "/vendor", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001495 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001496 if (rc == 0 && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
1497 rc = do_sync_sync(oem_src_path, "/oem", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001498 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001499 if (rc == 0 && (src.empty() || src == "data")) {
1500 rc = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001501 }
1502 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001503 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001504 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001505 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001506 !strcmp(argv[0],"get-serialno") ||
1507 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001508 {
1509 char *tmp;
1510
1511 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1512 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001513 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001514 printf("%s\n", tmp);
1515 return 0;
1516 } else {
1517 return 1;
1518 }
1519 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001520 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001521 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001522 status_window(ttype, serial);
1523 return 0;
1524 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001525 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001526 return logcat(ttype, serial, argc, argv);
1527 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001528 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001529 return ppp(argc, argv);
1530 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001531 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001532 return adb_connect("host:start-server");
1533 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001534 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001535 return backup(argc, argv);
1536 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001537 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001538 return restore(argc, argv);
1539 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001540 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001541 if (argc < 2) return usage();
1542 return adb_auth_keygen(argv[1]);
1543 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001544 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001545 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001546 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001547 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001548 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001549 help();
1550 return 0;
1551 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001552 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001553 version(stdout);
1554 return 0;
1555 }
1556
1557 usage();
1558 return 1;
1559}
1560
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001561#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001562static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001563{
Dan Albertbac34742015-02-25 17:51:28 -08001564 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001565 int argc;
1566 va_list ap;
1567
1568 va_start(ap, cmd);
1569 argc = 0;
1570
1571 if (serial) {
1572 argv[argc++] = "-s";
1573 argv[argc++] = serial;
1574 } else if (ttype == kTransportUsb) {
1575 argv[argc++] = "-d";
1576 } else if (ttype == kTransportLocal) {
1577 argv[argc++] = "-e";
1578 }
1579
1580 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001581 while(argc < MAX_ARGV_LENGTH &&
1582 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1583 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001584 va_end(ap);
1585
1586#if 0
1587 int n;
1588 fprintf(stderr,"argc = %d\n",argc);
1589 for(n = 0; n < argc; n++) {
1590 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1591 }
1592#endif
1593
1594 return adb_commandline(argc, argv);
1595}
1596
Dan Albertbac34742015-02-25 17:51:28 -08001597static int pm_command(transport_type transport, const char* serial,
1598 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001599{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001600 std::string cmd = "shell:pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001601
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001602 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001603 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001604 }
1605
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001606 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001607 return 0;
1608}
1609
Elliott Hughes58305772015-04-17 13:57:15 -07001610static int uninstall_app(transport_type transport, const char* serial, int argc,
1611 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001612{
1613 /* if the user choose the -k option, we refuse to do it until devices are
1614 out with the option to uninstall the remaining data somehow (adb/ui) */
1615 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1616 {
1617 printf(
1618 "The -k option uninstalls the application while retaining the data/cache.\n"
1619 "At the moment, there is no way to remove the remaining data.\n"
1620 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1621 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1622 return -1;
1623 }
1624
1625 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1626 return pm_command(transport, serial, argc, argv);
1627}
1628
Dan Albertbac34742015-02-25 17:51:28 -08001629static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001630{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001631 std::string cmd = "shell:rm -f " + escape_arg(filename);
1632 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001633 return 0;
1634}
1635
Kenny Root597ea5b2011-08-05 11:19:45 -07001636static const char* get_basename(const char* filename)
1637{
1638 const char* basename = adb_dirstop(filename);
1639 if (basename) {
1640 basename++;
1641 return basename;
1642 } else {
1643 return filename;
1644 }
1645}
1646
Elliott Hughes58305772015-04-17 13:57:15 -07001647static int install_app(transport_type transport, const char* serial, int argc,
1648 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001649{
1650 static const char *const DATA_DEST = "/data/local/tmp/%s";
1651 static const char *const SD_DEST = "/sdcard/tmp/%s";
1652 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001653 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001654 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001655
1656 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001657 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001658 where = SD_DEST;
1659 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001660 }
1661
Jeff Sharkey960df972014-06-09 17:30:57 -07001662 // Find last APK argument.
1663 // All other arguments passed through verbatim.
1664 int last_apk = -1;
1665 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001666 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001667 char* dot = strrchr(file, '.');
1668 if (dot && !strcasecmp(dot, ".apk")) {
1669 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1670 fprintf(stderr, "Invalid APK file: %s\n", file);
1671 return -1;
1672 }
1673
1674 last_apk = i;
1675 break;
1676 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001677 }
1678
Jeff Sharkey960df972014-06-09 17:30:57 -07001679 if (last_apk == -1) {
1680 fprintf(stderr, "Missing APK file\n");
1681 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001682 }
1683
Dan Albertbac34742015-02-25 17:51:28 -08001684 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001685 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001686 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001687 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001688 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001689 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001690 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001691 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001692 }
1693
1694 pm_command(transport, serial, argc, argv);
1695
Kenny Root60733e92012-03-26 16:14:02 -07001696cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001697 delete_file(transport, serial, apk_dest);
1698 return err;
1699}
1700
Elliott Hughes58305772015-04-17 13:57:15 -07001701static int install_multiple_app(transport_type transport, const char* serial, int argc,
1702 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001703{
Jeff Sharkey960df972014-06-09 17:30:57 -07001704 int i;
1705 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001706 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001707
1708 // Find all APK arguments starting at end.
1709 // All other arguments passed through verbatim.
1710 int first_apk = -1;
1711 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001712 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001713 char* dot = strrchr(file, '.');
1714 if (dot && !strcasecmp(dot, ".apk")) {
1715 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1716 fprintf(stderr, "Invalid APK file: %s\n", file);
1717 return -1;
1718 }
1719
1720 total_size += sb.st_size;
1721 first_apk = i;
1722 } else {
1723 break;
1724 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001725 }
1726
Jeff Sharkey960df972014-06-09 17:30:57 -07001727 if (first_apk == -1) {
1728 fprintf(stderr, "Missing APK file\n");
1729 return 1;
1730 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001731
Elliott Hughes53daee62015-04-19 13:17:01 -07001732#if defined(_WIN32) // Remove when we're using clang for Win32.
1733 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %u", (unsigned) total_size);
1734#else
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001735 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Elliott Hughes53daee62015-04-19 13:17:01 -07001736#endif
Jeff Sharkey960df972014-06-09 17:30:57 -07001737 for (i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001738 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001739 }
1740
1741 // Create install session
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001742 int fd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001743 if (fd < 0) {
1744 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1745 return -1;
1746 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001747 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001748 read_status_line(fd, buf, sizeof(buf));
1749 adb_close(fd);
1750
1751 int session_id = -1;
1752 if (!strncmp("Success", buf, 7)) {
1753 char* start = strrchr(buf, '[');
1754 char* end = strrchr(buf, ']');
1755 if (start && end) {
1756 *end = '\0';
1757 session_id = strtol(start + 1, NULL, 10);
1758 }
1759 }
1760 if (session_id < 0) {
1761 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001762 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001763 return -1;
1764 }
1765
1766 // Valid session, now stream the APKs
1767 int success = 1;
1768 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001769 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001770 if (stat(file, &sb) == -1) {
1771 fprintf(stderr, "Failed to stat %s\n", file);
1772 success = 0;
1773 goto finalize_session;
1774 }
1775
Elliott Hughes53daee62015-04-19 13:17:01 -07001776#if defined(_WIN32) // Remove when we're using clang for Win32.
1777 std::string cmd = android::base::StringPrintf(
1778 "exec:pm install-write -S %u %d %d_%s -",
1779 (unsigned) sb.st_size, session_id, i, get_basename(file));
1780#else
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001781 std::string cmd = android::base::StringPrintf(
1782 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
1783 static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
Elliott Hughes53daee62015-04-19 13:17:01 -07001784#endif
Jeff Sharkey960df972014-06-09 17:30:57 -07001785
1786 int localFd = adb_open(file, O_RDONLY);
1787 if (localFd < 0) {
1788 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
1789 success = 0;
1790 goto finalize_session;
1791 }
1792
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001793 int remoteFd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001794 if (remoteFd < 0) {
1795 fprintf(stderr, "Connect error for write: %s\n", adb_error());
1796 adb_close(localFd);
1797 success = 0;
1798 goto finalize_session;
1799 }
1800
1801 copy_to_file(localFd, remoteFd);
1802 read_status_line(remoteFd, buf, sizeof(buf));
1803
1804 adb_close(localFd);
1805 adb_close(remoteFd);
1806
1807 if (strncmp("Success", buf, 7)) {
1808 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001809 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001810 success = 0;
1811 goto finalize_session;
1812 }
1813 }
1814
1815finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001816 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07001817 if (success) {
1818 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
1819 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001820 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07001821 }
1822
1823 fd = adb_connect(buf);
1824 if (fd < 0) {
1825 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
1826 return -1;
1827 }
1828 read_status_line(fd, buf, sizeof(buf));
1829 adb_close(fd);
1830
1831 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001832 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001833 return 0;
1834 } else {
1835 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001836 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001837 return -1;
1838 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001839}