blob: 2632b1f31b819a371ff0585e6fb6a5897c583a52 [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
Yabin Cuiaed3c612015-09-22 15:52:57 -070017#define TRACE_TAG ADB
Dan Albert33134262015-03-19 15:21:08 -070018
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
David Pursell606835a2015-09-08 17:17:02 -070034#include <memory>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070035#include <string>
36
David Pursell606835a2015-09-08 17:17:02 -070037#include <base/logging.h>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070038#include <base/stringprintf.h>
David Pursell4e2fd362015-09-22 10:43:08 -070039#include <base/strings.h>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070040
Yabin Cuid325e862014-11-17 14:48:25 -080041#if !defined(_WIN32)
Josh Gao8dcdb572015-10-23 15:03:31 -070042#include <signal.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043#include <termios.h>
Dan Albert76649012015-02-24 15:51:19 -080044#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080045#endif
46
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080047#include "adb.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080048#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080049#include "adb_client.h"
50#include "adb_io.h"
Elliott Hughes58305772015-04-17 13:57:15 -070051#include "adb_utils.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080052#include "file_sync_service.h"
David Pursell70ef7b42015-09-30 13:35:42 -070053#include "services.h"
David Pursell606835a2015-09-08 17:17:02 -070054#include "shell_service.h"
55#include "transport.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080056
Elliott Hughes3bd73c12015-05-05 13:10:43 -070057static int install_app(TransportType t, const char* serial, int argc, const char** argv);
58static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
59static int uninstall_app(TransportType t, const char* serial, int argc, const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080060
Elliott Hughes58305772015-04-17 13:57:15 -070061static std::string gProductOutPath;
Matt Gumbeld7b33082012-11-14 10:16:17 -080062extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080063
Elliott Hughes58305772015-04-17 13:57:15 -070064static std::string product_file(const char *extra) {
65 if (gProductOutPath.empty()) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080066 fprintf(stderr, "adb: Product directory not specified; "
67 "use -p or define ANDROID_PRODUCT_OUT\n");
68 exit(1);
69 }
70
Elliott Hughes58305772015-04-17 13:57:15 -070071 return android::base::StringPrintf("%s%s%s",
72 gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080073}
74
Elliott Hughes58305772015-04-17 13:57:15 -070075static void help() {
Elliott Hughes42ae2602015-08-12 08:32:10 -070076 fprintf(stderr, "%s\n", adb_version().c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080077 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -080078 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080079 " -d - directs command to the only connected USB device\n"
80 " returns an error if more than one USB device is present.\n"
81 " -e - directs command to the only running emulator.\n"
82 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070083 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070084 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070085 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080086 " -p <product name or path> - simple product name like 'sooner', or\n"
87 " a relative/absolute path to a product\n"
88 " out directory like 'out/target/product/sooner'.\n"
89 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
90 " environment variable is used, which must\n"
91 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080092 " -H - Name of adb server host (default: localhost)\n"
93 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -070094 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070095 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -040096 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
97 " Port 5555 is used by default if no port number is specified.\n"
98 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
99 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200100 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400101 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800102 "\n"
103 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700104 " adb push [-p] <local> <remote>\n"
105 " - copy file/dir to device\n"
106 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700107 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700108 " - copy file/dir from device\n"
109 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700110 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800111 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600112 " (-l means list but don't copy)\n"
David Pursell70ef7b42015-09-30 13:35:42 -0700113 " adb shell [-Ttx] - run remote shell interactively\n"
114 " adb shell [-Ttx] <command> - run remote shell command\n"
David Pursell4e2fd362015-09-22 10:43:08 -0700115 " (-T disables PTY allocation)\n"
116 " (-t forces PTY allocation)\n"
David Pursell70ef7b42015-09-30 13:35:42 -0700117 " (-x disables remote exit codes and stdout/stderr separation)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800118 " adb emu <command> - run emulator console command\n"
119 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100120 " adb forward --list - list all forward socket connections.\n"
121 " the format is a list of lines with the following format:\n"
122 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800123 " adb forward <local> <remote> - forward socket connections\n"
124 " forward specs are one of: \n"
125 " tcp:<port>\n"
126 " localabstract:<unix domain socket name>\n"
127 " localreserved:<unix domain socket name>\n"
128 " localfilesystem:<unix domain socket name>\n"
129 " dev:<character device name>\n"
130 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100131 " adb forward --no-rebind <local> <remote>\n"
132 " - same as 'adb forward <local> <remote>' but fails\n"
133 " if <local> is already forwarded\n"
134 " adb forward --remove <local> - remove a specific forward socket connection\n"
135 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100136 " adb reverse --list - list all reverse socket connections from device\n"
137 " adb reverse <remote> <local> - reverse socket connections\n"
138 " reverse specs are one of:\n"
139 " tcp:<port>\n"
140 " localabstract:<unix domain socket name>\n"
141 " localreserved:<unix domain socket name>\n"
142 " localfilesystem:<unix domain socket name>\n"
143 " adb reverse --norebind <remote> <local>\n"
144 " - same as 'adb reverse <remote> <local>' but fails\n"
145 " if <remote> is already reversed.\n"
146 " adb reverse --remove <remote>\n"
147 " - remove a specific reversed socket connection\n"
148 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800149 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900150 " adb install [-lrtsdg] <file>\n"
Svetoslav23d84072015-06-01 16:02:50 -0700151 " - push this package file to the device and install it\n"
152 " (-l: forward lock application)\n"
153 " (-r: replace existing application)\n"
154 " (-t: allow test packages)\n"
155 " (-s: install application on sdcard)\n"
156 " (-d: allow version code downgrade)\n"
157 " (-g: grant all runtime permissions)\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900158 " adb install-multiple [-lrtsdpg] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700159 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700160 " (-l: forward lock application)\n"
161 " (-r: replace existing application)\n"
162 " (-t: allow test packages)\n"
163 " (-s: install application on sdcard)\n"
164 " (-d: allow version code downgrade)\n"
165 " (-p: partial application install)\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900166 " (-g: grant all runtime permissions)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800167 " adb uninstall [-k] <package> - remove this app package from the device\n"
168 " ('-k' means keep the data and cache directories)\n"
169 " adb bugreport - return all information from the device\n"
170 " that should be included in a bug report.\n"
171 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800172 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700173 " - write an archive of the device's data to <file>.\n"
174 " If no -f option is supplied then the data is written\n"
175 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700176 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700177 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800178 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
179 " (aka .obb) files associated with each application; the default\n"
180 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700181 " (-shared|-noshared enable/disable backup of the device's\n"
182 " shared storage / SD card contents; the default is noshared.)\n"
183 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700184 " (-system|-nosystem toggles whether -all automatically includes\n"
185 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700186 " (<packages...> is the list of applications to be backed up. If\n"
187 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700188 " list is optional. Applications explicitly given on the\n"
189 " command line will be included even if -nosystem would\n"
190 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700191 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700192 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700193 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800194 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
195 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800196 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
197 " and the public key is stored in <file>.pub. Any existing files\n"
198 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800199 " adb help - show this help message\n"
200 " adb version - show version num\n"
201 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800202 "scripting:\n"
203 " adb wait-for-device - block until device is online\n"
204 " adb start-server - ensure that there is a server running\n"
205 " adb kill-server - kill the server if it is running\n"
206 " adb get-state - prints: offline | bootloader | device\n"
207 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700208 " adb get-devpath - prints: <device-path>\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000209 " 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 -0700210 " adb reboot [bootloader|recovery]\n"
211 " - reboots the device, optionally into the bootloader or recovery program.\n"
212 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
213 " adb reboot sideload-auto-reboot\n"
214 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700215 " adb sideload <file> - sideloads the given package\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700216 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500217 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800218 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000219 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700220 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800221 "networking:\n"
222 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500223 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800224 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
225 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
226 "\n"
227 "adb sync notes: adb sync [ <directory> ]\n"
228 " <localdir> can be interpreted in several ways:\n"
229 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000230 " - 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 -0800231 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000232 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800233 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000234 "\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700235 "environment variables:\n"
Timcd643152010-02-16 20:18:29 +0000236 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
237 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
238 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
239 " 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 -0800240 );
241}
242
Elliott Hughes58305772015-04-17 13:57:15 -0700243static int usage() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800244 help();
245 return 1;
246}
247
Yabin Cuid325e862014-11-17 14:48:25 -0800248#if defined(_WIN32)
249
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700250// Implemented in sysdeps_win32.cpp.
Spencer Low50184062015-03-01 15:06:21 -0800251void stdin_raw_init(int fd);
252void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800253
254#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100255static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800256
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100257static void stdin_raw_init(int fd) {
258 if (tcgetattr(fd, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800259
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100260 termios tio;
261 if (tcgetattr(fd, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800262
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100263 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800264
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100265 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800266 tio.c_cc[VTIME] = 0;
267 tio.c_cc[VMIN] = 1;
268
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100269 tcsetattr(fd, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800270}
271
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100272static void stdin_raw_restore(int fd) {
273 tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800274}
275#endif
276
David Pursell606835a2015-09-08 17:17:02 -0700277// Reads from |fd| and prints received data. If |use_shell_protocol| is true
278// this expects that incoming data will use the shell protocol, in which case
279// stdout/stderr are routed independently and the remote exit code will be
280// returned.
281static int read_and_dump(int fd, bool use_shell_protocol=false) {
282 int exit_code = 0;
283 std::unique_ptr<ShellProtocol> protocol;
284 int length = 0;
285 FILE* outfile = stdout;
286
287 char raw_buffer[BUFSIZ];
288 char* buffer_ptr = raw_buffer;
289 if (use_shell_protocol) {
290 protocol.reset(new ShellProtocol(fd));
291 if (!protocol) {
292 LOG(ERROR) << "failed to allocate memory for ShellProtocol object";
293 return 1;
294 }
295 buffer_ptr = protocol->data();
296 }
297
Elliott Hughes5677c232015-05-07 23:37:40 -0700298 while (fd >= 0) {
David Pursell606835a2015-09-08 17:17:02 -0700299 if (use_shell_protocol) {
300 if (!protocol->Read()) {
301 break;
302 }
303 switch (protocol->id()) {
304 case ShellProtocol::kIdStdout:
305 outfile = stdout;
306 break;
307 case ShellProtocol::kIdStderr:
308 outfile = stderr;
309 break;
310 case ShellProtocol::kIdExit:
311 exit_code = protocol->data()[0];
312 continue;
313 default:
314 continue;
315 }
316 length = protocol->data_length();
317 } else {
318 D("read_and_dump(): pre adb_read(fd=%d)", fd);
319 length = adb_read(fd, raw_buffer, sizeof(raw_buffer));
320 D("read_and_dump(): post adb_read(fd=%d): length=%d", fd, length);
321 if (length <= 0) {
322 break;
323 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800324 }
325
David Pursell606835a2015-09-08 17:17:02 -0700326 fwrite(buffer_ptr, 1, length, outfile);
327 fflush(outfile);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800328 }
David Pursell606835a2015-09-08 17:17:02 -0700329
330 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800331}
332
Jeff Sharkey960df972014-06-09 17:30:57 -0700333static void read_status_line(int fd, char* buf, size_t count)
334{
335 count--;
336 while (count > 0) {
337 int len = adb_read(fd, buf, count);
Elliott Hughes8fcd8bc2015-08-25 10:59:45 -0700338 if (len <= 0) {
Jeff Sharkey960df972014-06-09 17:30:57 -0700339 break;
340 }
341
342 buf += len;
343 count -= len;
344 }
345 *buf = '\0';
346}
347
Christopher Tated2f54152011-04-21 12:53:28 -0700348static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700349 const size_t BUFSIZE = 32 * 1024;
350 char* buf = (char*) malloc(BUFSIZE);
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700351 if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
Christopher Tated2f54152011-04-21 12:53:28 -0700352 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700353 long total = 0;
Spencer Lowb7dfb792015-05-22 16:48:31 -0700354#ifdef _WIN32
355 int old_stdin_mode = -1;
356 int old_stdout_mode = -1;
357#endif
Christopher Tated2f54152011-04-21 12:53:28 -0700358
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700359 D("copy_to_file(%d -> %d)", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800360
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700361 if (inFd == STDIN_FILENO) {
362 stdin_raw_init(STDIN_FILENO);
Spencer Lowb7dfb792015-05-22 16:48:31 -0700363#ifdef _WIN32
364 old_stdin_mode = _setmode(STDIN_FILENO, _O_BINARY);
365 if (old_stdin_mode == -1) {
366 fatal_errno("could not set stdin to binary");
367 }
368#endif
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700369 }
Yabin Cuid325e862014-11-17 14:48:25 -0800370
Spencer Lowb7dfb792015-05-22 16:48:31 -0700371#ifdef _WIN32
372 if (outFd == STDOUT_FILENO) {
373 old_stdout_mode = _setmode(STDOUT_FILENO, _O_BINARY);
374 if (old_stdout_mode == -1) {
375 fatal_errno("could not set stdout to binary");
376 }
377 }
378#endif
379
Elliott Hughesa7090b92015-04-17 17:03:59 -0700380 while (true) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700381 if (inFd == STDIN_FILENO) {
382 len = unix_read(inFd, buf, BUFSIZE);
383 } else {
384 len = adb_read(inFd, buf, BUFSIZE);
385 }
Christopher Tated2f54152011-04-21 12:53:28 -0700386 if (len == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700387 D("copy_to_file() : read 0 bytes; exiting");
Christopher Tated2f54152011-04-21 12:53:28 -0700388 break;
389 }
390 if (len < 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700391 D("copy_to_file(): read failed: %s", strerror(errno));
Christopher Tated2f54152011-04-21 12:53:28 -0700392 break;
393 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700394 if (outFd == STDOUT_FILENO) {
395 fwrite(buf, 1, len, stdout);
396 fflush(stdout);
397 } else {
398 adb_write(outFd, buf, len);
399 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700400 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700401 }
Yabin Cuid325e862014-11-17 14:48:25 -0800402
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700403 if (inFd == STDIN_FILENO) {
404 stdin_raw_restore(STDIN_FILENO);
Spencer Lowb7dfb792015-05-22 16:48:31 -0700405#ifdef _WIN32
406 if (_setmode(STDIN_FILENO, old_stdin_mode) == -1) {
407 fatal_errno("could not restore stdin mode");
408 }
409#endif
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700410 }
Yabin Cuid325e862014-11-17 14:48:25 -0800411
Spencer Lowb7dfb792015-05-22 16:48:31 -0700412#ifdef _WIN32
413 if (outFd == STDOUT_FILENO) {
414 if (_setmode(STDOUT_FILENO, old_stdout_mode) == -1) {
415 fatal_errno("could not restore stdout mode");
416 }
417 }
418#endif
419
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700420 D("copy_to_file() finished after %lu bytes", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700421 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700422}
423
David Pursell606835a2015-09-08 17:17:02 -0700424namespace {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800425
David Pursell606835a2015-09-08 17:17:02 -0700426// Used to pass multiple values to the stdin read thread.
427struct StdinReadArgs {
428 int stdin_fd, write_fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700429 bool raw_stdin;
David Pursell606835a2015-09-08 17:17:02 -0700430 std::unique_ptr<ShellProtocol> protocol;
431};
432
433} // namespace
434
435// Loops to read from stdin and push the data to the given FD.
436// The argument should be a pointer to a StdinReadArgs object. This function
437// will take ownership of the object and delete it when finished.
438static void* stdin_read_thread(void* x) {
439 std::unique_ptr<StdinReadArgs> args(reinterpret_cast<StdinReadArgs*>(x));
440 int state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800441
Siva Velusamy49ee7cf2015-08-28 16:37:29 -0700442 adb_thread_setname("stdin reader");
443
Josh Gao8dcdb572015-10-23 15:03:31 -0700444#ifndef __WIN32
445 // Mask SIGTTIN in case we're in a backgrounded process
446 sigset_t sigset;
447 sigemptyset(&sigset);
448 sigaddset(&sigset, SIGTTIN);
449 pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
450#endif
451
David Pursell606835a2015-09-08 17:17:02 -0700452 char raw_buffer[1024];
453 char* buffer_ptr = raw_buffer;
454 size_t buffer_size = sizeof(raw_buffer);
455 if (args->protocol) {
456 buffer_ptr = args->protocol->data();
457 buffer_size = args->protocol->data_capacity();
458 }
459
Elliott Hughesaa245492015-08-03 10:38:08 -0700460 while (true) {
David Pursell606835a2015-09-08 17:17:02 -0700461 // Use unix_read() rather than adb_read() for stdin.
462 D("stdin_read_thread(): pre unix_read(fdi=%d,...)", args->stdin_fd);
463 int r = unix_read(args->stdin_fd, buffer_ptr, buffer_size);
464 D("stdin_read_thread(): post unix_read(fdi=%d,...)", args->stdin_fd);
David Pursell1ed57f02015-10-06 15:30:03 -0700465 if (r <= 0) {
466 // Only devices using the shell protocol know to close subprocess
467 // stdin. For older devices we want to just leave the connection
468 // open, otherwise an unpredictable amount of return data could
469 // be lost due to the FD closing before all data has been received.
470 if (args->protocol) {
471 args->protocol->Write(ShellProtocol::kIdCloseStdin, 0);
472 }
473 break;
474 }
475 // If we made stdin raw, check input for the "~." escape sequence. In
476 // this situation signals like Ctrl+C are sent remotely rather than
477 // interpreted locally so this provides an emergency out if the remote
478 // process starts ignoring the signal. SSH also does this, see the
479 // "escape characters" section on the ssh man page for more info.
480 if (args->raw_stdin) {
481 for (int n = 0; n < r; n++){
482 switch(buffer_ptr[n]) {
483 case '\n':
484 state = 1;
485 break;
486 case '\r':
487 state = 1;
488 break;
489 case '~':
David Pursell08a27092015-10-20 14:19:36 -0700490 if(state == 1) {
491 state++;
492 } else {
493 state = 0;
494 }
David Pursell1ed57f02015-10-06 15:30:03 -0700495 break;
496 case '.':
497 if(state == 2) {
498 stdin_raw_restore(args->stdin_fd);
499 fprintf(stderr,"\n* disconnect *\n");
500 exit(0);
501 }
502 default:
503 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800504 }
505 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800506 }
David Pursell606835a2015-09-08 17:17:02 -0700507 if (args->protocol) {
508 if (!args->protocol->Write(ShellProtocol::kIdStdin, r)) {
509 break;
510 }
511 } else {
512 if (!WriteFdExactly(args->write_fd, buffer_ptr, r)) {
513 break;
514 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800515 }
516 }
David Pursell606835a2015-09-08 17:17:02 -0700517
518 return nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800519}
520
David Pursell1ed57f02015-10-06 15:30:03 -0700521// Returns a shell service string with the indicated arguments and command.
522static std::string ShellServiceString(bool use_shell_protocol,
523 const std::string& type_arg,
524 const std::string& command) {
525 std::vector<std::string> args;
526 if (use_shell_protocol) {
527 args.push_back(kShellServiceArgShellProtocol);
528 }
529 if (!type_arg.empty()) {
530 args.push_back(type_arg);
531 }
532
533 // Shell service string can look like: shell[,arg1,arg2,...]:[command].
534 return android::base::StringPrintf("shell%s%s:%s",
535 args.empty() ? "" : ",",
536 android::base::Join(args, ',').c_str(),
537 command.c_str());
538}
539
540// Connects to a shell on the device and read/writes data.
541//
542// Note: currently this function doesn't properly clean up resources; the
543// FD connected to the adb server is never closed and the stdin read thread
544// may never exit.
545//
546// On success returns the remote exit code if |use_shell_protocol| is true,
547// 0 otherwise. On failure returns 1.
548static int RemoteShell(bool use_shell_protocol, const std::string& type_arg,
549 const std::string& command) {
550 std::string service_string = ShellServiceString(use_shell_protocol,
551 type_arg, command);
552
553 // Make local stdin raw if the device allocates a PTY, which happens if:
554 // 1. We are explicitly asking for a PTY shell, or
555 // 2. We don't specify shell type and are starting an interactive session.
556 bool raw_stdin = (type_arg == kShellServiceArgPty ||
557 (type_arg.empty() && command.empty()));
558
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700559 std::string error;
David Pursell4e2fd362015-09-22 10:43:08 -0700560 int fd = adb_connect(service_string, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700561 if (fd < 0) {
562 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800563 return 1;
564 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800565
David Pursell606835a2015-09-08 17:17:02 -0700566 StdinReadArgs* args = new StdinReadArgs;
567 if (!args) {
568 LOG(ERROR) << "couldn't allocate StdinReadArgs object";
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700569 return 1;
570 }
David Pursell1ed57f02015-10-06 15:30:03 -0700571 args->stdin_fd = STDIN_FILENO;
David Pursell606835a2015-09-08 17:17:02 -0700572 args->write_fd = fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700573 args->raw_stdin = raw_stdin;
David Pursell606835a2015-09-08 17:17:02 -0700574 if (use_shell_protocol) {
575 args->protocol.reset(new ShellProtocol(args->write_fd));
576 }
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700577
David Pursell1ed57f02015-10-06 15:30:03 -0700578 if (raw_stdin) {
579 stdin_raw_init(STDIN_FILENO);
580 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800581
David Pursell606835a2015-09-08 17:17:02 -0700582 int exit_code = 0;
583 if (!adb_thread_create(stdin_read_thread, args)) {
584 PLOG(ERROR) << "error starting stdin read thread";
585 exit_code = 1;
586 delete args;
587 } else {
588 exit_code = read_and_dump(fd, use_shell_protocol);
589 }
Elliott Hughes9b0f3542015-05-05 13:41:21 -0700590
David Pursell1ed57f02015-10-06 15:30:03 -0700591 if (raw_stdin) {
592 stdin_raw_restore(STDIN_FILENO);
593 }
594
595 // TODO(dpursell): properly exit stdin_read_thread and close |fd|.
596
David Pursell606835a2015-09-08 17:17:02 -0700597 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800598}
599
600
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700601static std::string format_host_command(const char* command, TransportType type, const char* serial) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800602 if (serial) {
Elliott Hughes6452a892015-04-29 12:28:13 -0700603 return android::base::StringPrintf("host-serial:%s:%s", serial, command);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800604 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700605
606 const char* prefix = "host";
607 if (type == kTransportUsb) {
608 prefix = "host-usb";
609 } else if (type == kTransportLocal) {
610 prefix = "host-local";
611 }
612 return android::base::StringPrintf("%s:%s", prefix, command);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800613}
614
David Pursell4e2fd362015-09-22 10:43:08 -0700615// Returns the FeatureSet for the indicated transport.
616static FeatureSet GetFeatureSet(TransportType transport_type,
David Pursell71c83122015-09-14 15:33:50 -0700617 const char* serial) {
David Pursell4e2fd362015-09-22 10:43:08 -0700618 std::string result, error;
619
620 if (adb_query(format_host_command("features", transport_type, serial),
621 &result, &error)) {
622 return StringToFeatureSet(result);
David Pursell71c83122015-09-14 15:33:50 -0700623 }
David Pursell4e2fd362015-09-22 10:43:08 -0700624 return FeatureSet();
David Pursell71c83122015-09-14 15:33:50 -0700625}
626
Elliott Hughes6452a892015-04-29 12:28:13 -0700627static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700628 bool show_progress)
Doug Zongker447f0612012-01-09 14:54:53 -0800629{
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700630 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700631 int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700632 if (fd < 0) {
633 fprintf(stderr,"error: %s\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800634 return -1;
635 }
636
637 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800638 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800639
Elliott Hughes6452a892015-04-29 12:28:13 -0700640 unsigned total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800641 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800642
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700643 if (show_progress) {
Elliott Hughes3e7048c2015-07-27 21:21:39 -0700644 const char* x = strrchr(service, ':');
645 if (x) service = x + 1;
Doug Zongker447f0612012-01-09 14:54:53 -0800646 }
647
Elliott Hughes6452a892015-04-29 12:28:13 -0700648 while (sz > 0) {
Doug Zongker447f0612012-01-09 14:54:53 -0800649 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700650 if (!WriteFdExactly(fd, ptr, xfer)) {
651 std::string error;
652 adb_status(fd, &error);
653 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800654 return -1;
655 }
656 sz -= xfer;
657 ptr += xfer;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700658 if (show_progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100659 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800660 fflush(stdout);
661 }
662 }
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700663 if (show_progress) {
Doug Zongker447f0612012-01-09 14:54:53 -0800664 printf("\n");
665 }
666
Elliott Hughese67f1f82015-04-30 17:32:03 -0700667 if (!adb_status(fd, &error)) {
668 fprintf(stderr,"* error response '%s' *\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800669 return -1;
670 }
671
672 adb_close(fd);
673 return 0;
674}
675
Doug Zongker71fe5842014-06-26 15:35:36 -0700676#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
677
678/*
679 * The sideload-host protocol serves the data in a file (given on the
680 * command line) to the client, using a simple protocol:
681 *
682 * - The connect message includes the total number of bytes in the
683 * file and a block size chosen by us.
684 *
685 * - The other side sends the desired block number as eight decimal
686 * digits (eg "00000023" for block 23). Blocks are numbered from
687 * zero.
688 *
689 * - We send back the data of the requested block. The last block is
690 * likely to be partial; when the last block is requested we only
691 * send the part of the block that exists, it's not padded up to the
692 * block size.
693 *
694 * - When the other side sends "DONEDONE" instead of a block number,
695 * we hang up.
696 */
Elliott Hughes58305772015-04-17 13:57:15 -0700697static int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700698 unsigned sz;
699 size_t xfer = 0;
700 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800701 int last_percent = -1;
702 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700703
704 printf("loading: '%s'", fn);
705 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800706 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700707 if (data == 0) {
708 printf("\n");
709 fprintf(stderr, "* cannot read '%s' *\n", fn);
710 return -1;
711 }
712
Elliott Hughes6452a892015-04-29 12:28:13 -0700713 std::string service =
714 android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700715 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700716 int fd = adb_connect(service, &error);
Doug Zongker71fe5842014-06-26 15:35:36 -0700717 if (fd < 0) {
718 // Try falling back to the older sideload method. Maybe this
719 // is an older device that doesn't support sideload-host.
720 printf("\n");
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700721 status = adb_download_buffer("sideload", fn, data, sz, true);
Doug Zongker71fe5842014-06-26 15:35:36 -0700722 goto done;
723 }
724
Spencer Lowf055c192015-01-25 14:40:16 -0800725 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700726
Elliott Hughesa7090b92015-04-17 17:03:59 -0700727 while (true) {
Elliott Hughes6452a892015-04-29 12:28:13 -0700728 char buf[9];
Dan Albertcc731cc2015-02-24 21:26:58 -0800729 if (!ReadFdExactly(fd, buf, 8)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700730 fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
Doug Zongker71fe5842014-06-26 15:35:36 -0700731 status = -1;
732 goto done;
733 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700734 buf[8] = '\0';
Doug Zongker71fe5842014-06-26 15:35:36 -0700735
Elliott Hughes6452a892015-04-29 12:28:13 -0700736 if (strcmp("DONEDONE", buf) == 0) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700737 status = 0;
738 break;
739 }
740
Doug Zongker71fe5842014-06-26 15:35:36 -0700741 int block = strtol(buf, NULL, 10);
742
743 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
744 if (offset >= sz) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700745 fprintf(stderr, "* attempt to read block %d past end\n", block);
Doug Zongker71fe5842014-06-26 15:35:36 -0700746 status = -1;
747 goto done;
748 }
749 uint8_t* start = data + offset;
750 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
751 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
752 if (offset_end > sz) {
753 to_write = sz - offset;
754 }
755
Dan Albertcc731cc2015-02-24 21:26:58 -0800756 if(!WriteFdExactly(fd, start, to_write)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700757 adb_status(fd, &error);
758 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Doug Zongker71fe5842014-06-26 15:35:36 -0700759 status = -1;
760 goto done;
761 }
762 xfer += to_write;
763
764 // For normal OTA packages, we expect to transfer every byte
765 // twice, plus a bit of overhead (one read during
766 // verification, one read of each byte for installation, plus
767 // extra access to things like the zip central directory).
768 // This estimate of the completion becomes 100% when we've
769 // transferred ~2.13 (=100/47) times the package size.
770 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
771 if (percent != last_percent) {
772 printf("\rserving: '%s' (~%d%%) ", fn, percent);
773 fflush(stdout);
774 last_percent = percent;
775 }
776 }
777
Colin Cross6d6a8982014-07-07 14:12:41 -0700778 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700779
780 done:
781 if (fd >= 0) adb_close(fd);
782 free(data);
783 return status;
784}
785
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800786/**
787 * Run ppp in "notty" mode against a resource listed as the first parameter
788 * eg:
789 *
790 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
791 *
792 */
Elliott Hughes58305772015-04-17 13:57:15 -0700793static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800794#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800795 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
796 return -1;
797#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800798 if (argc < 2) {
799 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
800 argv[0]);
801
802 return 1;
803 }
804
Dan Albertbac34742015-02-25 17:51:28 -0800805 const char* adb_service_name = argv[1];
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700806 std::string error;
807 int fd = adb_connect(adb_service_name, &error);
808 if (fd < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800809 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700810 adb_service_name, error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800811 return 1;
812 }
813
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700814 pid_t pid = fork();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800815
816 if (pid < 0) {
817 perror("from fork()");
818 return 1;
819 } else if (pid == 0) {
820 int err;
821 int i;
822 const char **ppp_args;
823
824 // copy args
825 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
826 ppp_args[0] = "pppd";
827 for (i = 2 ; i < argc ; i++) {
828 //argv[2] and beyond become ppp_args[1] and beyond
829 ppp_args[i - 1] = argv[i];
830 }
831 ppp_args[i-1] = NULL;
832
833 // child side
834
835 dup2(fd, STDIN_FILENO);
836 dup2(fd, STDOUT_FILENO);
837 adb_close(STDERR_FILENO);
838 adb_close(fd);
839
840 err = execvp("pppd", (char * const *)ppp_args);
841
842 if (err < 0) {
843 perror("execing pppd");
844 }
845 exit(-1);
846 } else {
847 // parent side
848
849 adb_close(fd);
850 return 0;
851 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800852#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800853}
854
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700855static bool wait_for_device(const char* service, TransportType t, const char* serial) {
Elliott Hughes2b101112015-05-04 19:29:32 -0700856 // Was the caller vague about what they'd like us to wait for?
857 // If so, check they weren't more specific in their choice of transport type.
858 if (strcmp(service, "wait-for-device") == 0) {
859 if (t == kTransportUsb) {
860 service = "wait-for-usb";
861 } else if (t == kTransportLocal) {
862 service = "wait-for-local";
863 } else {
864 service = "wait-for-any";
865 }
866 }
867
868 std::string cmd = format_host_command(service, t, serial);
Elliott Hughes424af022015-05-29 17:55:19 -0700869 return adb_command(cmd);
Elliott Hughes2b101112015-05-04 19:29:32 -0700870}
871
David Pursell70ef7b42015-09-30 13:35:42 -0700872// Connects to the device "shell" service with |command| and prints the
873// resulting output.
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700874static int send_shell_command(TransportType transport_type, const char* serial,
David Pursell70ef7b42015-09-30 13:35:42 -0700875 const std::string& command,
876 bool disable_shell_protocol) {
877 // Only use shell protocol if it's supported and the caller doesn't want
878 // to explicitly disable it.
879 bool use_shell_protocol = false;
880 if (!disable_shell_protocol) {
881 FeatureSet features = GetFeatureSet(transport_type, serial);
882 use_shell_protocol = CanUseFeature(features, kFeatureShell2);
883 }
884
885 std::string service_string = ShellServiceString(use_shell_protocol, "",
886 command);
887
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700888 int fd;
889 while (true) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700890 std::string error;
David Pursell70ef7b42015-09-30 13:35:42 -0700891 fd = adb_connect(service_string, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700892 if (fd >= 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800893 break;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700894 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800895 fprintf(stderr,"- waiting for device -\n");
896 adb_sleep_ms(1000);
Elliott Hughes2b101112015-05-04 19:29:32 -0700897 wait_for_device("wait-for-device", transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800898 }
899
David Pursell70ef7b42015-09-30 13:35:42 -0700900 int exit_code = read_and_dump(fd, use_shell_protocol);
David Pursell71c83122015-09-14 15:33:50 -0700901
902 if (adb_close(fd) < 0) {
903 PLOG(ERROR) << "failure closing FD " << fd;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700904 }
David Pursell71c83122015-09-14 15:33:50 -0700905
906 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800907}
908
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700909static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700910 char* log_tags = getenv("ANDROID_LOG_TAGS");
911 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800912
David Pursell70ef7b42015-09-30 13:35:42 -0700913 std::string cmd = "export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800914
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700915 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700916 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -0800917 }
918
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700919 --argc;
920 ++argv;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700921 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700922 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800923 }
924
David Pursell70ef7b42015-09-30 13:35:42 -0700925 // No need for shell protocol with logcat, always disable for simplicity.
926 return send_shell_command(transport, serial, cmd, true);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800927}
928
Dan Albertbac34742015-02-25 17:51:28 -0800929static int backup(int argc, const char** argv) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700930 const char* filename = "./backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -0700931
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700932 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700933 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700934 if (!strcmp("-f", argv[i])) {
935 if (i == argc-1) {
936 fprintf(stderr, "adb: -f passed with no filename\n");
937 return usage();
938 }
939 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700940 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700941 argv[i++] = argv[j++];
942 }
943 argc -= 2;
944 argv[argc] = NULL;
945 }
Christopher Tated2f54152011-04-21 12:53:28 -0700946 }
947
Christopher Tatebb86bc52011-08-22 17:12:08 -0700948 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
949 if (argc < 2) return usage();
950
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800951 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700952 mkdirs(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700953 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700954 if (outFd < 0) {
955 fprintf(stderr, "adb: unable to open file %s\n", filename);
956 return -1;
957 }
958
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700959 std::string cmd = "backup:";
960 --argc;
961 ++argv;
962 while (argc-- > 0) {
963 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -0700964 }
965
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700966 D("backup. filename=%s cmd=%s", filename, cmd.c_str());
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700967 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700968 int fd = adb_connect(cmd, &error);
Christopher Tated2f54152011-04-21 12:53:28 -0700969 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700970 fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -0700971 adb_close(outFd);
972 return -1;
973 }
974
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800975 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700976 copy_to_file(fd, outFd);
977
978 adb_close(fd);
979 adb_close(outFd);
980 return 0;
981}
982
Dan Albertbac34742015-02-25 17:51:28 -0800983static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700984 if (argc != 2) return usage();
985
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700986 const char* filename = argv[1];
987 int tarFd = adb_open(filename, O_RDONLY);
Christopher Tate702967a2011-05-17 15:52:54 -0700988 if (tarFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700989 fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
Christopher Tate702967a2011-05-17 15:52:54 -0700990 return -1;
991 }
992
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700993 std::string error;
994 int fd = adb_connect("restore:", &error);
Christopher Tate702967a2011-05-17 15:52:54 -0700995 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700996 fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
Christopher Tate702967a2011-05-17 15:52:54 -0700997 adb_close(tarFd);
998 return -1;
999 }
1000
Christopher Tatebffa4ca2012-01-06 15:43:03 -08001001 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -07001002 copy_to_file(tarFd, fd);
1003
1004 adb_close(fd);
1005 adb_close(tarFd);
1006 return 0;
1007}
1008
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001009/* <hint> may be:
1010 * - A simple product name
1011 * e.g., "sooner"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001012 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1013 * e.g., "out/target/product/sooner"
1014 * - An absolute path to the PRODUCT_OUT dir
1015 * e.g., "/src/device/out/target/product/sooner"
1016 *
1017 * Given <hint>, try to construct an absolute path to the
1018 * ANDROID_PRODUCT_OUT dir.
1019 */
Elliott Hughes5c742702015-07-30 17:42:01 -07001020static std::string find_product_out_path(const std::string& hint) {
1021 if (hint.empty()) {
Elliott Hughes58305772015-04-17 13:57:15 -07001022 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001023 }
1024
Elliott Hughes58305772015-04-17 13:57:15 -07001025 // If it's already absolute, don't bother doing any work.
Elliott Hughes5c742702015-07-30 17:42:01 -07001026 if (adb_is_absolute_host_path(hint.c_str())) {
Elliott Hughes58305772015-04-17 13:57:15 -07001027 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001028 }
1029
Elliott Hughes58305772015-04-17 13:57:15 -07001030 // If there are any slashes in it, assume it's a relative path;
1031 // make it absolute.
Elliott Hughes5c742702015-07-30 17:42:01 -07001032 if (hint.find_first_of(OS_PATH_SEPARATORS) != std::string::npos) {
Elliott Hughesa7090b92015-04-17 17:03:59 -07001033 std::string cwd;
1034 if (!getcwd(&cwd)) {
1035 fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -07001036 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001037 }
Elliott Hughes5c742702015-07-30 17:42:01 -07001038 return android::base::StringPrintf("%s%c%s", cwd.c_str(), OS_PATH_SEPARATOR, hint.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001039 }
1040
Elliott Hughes58305772015-04-17 13:57:15 -07001041 // It's a string without any slashes. Try to do something with it.
1042 //
1043 // Try to find the root of the build tree, and build a PRODUCT_OUT
1044 // path from there.
Elliott Hughesa7090b92015-04-17 17:03:59 -07001045 char* top = getenv("ANDROID_BUILD_TOP");
Elliott Hughes58305772015-04-17 13:57:15 -07001046 if (top == nullptr) {
Elliott Hughesa7090b92015-04-17 17:03:59 -07001047 fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
Elliott Hughes58305772015-04-17 13:57:15 -07001048 return "";
1049 }
Elliott Hughesa7090b92015-04-17 17:03:59 -07001050
1051 std::string path = top;
Elliott Hughes58305772015-04-17 13:57:15 -07001052 path += OS_PATH_SEPARATOR_STR;
1053 path += "out";
1054 path += OS_PATH_SEPARATOR_STR;
1055 path += "target";
1056 path += OS_PATH_SEPARATOR_STR;
1057 path += "product";
1058 path += OS_PATH_SEPARATOR_STR;
1059 path += hint;
1060 if (!directory_exists(path)) {
1061 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
Elliott Hughes5c742702015-07-30 17:42:01 -07001062 "\"%s\" doesn't exist\n", hint.c_str(), path.c_str());
Elliott Hughesa7090b92015-04-17 17:03:59 -07001063 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001064 }
Elliott Hughes58305772015-04-17 13:57:15 -07001065 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001066}
1067
Dan Albertbac34742015-02-25 17:51:28 -08001068static void parse_push_pull_args(const char **arg, int narg, char const **path1,
Elliott Hughesaa245492015-08-03 10:38:08 -07001069 char const **path2, bool* show_progress,
Dan Albertbac34742015-02-25 17:51:28 -08001070 int *copy_attrs) {
Elliott Hughesaa245492015-08-03 10:38:08 -07001071 *show_progress = false;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001072 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001073
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001074 while (narg > 0) {
1075 if (!strcmp(*arg, "-p")) {
Elliott Hughesaa245492015-08-03 10:38:08 -07001076 *show_progress = true;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001077 } else if (!strcmp(*arg, "-a")) {
1078 *copy_attrs = 1;
1079 } else {
1080 break;
1081 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001082 ++arg;
1083 --narg;
1084 }
1085
1086 if (narg > 0) {
1087 *path1 = *arg;
1088 ++arg;
1089 --narg;
1090 }
1091
1092 if (narg > 0) {
1093 *path2 = *arg;
1094 }
1095}
1096
Elliott Hughes6452a892015-04-29 12:28:13 -07001097static int adb_connect_command(const std::string& command) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001098 std::string error;
1099 int fd = adb_connect(command, &error);
Elliott Hughes5677c232015-05-07 23:37:40 -07001100 if (fd < 0) {
1101 fprintf(stderr, "error: %s\n", error.c_str());
1102 return 1;
Tao Bao175b7bb2015-03-29 11:22:34 -07001103 }
Elliott Hughes5677c232015-05-07 23:37:40 -07001104 read_and_dump(fd);
1105 adb_close(fd);
1106 return 0;
Tao Bao175b7bb2015-03-29 11:22:34 -07001107}
1108
Elliott Hughes6452a892015-04-29 12:28:13 -07001109static int adb_query_command(const std::string& command) {
1110 std::string result;
1111 std::string error;
1112 if (!adb_query(command, &result, &error)) {
1113 fprintf(stderr, "error: %s\n", error.c_str());
1114 return 1;
1115 }
1116 printf("%s\n", result.c_str());
1117 return 0;
1118}
1119
Spencer Lowa13df302015-09-07 16:20:13 -07001120// Disallow stdin, stdout, and stderr.
1121static bool _is_valid_ack_reply_fd(const int ack_reply_fd) {
1122#ifdef _WIN32
1123 const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
1124 return (GetStdHandle(STD_INPUT_HANDLE) != ack_reply_handle) &&
1125 (GetStdHandle(STD_OUTPUT_HANDLE) != ack_reply_handle) &&
1126 (GetStdHandle(STD_ERROR_HANDLE) != ack_reply_handle);
1127#else
1128 return ack_reply_fd > 2;
1129#endif
1130}
1131
Elliott Hughesab52c182015-05-01 17:04:38 -07001132int adb_commandline(int argc, const char **argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001133 int no_daemon = 0;
1134 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001135 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001136 int r;
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001137 TransportType transport_type = kTransportAny;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001138 int ack_reply_fd = -1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001139
Elliott Hughes58305772015-04-17 13:57:15 -07001140 // If defined, this should be an absolute path to
1141 // the directory containing all of the various system images
1142 // for a particular product. If not defined, and the adb
1143 // command requires this information, then the user must
1144 // specify the path using "-p".
1145 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
1146 if (ANDROID_PRODUCT_OUT != nullptr) {
1147 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001148 }
1149 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1150
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001151 /* Validate and assign the server port */
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001152 const char* server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001153 int server_port = DEFAULT_ADB_PORT;
1154 if (server_port_str && strlen(server_port_str) > 0) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001155 server_port = strtol(server_port_str, nullptr, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001156 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001157 fprintf(stderr,
Spencer Lowf18fc082015-08-11 17:05:02 -07001158 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65536. Got \"%s\"\n",
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001159 server_port_str);
1160 return usage();
1161 }
1162 }
1163
Elliott Hughes8d28e192015-10-07 14:55:10 -07001164 // We need to check for -d and -e before we look at $ANDROID_SERIAL.
1165 const char* serial = nullptr;
1166
Riley Andrews98f58e82014-12-05 17:37:24 -08001167 while (argc > 0) {
1168 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001169 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001170 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001171 no_daemon = 1;
1172 } else if (!strcmp(argv[0], "fork-server")) {
1173 /* this is a special flag used only when the ADB client launches the ADB Server */
1174 is_daemon = 1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001175 } else if (!strcmp(argv[0], "--reply-fd")) {
1176 if (argc < 2) return usage();
1177 const char* reply_fd_str = argv[1];
1178 argc--;
1179 argv++;
1180 ack_reply_fd = strtol(reply_fd_str, nullptr, 10);
Spencer Lowa13df302015-09-07 16:20:13 -07001181 if (!_is_valid_ack_reply_fd(ack_reply_fd)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001182 fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
1183 return usage();
1184 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001185 } else if (!strncmp(argv[0], "-p", 2)) {
Elliott Hughes048b27c2015-07-31 13:18:22 -07001186 const char* product = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001187 if (argv[0][2] == '\0') {
1188 if (argc < 2) return usage();
1189 product = argv[1];
1190 argc--;
1191 argv++;
1192 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001193 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001194 }
Elliott Hughes048b27c2015-07-31 13:18:22 -07001195 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -07001196 if (gProductOutPath.empty()) {
1197 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001198 return usage();
1199 }
1200 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1201 if (isdigit(argv[0][2])) {
1202 serial = argv[0] + 2;
1203 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001204 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001205 serial = argv[1];
1206 argc--;
1207 argv++;
1208 }
1209 } else if (!strcmp(argv[0],"-d")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001210 transport_type = kTransportUsb;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001211 } else if (!strcmp(argv[0],"-e")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001212 transport_type = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001213 } else if (!strcmp(argv[0],"-a")) {
1214 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001215 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001216 const char *hostname = NULL;
1217 if (argv[0][2] == '\0') {
1218 if (argc < 2) return usage();
1219 hostname = argv[1];
1220 argc--;
1221 argv++;
1222 } else {
1223 hostname = argv[0] + 2;
1224 }
1225 adb_set_tcp_name(hostname);
1226
Riley Andrews98f58e82014-12-05 17:37:24 -08001227 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001228 if (argv[0][2] == '\0') {
1229 if (argc < 2) return usage();
1230 server_port_str = argv[1];
1231 argc--;
1232 argv++;
1233 } else {
1234 server_port_str = argv[0] + 2;
1235 }
1236 if (strlen(server_port_str) > 0) {
1237 server_port = (int) strtol(server_port_str, NULL, 0);
1238 if (server_port <= 0 || server_port > 65535) {
1239 fprintf(stderr,
1240 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1241 server_port_str);
1242 return usage();
1243 }
1244 } else {
1245 fprintf(stderr,
1246 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1247 return usage();
1248 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001249 } else {
1250 /* out of recognized modifiers and flags */
1251 break;
1252 }
1253 argc--;
1254 argv++;
1255 }
1256
Elliott Hughes8d28e192015-10-07 14:55:10 -07001257 // If none of -d, -e, or -s were specified, try $ANDROID_SERIAL.
1258 if (transport_type == kTransportAny && serial == nullptr) {
1259 serial = getenv("ANDROID_SERIAL");
1260 }
1261
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001262 adb_set_transport(transport_type, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001263 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001264
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001265 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001266 if (no_daemon || is_daemon) {
Spencer Low5c398d22015-08-08 15:07:07 -07001267 if (is_daemon && (ack_reply_fd == -1)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001268 fprintf(stderr, "reply fd for adb server to client communication not specified.\n");
1269 return usage();
1270 }
1271 r = adb_main(is_daemon, server_port, ack_reply_fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001272 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001273 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001274 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001275 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001276 fprintf(stderr,"* could not start server *\n");
1277 }
1278 return r;
1279 }
1280
Riley Andrews98f58e82014-12-05 17:37:24 -08001281 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001282 return usage();
1283 }
1284
Riley Andrewsc8514c82014-12-05 17:32:46 -08001285 /* handle wait-for-* prefix */
1286 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001287 const char* service = argv[0];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001288
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001289 if (!wait_for_device(service, transport_type, serial)) {
Riley Andrewsc8514c82014-12-05 17:32:46 -08001290 return 1;
1291 }
1292
Elliott Hughes2b101112015-05-04 19:29:32 -07001293 // Allow a command to be run after wait-for-device,
1294 // e.g. 'adb wait-for-device shell'.
Riley Andrewsc8514c82014-12-05 17:32:46 -08001295 if (argc == 1) {
1296 return 0;
1297 }
1298
1299 /* Fall through */
1300 argc--;
1301 argv++;
1302 }
1303
1304 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001305 if (!strcmp(argv[0], "devices")) {
Dan Albertbac34742015-02-25 17:51:28 -08001306 const char *listopt;
Elliott Hughes6452a892015-04-29 12:28:13 -07001307 if (argc < 2) {
Scott Andersone109d262012-04-20 11:21:14 -07001308 listopt = "";
Elliott Hughes6452a892015-04-29 12:28:13 -07001309 } else if (argc == 2 && !strcmp(argv[1], "-l")) {
Scott Andersone109d262012-04-20 11:21:14 -07001310 listopt = argv[1];
Elliott Hughes6452a892015-04-29 12:28:13 -07001311 } else {
Scott Andersone109d262012-04-20 11:21:14 -07001312 fprintf(stderr, "Usage: adb devices [-l]\n");
1313 return 1;
1314 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001315
1316 std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
1317 printf("List of devices attached\n");
1318 return adb_query_command(query);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001319 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001320 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001321 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001322 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001323 return 1;
1324 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001325
1326 std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
1327 return adb_query_command(query);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001328 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001329 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001330 if (argc > 2) {
1331 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1332 return 1;
1333 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001334
1335 std::string query = android::base::StringPrintf("host:disconnect:%s",
1336 (argc == 2) ? argv[1] : "");
1337 return adb_query_command(query);
Mike Lockwoodff196702009-08-24 15:58:40 -07001338 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001339 else if (!strcmp(argv[0], "emu")) {
Spencer Low142ec752015-05-06 16:13:42 -07001340 return adb_send_emulator_command(argc, argv, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001341 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001342 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001343 char h = (argv[0][0] == 'h');
1344
David Pursell4e2fd362015-09-22 10:43:08 -07001345 FeatureSet features = GetFeatureSet(transport_type, serial);
1346
David Pursell70ef7b42015-09-30 13:35:42 -07001347 bool use_shell_protocol = CanUseFeature(features, kFeatureShell2);
David Pursell4e2fd362015-09-22 10:43:08 -07001348 if (!use_shell_protocol) {
1349 D("shell protocol not supported, using raw data transfer");
1350 } else {
1351 D("using shell protocol");
1352 }
1353
1354 // Parse shell-specific command-line options.
1355 // argv[0] is always "shell".
1356 --argc;
1357 ++argv;
David Pursell08a27092015-10-20 14:19:36 -07001358 int t_arg_count = 0;
David Pursell4e2fd362015-09-22 10:43:08 -07001359 while (argc) {
1360 if (!strcmp(argv[0], "-T") || !strcmp(argv[0], "-t")) {
David Pursell70ef7b42015-09-30 13:35:42 -07001361 if (!CanUseFeature(features, kFeatureShell2)) {
David Pursell4e2fd362015-09-22 10:43:08 -07001362 fprintf(stderr, "error: target doesn't support PTY args -Tt\n");
1363 return 1;
1364 }
David Pursell08a27092015-10-20 14:19:36 -07001365 // Like ssh, -t arguments are cumulative so that multiple -t's
1366 // are needed to force a PTY.
1367 if (argv[0][1] == 't') {
1368 ++t_arg_count;
1369 } else {
1370 t_arg_count = -1;
1371 }
David Pursell70ef7b42015-09-30 13:35:42 -07001372 --argc;
1373 ++argv;
1374 } else if (!strcmp(argv[0], "-x")) {
1375 use_shell_protocol = false;
David Pursell4e2fd362015-09-22 10:43:08 -07001376 --argc;
1377 ++argv;
1378 } else {
1379 break;
1380 }
1381 }
David Pursell4e2fd362015-09-22 10:43:08 -07001382
David Pursell08a27092015-10-20 14:19:36 -07001383 std::string shell_type_arg;
1384 if (CanUseFeature(features, kFeatureShell2)) {
1385 if (t_arg_count < 0) {
1386 shell_type_arg = kShellServiceArgRaw;
1387 } else if (t_arg_count == 0) {
1388 // If stdin isn't a TTY, default to a raw shell; this lets
1389 // things like `adb shell < my_script.sh` work as expected.
1390 // Otherwise leave |shell_type_arg| blank which uses PTY for
1391 // interactive shells and raw for non-interactive.
1392 if (!isatty(STDIN_FILENO)) {
1393 shell_type_arg = kShellServiceArgRaw;
1394 }
1395 } else if (t_arg_count == 1) {
1396 // A single -t arg isn't enough to override implicit -T.
1397 if (!isatty(STDIN_FILENO)) {
1398 fprintf(stderr,
1399 "Remote PTY will not be allocated because stdin is not a terminal.\n"
1400 "Use multiple -t options to force remote PTY allocation.\n");
1401 shell_type_arg = kShellServiceArgRaw;
1402 } else {
1403 shell_type_arg = kShellServiceArgPty;
1404 }
1405 } else {
1406 shell_type_arg = kShellServiceArgPty;
1407 }
1408 }
1409
David Pursell1ed57f02015-10-06 15:30:03 -07001410 std::string command;
1411 if (argc) {
1412 // We don't escape here, just like ssh(1). http://b/20564385.
1413 command = android::base::Join(
1414 std::vector<const char*>(argv, argv + argc), ' ');
1415 }
1416
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001417 if (h) {
1418 printf("\x1b[41;33m");
1419 fflush(stdout);
1420 }
1421
David Pursell1ed57f02015-10-06 15:30:03 -07001422 r = RemoteShell(use_shell_protocol, shell_type_arg, command);
1423
1424 if (h) {
1425 printf("\x1b[0m");
1426 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001427 }
1428
David Pursell1ed57f02015-10-06 15:30:03 -07001429 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001430 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001431 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001432 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001433
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001434 std::string cmd = "exec:";
1435 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001436 argc -= 2;
1437 argv += 2;
1438 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001439 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001440 }
1441
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001442 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001443 int fd = adb_connect(cmd, &error);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001444 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001445 fprintf(stderr, "error: %s\n", error.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001446 return -1;
1447 }
1448
1449 if (exec_in) {
1450 copy_to_file(STDIN_FILENO, fd);
1451 } else {
1452 copy_to_file(fd, STDOUT_FILENO);
1453 }
1454
1455 adb_close(fd);
1456 return 0;
1457 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001458 else if (!strcmp(argv[0], "kill-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001459 std::string error;
1460 int fd = _adb_connect("host:kill", &error);
Spencer Lowf18fc082015-08-11 17:05:02 -07001461 if (fd == -2) {
1462 // Failed to make network connection to server. Don't output the
1463 // network error since that is expected.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001464 fprintf(stderr,"* server not running *\n");
Spencer Lowf18fc082015-08-11 17:05:02 -07001465 // Successful exit code because the server is already "killed".
1466 return 0;
1467 } else if (fd == -1) {
1468 // Some other error.
1469 fprintf(stderr, "error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001470 return 1;
Spencer Lowf18fc082015-08-11 17:05:02 -07001471 } else {
1472 // Successfully connected, kill command sent, okay status came back.
1473 // Server should exit() in a moment, if not already.
1474 adb_close(fd);
1475 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001476 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001477 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001478 else if (!strcmp(argv[0], "sideload")) {
1479 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001480 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001481 return 1;
1482 } else {
1483 return 0;
1484 }
1485 }
Elliott Hughes19d80b82015-07-21 16:13:40 -07001486 else if (!strcmp(argv[0], "tcpip") && argc > 1) {
1487 return adb_connect_command(android::base::StringPrintf("tcpip:%s", argv[1]));
1488 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001489 else if (!strcmp(argv[0], "remount") ||
1490 !strcmp(argv[0], "reboot") ||
1491 !strcmp(argv[0], "reboot-bootloader") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001492 !strcmp(argv[0], "usb") ||
1493 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001494 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001495 !strcmp(argv[0], "disable-verity") ||
1496 !strcmp(argv[0], "enable-verity")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001497 std::string command;
Tao Bao175b7bb2015-03-29 11:22:34 -07001498 if (!strcmp(argv[0], "reboot-bootloader")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001499 command = "reboot:bootloader";
Tao Bao175b7bb2015-03-29 11:22:34 -07001500 } else if (argc > 1) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001501 command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001502 } else {
Elliott Hughes5677c232015-05-07 23:37:40 -07001503 command = android::base::StringPrintf("%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001504 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001505 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001506 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001507 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001508 if (argc != 1) return usage();
David Pursell70ef7b42015-09-30 13:35:42 -07001509 // No need for shell protocol with bugreport, always disable for
1510 // simplicity.
1511 return send_shell_command(transport_type, serial, "bugreport", true);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001512 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001513 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
Elliott Hughes424af022015-05-29 17:55:19 -07001514 bool reverse = !strcmp(argv[0], "reverse");
1515 ++argv;
1516 --argc;
1517 if (argc < 1) return usage();
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001518
1519 // Determine the <host-prefix> for this command.
Elliott Hughes424af022015-05-29 17:55:19 -07001520 std::string host_prefix;
David 'Digit' Turner25258692013-03-21 21:07:42 +01001521 if (reverse) {
Elliott Hughes424af022015-05-29 17:55:19 -07001522 host_prefix = "reverse";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001523 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001524 if (serial) {
Elliott Hughes424af022015-05-29 17:55:19 -07001525 host_prefix = android::base::StringPrintf("host-serial:%s", serial);
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001526 } else if (transport_type == kTransportUsb) {
Elliott Hughes424af022015-05-29 17:55:19 -07001527 host_prefix = "host-usb";
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001528 } else if (transport_type == kTransportLocal) {
Elliott Hughes424af022015-05-29 17:55:19 -07001529 host_prefix = "host-local";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001530 } else {
Elliott Hughes424af022015-05-29 17:55:19 -07001531 host_prefix = "host";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001532 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001533 }
1534
Elliott Hughes424af022015-05-29 17:55:19 -07001535 std::string cmd;
1536 if (strcmp(argv[0], "--list") == 0) {
Elliott Hughesab52c182015-05-01 17:04:38 -07001537 if (argc != 1) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001538 return adb_query_command(host_prefix + ":list-forward");
1539 } else if (strcmp(argv[0], "--remove-all") == 0) {
1540 if (argc != 1) return usage();
1541 cmd = host_prefix + ":killforward-all";
1542 } else if (strcmp(argv[0], "--remove") == 0) {
1543 // forward --remove <local>
Elliott Hughesab52c182015-05-01 17:04:38 -07001544 if (argc != 2) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001545 cmd = host_prefix + ":killforward:" + argv[1];
1546 } else if (strcmp(argv[0], "--no-rebind") == 0) {
1547 // forward --no-rebind <local> <remote>
Elliott Hughesab52c182015-05-01 17:04:38 -07001548 if (argc != 3) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001549 cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
1550 } else {
1551 // forward <local> <remote>
1552 if (argc != 2) return usage();
1553 cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001554 }
1555
Elliott Hughes424af022015-05-29 17:55:19 -07001556 return adb_command(cmd) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001557 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001558 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001559 else if (!strcmp(argv[0], "ls")) {
1560 if (argc != 2) return usage();
Elliott Hughesaa245492015-08-03 10:38:08 -07001561 return do_sync_ls(argv[1]) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001562 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001563 else if (!strcmp(argv[0], "push")) {
Elliott Hughesaa245492015-08-03 10:38:08 -07001564 bool show_progress = false;
1565 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001566 const char* lpath = NULL, *rpath = NULL;
1567
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001568 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Elliott Hughesaa245492015-08-03 10:38:08 -07001569 if (!lpath || !rpath || copy_attrs != 0) return usage();
1570 return do_sync_push(lpath, rpath, show_progress) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001571 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001572 else if (!strcmp(argv[0], "pull")) {
Elliott Hughesaa245492015-08-03 10:38:08 -07001573 bool show_progress = false;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001574 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001575 const char* rpath = NULL, *lpath = ".";
1576
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001577 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Elliott Hughesaa245492015-08-03 10:38:08 -07001578 if (!rpath) return usage();
1579 return do_sync_pull(rpath, lpath, show_progress, copy_attrs) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001580 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001581 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001582 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001583 return install_app(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001584 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001585 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001586 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001587 return install_multiple_app(transport_type, serial, argc, argv);
Jeff Sharkey960df972014-06-09 17:30:57 -07001588 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001589 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001590 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001591 return uninstall_app(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001592 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001593 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001594 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001595 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001596 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001597 // No local path was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001598 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001599 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001600 list_only = true;
Anthony Newnam705c9442010-02-22 08:36:49 -06001601 if (argc == 3) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001602 src = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001603 } else {
Elliott Hughesd236d072015-04-21 10:17:07 -07001604 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001605 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001606 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001607 // A local path or "android"/"data" arg was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001608 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001609 } else {
1610 return usage();
1611 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001612
Elliott Hughesd236d072015-04-21 10:17:07 -07001613 if (src != "" &&
1614 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes58305772015-04-17 13:57:15 -07001615 return usage();
1616 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001617
Elliott Hughes58305772015-04-17 13:57:15 -07001618 std::string system_src_path = product_file("system");
1619 std::string data_src_path = product_file("data");
1620 std::string vendor_src_path = product_file("vendor");
1621 std::string oem_src_path = product_file("oem");
Elliott Hughes58305772015-04-17 13:57:15 -07001622
Elliott Hughesaa245492015-08-03 10:38:08 -07001623 bool okay = true;
1624 if (okay && (src.empty() || src == "system")) {
1625 okay = do_sync_sync(system_src_path, "/system", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001626 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001627 if (okay && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
1628 okay = do_sync_sync(vendor_src_path, "/vendor", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001629 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001630 if (okay && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
1631 okay = do_sync_sync(oem_src_path, "/oem", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001632 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001633 if (okay && (src.empty() || src == "data")) {
1634 okay = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001635 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001636 return okay ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001637 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001638 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001639 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001640 !strcmp(argv[0],"get-serialno") ||
1641 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001642 {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001643 return adb_query_command(format_host_command(argv[0], transport_type, serial));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001644 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001645 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001646 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001647 return logcat(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001648 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001649 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001650 return ppp(argc, argv);
1651 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001652 else if (!strcmp(argv[0], "start-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001653 std::string error;
Spencer Lowf18fc082015-08-11 17:05:02 -07001654 const int result = adb_connect("host:start-server", &error);
1655 if (result < 0) {
1656 fprintf(stderr, "error: %s\n", error.c_str());
1657 }
1658 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001659 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001660 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001661 return backup(argc, argv);
1662 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001663 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001664 return restore(argc, argv);
1665 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001666 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001667 if (argc < 2) return usage();
Yabin Cuiaed3c612015-09-22 15:52:57 -07001668 // Always print key generation information for keygen command.
1669 adb_trace_enable(AUTH);
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001670 return adb_auth_keygen(argv[1]);
1671 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001672 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001673 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001674 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001675 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001676 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001677 help();
1678 return 0;
1679 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001680 else if (!strcmp(argv[0], "version")) {
Elliott Hughes42ae2602015-08-12 08:32:10 -07001681 fprintf(stdout, "%s", adb_version().c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001682 return 0;
1683 }
Dan Albert90d4b732015-05-20 18:58:41 -07001684 else if (!strcmp(argv[0], "features")) {
David Pursell4e2fd362015-09-22 10:43:08 -07001685 // Only list the features common to both the adb client and the device.
1686 FeatureSet features = GetFeatureSet(transport_type, serial);
1687 for (const std::string& name : features) {
David Pursell70ef7b42015-09-30 13:35:42 -07001688 if (CanUseFeature(features, name)) {
David Pursell4e2fd362015-09-22 10:43:08 -07001689 printf("%s\n", name.c_str());
1690 }
1691 }
1692 return 0;
Dan Albert90d4b732015-05-20 18:58:41 -07001693 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001694
1695 usage();
1696 return 1;
1697}
1698
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001699static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
David Pursell70ef7b42015-09-30 13:35:42 -07001700 std::string cmd = "pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001701
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001702 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001703 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001704 }
1705
David Pursell70ef7b42015-09-30 13:35:42 -07001706 // TODO(dpursell): add command-line arguments to install/uninstall to
1707 // manually disable shell protocol if needed.
1708 return send_shell_command(transport, serial, cmd, false);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001709}
1710
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001711static int uninstall_app(TransportType transport, const char* serial, int argc, const char** argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001712 /* if the user choose the -k option, we refuse to do it until devices are
1713 out with the option to uninstall the remaining data somehow (adb/ui) */
1714 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1715 {
1716 printf(
1717 "The -k option uninstalls the application while retaining the data/cache.\n"
1718 "At the moment, there is no way to remove the remaining data.\n"
1719 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1720 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1721 return -1;
1722 }
1723
1724 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1725 return pm_command(transport, serial, argc, argv);
1726}
1727
Elliott Hughes5c742702015-07-30 17:42:01 -07001728static int delete_file(TransportType transport, const char* serial, const std::string& filename) {
David Pursell70ef7b42015-09-30 13:35:42 -07001729 std::string cmd = "rm -f " + escape_arg(filename);
1730 return send_shell_command(transport, serial, cmd, false);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001731}
1732
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001733static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
Dan Albert286bb6d2015-07-09 20:35:09 +00001734 static const char *const DATA_DEST = "/data/local/tmp/%s";
1735 static const char *const SD_DEST = "/sdcard/tmp/%s";
Kenny Root597ea5b2011-08-05 11:19:45 -07001736 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001737 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001738 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001739
1740 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001741 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001742 where = SD_DEST;
1743 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001744 }
1745
Jeff Sharkey960df972014-06-09 17:30:57 -07001746 // Find last APK argument.
1747 // All other arguments passed through verbatim.
1748 int last_apk = -1;
1749 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001750 const char* file = argv[i];
Elliott Hughes3e7048c2015-07-27 21:21:39 -07001751 const char* dot = strrchr(file, '.');
Jeff Sharkey960df972014-06-09 17:30:57 -07001752 if (dot && !strcasecmp(dot, ".apk")) {
1753 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1754 fprintf(stderr, "Invalid APK file: %s\n", file);
1755 return -1;
1756 }
1757
1758 last_apk = i;
1759 break;
1760 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001761 }
1762
Jeff Sharkey960df972014-06-09 17:30:57 -07001763 if (last_apk == -1) {
1764 fprintf(stderr, "Missing APK file\n");
1765 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001766 }
1767
Elliott Hughesaa245492015-08-03 10:38:08 -07001768 int result = -1;
Dan Albertbac34742015-02-25 17:51:28 -08001769 const char* apk_file = argv[last_apk];
Elliott Hughes5c742702015-07-30 17:42:01 -07001770 std::string apk_dest = android::base::StringPrintf(where, adb_basename(apk_file).c_str());
Elliott Hughesaa245492015-08-03 10:38:08 -07001771 if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
1772 argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
1773 result = pm_command(transport, serial, argc, argv);
Kenny Root597ea5b2011-08-05 11:19:45 -07001774
Kenny Root60733e92012-03-26 16:14:02 -07001775cleanup_apk:
Dan Albert286bb6d2015-07-09 20:35:09 +00001776 delete_file(transport, serial, apk_dest);
Elliott Hughesaa245492015-08-03 10:38:08 -07001777 return result;
Jeff Sharkey960df972014-06-09 17:30:57 -07001778}
1779
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001780static int install_multiple_app(TransportType transport, const char* serial, int argc,
Elliott Hughes58305772015-04-17 13:57:15 -07001781 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001782{
Jeff Sharkey960df972014-06-09 17:30:57 -07001783 int i;
1784 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001785 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001786
1787 // Find all APK arguments starting at end.
1788 // All other arguments passed through verbatim.
1789 int first_apk = -1;
1790 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001791 const char* file = argv[i];
Elliott Hughes3e7048c2015-07-27 21:21:39 -07001792 const char* dot = strrchr(file, '.');
Jeff Sharkey960df972014-06-09 17:30:57 -07001793 if (dot && !strcasecmp(dot, ".apk")) {
1794 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1795 fprintf(stderr, "Invalid APK file: %s\n", file);
1796 return -1;
1797 }
1798
1799 total_size += sb.st_size;
1800 first_apk = i;
1801 } else {
1802 break;
1803 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001804 }
1805
Jeff Sharkey960df972014-06-09 17:30:57 -07001806 if (first_apk == -1) {
1807 fprintf(stderr, "Missing APK file\n");
1808 return 1;
1809 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001810
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001811 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Jeff Sharkey960df972014-06-09 17:30:57 -07001812 for (i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001813 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001814 }
1815
1816 // Create install session
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001817 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001818 int fd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001819 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001820 fprintf(stderr, "Connect error for create: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001821 return -1;
1822 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001823 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001824 read_status_line(fd, buf, sizeof(buf));
1825 adb_close(fd);
1826
1827 int session_id = -1;
1828 if (!strncmp("Success", buf, 7)) {
1829 char* start = strrchr(buf, '[');
1830 char* end = strrchr(buf, ']');
1831 if (start && end) {
1832 *end = '\0';
1833 session_id = strtol(start + 1, NULL, 10);
1834 }
1835 }
1836 if (session_id < 0) {
1837 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001838 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001839 return -1;
1840 }
1841
1842 // Valid session, now stream the APKs
1843 int success = 1;
1844 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001845 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001846 if (stat(file, &sb) == -1) {
1847 fprintf(stderr, "Failed to stat %s\n", file);
1848 success = 0;
1849 goto finalize_session;
1850 }
1851
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001852 std::string cmd = android::base::StringPrintf(
1853 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
Elliott Hughes5c742702015-07-30 17:42:01 -07001854 static_cast<uint64_t>(sb.st_size), session_id, i, adb_basename(file).c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001855
1856 int localFd = adb_open(file, O_RDONLY);
1857 if (localFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001858 fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
Jeff Sharkey960df972014-06-09 17:30:57 -07001859 success = 0;
1860 goto finalize_session;
1861 }
1862
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001863 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001864 int remoteFd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001865 if (remoteFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001866 fprintf(stderr, "Connect error for write: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001867 adb_close(localFd);
1868 success = 0;
1869 goto finalize_session;
1870 }
1871
1872 copy_to_file(localFd, remoteFd);
1873 read_status_line(remoteFd, buf, sizeof(buf));
1874
1875 adb_close(localFd);
1876 adb_close(remoteFd);
1877
1878 if (strncmp("Success", buf, 7)) {
1879 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001880 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001881 success = 0;
1882 goto finalize_session;
1883 }
1884 }
1885
1886finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001887 // Commit session if we streamed everything okay; otherwise abandon
Elliott Hughes6452a892015-04-29 12:28:13 -07001888 std::string service =
1889 android::base::StringPrintf("exec:pm install-%s %d",
1890 success ? "commit" : "abandon", session_id);
1891 fd = adb_connect(service, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001892 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001893 fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001894 return -1;
1895 }
1896 read_status_line(fd, buf, sizeof(buf));
1897 adb_close(fd);
1898
1899 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001900 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001901 return 0;
1902 } else {
1903 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001904 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001905 return -1;
1906 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001907}