blob: e76c3411934716098c1ae9c27f07d67d9ac1e026 [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 Lockwoodcbbe79a2010-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 Lockwoodcbbe79a2010-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 Hughes15551472015-04-21 17:58:55 -0700767 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800768}
769
Mark Salyzyn60299df2014-04-30 09:10:31 -0700770static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800771{
772 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700773 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800774
775 for(;;) {
776 x = adb_dirstart(x);
777 if(x == 0) return 0;
778 *x = 0;
779 ret = adb_mkdir(path, 0775);
780 *x = OS_PATH_SEPARATOR;
781 if((ret < 0) && (errno != EEXIST)) {
782 return ret;
783 }
784 x++;
785 }
786 return 0;
787}
788
Dan Albertbac34742015-02-25 17:51:28 -0800789static int backup(int argc, const char** argv) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700790 const char* filename = "./backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -0700791
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700792 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700793 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700794 if (!strcmp("-f", argv[i])) {
795 if (i == argc-1) {
796 fprintf(stderr, "adb: -f passed with no filename\n");
797 return usage();
798 }
799 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700800 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700801 argv[i++] = argv[j++];
802 }
803 argc -= 2;
804 argv[argc] = NULL;
805 }
Christopher Tated2f54152011-04-21 12:53:28 -0700806 }
807
Christopher Tatebb86bc52011-08-22 17:12:08 -0700808 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
809 if (argc < 2) return usage();
810
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800811 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700812 mkdirs(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700813 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700814 if (outFd < 0) {
815 fprintf(stderr, "adb: unable to open file %s\n", filename);
816 return -1;
817 }
818
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700819 std::string cmd = "backup:";
820 --argc;
821 ++argv;
822 while (argc-- > 0) {
823 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -0700824 }
825
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700826 D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
827 int fd = adb_connect(cmd.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -0700828 if (fd < 0) {
829 fprintf(stderr, "adb: unable to connect for backup\n");
830 adb_close(outFd);
831 return -1;
832 }
833
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800834 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700835 copy_to_file(fd, outFd);
836
837 adb_close(fd);
838 adb_close(outFd);
839 return 0;
840}
841
Dan Albertbac34742015-02-25 17:51:28 -0800842static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700843 const char* filename;
844 int fd, tarFd;
845
846 if (argc != 2) return usage();
847
848 filename = argv[1];
849 tarFd = adb_open(filename, O_RDONLY);
850 if (tarFd < 0) {
851 fprintf(stderr, "adb: unable to open file %s\n", filename);
852 return -1;
853 }
854
855 fd = adb_connect("restore:");
856 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700857 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700858 adb_close(tarFd);
859 return -1;
860 }
861
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800862 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700863 copy_to_file(tarFd, fd);
864
865 adb_close(fd);
866 adb_close(tarFd);
867 return 0;
868}
869
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800870/* <hint> may be:
871 * - A simple product name
872 * e.g., "sooner"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800873 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
874 * e.g., "out/target/product/sooner"
875 * - An absolute path to the PRODUCT_OUT dir
876 * e.g., "/src/device/out/target/product/sooner"
877 *
878 * Given <hint>, try to construct an absolute path to the
879 * ANDROID_PRODUCT_OUT dir.
880 */
Elliott Hughes58305772015-04-17 13:57:15 -0700881static std::string find_product_out_path(const char* hint) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800882 if (hint == NULL || hint[0] == '\0') {
Elliott Hughes58305772015-04-17 13:57:15 -0700883 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800884 }
885
Elliott Hughes58305772015-04-17 13:57:15 -0700886 // If it's already absolute, don't bother doing any work.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800887 if (adb_is_absolute_host_path(hint)) {
Elliott Hughes58305772015-04-17 13:57:15 -0700888 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800889 }
890
Elliott Hughes58305772015-04-17 13:57:15 -0700891 // If there are any slashes in it, assume it's a relative path;
892 // make it absolute.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700893 if (adb_dirstart(hint) != nullptr) {
894 std::string cwd;
895 if (!getcwd(&cwd)) {
896 fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -0700897 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800898 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700899 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 -0800900 }
901
Elliott Hughes58305772015-04-17 13:57:15 -0700902 // 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.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700906 char* top = getenv("ANDROID_BUILD_TOP");
Elliott Hughes58305772015-04-17 13:57:15 -0700907 if (top == nullptr) {
Elliott Hughesa7090b92015-04-17 17:03:59 -0700908 fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
Elliott Hughes58305772015-04-17 13:57:15 -0700909 return "";
910 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700911
912 std::string path = top;
Elliott Hughes58305772015-04-17 13:57:15 -0700913 path += OS_PATH_SEPARATOR_STR;
914 path += "out";
915 path += OS_PATH_SEPARATOR_STR;
916 path += "target";
917 path += OS_PATH_SEPARATOR_STR;
918 path += "product";
919 path += OS_PATH_SEPARATOR_STR;
920 path += hint;
921 if (!directory_exists(path)) {
922 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
923 "\"%s\" doesn't exist\n", hint, path.c_str());
Elliott Hughesa7090b92015-04-17 17:03:59 -0700924 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800925 }
Elliott Hughes58305772015-04-17 13:57:15 -0700926 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800927}
928
Dan Albertbac34742015-02-25 17:51:28 -0800929static void parse_push_pull_args(const char **arg, int narg, char const **path1,
930 char const **path2, int *show_progress,
931 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -0700932 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700933 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -0700934
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700935 while (narg > 0) {
936 if (!strcmp(*arg, "-p")) {
937 *show_progress = 1;
938 } else if (!strcmp(*arg, "-a")) {
939 *copy_attrs = 1;
940 } else {
941 break;
942 }
Mark Lindner76f2a932014-03-11 17:55:59 -0700943 ++arg;
944 --narg;
945 }
946
947 if (narg > 0) {
948 *path1 = *arg;
949 ++arg;
950 --narg;
951 }
952
953 if (narg > 0) {
954 *path2 = *arg;
955 }
956}
957
Tao Bao175b7bb2015-03-29 11:22:34 -0700958static int adb_connect_command(const char* command) {
959 int fd = adb_connect(command);
960 if (fd != -1) {
961 read_and_dump(fd);
962 adb_close(fd);
963 return 0;
964 }
965 fprintf(stderr, "Error: %s\n", adb_error());
966 return 1;
967}
968
Dan Albertbac34742015-02-25 17:51:28 -0800969int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800970{
971 char buf[4096];
972 int no_daemon = 0;
973 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100974 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800975 int persist = 0;
976 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800977 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -0800978 const char* serial = NULL;
979 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800980
Elliott Hughes58305772015-04-17 13:57:15 -0700981 // If defined, this should be an absolute path to
982 // the directory containing all of the various system images
983 // for a particular product. If not defined, and the adb
984 // command requires this information, then the user must
985 // specify the path using "-p".
986 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
987 if (ANDROID_PRODUCT_OUT != nullptr) {
988 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800989 }
990 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
991
Nick Pellydb449262009-05-07 12:48:03 -0700992 serial = getenv("ANDROID_SERIAL");
993
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100994 /* Validate and assign the server port */
995 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
996 int server_port = DEFAULT_ADB_PORT;
997 if (server_port_str && strlen(server_port_str) > 0) {
998 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -0800999 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001000 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001001 "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 +01001002 server_port_str);
1003 return usage();
1004 }
1005 }
1006
1007 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001008 while (argc > 0) {
1009 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001010 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001011 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001012 no_daemon = 1;
1013 } else if (!strcmp(argv[0], "fork-server")) {
1014 /* this is a special flag used only when the ADB client launches the ADB Server */
1015 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001016 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001017 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001018 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001019 const char *product = NULL;
1020 if (argv[0][2] == '\0') {
1021 if (argc < 2) return usage();
1022 product = argv[1];
1023 argc--;
1024 argv++;
1025 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001026 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001027 }
1028 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -07001029 if (gProductOutPath.empty()) {
1030 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001031 return usage();
1032 }
1033 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1034 if (isdigit(argv[0][2])) {
1035 serial = argv[0] + 2;
1036 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001037 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001038 serial = argv[1];
1039 argc--;
1040 argv++;
1041 }
1042 } else if (!strcmp(argv[0],"-d")) {
1043 ttype = kTransportUsb;
1044 } else if (!strcmp(argv[0],"-e")) {
1045 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001046 } else if (!strcmp(argv[0],"-a")) {
1047 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001048 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001049 const char *hostname = NULL;
1050 if (argv[0][2] == '\0') {
1051 if (argc < 2) return usage();
1052 hostname = argv[1];
1053 argc--;
1054 argv++;
1055 } else {
1056 hostname = argv[0] + 2;
1057 }
1058 adb_set_tcp_name(hostname);
1059
Riley Andrews98f58e82014-12-05 17:37:24 -08001060 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001061 if (argv[0][2] == '\0') {
1062 if (argc < 2) return usage();
1063 server_port_str = argv[1];
1064 argc--;
1065 argv++;
1066 } else {
1067 server_port_str = argv[0] + 2;
1068 }
1069 if (strlen(server_port_str) > 0) {
1070 server_port = (int) strtol(server_port_str, NULL, 0);
1071 if (server_port <= 0 || server_port > 65535) {
1072 fprintf(stderr,
1073 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1074 server_port_str);
1075 return usage();
1076 }
1077 } else {
1078 fprintf(stderr,
1079 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1080 return usage();
1081 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001082 } else {
1083 /* out of recognized modifiers and flags */
1084 break;
1085 }
1086 argc--;
1087 argv++;
1088 }
1089
1090 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001091 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001092
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001093 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001094 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001095 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001096 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001097 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001098 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001099 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001100 fprintf(stderr,"* could not start server *\n");
1101 }
1102 return r;
1103 }
1104
Riley Andrews98f58e82014-12-05 17:37:24 -08001105 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001106 return usage();
1107 }
1108
Riley Andrewsc8514c82014-12-05 17:32:46 -08001109 /* handle wait-for-* prefix */
1110 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001111 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001112 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1113 if (ttype == kTransportUsb) {
1114 service = "wait-for-usb";
1115 } else if (ttype == kTransportLocal) {
1116 service = "wait-for-local";
1117 } else {
1118 service = "wait-for-any";
1119 }
1120 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001121
Riley Andrewsc8514c82014-12-05 17:32:46 -08001122 format_host_command(buf, sizeof buf, service, ttype, serial);
1123
1124 if (adb_command(buf)) {
1125 D("failure: %s *\n",adb_error());
1126 fprintf(stderr,"error: %s\n", adb_error());
1127 return 1;
1128 }
1129
1130 /* Allow a command to be run after wait-for-device,
1131 * e.g. 'adb wait-for-device shell'.
1132 */
1133 if (argc == 1) {
1134 return 0;
1135 }
1136
1137 /* Fall through */
1138 argc--;
1139 argv++;
1140 }
1141
1142 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001143 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001144 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001145 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001146 if (argc < 2)
1147 listopt = "";
1148 else if (argc == 2 && !strcmp(argv[1], "-l"))
1149 listopt = argv[1];
1150 else {
1151 fprintf(stderr, "Usage: adb devices [-l]\n");
1152 return 1;
1153 }
1154 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001155 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001156 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001157 printf("List of devices attached \n");
1158 printf("%s\n", tmp);
1159 return 0;
1160 } else {
1161 return 1;
1162 }
1163 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001164 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001165 char *tmp;
1166 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001167 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001168 return 1;
1169 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001170 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1171 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001172 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001173 printf("%s\n", tmp);
1174 return 0;
1175 } else {
1176 return 1;
1177 }
1178 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001179 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001180 char *tmp;
1181 if (argc > 2) {
1182 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1183 return 1;
1184 }
1185 if (argc == 2) {
1186 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1187 } else {
1188 snprintf(buf, sizeof buf, "host:disconnect:");
1189 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001190 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001191 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001192 printf("%s\n", tmp);
1193 return 0;
1194 } else {
1195 return 1;
1196 }
1197 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001198 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001199 return adb_send_emulator_command(argc, argv);
1200 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001201 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001202 char h = (argv[0][0] == 'h');
1203
1204 if (h) {
1205 printf("\x1b[41;33m");
1206 fflush(stdout);
1207 }
1208
Riley Andrews98f58e82014-12-05 17:37:24 -08001209 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001210 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001211 r = interactive_shell();
1212 if (h) {
1213 printf("\x1b[0m");
1214 fflush(stdout);
1215 }
1216 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001217 }
1218
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001219 std::string cmd = "shell:";
1220 cmd += argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001221 argc -= 2;
1222 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001223 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001224 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001225 }
1226
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001227 while (true) {
1228 D("interactive shell loop. cmd=%s\n", cmd.c_str());
1229 int fd = adb_connect(cmd.c_str());
1230 int r;
Riley Andrews98f58e82014-12-05 17:37:24 -08001231 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001232 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001233 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001234 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001235 adb_close(fd);
1236 r = 0;
1237 } else {
1238 fprintf(stderr,"error: %s\n", adb_error());
1239 r = -1;
1240 }
1241
Riley Andrews98f58e82014-12-05 17:37:24 -08001242 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001243 fprintf(stderr,"\n- waiting for device -\n");
1244 adb_sleep_ms(1000);
1245 do_cmd(ttype, serial, "wait-for-device", 0);
1246 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001247 if (h) {
1248 printf("\x1b[0m");
1249 fflush(stdout);
1250 }
JP Abgrall408fa572011-03-16 15:57:42 -07001251 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001252 return r;
1253 }
1254 }
1255 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001256 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001257 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001258
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001259 std::string cmd = "exec:";
1260 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001261 argc -= 2;
1262 argv += 2;
1263 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001264 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001265 }
1266
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001267 int fd = adb_connect(cmd.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001268 if (fd < 0) {
1269 fprintf(stderr, "error: %s\n", adb_error());
1270 return -1;
1271 }
1272
1273 if (exec_in) {
1274 copy_to_file(STDIN_FILENO, fd);
1275 } else {
1276 copy_to_file(fd, STDOUT_FILENO);
1277 }
1278
1279 adb_close(fd);
1280 return 0;
1281 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001282 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001283 int fd;
1284 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001285 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001286 fprintf(stderr,"* server not running *\n");
1287 return 1;
1288 }
1289 return 0;
1290 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001291 else if (!strcmp(argv[0], "sideload")) {
1292 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001293 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001294 return 1;
1295 } else {
1296 return 0;
1297 }
1298 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001299 else if (!strcmp(argv[0], "remount") ||
1300 !strcmp(argv[0], "reboot") ||
1301 !strcmp(argv[0], "reboot-bootloader") ||
1302 !strcmp(argv[0], "tcpip") ||
1303 !strcmp(argv[0], "usb") ||
1304 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001305 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001306 !strcmp(argv[0], "disable-verity") ||
1307 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001308 char command[100];
Tao Bao175b7bb2015-03-29 11:22:34 -07001309 if (!strcmp(argv[0], "reboot-bootloader")) {
Romain Guy311add42009-12-14 14:42:17 -08001310 snprintf(command, sizeof(command), "reboot:bootloader");
Tao Bao175b7bb2015-03-29 11:22:34 -07001311 } else if (argc > 1) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001312 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001313 } else {
Mike Lockwoodff196702009-08-24 15:58:40 -07001314 snprintf(command, sizeof(command), "%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001315 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001316 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001317 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001318 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001319 if (argc != 1) return usage();
1320 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001321 return 0;
1322 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001323 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001324 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001325 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001326 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001327 char remove = 0;
1328 char remove_all = 0;
1329 char list = 0;
1330 char no_rebind = 0;
1331
1332 // Parse options here.
1333 while (argc > 1 && argv[1][0] == '-') {
1334 if (!strcmp(argv[1], "--list"))
1335 list = 1;
1336 else if (!strcmp(argv[1], "--remove"))
1337 remove = 1;
1338 else if (!strcmp(argv[1], "--remove-all"))
1339 remove_all = 1;
1340 else if (!strcmp(argv[1], "--no-rebind"))
1341 no_rebind = 1;
1342 else {
1343 return usage();
1344 }
1345 argc--;
1346 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001347 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001348
1349 // Ensure we can only use one option at a time.
1350 if (list + remove + remove_all + no_rebind > 1) {
1351 return usage();
1352 }
1353
1354 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001355 if (reverse) {
1356 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001357 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001358 if (serial) {
1359 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1360 serial);
1361 } else if (ttype == kTransportUsb) {
1362 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1363 } else if (ttype == kTransportLocal) {
1364 snprintf(host_prefix, sizeof host_prefix, "host-local");
1365 } else {
1366 snprintf(host_prefix, sizeof host_prefix, "host");
1367 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001368 }
1369
1370 // Implement forward --list
1371 if (list) {
1372 if (argc != 1)
1373 return usage();
1374 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1375 char* forwards = adb_query(buf);
1376 if (forwards == NULL) {
1377 fprintf(stderr, "error: %s\n", adb_error());
1378 return 1;
1379 }
1380 printf("%s", forwards);
1381 free(forwards);
1382 return 0;
1383 }
1384
1385 // Implement forward --remove-all
1386 else if (remove_all) {
1387 if (argc != 1)
1388 return usage();
1389 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1390 }
1391
1392 // Implement forward --remove <local>
1393 else if (remove) {
1394 if (argc != 2)
1395 return usage();
1396 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1397 }
1398 // Or implement one of:
1399 // forward <local> <remote>
1400 // forward --no-rebind <local> <remote>
1401 else
1402 {
1403 if (argc != 3)
1404 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001405 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001406 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1407 }
1408
Riley Andrews98f58e82014-12-05 17:37:24 -08001409 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001410 fprintf(stderr,"error: %s\n", adb_error());
1411 return 1;
1412 }
1413 return 0;
1414 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001415 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001416 else if (!strcmp(argv[0], "ls")) {
1417 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001418 return do_sync_ls(argv[1]);
1419 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001420 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001421 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001422 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001423 const char* lpath = NULL, *rpath = NULL;
1424
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001425 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001426
1427 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001428 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001429 }
1430
1431 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001432 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001433 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001434 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001435 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001436 const char* rpath = NULL, *lpath = ".";
1437
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001438 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001439
1440 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001441 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001442 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001443
1444 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001445 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001446 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001447 if (argc < 2) return usage();
1448 return install_app(ttype, serial, argc, argv);
1449 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001450 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001451 if (argc < 2) return usage();
1452 return install_multiple_app(ttype, serial, argc, argv);
1453 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001454 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001455 if (argc < 2) return usage();
1456 return uninstall_app(ttype, serial, argc, argv);
1457 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001458 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001459 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001460 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001461 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001462 // No local path was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001463 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001464 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001465 list_only = true;
Anthony Newnam705c9442010-02-22 08:36:49 -06001466 if (argc == 3) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001467 src = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001468 } else {
Elliott Hughesd236d072015-04-21 10:17:07 -07001469 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001470 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001471 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001472 // A local path or "android"/"data" arg was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001473 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001474 } else {
1475 return usage();
1476 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001477
Elliott Hughesd236d072015-04-21 10:17:07 -07001478 if (src != "" &&
1479 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes58305772015-04-17 13:57:15 -07001480 return usage();
1481 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001482
Elliott Hughes58305772015-04-17 13:57:15 -07001483 std::string system_src_path = product_file("system");
1484 std::string data_src_path = product_file("data");
1485 std::string vendor_src_path = product_file("vendor");
1486 std::string oem_src_path = product_file("oem");
Elliott Hughes58305772015-04-17 13:57:15 -07001487
1488 int rc = 0;
Elliott Hughesd236d072015-04-21 10:17:07 -07001489 if (rc == 0 && (src.empty() || src == "system")) {
1490 rc = do_sync_sync(system_src_path, "/system", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001491 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001492 if (rc == 0 && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
1493 rc = do_sync_sync(vendor_src_path, "/vendor", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001494 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001495 if (rc == 0 && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
1496 rc = do_sync_sync(oem_src_path, "/oem", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001497 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001498 if (rc == 0 && (src.empty() || src == "data")) {
1499 rc = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001500 }
1501 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001502 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001503 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001504 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001505 !strcmp(argv[0],"get-serialno") ||
1506 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001507 {
1508 char *tmp;
1509
1510 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1511 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001512 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001513 printf("%s\n", tmp);
1514 return 0;
1515 } else {
1516 return 1;
1517 }
1518 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001519 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001520 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001521 status_window(ttype, serial);
1522 return 0;
1523 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001524 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001525 return logcat(ttype, serial, argc, argv);
1526 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001527 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001528 return ppp(argc, argv);
1529 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001530 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001531 return adb_connect("host:start-server");
1532 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001533 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001534 return backup(argc, argv);
1535 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001536 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001537 return restore(argc, argv);
1538 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001539 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001540 if (argc < 2) return usage();
1541 return adb_auth_keygen(argv[1]);
1542 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001543 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001544 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001545 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001546 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001547 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001548 help();
1549 return 0;
1550 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001551 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001552 version(stdout);
1553 return 0;
1554 }
1555
1556 usage();
1557 return 1;
1558}
1559
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001560#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001561static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001562{
Dan Albertbac34742015-02-25 17:51:28 -08001563 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001564 int argc;
1565 va_list ap;
1566
1567 va_start(ap, cmd);
1568 argc = 0;
1569
1570 if (serial) {
1571 argv[argc++] = "-s";
1572 argv[argc++] = serial;
1573 } else if (ttype == kTransportUsb) {
1574 argv[argc++] = "-d";
1575 } else if (ttype == kTransportLocal) {
1576 argv[argc++] = "-e";
1577 }
1578
1579 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001580 while(argc < MAX_ARGV_LENGTH &&
1581 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1582 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001583 va_end(ap);
1584
1585#if 0
1586 int n;
1587 fprintf(stderr,"argc = %d\n",argc);
1588 for(n = 0; n < argc; n++) {
1589 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1590 }
1591#endif
1592
1593 return adb_commandline(argc, argv);
1594}
1595
Dan Albertbac34742015-02-25 17:51:28 -08001596static int pm_command(transport_type transport, const char* serial,
1597 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001598{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001599 std::string cmd = "shell:pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001600
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001601 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001602 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001603 }
1604
Elliott Hughes15551472015-04-21 17:58:55 -07001605 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001606}
1607
Elliott Hughes58305772015-04-17 13:57:15 -07001608static int uninstall_app(transport_type transport, const char* serial, int argc,
1609 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001610{
1611 /* if the user choose the -k option, we refuse to do it until devices are
1612 out with the option to uninstall the remaining data somehow (adb/ui) */
1613 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1614 {
1615 printf(
1616 "The -k option uninstalls the application while retaining the data/cache.\n"
1617 "At the moment, there is no way to remove the remaining data.\n"
1618 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1619 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1620 return -1;
1621 }
1622
1623 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1624 return pm_command(transport, serial, argc, argv);
1625}
1626
Dan Albertbac34742015-02-25 17:51:28 -08001627static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001628{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001629 std::string cmd = "shell:rm -f " + escape_arg(filename);
Elliott Hughes15551472015-04-21 17:58:55 -07001630 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001631}
1632
Kenny Root597ea5b2011-08-05 11:19:45 -07001633static const char* get_basename(const char* filename)
1634{
1635 const char* basename = adb_dirstop(filename);
1636 if (basename) {
1637 basename++;
1638 return basename;
1639 } else {
1640 return filename;
1641 }
1642}
1643
Elliott Hughes58305772015-04-17 13:57:15 -07001644static int install_app(transport_type transport, const char* serial, int argc,
1645 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001646{
1647 static const char *const DATA_DEST = "/data/local/tmp/%s";
1648 static const char *const SD_DEST = "/sdcard/tmp/%s";
1649 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001650 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001651 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001652
1653 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001654 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001655 where = SD_DEST;
1656 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001657 }
1658
Jeff Sharkey960df972014-06-09 17:30:57 -07001659 // Find last APK argument.
1660 // All other arguments passed through verbatim.
1661 int last_apk = -1;
1662 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001663 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001664 char* dot = strrchr(file, '.');
1665 if (dot && !strcasecmp(dot, ".apk")) {
1666 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1667 fprintf(stderr, "Invalid APK file: %s\n", file);
1668 return -1;
1669 }
1670
1671 last_apk = i;
1672 break;
1673 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001674 }
1675
Jeff Sharkey960df972014-06-09 17:30:57 -07001676 if (last_apk == -1) {
1677 fprintf(stderr, "Missing APK file\n");
1678 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001679 }
1680
Dan Albertbac34742015-02-25 17:51:28 -08001681 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001682 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001683 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001684 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001685 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001686 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001687 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001688 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001689 }
1690
Elliott Hughes15551472015-04-21 17:58:55 -07001691 err = pm_command(transport, serial, argc, argv);
Kenny Root597ea5b2011-08-05 11:19:45 -07001692
Kenny Root60733e92012-03-26 16:14:02 -07001693cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001694 delete_file(transport, serial, apk_dest);
1695 return err;
1696}
1697
Elliott Hughes58305772015-04-17 13:57:15 -07001698static int install_multiple_app(transport_type transport, const char* serial, int argc,
1699 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001700{
Jeff Sharkey960df972014-06-09 17:30:57 -07001701 int i;
1702 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001703 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001704
1705 // Find all APK arguments starting at end.
1706 // All other arguments passed through verbatim.
1707 int first_apk = -1;
1708 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001709 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001710 char* dot = strrchr(file, '.');
1711 if (dot && !strcasecmp(dot, ".apk")) {
1712 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1713 fprintf(stderr, "Invalid APK file: %s\n", file);
1714 return -1;
1715 }
1716
1717 total_size += sb.st_size;
1718 first_apk = i;
1719 } else {
1720 break;
1721 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001722 }
1723
Jeff Sharkey960df972014-06-09 17:30:57 -07001724 if (first_apk == -1) {
1725 fprintf(stderr, "Missing APK file\n");
1726 return 1;
1727 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001728
Elliott Hughes53daee62015-04-19 13:17:01 -07001729#if defined(_WIN32) // Remove when we're using clang for Win32.
1730 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %u", (unsigned) total_size);
1731#else
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001732 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Elliott Hughes53daee62015-04-19 13:17:01 -07001733#endif
Jeff Sharkey960df972014-06-09 17:30:57 -07001734 for (i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001735 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001736 }
1737
1738 // Create install session
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001739 int fd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001740 if (fd < 0) {
1741 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1742 return -1;
1743 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001744 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001745 read_status_line(fd, buf, sizeof(buf));
1746 adb_close(fd);
1747
1748 int session_id = -1;
1749 if (!strncmp("Success", buf, 7)) {
1750 char* start = strrchr(buf, '[');
1751 char* end = strrchr(buf, ']');
1752 if (start && end) {
1753 *end = '\0';
1754 session_id = strtol(start + 1, NULL, 10);
1755 }
1756 }
1757 if (session_id < 0) {
1758 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001759 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001760 return -1;
1761 }
1762
1763 // Valid session, now stream the APKs
1764 int success = 1;
1765 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001766 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001767 if (stat(file, &sb) == -1) {
1768 fprintf(stderr, "Failed to stat %s\n", file);
1769 success = 0;
1770 goto finalize_session;
1771 }
1772
Elliott Hughes53daee62015-04-19 13:17:01 -07001773#if defined(_WIN32) // Remove when we're using clang for Win32.
1774 std::string cmd = android::base::StringPrintf(
1775 "exec:pm install-write -S %u %d %d_%s -",
1776 (unsigned) sb.st_size, session_id, i, get_basename(file));
1777#else
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001778 std::string cmd = android::base::StringPrintf(
1779 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
1780 static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
Elliott Hughes53daee62015-04-19 13:17:01 -07001781#endif
Jeff Sharkey960df972014-06-09 17:30:57 -07001782
1783 int localFd = adb_open(file, O_RDONLY);
1784 if (localFd < 0) {
1785 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
1786 success = 0;
1787 goto finalize_session;
1788 }
1789
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001790 int remoteFd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001791 if (remoteFd < 0) {
1792 fprintf(stderr, "Connect error for write: %s\n", adb_error());
1793 adb_close(localFd);
1794 success = 0;
1795 goto finalize_session;
1796 }
1797
1798 copy_to_file(localFd, remoteFd);
1799 read_status_line(remoteFd, buf, sizeof(buf));
1800
1801 adb_close(localFd);
1802 adb_close(remoteFd);
1803
1804 if (strncmp("Success", buf, 7)) {
1805 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001806 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001807 success = 0;
1808 goto finalize_session;
1809 }
1810 }
1811
1812finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001813 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07001814 if (success) {
1815 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
1816 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001817 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07001818 }
1819
1820 fd = adb_connect(buf);
1821 if (fd < 0) {
1822 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
1823 return -1;
1824 }
1825 read_status_line(fd, buf, sizeof(buf));
1826 adb_close(fd);
1827
1828 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001829 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001830 return 0;
1831 } else {
1832 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001833 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001834 return -1;
1835 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001836}