blob: c6d7de6cbb76342bd95a4ab7708ec42a2c2f9584 [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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800761 argc -= 1;
762 argv += 1;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700763 while (argc-- > 0) {
764 cmd += " ";
765 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800766 }
767
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700768 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800769 return 0;
770}
771
Mark Salyzyn60299df2014-04-30 09:10:31 -0700772static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800773{
774 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700775 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800776
777 for(;;) {
778 x = adb_dirstart(x);
779 if(x == 0) return 0;
780 *x = 0;
781 ret = adb_mkdir(path, 0775);
782 *x = OS_PATH_SEPARATOR;
783 if((ret < 0) && (errno != EEXIST)) {
784 return ret;
785 }
786 x++;
787 }
788 return 0;
789}
790
Dan Albertbac34742015-02-25 17:51:28 -0800791static int backup(int argc, const char** argv) {
Christopher Tated2f54152011-04-21 12:53:28 -0700792 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800793 char default_name[32];
794 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700795 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700796 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700797
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700798 /* find, extract, and use any -f argument */
799 for (i = 1; i < argc; i++) {
800 if (!strcmp("-f", argv[i])) {
801 if (i == argc-1) {
802 fprintf(stderr, "adb: -f passed with no filename\n");
803 return usage();
804 }
805 filename = argv[i+1];
806 for (j = i+2; j <= argc; ) {
807 argv[i++] = argv[j++];
808 }
809 argc -= 2;
810 argv[argc] = NULL;
811 }
Christopher Tated2f54152011-04-21 12:53:28 -0700812 }
813
Christopher Tatebb86bc52011-08-22 17:12:08 -0700814 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
815 if (argc < 2) return usage();
816
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800817 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700818 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800819 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700820 if (outFd < 0) {
821 fprintf(stderr, "adb: unable to open file %s\n", filename);
822 return -1;
823 }
824
825 snprintf(buf, sizeof(buf), "backup");
826 for (argc--, argv++; argc; argc--, argv++) {
827 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
828 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
829 }
830
831 D("backup. filename=%s buf=%s\n", filename, buf);
832 fd = adb_connect(buf);
833 if (fd < 0) {
834 fprintf(stderr, "adb: unable to connect for backup\n");
835 adb_close(outFd);
836 return -1;
837 }
838
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800839 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700840 copy_to_file(fd, outFd);
841
842 adb_close(fd);
843 adb_close(outFd);
844 return 0;
845}
846
Dan Albertbac34742015-02-25 17:51:28 -0800847static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700848 const char* filename;
849 int fd, tarFd;
850
851 if (argc != 2) return usage();
852
853 filename = argv[1];
854 tarFd = adb_open(filename, O_RDONLY);
855 if (tarFd < 0) {
856 fprintf(stderr, "adb: unable to open file %s\n", filename);
857 return -1;
858 }
859
860 fd = adb_connect("restore:");
861 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700862 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700863 adb_close(tarFd);
864 return -1;
865 }
866
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800867 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700868 copy_to_file(tarFd, fd);
869
870 adb_close(fd);
871 adb_close(tarFd);
872 return 0;
873}
874
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800875/* <hint> may be:
876 * - A simple product name
877 * e.g., "sooner"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800878 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
879 * e.g., "out/target/product/sooner"
880 * - An absolute path to the PRODUCT_OUT dir
881 * e.g., "/src/device/out/target/product/sooner"
882 *
883 * Given <hint>, try to construct an absolute path to the
884 * ANDROID_PRODUCT_OUT dir.
885 */
Elliott Hughes58305772015-04-17 13:57:15 -0700886static std::string find_product_out_path(const char* hint) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800887 if (hint == NULL || hint[0] == '\0') {
Elliott Hughes58305772015-04-17 13:57:15 -0700888 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800889 }
890
Elliott Hughes58305772015-04-17 13:57:15 -0700891 // If it's already absolute, don't bother doing any work.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800892 if (adb_is_absolute_host_path(hint)) {
Elliott Hughes58305772015-04-17 13:57:15 -0700893 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800894 }
895
Elliott Hughes58305772015-04-17 13:57:15 -0700896 // If there are any slashes in it, assume it's a relative path;
897 // make it absolute.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700898 if (adb_dirstart(hint) != nullptr) {
899 std::string cwd;
900 if (!getcwd(&cwd)) {
901 fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -0700902 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800903 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700904 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 -0800905 }
906
Elliott Hughes58305772015-04-17 13:57:15 -0700907 // It's a string without any slashes. Try to do something with it.
908 //
909 // Try to find the root of the build tree, and build a PRODUCT_OUT
910 // path from there.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700911 char* top = getenv("ANDROID_BUILD_TOP");
Elliott Hughes58305772015-04-17 13:57:15 -0700912 if (top == nullptr) {
Elliott Hughesa7090b92015-04-17 17:03:59 -0700913 fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
Elliott Hughes58305772015-04-17 13:57:15 -0700914 return "";
915 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700916
917 std::string path = top;
Elliott Hughes58305772015-04-17 13:57:15 -0700918 path += OS_PATH_SEPARATOR_STR;
919 path += "out";
920 path += OS_PATH_SEPARATOR_STR;
921 path += "target";
922 path += OS_PATH_SEPARATOR_STR;
923 path += "product";
924 path += OS_PATH_SEPARATOR_STR;
925 path += hint;
926 if (!directory_exists(path)) {
927 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
928 "\"%s\" doesn't exist\n", hint, path.c_str());
Elliott Hughesa7090b92015-04-17 17:03:59 -0700929 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800930 }
Elliott Hughes58305772015-04-17 13:57:15 -0700931 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800932}
933
Dan Albertbac34742015-02-25 17:51:28 -0800934static void parse_push_pull_args(const char **arg, int narg, char const **path1,
935 char const **path2, int *show_progress,
936 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -0700937 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700938 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -0700939
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700940 while (narg > 0) {
941 if (!strcmp(*arg, "-p")) {
942 *show_progress = 1;
943 } else if (!strcmp(*arg, "-a")) {
944 *copy_attrs = 1;
945 } else {
946 break;
947 }
Mark Lindner76f2a932014-03-11 17:55:59 -0700948 ++arg;
949 --narg;
950 }
951
952 if (narg > 0) {
953 *path1 = *arg;
954 ++arg;
955 --narg;
956 }
957
958 if (narg > 0) {
959 *path2 = *arg;
960 }
961}
962
Tao Bao175b7bb2015-03-29 11:22:34 -0700963static int adb_connect_command(const char* command) {
964 int fd = adb_connect(command);
965 if (fd != -1) {
966 read_and_dump(fd);
967 adb_close(fd);
968 return 0;
969 }
970 fprintf(stderr, "Error: %s\n", adb_error());
971 return 1;
972}
973
Dan Albertbac34742015-02-25 17:51:28 -0800974int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800975{
976 char buf[4096];
977 int no_daemon = 0;
978 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100979 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800980 int persist = 0;
981 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800982 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -0800983 const char* serial = NULL;
984 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800985
Elliott Hughes58305772015-04-17 13:57:15 -0700986 // If defined, this should be an absolute path to
987 // the directory containing all of the various system images
988 // for a particular product. If not defined, and the adb
989 // command requires this information, then the user must
990 // specify the path using "-p".
991 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
992 if (ANDROID_PRODUCT_OUT != nullptr) {
993 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800994 }
995 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
996
Nick Pellydb449262009-05-07 12:48:03 -0700997 serial = getenv("ANDROID_SERIAL");
998
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100999 /* Validate and assign the server port */
1000 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1001 int server_port = DEFAULT_ADB_PORT;
1002 if (server_port_str && strlen(server_port_str) > 0) {
1003 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001004 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001005 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001006 "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 +01001007 server_port_str);
1008 return usage();
1009 }
1010 }
1011
1012 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001013 while (argc > 0) {
1014 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001015 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001016 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001017 no_daemon = 1;
1018 } else if (!strcmp(argv[0], "fork-server")) {
1019 /* this is a special flag used only when the ADB client launches the ADB Server */
1020 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001021 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001022 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001023 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001024 const char *product = NULL;
1025 if (argv[0][2] == '\0') {
1026 if (argc < 2) return usage();
1027 product = argv[1];
1028 argc--;
1029 argv++;
1030 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001031 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001032 }
1033 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -07001034 if (gProductOutPath.empty()) {
1035 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001036 return usage();
1037 }
1038 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1039 if (isdigit(argv[0][2])) {
1040 serial = argv[0] + 2;
1041 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001042 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001043 serial = argv[1];
1044 argc--;
1045 argv++;
1046 }
1047 } else if (!strcmp(argv[0],"-d")) {
1048 ttype = kTransportUsb;
1049 } else if (!strcmp(argv[0],"-e")) {
1050 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001051 } else if (!strcmp(argv[0],"-a")) {
1052 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001053 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001054 const char *hostname = NULL;
1055 if (argv[0][2] == '\0') {
1056 if (argc < 2) return usage();
1057 hostname = argv[1];
1058 argc--;
1059 argv++;
1060 } else {
1061 hostname = argv[0] + 2;
1062 }
1063 adb_set_tcp_name(hostname);
1064
Riley Andrews98f58e82014-12-05 17:37:24 -08001065 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001066 if (argv[0][2] == '\0') {
1067 if (argc < 2) return usage();
1068 server_port_str = argv[1];
1069 argc--;
1070 argv++;
1071 } else {
1072 server_port_str = argv[0] + 2;
1073 }
1074 if (strlen(server_port_str) > 0) {
1075 server_port = (int) strtol(server_port_str, NULL, 0);
1076 if (server_port <= 0 || server_port > 65535) {
1077 fprintf(stderr,
1078 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1079 server_port_str);
1080 return usage();
1081 }
1082 } else {
1083 fprintf(stderr,
1084 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1085 return usage();
1086 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001087 } else {
1088 /* out of recognized modifiers and flags */
1089 break;
1090 }
1091 argc--;
1092 argv++;
1093 }
1094
1095 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001096 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001097
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001098 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001099 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001100 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001101 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001102 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001103 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001104 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001105 fprintf(stderr,"* could not start server *\n");
1106 }
1107 return r;
1108 }
1109
Riley Andrews98f58e82014-12-05 17:37:24 -08001110 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001111 return usage();
1112 }
1113
Riley Andrewsc8514c82014-12-05 17:32:46 -08001114 /* handle wait-for-* prefix */
1115 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001116 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001117 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1118 if (ttype == kTransportUsb) {
1119 service = "wait-for-usb";
1120 } else if (ttype == kTransportLocal) {
1121 service = "wait-for-local";
1122 } else {
1123 service = "wait-for-any";
1124 }
1125 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001126
Riley Andrewsc8514c82014-12-05 17:32:46 -08001127 format_host_command(buf, sizeof buf, service, ttype, serial);
1128
1129 if (adb_command(buf)) {
1130 D("failure: %s *\n",adb_error());
1131 fprintf(stderr,"error: %s\n", adb_error());
1132 return 1;
1133 }
1134
1135 /* Allow a command to be run after wait-for-device,
1136 * e.g. 'adb wait-for-device shell'.
1137 */
1138 if (argc == 1) {
1139 return 0;
1140 }
1141
1142 /* Fall through */
1143 argc--;
1144 argv++;
1145 }
1146
1147 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001148 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001149 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001150 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001151 if (argc < 2)
1152 listopt = "";
1153 else if (argc == 2 && !strcmp(argv[1], "-l"))
1154 listopt = argv[1];
1155 else {
1156 fprintf(stderr, "Usage: adb devices [-l]\n");
1157 return 1;
1158 }
1159 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001160 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001161 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001162 printf("List of devices attached \n");
1163 printf("%s\n", tmp);
1164 return 0;
1165 } else {
1166 return 1;
1167 }
1168 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001169 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001170 char *tmp;
1171 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001172 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001173 return 1;
1174 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001175 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1176 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001177 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001178 printf("%s\n", tmp);
1179 return 0;
1180 } else {
1181 return 1;
1182 }
1183 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001184 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001185 char *tmp;
1186 if (argc > 2) {
1187 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1188 return 1;
1189 }
1190 if (argc == 2) {
1191 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1192 } else {
1193 snprintf(buf, sizeof buf, "host:disconnect:");
1194 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001195 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001196 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001197 printf("%s\n", tmp);
1198 return 0;
1199 } else {
1200 return 1;
1201 }
1202 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001203 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001204 return adb_send_emulator_command(argc, argv);
1205 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001206 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001207 char h = (argv[0][0] == 'h');
1208
1209 if (h) {
1210 printf("\x1b[41;33m");
1211 fflush(stdout);
1212 }
1213
Riley Andrews98f58e82014-12-05 17:37:24 -08001214 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001215 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001216 r = interactive_shell();
1217 if (h) {
1218 printf("\x1b[0m");
1219 fflush(stdout);
1220 }
1221 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001222 }
1223
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001224 std::string cmd = "shell:";
1225 cmd += argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001226 argc -= 2;
1227 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001228 while (argc-- > 0) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001229 cmd += " ";
1230 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001231 }
1232
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001233 while (true) {
1234 D("interactive shell loop. cmd=%s\n", cmd.c_str());
1235 int fd = adb_connect(cmd.c_str());
1236 int r;
Riley Andrews98f58e82014-12-05 17:37:24 -08001237 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001238 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001239 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001240 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001241 adb_close(fd);
1242 r = 0;
1243 } else {
1244 fprintf(stderr,"error: %s\n", adb_error());
1245 r = -1;
1246 }
1247
Riley Andrews98f58e82014-12-05 17:37:24 -08001248 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001249 fprintf(stderr,"\n- waiting for device -\n");
1250 adb_sleep_ms(1000);
1251 do_cmd(ttype, serial, "wait-for-device", 0);
1252 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001253 if (h) {
1254 printf("\x1b[0m");
1255 fflush(stdout);
1256 }
JP Abgrall408fa572011-03-16 15:57:42 -07001257 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001258 return r;
1259 }
1260 }
1261 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001262 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001263 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001264
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001265 std::string cmd = "exec:";
1266 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001267 argc -= 2;
1268 argv += 2;
1269 while (argc-- > 0) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001270 cmd += " ";
1271 cmd += escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001272 }
1273
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001274 int fd = adb_connect(cmd.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001275 if (fd < 0) {
1276 fprintf(stderr, "error: %s\n", adb_error());
1277 return -1;
1278 }
1279
1280 if (exec_in) {
1281 copy_to_file(STDIN_FILENO, fd);
1282 } else {
1283 copy_to_file(fd, STDOUT_FILENO);
1284 }
1285
1286 adb_close(fd);
1287 return 0;
1288 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001289 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001290 int fd;
1291 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001292 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001293 fprintf(stderr,"* server not running *\n");
1294 return 1;
1295 }
1296 return 0;
1297 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001298 else if (!strcmp(argv[0], "sideload")) {
1299 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001300 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001301 return 1;
1302 } else {
1303 return 0;
1304 }
1305 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001306 else if (!strcmp(argv[0], "remount") ||
1307 !strcmp(argv[0], "reboot") ||
1308 !strcmp(argv[0], "reboot-bootloader") ||
1309 !strcmp(argv[0], "tcpip") ||
1310 !strcmp(argv[0], "usb") ||
1311 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001312 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001313 !strcmp(argv[0], "disable-verity") ||
1314 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001315 char command[100];
Tao Bao175b7bb2015-03-29 11:22:34 -07001316 if (!strcmp(argv[0], "reboot-bootloader")) {
Romain Guy311add42009-12-14 14:42:17 -08001317 snprintf(command, sizeof(command), "reboot:bootloader");
Tao Bao175b7bb2015-03-29 11:22:34 -07001318 } else if (argc > 1) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001319 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001320 } else {
Mike Lockwoodff196702009-08-24 15:58:40 -07001321 snprintf(command, sizeof(command), "%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001322 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001323 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001324 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001325 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001326 if (argc != 1) return usage();
1327 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001328 return 0;
1329 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001330 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001331 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001332 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001333 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001334 char remove = 0;
1335 char remove_all = 0;
1336 char list = 0;
1337 char no_rebind = 0;
1338
1339 // Parse options here.
1340 while (argc > 1 && argv[1][0] == '-') {
1341 if (!strcmp(argv[1], "--list"))
1342 list = 1;
1343 else if (!strcmp(argv[1], "--remove"))
1344 remove = 1;
1345 else if (!strcmp(argv[1], "--remove-all"))
1346 remove_all = 1;
1347 else if (!strcmp(argv[1], "--no-rebind"))
1348 no_rebind = 1;
1349 else {
1350 return usage();
1351 }
1352 argc--;
1353 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001354 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001355
1356 // Ensure we can only use one option at a time.
1357 if (list + remove + remove_all + no_rebind > 1) {
1358 return usage();
1359 }
1360
1361 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001362 if (reverse) {
1363 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001364 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001365 if (serial) {
1366 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1367 serial);
1368 } else if (ttype == kTransportUsb) {
1369 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1370 } else if (ttype == kTransportLocal) {
1371 snprintf(host_prefix, sizeof host_prefix, "host-local");
1372 } else {
1373 snprintf(host_prefix, sizeof host_prefix, "host");
1374 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001375 }
1376
1377 // Implement forward --list
1378 if (list) {
1379 if (argc != 1)
1380 return usage();
1381 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1382 char* forwards = adb_query(buf);
1383 if (forwards == NULL) {
1384 fprintf(stderr, "error: %s\n", adb_error());
1385 return 1;
1386 }
1387 printf("%s", forwards);
1388 free(forwards);
1389 return 0;
1390 }
1391
1392 // Implement forward --remove-all
1393 else if (remove_all) {
1394 if (argc != 1)
1395 return usage();
1396 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1397 }
1398
1399 // Implement forward --remove <local>
1400 else if (remove) {
1401 if (argc != 2)
1402 return usage();
1403 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1404 }
1405 // Or implement one of:
1406 // forward <local> <remote>
1407 // forward --no-rebind <local> <remote>
1408 else
1409 {
1410 if (argc != 3)
1411 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001412 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001413 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1414 }
1415
Riley Andrews98f58e82014-12-05 17:37:24 -08001416 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001417 fprintf(stderr,"error: %s\n", adb_error());
1418 return 1;
1419 }
1420 return 0;
1421 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001422 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001423 else if (!strcmp(argv[0], "ls")) {
1424 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001425 return do_sync_ls(argv[1]);
1426 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001427 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001428 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001429 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001430 const char* lpath = NULL, *rpath = NULL;
1431
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001432 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001433
1434 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001435 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001436 }
1437
1438 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001439 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001440 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001441 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001442 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001443 const char* rpath = NULL, *lpath = ".";
1444
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001445 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001446
1447 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001448 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001449 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001450
1451 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001452 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001453 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001454 if (argc < 2) return usage();
1455 return install_app(ttype, serial, argc, argv);
1456 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001457 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001458 if (argc < 2) return usage();
1459 return install_multiple_app(ttype, serial, argc, argv);
1460 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001461 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001462 if (argc < 2) return usage();
1463 return uninstall_app(ttype, serial, argc, argv);
1464 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001465 else if (!strcmp(argv[0], "sync")) {
Elliott Hughes58305772015-04-17 13:57:15 -07001466 std::string src_arg;
1467 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001468 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001469 // No local path was specified.
1470 src_arg = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001471 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughes58305772015-04-17 13:57:15 -07001472 list_only = 1;
Anthony Newnam705c9442010-02-22 08:36:49 -06001473 if (argc == 3) {
Elliott Hughes58305772015-04-17 13:57:15 -07001474 src_arg = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001475 } else {
Elliott Hughes58305772015-04-17 13:57:15 -07001476 src_arg = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001477 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001478 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001479 // A local path or "android"/"data" arg was specified.
1480 src_arg = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001481 } else {
1482 return usage();
1483 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001484
Elliott Hughes58305772015-04-17 13:57:15 -07001485 if (src_arg != "" &&
1486 src_arg != "system" && src_arg != "data" && src_arg != "vendor" && src_arg != "oem") {
1487 return usage();
1488 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001489
Elliott Hughes58305772015-04-17 13:57:15 -07001490 std::string system_src_path = product_file("system");
1491 std::string data_src_path = product_file("data");
1492 std::string vendor_src_path = product_file("vendor");
1493 std::string oem_src_path = product_file("oem");
1494 if (!directory_exists(vendor_src_path)) {
1495 vendor_src_path = "";
1496 }
1497 if (!directory_exists(oem_src_path)) {
1498 oem_src_path = "";
1499 }
1500
1501 int rc = 0;
1502 if (rc == 0 && (src_arg.empty() || src_arg == "system")) {
1503 rc = do_sync_sync(system_src_path.c_str(), "/system", list_only);
1504 }
1505 if (rc == 0 && (src_arg.empty() || src_arg == "vendor")) {
1506 rc = do_sync_sync(vendor_src_path.c_str(), "/vendor", list_only);
1507 }
1508 if(rc == 0 && (src_arg.empty() || src_arg == "oem")) {
1509 rc = do_sync_sync(oem_src_path.c_str(), "/oem", list_only);
1510 }
1511 if (rc == 0 && (src_arg.empty() || src_arg == "data")) {
1512 rc = do_sync_sync(data_src_path.c_str(), "/data", list_only);
1513 }
1514 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001515 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001516 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001517 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001518 !strcmp(argv[0],"get-serialno") ||
1519 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001520 {
1521 char *tmp;
1522
1523 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1524 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001525 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001526 printf("%s\n", tmp);
1527 return 0;
1528 } else {
1529 return 1;
1530 }
1531 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001532 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001533 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001534 status_window(ttype, serial);
1535 return 0;
1536 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001537 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001538 return logcat(ttype, serial, argc, argv);
1539 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001540 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001541 return ppp(argc, argv);
1542 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001543 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001544 return adb_connect("host:start-server");
1545 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001546 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001547 return backup(argc, argv);
1548 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001549 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001550 return restore(argc, argv);
1551 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001552 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001553 if (argc < 2) return usage();
1554 return adb_auth_keygen(argv[1]);
1555 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001556 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001557 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001558 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001559 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001560 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001561 help();
1562 return 0;
1563 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001564 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001565 version(stdout);
1566 return 0;
1567 }
1568
1569 usage();
1570 return 1;
1571}
1572
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001573#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001574static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001575{
Dan Albertbac34742015-02-25 17:51:28 -08001576 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001577 int argc;
1578 va_list ap;
1579
1580 va_start(ap, cmd);
1581 argc = 0;
1582
1583 if (serial) {
1584 argv[argc++] = "-s";
1585 argv[argc++] = serial;
1586 } else if (ttype == kTransportUsb) {
1587 argv[argc++] = "-d";
1588 } else if (ttype == kTransportLocal) {
1589 argv[argc++] = "-e";
1590 }
1591
1592 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001593 while(argc < MAX_ARGV_LENGTH &&
1594 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1595 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001596 va_end(ap);
1597
1598#if 0
1599 int n;
1600 fprintf(stderr,"argc = %d\n",argc);
1601 for(n = 0; n < argc; n++) {
1602 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1603 }
1604#endif
1605
1606 return adb_commandline(argc, argv);
1607}
1608
Dan Albertbac34742015-02-25 17:51:28 -08001609static int pm_command(transport_type transport, const char* serial,
1610 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001611{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001612 std::string cmd = "shell:pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001613
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001614 while (argc-- > 0) {
1615 cmd += " ";
1616 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001617 }
1618
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001619 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001620 return 0;
1621}
1622
Elliott Hughes58305772015-04-17 13:57:15 -07001623static int uninstall_app(transport_type transport, const char* serial, int argc,
1624 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001625{
1626 /* if the user choose the -k option, we refuse to do it until devices are
1627 out with the option to uninstall the remaining data somehow (adb/ui) */
1628 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1629 {
1630 printf(
1631 "The -k option uninstalls the application while retaining the data/cache.\n"
1632 "At the moment, there is no way to remove the remaining data.\n"
1633 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1634 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1635 return -1;
1636 }
1637
1638 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1639 return pm_command(transport, serial, argc, argv);
1640}
1641
Dan Albertbac34742015-02-25 17:51:28 -08001642static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001643{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001644 std::string cmd = "shell:rm -f " + escape_arg(filename);
1645 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001646 return 0;
1647}
1648
Kenny Root597ea5b2011-08-05 11:19:45 -07001649static const char* get_basename(const char* filename)
1650{
1651 const char* basename = adb_dirstop(filename);
1652 if (basename) {
1653 basename++;
1654 return basename;
1655 } else {
1656 return filename;
1657 }
1658}
1659
Elliott Hughes58305772015-04-17 13:57:15 -07001660static int install_app(transport_type transport, const char* serial, int argc,
1661 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001662{
1663 static const char *const DATA_DEST = "/data/local/tmp/%s";
1664 static const char *const SD_DEST = "/sdcard/tmp/%s";
1665 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001666 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001667 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001668
1669 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001670 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001671 where = SD_DEST;
1672 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001673 }
1674
Jeff Sharkey960df972014-06-09 17:30:57 -07001675 // Find last APK argument.
1676 // All other arguments passed through verbatim.
1677 int last_apk = -1;
1678 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001679 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001680 char* dot = strrchr(file, '.');
1681 if (dot && !strcasecmp(dot, ".apk")) {
1682 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1683 fprintf(stderr, "Invalid APK file: %s\n", file);
1684 return -1;
1685 }
1686
1687 last_apk = i;
1688 break;
1689 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001690 }
1691
Jeff Sharkey960df972014-06-09 17:30:57 -07001692 if (last_apk == -1) {
1693 fprintf(stderr, "Missing APK file\n");
1694 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001695 }
1696
Dan Albertbac34742015-02-25 17:51:28 -08001697 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001698 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001699 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001700 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001701 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001702 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001703 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001704 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001705 }
1706
1707 pm_command(transport, serial, argc, argv);
1708
Kenny Root60733e92012-03-26 16:14:02 -07001709cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001710 delete_file(transport, serial, apk_dest);
1711 return err;
1712}
1713
Elliott Hughes58305772015-04-17 13:57:15 -07001714static int install_multiple_app(transport_type transport, const char* serial, int argc,
1715 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001716{
Jeff Sharkey960df972014-06-09 17:30:57 -07001717 int i;
1718 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001719 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001720
1721 // Find all APK arguments starting at end.
1722 // All other arguments passed through verbatim.
1723 int first_apk = -1;
1724 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001725 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001726 char* dot = strrchr(file, '.');
1727 if (dot && !strcasecmp(dot, ".apk")) {
1728 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1729 fprintf(stderr, "Invalid APK file: %s\n", file);
1730 return -1;
1731 }
1732
1733 total_size += sb.st_size;
1734 first_apk = i;
1735 } else {
1736 break;
1737 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001738 }
1739
Jeff Sharkey960df972014-06-09 17:30:57 -07001740 if (first_apk == -1) {
1741 fprintf(stderr, "Missing APK file\n");
1742 return 1;
1743 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001744
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001745 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Jeff Sharkey960df972014-06-09 17:30:57 -07001746 for (i = 1; i < first_apk; i++) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001747 cmd += " ";
1748 cmd += escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001749 }
1750
1751 // Create install session
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001752 int fd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001753 if (fd < 0) {
1754 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1755 return -1;
1756 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001757 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001758 read_status_line(fd, buf, sizeof(buf));
1759 adb_close(fd);
1760
1761 int session_id = -1;
1762 if (!strncmp("Success", buf, 7)) {
1763 char* start = strrchr(buf, '[');
1764 char* end = strrchr(buf, ']');
1765 if (start && end) {
1766 *end = '\0';
1767 session_id = strtol(start + 1, NULL, 10);
1768 }
1769 }
1770 if (session_id < 0) {
1771 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001772 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001773 return -1;
1774 }
1775
1776 // Valid session, now stream the APKs
1777 int success = 1;
1778 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001779 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001780 if (stat(file, &sb) == -1) {
1781 fprintf(stderr, "Failed to stat %s\n", file);
1782 success = 0;
1783 goto finalize_session;
1784 }
1785
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001786 std::string cmd = android::base::StringPrintf(
1787 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
1788 static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001789
1790 int localFd = adb_open(file, O_RDONLY);
1791 if (localFd < 0) {
1792 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
1793 success = 0;
1794 goto finalize_session;
1795 }
1796
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001797 int remoteFd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001798 if (remoteFd < 0) {
1799 fprintf(stderr, "Connect error for write: %s\n", adb_error());
1800 adb_close(localFd);
1801 success = 0;
1802 goto finalize_session;
1803 }
1804
1805 copy_to_file(localFd, remoteFd);
1806 read_status_line(remoteFd, buf, sizeof(buf));
1807
1808 adb_close(localFd);
1809 adb_close(remoteFd);
1810
1811 if (strncmp("Success", buf, 7)) {
1812 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001813 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001814 success = 0;
1815 goto finalize_session;
1816 }
1817 }
1818
1819finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001820 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07001821 if (success) {
1822 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
1823 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001824 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07001825 }
1826
1827 fd = adb_connect(buf);
1828 if (fd < 0) {
1829 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
1830 return -1;
1831 }
1832 read_status_line(fd, buf, sizeof(buf));
1833 adb_close(fd);
1834
1835 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001836 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001837 return 0;
1838 } else {
1839 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001840 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001841 return -1;
1842 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001843}