blob: 2aa922de13e72a6a7a72fb4b1ddb1daaf7f16be9 [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>
Josh Gao05786772015-10-30 16:57:19 -070036#include <vector>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070037
David Pursell606835a2015-09-08 17:17:02 -070038#include <base/logging.h>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070039#include <base/stringprintf.h>
David Pursell4e2fd362015-09-22 10:43:08 -070040#include <base/strings.h>
Elliott Hughes2baae3a2015-04-17 10:59:34 -070041
Yabin Cuid325e862014-11-17 14:48:25 -080042#if !defined(_WIN32)
Josh Gao8dcdb572015-10-23 15:03:31 -070043#include <signal.h>
Elliott Hughesc15b17f2015-11-03 11:18:40 -080044#include <termio.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080045#include <termios.h>
Dan Albert76649012015-02-24 15:51:19 -080046#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080047#endif
48
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080049#include "adb.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080050#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080051#include "adb_client.h"
52#include "adb_io.h"
Elliott Hughes58305772015-04-17 13:57:15 -070053#include "adb_utils.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080054#include "file_sync_service.h"
David Pursell70ef7b42015-09-30 13:35:42 -070055#include "services.h"
David Pursell606835a2015-09-08 17:17:02 -070056#include "shell_service.h"
57#include "transport.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080058
Elliott Hughes3bd73c12015-05-05 13:10:43 -070059static int install_app(TransportType t, const char* serial, int argc, const char** argv);
60static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
61static int uninstall_app(TransportType t, const char* serial, int argc, const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080062
Elliott Hughes58305772015-04-17 13:57:15 -070063static std::string gProductOutPath;
Matt Gumbeld7b33082012-11-14 10:16:17 -080064extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080065
Elliott Hughes58305772015-04-17 13:57:15 -070066static std::string product_file(const char *extra) {
67 if (gProductOutPath.empty()) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080068 fprintf(stderr, "adb: Product directory not specified; "
69 "use -p or define ANDROID_PRODUCT_OUT\n");
70 exit(1);
71 }
72
Elliott Hughes58305772015-04-17 13:57:15 -070073 return android::base::StringPrintf("%s%s%s",
74 gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080075}
76
Elliott Hughes58305772015-04-17 13:57:15 -070077static void help() {
Elliott Hughes42ae2602015-08-12 08:32:10 -070078 fprintf(stderr, "%s\n", adb_version().c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080079 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -080080 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080081 " -d - directs command to the only connected USB device\n"
82 " returns an error if more than one USB device is present.\n"
83 " -e - directs command to the only running emulator.\n"
84 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070085 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070086 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070087 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080088 " -p <product name or path> - simple product name like 'sooner', or\n"
89 " a relative/absolute path to a product\n"
90 " out directory like 'out/target/product/sooner'.\n"
91 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
92 " environment variable is used, which must\n"
93 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080094 " -H - Name of adb server host (default: localhost)\n"
95 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -070096 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070097 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -040098 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
99 " Port 5555 is used by default if no port number is specified.\n"
100 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
101 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200102 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -0400103 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800104 "\n"
105 "device commands:\n"
Josh Gao05786772015-10-30 16:57:19 -0700106 " adb push <local>... <remote>\n"
107 " - copy files/dirs to device\n"
108 " adb pull [-a] <remote>... <local>\n"
109 " - copy files/dirs from device\n"
110 " (-a preserves file 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"
Spencer Low587ea202015-11-02 17:34:49 -0800143 " adb reverse --no-rebind <remote> <local>\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100144 " - 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.
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800251void stdin_raw_init();
252void stdin_raw_restore();
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
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800257static void stdin_raw_init() {
258 if (tcgetattr(STDIN_FILENO, &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;
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800261 if (tcgetattr(STDIN_FILENO, &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
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800269 tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800270}
271
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800272static void stdin_raw_restore() {
273 tcsetattr(STDIN_FILENO, 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) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800362 stdin_raw_init();
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) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800404 stdin_raw_restore();
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
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800424static std::string format_host_command(const char* command,
425 TransportType type, const char* serial) {
426 if (serial) {
427 return android::base::StringPrintf("host-serial:%s:%s", serial, command);
428 }
429
430 const char* prefix = "host";
431 if (type == kTransportUsb) {
432 prefix = "host-usb";
433 } else if (type == kTransportLocal) {
434 prefix = "host-local";
435 }
436 return android::base::StringPrintf("%s:%s", prefix, command);
437}
438
439// Returns the FeatureSet for the indicated transport.
440static FeatureSet GetFeatureSet(TransportType transport_type, const char* serial) {
441 std::string result, error;
442 if (adb_query(format_host_command("features", transport_type, serial), &result, &error)) {
443 return StringToFeatureSet(result);
444 }
445 return FeatureSet();
446}
447
448static void send_window_size_change(int fd, std::unique_ptr<ShellProtocol>& shell) {
449#if !defined(_WIN32)
450 // Old devices can't handle window size changes.
451 if (shell == nullptr) return;
452
453 winsize ws;
454 if (ioctl(fd, TIOCGWINSZ, &ws) == -1) return;
455
456 // Send the new window size as human-readable ASCII for debugging convenience.
457 size_t l = snprintf(shell->data(), shell->data_capacity(), "%dx%d,%dx%d",
458 ws.ws_row, ws.ws_col, ws.ws_xpixel, ws.ws_ypixel);
459 shell->Write(ShellProtocol::kIdWindowSizeChange, l + 1);
460#endif
461}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800462
David Pursell606835a2015-09-08 17:17:02 -0700463// Used to pass multiple values to the stdin read thread.
464struct StdinReadArgs {
465 int stdin_fd, write_fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700466 bool raw_stdin;
David Pursell606835a2015-09-08 17:17:02 -0700467 std::unique_ptr<ShellProtocol> protocol;
468};
469
David Pursell606835a2015-09-08 17:17:02 -0700470// Loops to read from stdin and push the data to the given FD.
471// The argument should be a pointer to a StdinReadArgs object. This function
472// will take ownership of the object and delete it when finished.
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800473static void* stdin_read_thread_loop(void* x) {
David Pursell606835a2015-09-08 17:17:02 -0700474 std::unique_ptr<StdinReadArgs> args(reinterpret_cast<StdinReadArgs*>(x));
475 int state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800476
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800477#if !defined(_WIN32)
478 // Mask SIGTTIN in case we're in a backgrounded process.
Josh Gao8dcdb572015-10-23 15:03:31 -0700479 sigset_t sigset;
480 sigemptyset(&sigset);
481 sigaddset(&sigset, SIGTTIN);
482 pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
483#endif
484
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800485#if !defined(_WIN32)
486 // Unblock SIGWINCH for this thread, so our read(2) below will be
487 // interrupted if the window size changes.
488 sigset_t mask;
489 sigemptyset(&mask);
490 sigaddset(&mask, SIGWINCH);
491 pthread_sigmask(SIG_UNBLOCK, &mask, nullptr);
492#endif
493
494 // Set up the initial window size.
495 send_window_size_change(args->stdin_fd, args->protocol);
496
David Pursell606835a2015-09-08 17:17:02 -0700497 char raw_buffer[1024];
498 char* buffer_ptr = raw_buffer;
499 size_t buffer_size = sizeof(raw_buffer);
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800500 if (args->protocol != nullptr) {
David Pursell606835a2015-09-08 17:17:02 -0700501 buffer_ptr = args->protocol->data();
502 buffer_size = args->protocol->data_capacity();
503 }
504
Elliott Hughesaa245492015-08-03 10:38:08 -0700505 while (true) {
David Pursell606835a2015-09-08 17:17:02 -0700506 // Use unix_read() rather than adb_read() for stdin.
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800507 D("stdin_read_thread_loop(): pre unix_read(fdi=%d,...)", args->stdin_fd);
508#if !defined(_WIN32)
509#undef read
510 int r = read(args->stdin_fd, buffer_ptr, buffer_size);
511 if (r == -1 && errno == EINTR) {
512 send_window_size_change(args->stdin_fd, args->protocol);
513 continue;
514 }
515#define read ___xxx_read
516#else
David Pursell606835a2015-09-08 17:17:02 -0700517 int r = unix_read(args->stdin_fd, buffer_ptr, buffer_size);
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800518#endif
519 D("stdin_read_thread_loop(): post unix_read(fdi=%d,...)", args->stdin_fd);
David Pursell1ed57f02015-10-06 15:30:03 -0700520 if (r <= 0) {
521 // Only devices using the shell protocol know to close subprocess
522 // stdin. For older devices we want to just leave the connection
523 // open, otherwise an unpredictable amount of return data could
524 // be lost due to the FD closing before all data has been received.
525 if (args->protocol) {
526 args->protocol->Write(ShellProtocol::kIdCloseStdin, 0);
527 }
528 break;
529 }
530 // If we made stdin raw, check input for the "~." escape sequence. In
531 // this situation signals like Ctrl+C are sent remotely rather than
532 // interpreted locally so this provides an emergency out if the remote
533 // process starts ignoring the signal. SSH also does this, see the
534 // "escape characters" section on the ssh man page for more info.
535 if (args->raw_stdin) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800536 for (int n = 0; n < r; n++) {
537 switch (buffer_ptr[n]) {
David Pursell1ed57f02015-10-06 15:30:03 -0700538 case '\n':
539 state = 1;
540 break;
541 case '\r':
542 state = 1;
543 break;
544 case '~':
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800545 if (state == 1) {
David Pursell08a27092015-10-20 14:19:36 -0700546 state++;
547 } else {
548 state = 0;
549 }
David Pursell1ed57f02015-10-06 15:30:03 -0700550 break;
551 case '.':
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800552 if (state == 2) {
553 fprintf(stderr,"\r\n* disconnect *\r\n");
554 stdin_raw_restore();
David Pursell1ed57f02015-10-06 15:30:03 -0700555 exit(0);
556 }
557 default:
558 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800559 }
560 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800561 }
David Pursell606835a2015-09-08 17:17:02 -0700562 if (args->protocol) {
563 if (!args->protocol->Write(ShellProtocol::kIdStdin, r)) {
564 break;
565 }
566 } else {
567 if (!WriteFdExactly(args->write_fd, buffer_ptr, r)) {
568 break;
569 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800570 }
571 }
David Pursell606835a2015-09-08 17:17:02 -0700572
573 return nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800574}
575
David Pursell1ed57f02015-10-06 15:30:03 -0700576// Returns a shell service string with the indicated arguments and command.
577static std::string ShellServiceString(bool use_shell_protocol,
578 const std::string& type_arg,
579 const std::string& command) {
580 std::vector<std::string> args;
581 if (use_shell_protocol) {
582 args.push_back(kShellServiceArgShellProtocol);
583 }
584 if (!type_arg.empty()) {
585 args.push_back(type_arg);
586 }
587
588 // Shell service string can look like: shell[,arg1,arg2,...]:[command].
589 return android::base::StringPrintf("shell%s%s:%s",
590 args.empty() ? "" : ",",
591 android::base::Join(args, ',').c_str(),
592 command.c_str());
593}
594
595// Connects to a shell on the device and read/writes data.
596//
597// Note: currently this function doesn't properly clean up resources; the
598// FD connected to the adb server is never closed and the stdin read thread
599// may never exit.
600//
601// On success returns the remote exit code if |use_shell_protocol| is true,
602// 0 otherwise. On failure returns 1.
603static int RemoteShell(bool use_shell_protocol, const std::string& type_arg,
604 const std::string& command) {
605 std::string service_string = ShellServiceString(use_shell_protocol,
606 type_arg, command);
607
608 // Make local stdin raw if the device allocates a PTY, which happens if:
609 // 1. We are explicitly asking for a PTY shell, or
610 // 2. We don't specify shell type and are starting an interactive session.
611 bool raw_stdin = (type_arg == kShellServiceArgPty ||
612 (type_arg.empty() && command.empty()));
613
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700614 std::string error;
David Pursell4e2fd362015-09-22 10:43:08 -0700615 int fd = adb_connect(service_string, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700616 if (fd < 0) {
617 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800618 return 1;
619 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800620
David Pursell606835a2015-09-08 17:17:02 -0700621 StdinReadArgs* args = new StdinReadArgs;
622 if (!args) {
623 LOG(ERROR) << "couldn't allocate StdinReadArgs object";
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700624 return 1;
625 }
David Pursell1ed57f02015-10-06 15:30:03 -0700626 args->stdin_fd = STDIN_FILENO;
David Pursell606835a2015-09-08 17:17:02 -0700627 args->write_fd = fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700628 args->raw_stdin = raw_stdin;
David Pursell606835a2015-09-08 17:17:02 -0700629 if (use_shell_protocol) {
630 args->protocol.reset(new ShellProtocol(args->write_fd));
631 }
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700632
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800633 if (raw_stdin) stdin_raw_init();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800634
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800635#if !defined(_WIN32)
636 // Ensure our process is notified if the local window size changes.
637 // We use sigaction(2) to ensure that the SA_RESTART flag is not set,
638 // because the whole reason we're sending signals is to unblock the read(2)!
639 // That also means we don't need to do anything in the signal handler:
640 // the side effect of delivering the signal is all we need.
641 struct sigaction sa;
642 memset(&sa, 0, sizeof(sa));
643 sa.sa_handler = [](int) {};
644 sa.sa_flags = 0;
645 sigaction(SIGWINCH, &sa, nullptr);
646
647 // Now block SIGWINCH in this thread (the main thread) and all threads spawned
648 // from it. The stdin read thread will unblock this signal to ensure that it's
649 // the thread that receives the signal.
650 sigset_t mask;
651 sigemptyset(&mask);
652 sigaddset(&mask, SIGWINCH);
653 pthread_sigmask(SIG_BLOCK, &mask, nullptr);
654#endif
655
656 // TODO: combine read_and_dump with stdin_read_thread to make life simpler?
657 int exit_code = 1;
658 if (!adb_thread_create(stdin_read_thread_loop, args)) {
David Pursell606835a2015-09-08 17:17:02 -0700659 PLOG(ERROR) << "error starting stdin read thread";
David Pursell606835a2015-09-08 17:17:02 -0700660 delete args;
661 } else {
662 exit_code = read_and_dump(fd, use_shell_protocol);
663 }
Elliott Hughes9b0f3542015-05-05 13:41:21 -0700664
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800665 // TODO: properly exit stdin_read_thread_loop and close |fd|.
David Pursell1ed57f02015-10-06 15:30:03 -0700666
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800667 // TODO: we should probably install signal handlers for this.
668 // TODO: can we use atexit? even on Windows?
669 if (raw_stdin) stdin_raw_restore();
David Pursell1ed57f02015-10-06 15:30:03 -0700670
David Pursell606835a2015-09-08 17:17:02 -0700671 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800672}
673
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800674static int adb_shell(int argc, const char** argv,
675 TransportType transport_type, const char* serial) {
676 FeatureSet features = GetFeatureSet(transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800677
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800678 bool use_shell_protocol = CanUseFeature(features, kFeatureShell2);
679 if (!use_shell_protocol) {
680 D("shell protocol not supported, using raw data transfer");
681 } else {
682 D("using shell protocol");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800683 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700684
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800685 // Parse shell-specific command-line options.
686 // argv[0] is always "shell".
687 --argc;
688 ++argv;
689 int t_arg_count = 0;
690 while (argc) {
691 if (!strcmp(argv[0], "-T") || !strcmp(argv[0], "-t")) {
692 if (!CanUseFeature(features, kFeatureShell2)) {
693 fprintf(stderr, "error: target doesn't support PTY args -Tt\n");
694 return 1;
695 }
696 // Like ssh, -t arguments are cumulative so that multiple -t's
697 // are needed to force a PTY.
698 if (argv[0][1] == 't') {
699 ++t_arg_count;
700 } else {
701 t_arg_count = -1;
702 }
703 --argc;
704 ++argv;
705 } else if (!strcmp(argv[0], "-x")) {
706 use_shell_protocol = false;
707 --argc;
708 ++argv;
709 } else {
710 break;
711 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700712 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800713
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800714 std::string shell_type_arg;
715 if (CanUseFeature(features, kFeatureShell2)) {
716 if (t_arg_count < 0) {
717 shell_type_arg = kShellServiceArgRaw;
718 } else if (t_arg_count == 0) {
719 // If stdin isn't a TTY, default to a raw shell; this lets
720 // things like `adb shell < my_script.sh` work as expected.
721 // Otherwise leave |shell_type_arg| blank which uses PTY for
722 // interactive shells and raw for non-interactive.
723 if (!unix_isatty(STDIN_FILENO)) {
724 shell_type_arg = kShellServiceArgRaw;
725 }
726 } else if (t_arg_count == 1) {
727 // A single -t arg isn't enough to override implicit -T.
728 if (!unix_isatty(STDIN_FILENO)) {
729 fprintf(stderr,
730 "Remote PTY will not be allocated because stdin is not a terminal.\n"
731 "Use multiple -t options to force remote PTY allocation.\n");
732 shell_type_arg = kShellServiceArgRaw;
733 } else {
734 shell_type_arg = kShellServiceArgPty;
735 }
736 } else {
737 shell_type_arg = kShellServiceArgPty;
738 }
David Pursell71c83122015-09-14 15:33:50 -0700739 }
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800740
741 std::string command;
742 if (argc) {
743 // We don't escape here, just like ssh(1). http://b/20564385.
744 command = android::base::Join(std::vector<const char*>(argv, argv + argc), ' ');
745 }
746
747 return RemoteShell(use_shell_protocol, shell_type_arg, command);
David Pursell71c83122015-09-14 15:33:50 -0700748}
749
Elliott Hughes6452a892015-04-29 12:28:13 -0700750static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700751 bool show_progress)
Doug Zongker447f0612012-01-09 14:54:53 -0800752{
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700753 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700754 int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700755 if (fd < 0) {
756 fprintf(stderr,"error: %s\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800757 return -1;
758 }
759
760 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800761 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800762
Elliott Hughes6452a892015-04-29 12:28:13 -0700763 unsigned total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800764 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800765
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700766 if (show_progress) {
Elliott Hughes3e7048c2015-07-27 21:21:39 -0700767 const char* x = strrchr(service, ':');
768 if (x) service = x + 1;
Doug Zongker447f0612012-01-09 14:54:53 -0800769 }
770
Elliott Hughes6452a892015-04-29 12:28:13 -0700771 while (sz > 0) {
Doug Zongker447f0612012-01-09 14:54:53 -0800772 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700773 if (!WriteFdExactly(fd, ptr, xfer)) {
774 std::string error;
775 adb_status(fd, &error);
776 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Spencer Low351ecd12015-10-14 17:32:44 -0700777 adb_close(fd);
Doug Zongker447f0612012-01-09 14:54:53 -0800778 return -1;
779 }
780 sz -= xfer;
781 ptr += xfer;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700782 if (show_progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100783 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800784 fflush(stdout);
785 }
786 }
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700787 if (show_progress) {
Doug Zongker447f0612012-01-09 14:54:53 -0800788 printf("\n");
789 }
790
Elliott Hughese67f1f82015-04-30 17:32:03 -0700791 if (!adb_status(fd, &error)) {
792 fprintf(stderr,"* error response '%s' *\n", error.c_str());
Spencer Low351ecd12015-10-14 17:32:44 -0700793 adb_close(fd);
Doug Zongker447f0612012-01-09 14:54:53 -0800794 return -1;
795 }
796
797 adb_close(fd);
798 return 0;
799}
800
Doug Zongker71fe5842014-06-26 15:35:36 -0700801#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
802
803/*
804 * The sideload-host protocol serves the data in a file (given on the
805 * command line) to the client, using a simple protocol:
806 *
807 * - The connect message includes the total number of bytes in the
808 * file and a block size chosen by us.
809 *
810 * - The other side sends the desired block number as eight decimal
811 * digits (eg "00000023" for block 23). Blocks are numbered from
812 * zero.
813 *
814 * - We send back the data of the requested block. The last block is
815 * likely to be partial; when the last block is requested we only
816 * send the part of the block that exists, it's not padded up to the
817 * block size.
818 *
819 * - When the other side sends "DONEDONE" instead of a block number,
820 * we hang up.
821 */
Elliott Hughes58305772015-04-17 13:57:15 -0700822static int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700823 unsigned sz;
824 size_t xfer = 0;
825 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800826 int last_percent = -1;
827 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700828
829 printf("loading: '%s'", fn);
830 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800831 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700832 if (data == 0) {
833 printf("\n");
834 fprintf(stderr, "* cannot read '%s' *\n", fn);
835 return -1;
836 }
837
Elliott Hughes6452a892015-04-29 12:28:13 -0700838 std::string service =
839 android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700840 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700841 int fd = adb_connect(service, &error);
Doug Zongker71fe5842014-06-26 15:35:36 -0700842 if (fd < 0) {
843 // Try falling back to the older sideload method. Maybe this
844 // is an older device that doesn't support sideload-host.
845 printf("\n");
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700846 status = adb_download_buffer("sideload", fn, data, sz, true);
Doug Zongker71fe5842014-06-26 15:35:36 -0700847 goto done;
848 }
849
Spencer Lowf055c192015-01-25 14:40:16 -0800850 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700851
Elliott Hughesa7090b92015-04-17 17:03:59 -0700852 while (true) {
Elliott Hughes6452a892015-04-29 12:28:13 -0700853 char buf[9];
Dan Albertcc731cc2015-02-24 21:26:58 -0800854 if (!ReadFdExactly(fd, buf, 8)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700855 fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
Doug Zongker71fe5842014-06-26 15:35:36 -0700856 status = -1;
857 goto done;
858 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700859 buf[8] = '\0';
Doug Zongker71fe5842014-06-26 15:35:36 -0700860
Elliott Hughes6452a892015-04-29 12:28:13 -0700861 if (strcmp("DONEDONE", buf) == 0) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700862 status = 0;
863 break;
864 }
865
Doug Zongker71fe5842014-06-26 15:35:36 -0700866 int block = strtol(buf, NULL, 10);
867
868 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
869 if (offset >= sz) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700870 fprintf(stderr, "* attempt to read block %d past end\n", block);
Doug Zongker71fe5842014-06-26 15:35:36 -0700871 status = -1;
872 goto done;
873 }
874 uint8_t* start = data + offset;
875 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
876 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
877 if (offset_end > sz) {
878 to_write = sz - offset;
879 }
880
Dan Albertcc731cc2015-02-24 21:26:58 -0800881 if(!WriteFdExactly(fd, start, to_write)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700882 adb_status(fd, &error);
883 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Doug Zongker71fe5842014-06-26 15:35:36 -0700884 status = -1;
885 goto done;
886 }
887 xfer += to_write;
888
889 // For normal OTA packages, we expect to transfer every byte
890 // twice, plus a bit of overhead (one read during
891 // verification, one read of each byte for installation, plus
892 // extra access to things like the zip central directory).
893 // This estimate of the completion becomes 100% when we've
894 // transferred ~2.13 (=100/47) times the package size.
895 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
896 if (percent != last_percent) {
897 printf("\rserving: '%s' (~%d%%) ", fn, percent);
898 fflush(stdout);
899 last_percent = percent;
900 }
901 }
902
Colin Cross6d6a8982014-07-07 14:12:41 -0700903 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700904
905 done:
906 if (fd >= 0) adb_close(fd);
907 free(data);
908 return status;
909}
910
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800911/**
912 * Run ppp in "notty" mode against a resource listed as the first parameter
913 * eg:
914 *
915 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
916 *
917 */
Elliott Hughes58305772015-04-17 13:57:15 -0700918static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800919#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800920 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
921 return -1;
922#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800923 if (argc < 2) {
924 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
925 argv[0]);
926
927 return 1;
928 }
929
Dan Albertbac34742015-02-25 17:51:28 -0800930 const char* adb_service_name = argv[1];
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700931 std::string error;
932 int fd = adb_connect(adb_service_name, &error);
933 if (fd < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800934 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700935 adb_service_name, error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800936 return 1;
937 }
938
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700939 pid_t pid = fork();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800940
941 if (pid < 0) {
942 perror("from fork()");
943 return 1;
944 } else if (pid == 0) {
945 int err;
946 int i;
947 const char **ppp_args;
948
949 // copy args
950 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
951 ppp_args[0] = "pppd";
952 for (i = 2 ; i < argc ; i++) {
953 //argv[2] and beyond become ppp_args[1] and beyond
954 ppp_args[i - 1] = argv[i];
955 }
956 ppp_args[i-1] = NULL;
957
958 // child side
959
960 dup2(fd, STDIN_FILENO);
961 dup2(fd, STDOUT_FILENO);
962 adb_close(STDERR_FILENO);
963 adb_close(fd);
964
965 err = execvp("pppd", (char * const *)ppp_args);
966
967 if (err < 0) {
968 perror("execing pppd");
969 }
970 exit(-1);
971 } else {
972 // parent side
973
974 adb_close(fd);
975 return 0;
976 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800977#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800978}
979
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700980static bool wait_for_device(const char* service, TransportType t, const char* serial) {
Elliott Hughes2b101112015-05-04 19:29:32 -0700981 // Was the caller vague about what they'd like us to wait for?
982 // If so, check they weren't more specific in their choice of transport type.
983 if (strcmp(service, "wait-for-device") == 0) {
984 if (t == kTransportUsb) {
985 service = "wait-for-usb";
986 } else if (t == kTransportLocal) {
987 service = "wait-for-local";
988 } else {
989 service = "wait-for-any";
990 }
991 }
992
993 std::string cmd = format_host_command(service, t, serial);
Elliott Hughes424af022015-05-29 17:55:19 -0700994 return adb_command(cmd);
Elliott Hughes2b101112015-05-04 19:29:32 -0700995}
996
David Pursell70ef7b42015-09-30 13:35:42 -0700997// Connects to the device "shell" service with |command| and prints the
998// resulting output.
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700999static int send_shell_command(TransportType transport_type, const char* serial,
David Pursell70ef7b42015-09-30 13:35:42 -07001000 const std::string& command,
1001 bool disable_shell_protocol) {
1002 // Only use shell protocol if it's supported and the caller doesn't want
1003 // to explicitly disable it.
1004 bool use_shell_protocol = false;
1005 if (!disable_shell_protocol) {
1006 FeatureSet features = GetFeatureSet(transport_type, serial);
1007 use_shell_protocol = CanUseFeature(features, kFeatureShell2);
1008 }
1009
1010 std::string service_string = ShellServiceString(use_shell_protocol, "",
1011 command);
1012
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001013 int fd;
1014 while (true) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001015 std::string error;
David Pursell70ef7b42015-09-30 13:35:42 -07001016 fd = adb_connect(service_string, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001017 if (fd >= 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001018 break;
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001019 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001020 fprintf(stderr,"- waiting for device -\n");
1021 adb_sleep_ms(1000);
Elliott Hughes2b101112015-05-04 19:29:32 -07001022 wait_for_device("wait-for-device", transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001023 }
1024
David Pursell70ef7b42015-09-30 13:35:42 -07001025 int exit_code = read_and_dump(fd, use_shell_protocol);
David Pursell71c83122015-09-14 15:33:50 -07001026
1027 if (adb_close(fd) < 0) {
1028 PLOG(ERROR) << "failure closing FD " << fd;
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001029 }
David Pursell71c83122015-09-14 15:33:50 -07001030
1031 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001032}
1033
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001034static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001035 char* log_tags = getenv("ANDROID_LOG_TAGS");
1036 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001037
David Pursell70ef7b42015-09-30 13:35:42 -07001038 std::string cmd = "export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001039
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001040 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001041 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -08001042 }
1043
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001044 --argc;
1045 ++argv;
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001046 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001047 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001048 }
1049
David Pursell70ef7b42015-09-30 13:35:42 -07001050 // No need for shell protocol with logcat, always disable for simplicity.
1051 return send_shell_command(transport, serial, cmd, true);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001052}
1053
Dan Albertbac34742015-02-25 17:51:28 -08001054static int backup(int argc, const char** argv) {
Elliott Hughes24f165f2015-08-21 20:31:31 -07001055 const char* filename = "backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -07001056
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001057 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001058 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001059 if (!strcmp("-f", argv[i])) {
1060 if (i == argc-1) {
1061 fprintf(stderr, "adb: -f passed with no filename\n");
1062 return usage();
1063 }
1064 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001065 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001066 argv[i++] = argv[j++];
1067 }
1068 argc -= 2;
1069 argv[argc] = NULL;
1070 }
Christopher Tated2f54152011-04-21 12:53:28 -07001071 }
1072
Christopher Tatebb86bc52011-08-22 17:12:08 -07001073 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
1074 if (argc < 2) return usage();
1075
Christopher Tateb1dfffe2011-12-08 19:04:34 -08001076 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -07001077 mkdirs(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001078 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -07001079 if (outFd < 0) {
1080 fprintf(stderr, "adb: unable to open file %s\n", filename);
1081 return -1;
1082 }
1083
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001084 std::string cmd = "backup:";
1085 --argc;
1086 ++argv;
1087 while (argc-- > 0) {
1088 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -07001089 }
1090
Yabin Cui7a3f8d62015-09-02 17:44:28 -07001091 D("backup. filename=%s cmd=%s", filename, cmd.c_str());
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001092 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001093 int fd = adb_connect(cmd, &error);
Christopher Tated2f54152011-04-21 12:53:28 -07001094 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001095 fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -07001096 adb_close(outFd);
1097 return -1;
1098 }
1099
Christopher Tatebffa4ca2012-01-06 15:43:03 -08001100 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -07001101 copy_to_file(fd, outFd);
1102
1103 adb_close(fd);
1104 adb_close(outFd);
1105 return 0;
1106}
1107
Dan Albertbac34742015-02-25 17:51:28 -08001108static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -07001109 if (argc != 2) return usage();
1110
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001111 const char* filename = argv[1];
1112 int tarFd = adb_open(filename, O_RDONLY);
Christopher Tate702967a2011-05-17 15:52:54 -07001113 if (tarFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001114 fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
Christopher Tate702967a2011-05-17 15:52:54 -07001115 return -1;
1116 }
1117
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001118 std::string error;
1119 int fd = adb_connect("restore:", &error);
Christopher Tate702967a2011-05-17 15:52:54 -07001120 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001121 fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
Christopher Tate702967a2011-05-17 15:52:54 -07001122 adb_close(tarFd);
1123 return -1;
1124 }
1125
Christopher Tatebffa4ca2012-01-06 15:43:03 -08001126 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -07001127 copy_to_file(tarFd, fd);
1128
1129 adb_close(fd);
1130 adb_close(tarFd);
1131 return 0;
1132}
1133
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001134/* <hint> may be:
1135 * - A simple product name
1136 * e.g., "sooner"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001137 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1138 * e.g., "out/target/product/sooner"
1139 * - An absolute path to the PRODUCT_OUT dir
1140 * e.g., "/src/device/out/target/product/sooner"
1141 *
1142 * Given <hint>, try to construct an absolute path to the
1143 * ANDROID_PRODUCT_OUT dir.
1144 */
Elliott Hughes5c742702015-07-30 17:42:01 -07001145static std::string find_product_out_path(const std::string& hint) {
1146 if (hint.empty()) {
Elliott Hughes58305772015-04-17 13:57:15 -07001147 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001148 }
1149
Elliott Hughes58305772015-04-17 13:57:15 -07001150 // If it's already absolute, don't bother doing any work.
Elliott Hughes5c742702015-07-30 17:42:01 -07001151 if (adb_is_absolute_host_path(hint.c_str())) {
Elliott Hughes58305772015-04-17 13:57:15 -07001152 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001153 }
1154
Elliott Hughes58305772015-04-17 13:57:15 -07001155 // If there are any slashes in it, assume it's a relative path;
1156 // make it absolute.
Elliott Hughes5c742702015-07-30 17:42:01 -07001157 if (hint.find_first_of(OS_PATH_SEPARATORS) != std::string::npos) {
Elliott Hughesa7090b92015-04-17 17:03:59 -07001158 std::string cwd;
1159 if (!getcwd(&cwd)) {
1160 fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -07001161 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001162 }
Elliott Hughes5c742702015-07-30 17:42:01 -07001163 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 -08001164 }
1165
Elliott Hughes58305772015-04-17 13:57:15 -07001166 // It's a string without any slashes. Try to do something with it.
1167 //
1168 // Try to find the root of the build tree, and build a PRODUCT_OUT
1169 // path from there.
Elliott Hughesa7090b92015-04-17 17:03:59 -07001170 char* top = getenv("ANDROID_BUILD_TOP");
Elliott Hughes58305772015-04-17 13:57:15 -07001171 if (top == nullptr) {
Elliott Hughesa7090b92015-04-17 17:03:59 -07001172 fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
Elliott Hughes58305772015-04-17 13:57:15 -07001173 return "";
1174 }
Elliott Hughesa7090b92015-04-17 17:03:59 -07001175
1176 std::string path = top;
Elliott Hughes58305772015-04-17 13:57:15 -07001177 path += OS_PATH_SEPARATOR_STR;
1178 path += "out";
1179 path += OS_PATH_SEPARATOR_STR;
1180 path += "target";
1181 path += OS_PATH_SEPARATOR_STR;
1182 path += "product";
1183 path += OS_PATH_SEPARATOR_STR;
1184 path += hint;
1185 if (!directory_exists(path)) {
1186 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
Elliott Hughes5c742702015-07-30 17:42:01 -07001187 "\"%s\" doesn't exist\n", hint.c_str(), path.c_str());
Elliott Hughesa7090b92015-04-17 17:03:59 -07001188 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001189 }
Elliott Hughes58305772015-04-17 13:57:15 -07001190 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001191}
1192
Josh Gao05786772015-10-30 16:57:19 -07001193static void parse_push_pull_args(const char** arg, int narg,
1194 std::vector<const char*>* srcs,
1195 const char** dst, bool* copy_attrs) {
1196 *copy_attrs = false;
Mark Lindner76f2a932014-03-11 17:55:59 -07001197
Josh Gao05786772015-10-30 16:57:19 -07001198 srcs->clear();
1199 bool ignore_flags = false;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001200 while (narg > 0) {
Josh Gao05786772015-10-30 16:57:19 -07001201 if (ignore_flags || *arg[0] != '-') {
1202 srcs->push_back(*arg);
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001203 } else {
Josh Gao05786772015-10-30 16:57:19 -07001204 if (!strcmp(*arg, "-p")) {
1205 // Silently ignore for backwards compatibility.
1206 } else if (!strcmp(*arg, "-a")) {
1207 *copy_attrs = true;
1208 } else if (!strcmp(*arg, "--")) {
1209 ignore_flags = true;
1210 } else {
1211 fprintf(stderr, "adb: unrecognized option '%s'\n", *arg);
1212 exit(1);
1213 }
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001214 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001215 ++arg;
1216 --narg;
1217 }
1218
Josh Gao05786772015-10-30 16:57:19 -07001219 if (srcs->size() > 1) {
1220 *dst = srcs->back();
1221 srcs->pop_back();
Mark Lindner76f2a932014-03-11 17:55:59 -07001222 }
1223}
1224
Elliott Hughes6452a892015-04-29 12:28:13 -07001225static int adb_connect_command(const std::string& command) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001226 std::string error;
1227 int fd = adb_connect(command, &error);
Elliott Hughes5677c232015-05-07 23:37:40 -07001228 if (fd < 0) {
1229 fprintf(stderr, "error: %s\n", error.c_str());
1230 return 1;
Tao Bao175b7bb2015-03-29 11:22:34 -07001231 }
Elliott Hughes5677c232015-05-07 23:37:40 -07001232 read_and_dump(fd);
1233 adb_close(fd);
1234 return 0;
Tao Bao175b7bb2015-03-29 11:22:34 -07001235}
1236
Elliott Hughes6452a892015-04-29 12:28:13 -07001237static int adb_query_command(const std::string& command) {
1238 std::string result;
1239 std::string error;
1240 if (!adb_query(command, &result, &error)) {
1241 fprintf(stderr, "error: %s\n", error.c_str());
1242 return 1;
1243 }
1244 printf("%s\n", result.c_str());
1245 return 0;
1246}
1247
Spencer Lowa13df302015-09-07 16:20:13 -07001248// Disallow stdin, stdout, and stderr.
1249static bool _is_valid_ack_reply_fd(const int ack_reply_fd) {
1250#ifdef _WIN32
1251 const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
1252 return (GetStdHandle(STD_INPUT_HANDLE) != ack_reply_handle) &&
1253 (GetStdHandle(STD_OUTPUT_HANDLE) != ack_reply_handle) &&
1254 (GetStdHandle(STD_ERROR_HANDLE) != ack_reply_handle);
1255#else
1256 return ack_reply_fd > 2;
1257#endif
1258}
1259
Elliott Hughesab52c182015-05-01 17:04:38 -07001260int adb_commandline(int argc, const char **argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001261 int no_daemon = 0;
1262 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001263 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001264 int r;
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001265 TransportType transport_type = kTransportAny;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001266 int ack_reply_fd = -1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001267
Elliott Hughes58305772015-04-17 13:57:15 -07001268 // If defined, this should be an absolute path to
1269 // the directory containing all of the various system images
1270 // for a particular product. If not defined, and the adb
1271 // command requires this information, then the user must
1272 // specify the path using "-p".
1273 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
1274 if (ANDROID_PRODUCT_OUT != nullptr) {
1275 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001276 }
1277 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1278
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001279 /* Validate and assign the server port */
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001280 const char* server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001281 int server_port = DEFAULT_ADB_PORT;
1282 if (server_port_str && strlen(server_port_str) > 0) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001283 server_port = strtol(server_port_str, nullptr, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001284 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001285 fprintf(stderr,
Spencer Lowf18fc082015-08-11 17:05:02 -07001286 "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 +01001287 server_port_str);
1288 return usage();
1289 }
1290 }
1291
Elliott Hughes8d28e192015-10-07 14:55:10 -07001292 // We need to check for -d and -e before we look at $ANDROID_SERIAL.
1293 const char* serial = nullptr;
1294
Riley Andrews98f58e82014-12-05 17:37:24 -08001295 while (argc > 0) {
1296 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001297 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001298 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001299 no_daemon = 1;
1300 } else if (!strcmp(argv[0], "fork-server")) {
1301 /* this is a special flag used only when the ADB client launches the ADB Server */
1302 is_daemon = 1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001303 } else if (!strcmp(argv[0], "--reply-fd")) {
1304 if (argc < 2) return usage();
1305 const char* reply_fd_str = argv[1];
1306 argc--;
1307 argv++;
1308 ack_reply_fd = strtol(reply_fd_str, nullptr, 10);
Spencer Lowa13df302015-09-07 16:20:13 -07001309 if (!_is_valid_ack_reply_fd(ack_reply_fd)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001310 fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
1311 return usage();
1312 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001313 } else if (!strncmp(argv[0], "-p", 2)) {
Elliott Hughes048b27c2015-07-31 13:18:22 -07001314 const char* product = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001315 if (argv[0][2] == '\0') {
1316 if (argc < 2) return usage();
1317 product = argv[1];
1318 argc--;
1319 argv++;
1320 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001321 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001322 }
Elliott Hughes048b27c2015-07-31 13:18:22 -07001323 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -07001324 if (gProductOutPath.empty()) {
1325 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001326 return usage();
1327 }
1328 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1329 if (isdigit(argv[0][2])) {
1330 serial = argv[0] + 2;
1331 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001332 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001333 serial = argv[1];
1334 argc--;
1335 argv++;
1336 }
1337 } else if (!strcmp(argv[0],"-d")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001338 transport_type = kTransportUsb;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001339 } else if (!strcmp(argv[0],"-e")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001340 transport_type = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001341 } else if (!strcmp(argv[0],"-a")) {
1342 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001343 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001344 const char *hostname = NULL;
1345 if (argv[0][2] == '\0') {
1346 if (argc < 2) return usage();
1347 hostname = argv[1];
1348 argc--;
1349 argv++;
1350 } else {
1351 hostname = argv[0] + 2;
1352 }
1353 adb_set_tcp_name(hostname);
1354
Riley Andrews98f58e82014-12-05 17:37:24 -08001355 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001356 if (argv[0][2] == '\0') {
1357 if (argc < 2) return usage();
1358 server_port_str = argv[1];
1359 argc--;
1360 argv++;
1361 } else {
1362 server_port_str = argv[0] + 2;
1363 }
1364 if (strlen(server_port_str) > 0) {
1365 server_port = (int) strtol(server_port_str, NULL, 0);
1366 if (server_port <= 0 || server_port > 65535) {
1367 fprintf(stderr,
1368 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1369 server_port_str);
1370 return usage();
1371 }
1372 } else {
1373 fprintf(stderr,
1374 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1375 return usage();
1376 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001377 } else {
1378 /* out of recognized modifiers and flags */
1379 break;
1380 }
1381 argc--;
1382 argv++;
1383 }
1384
Elliott Hughes8d28e192015-10-07 14:55:10 -07001385 // If none of -d, -e, or -s were specified, try $ANDROID_SERIAL.
1386 if (transport_type == kTransportAny && serial == nullptr) {
1387 serial = getenv("ANDROID_SERIAL");
1388 }
1389
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001390 adb_set_transport(transport_type, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001391 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001392
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001393 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001394 if (no_daemon || is_daemon) {
Spencer Low5c398d22015-08-08 15:07:07 -07001395 if (is_daemon && (ack_reply_fd == -1)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001396 fprintf(stderr, "reply fd for adb server to client communication not specified.\n");
1397 return usage();
1398 }
1399 r = adb_main(is_daemon, server_port, ack_reply_fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001400 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001401 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001402 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001403 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001404 fprintf(stderr,"* could not start server *\n");
1405 }
1406 return r;
1407 }
1408
Riley Andrews98f58e82014-12-05 17:37:24 -08001409 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001410 return usage();
1411 }
1412
Riley Andrewsc8514c82014-12-05 17:32:46 -08001413 /* handle wait-for-* prefix */
1414 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001415 const char* service = argv[0];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001416
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001417 if (!wait_for_device(service, transport_type, serial)) {
Riley Andrewsc8514c82014-12-05 17:32:46 -08001418 return 1;
1419 }
1420
Elliott Hughes2b101112015-05-04 19:29:32 -07001421 // Allow a command to be run after wait-for-device,
1422 // e.g. 'adb wait-for-device shell'.
Riley Andrewsc8514c82014-12-05 17:32:46 -08001423 if (argc == 1) {
1424 return 0;
1425 }
1426
1427 /* Fall through */
1428 argc--;
1429 argv++;
1430 }
1431
1432 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001433 if (!strcmp(argv[0], "devices")) {
Dan Albertbac34742015-02-25 17:51:28 -08001434 const char *listopt;
Elliott Hughes6452a892015-04-29 12:28:13 -07001435 if (argc < 2) {
Scott Andersone109d262012-04-20 11:21:14 -07001436 listopt = "";
Elliott Hughes6452a892015-04-29 12:28:13 -07001437 } else if (argc == 2 && !strcmp(argv[1], "-l")) {
Scott Andersone109d262012-04-20 11:21:14 -07001438 listopt = argv[1];
Elliott Hughes6452a892015-04-29 12:28:13 -07001439 } else {
Scott Andersone109d262012-04-20 11:21:14 -07001440 fprintf(stderr, "Usage: adb devices [-l]\n");
1441 return 1;
1442 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001443
1444 std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
1445 printf("List of devices attached\n");
1446 return adb_query_command(query);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001447 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001448 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001449 if (argc != 2) {
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001450 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001451 return 1;
1452 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001453
1454 std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
1455 return adb_query_command(query);
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001456 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001457 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79ad2010-05-24 10:44:35 -04001458 if (argc > 2) {
1459 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1460 return 1;
1461 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001462
1463 std::string query = android::base::StringPrintf("host:disconnect:%s",
1464 (argc == 2) ? argv[1] : "");
1465 return adb_query_command(query);
Mike Lockwoodff196702009-08-24 15:58:40 -07001466 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001467 else if (!strcmp(argv[0], "emu")) {
Spencer Low142ec752015-05-06 16:13:42 -07001468 return adb_send_emulator_command(argc, argv, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001469 }
Elliott Hughesc15b17f2015-11-03 11:18:40 -08001470 else if (!strcmp(argv[0], "shell")) {
1471 return adb_shell(argc, argv, transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001472 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001473 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001474 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001475
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001476 std::string cmd = "exec:";
1477 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001478 argc -= 2;
1479 argv += 2;
1480 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001481 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001482 }
1483
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001484 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001485 int fd = adb_connect(cmd, &error);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001486 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001487 fprintf(stderr, "error: %s\n", error.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001488 return -1;
1489 }
1490
1491 if (exec_in) {
1492 copy_to_file(STDIN_FILENO, fd);
1493 } else {
1494 copy_to_file(fd, STDOUT_FILENO);
1495 }
1496
1497 adb_close(fd);
1498 return 0;
1499 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001500 else if (!strcmp(argv[0], "kill-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001501 std::string error;
1502 int fd = _adb_connect("host:kill", &error);
Spencer Lowf18fc082015-08-11 17:05:02 -07001503 if (fd == -2) {
1504 // Failed to make network connection to server. Don't output the
1505 // network error since that is expected.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001506 fprintf(stderr,"* server not running *\n");
Spencer Lowf18fc082015-08-11 17:05:02 -07001507 // Successful exit code because the server is already "killed".
1508 return 0;
1509 } else if (fd == -1) {
1510 // Some other error.
1511 fprintf(stderr, "error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001512 return 1;
Spencer Lowf18fc082015-08-11 17:05:02 -07001513 } else {
1514 // Successfully connected, kill command sent, okay status came back.
1515 // Server should exit() in a moment, if not already.
Spencer Low351ecd12015-10-14 17:32:44 -07001516 ReadOrderlyShutdown(fd);
Spencer Lowf18fc082015-08-11 17:05:02 -07001517 adb_close(fd);
1518 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001519 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001520 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001521 else if (!strcmp(argv[0], "sideload")) {
1522 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001523 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001524 return 1;
1525 } else {
1526 return 0;
1527 }
1528 }
Elliott Hughes19d80b82015-07-21 16:13:40 -07001529 else if (!strcmp(argv[0], "tcpip") && argc > 1) {
1530 return adb_connect_command(android::base::StringPrintf("tcpip:%s", argv[1]));
1531 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001532 else if (!strcmp(argv[0], "remount") ||
1533 !strcmp(argv[0], "reboot") ||
1534 !strcmp(argv[0], "reboot-bootloader") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001535 !strcmp(argv[0], "usb") ||
1536 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001537 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001538 !strcmp(argv[0], "disable-verity") ||
1539 !strcmp(argv[0], "enable-verity")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001540 std::string command;
Tao Bao175b7bb2015-03-29 11:22:34 -07001541 if (!strcmp(argv[0], "reboot-bootloader")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001542 command = "reboot:bootloader";
Tao Bao175b7bb2015-03-29 11:22:34 -07001543 } else if (argc > 1) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001544 command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001545 } else {
Elliott Hughes5677c232015-05-07 23:37:40 -07001546 command = android::base::StringPrintf("%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001547 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001548 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001549 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001550 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001551 if (argc != 1) return usage();
David Pursell70ef7b42015-09-30 13:35:42 -07001552 // No need for shell protocol with bugreport, always disable for
1553 // simplicity.
1554 return send_shell_command(transport_type, serial, "bugreport", true);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001555 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001556 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
Elliott Hughes424af022015-05-29 17:55:19 -07001557 bool reverse = !strcmp(argv[0], "reverse");
1558 ++argv;
1559 --argc;
1560 if (argc < 1) return usage();
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001561
1562 // Determine the <host-prefix> for this command.
Elliott Hughes424af022015-05-29 17:55:19 -07001563 std::string host_prefix;
David 'Digit' Turner25258692013-03-21 21:07:42 +01001564 if (reverse) {
Elliott Hughes424af022015-05-29 17:55:19 -07001565 host_prefix = "reverse";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001566 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001567 if (serial) {
Elliott Hughes424af022015-05-29 17:55:19 -07001568 host_prefix = android::base::StringPrintf("host-serial:%s", serial);
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001569 } else if (transport_type == kTransportUsb) {
Elliott Hughes424af022015-05-29 17:55:19 -07001570 host_prefix = "host-usb";
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001571 } else if (transport_type == kTransportLocal) {
Elliott Hughes424af022015-05-29 17:55:19 -07001572 host_prefix = "host-local";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001573 } else {
Elliott Hughes424af022015-05-29 17:55:19 -07001574 host_prefix = "host";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001575 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001576 }
1577
Elliott Hughes424af022015-05-29 17:55:19 -07001578 std::string cmd;
1579 if (strcmp(argv[0], "--list") == 0) {
Elliott Hughesab52c182015-05-01 17:04:38 -07001580 if (argc != 1) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001581 return adb_query_command(host_prefix + ":list-forward");
1582 } else if (strcmp(argv[0], "--remove-all") == 0) {
1583 if (argc != 1) return usage();
1584 cmd = host_prefix + ":killforward-all";
1585 } else if (strcmp(argv[0], "--remove") == 0) {
1586 // forward --remove <local>
Elliott Hughesab52c182015-05-01 17:04:38 -07001587 if (argc != 2) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001588 cmd = host_prefix + ":killforward:" + argv[1];
1589 } else if (strcmp(argv[0], "--no-rebind") == 0) {
1590 // forward --no-rebind <local> <remote>
Elliott Hughesab52c182015-05-01 17:04:38 -07001591 if (argc != 3) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001592 cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
1593 } else {
1594 // forward <local> <remote>
1595 if (argc != 2) return usage();
1596 cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001597 }
1598
Elliott Hughes424af022015-05-29 17:55:19 -07001599 return adb_command(cmd) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001600 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001601 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001602 else if (!strcmp(argv[0], "ls")) {
1603 if (argc != 2) return usage();
Elliott Hughesaa245492015-08-03 10:38:08 -07001604 return do_sync_ls(argv[1]) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001605 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001606 else if (!strcmp(argv[0], "push")) {
Josh Gao05786772015-10-30 16:57:19 -07001607 bool copy_attrs = false;
1608 std::vector<const char*> srcs;
1609 const char* dst = nullptr;
Mark Lindner76f2a932014-03-11 17:55:59 -07001610
Josh Gao05786772015-10-30 16:57:19 -07001611 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
1612 if (srcs.empty() || !dst) return usage();
1613 return do_sync_push(srcs, dst) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001614 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001615 else if (!strcmp(argv[0], "pull")) {
Josh Gao05786772015-10-30 16:57:19 -07001616 bool copy_attrs = false;
1617 std::vector<const char*> srcs;
1618 const char* dst = ".";
Mark Lindner76f2a932014-03-11 17:55:59 -07001619
Josh Gao05786772015-10-30 16:57:19 -07001620 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
1621 if (srcs.empty()) return usage();
1622 return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001623 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001624 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001625 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001626 return install_app(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001627 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001628 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001629 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001630 return install_multiple_app(transport_type, serial, argc, argv);
Jeff Sharkey960df972014-06-09 17:30:57 -07001631 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001632 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001633 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001634 return uninstall_app(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001635 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001636 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001637 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001638 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001639 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001640 // No local path was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001641 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001642 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001643 list_only = true;
Anthony Newnam705c9442010-02-22 08:36:49 -06001644 if (argc == 3) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001645 src = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001646 } else {
Elliott Hughesd236d072015-04-21 10:17:07 -07001647 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001648 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001649 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001650 // A local path or "android"/"data" arg was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001651 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001652 } else {
1653 return usage();
1654 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001655
Elliott Hughesd236d072015-04-21 10:17:07 -07001656 if (src != "" &&
1657 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes58305772015-04-17 13:57:15 -07001658 return usage();
1659 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001660
Elliott Hughes58305772015-04-17 13:57:15 -07001661 std::string system_src_path = product_file("system");
1662 std::string data_src_path = product_file("data");
1663 std::string vendor_src_path = product_file("vendor");
1664 std::string oem_src_path = product_file("oem");
Elliott Hughes58305772015-04-17 13:57:15 -07001665
Elliott Hughesaa245492015-08-03 10:38:08 -07001666 bool okay = true;
1667 if (okay && (src.empty() || src == "system")) {
1668 okay = do_sync_sync(system_src_path, "/system", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001669 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001670 if (okay && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
1671 okay = do_sync_sync(vendor_src_path, "/vendor", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001672 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001673 if (okay && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
1674 okay = do_sync_sync(oem_src_path, "/oem", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001675 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001676 if (okay && (src.empty() || src == "data")) {
1677 okay = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001678 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001679 return okay ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001680 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001681 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001682 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001683 !strcmp(argv[0],"get-serialno") ||
1684 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001685 {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001686 return adb_query_command(format_host_command(argv[0], transport_type, serial));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001687 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001688 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001689 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001690 return logcat(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001691 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001692 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001693 return ppp(argc, argv);
1694 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001695 else if (!strcmp(argv[0], "start-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001696 std::string error;
Spencer Lowf18fc082015-08-11 17:05:02 -07001697 const int result = adb_connect("host:start-server", &error);
1698 if (result < 0) {
1699 fprintf(stderr, "error: %s\n", error.c_str());
1700 }
1701 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001702 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001703 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001704 return backup(argc, argv);
1705 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001706 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001707 return restore(argc, argv);
1708 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001709 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001710 if (argc < 2) return usage();
Yabin Cuiaed3c612015-09-22 15:52:57 -07001711 // Always print key generation information for keygen command.
1712 adb_trace_enable(AUTH);
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001713 return adb_auth_keygen(argv[1]);
1714 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001715 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001716 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001717 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001718 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001719 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001720 help();
1721 return 0;
1722 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001723 else if (!strcmp(argv[0], "version")) {
Elliott Hughes42ae2602015-08-12 08:32:10 -07001724 fprintf(stdout, "%s", adb_version().c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001725 return 0;
1726 }
Dan Albert90d4b732015-05-20 18:58:41 -07001727 else if (!strcmp(argv[0], "features")) {
David Pursell4e2fd362015-09-22 10:43:08 -07001728 // Only list the features common to both the adb client and the device.
1729 FeatureSet features = GetFeatureSet(transport_type, serial);
1730 for (const std::string& name : features) {
David Pursell70ef7b42015-09-30 13:35:42 -07001731 if (CanUseFeature(features, name)) {
David Pursell4e2fd362015-09-22 10:43:08 -07001732 printf("%s\n", name.c_str());
1733 }
1734 }
1735 return 0;
Dan Albert90d4b732015-05-20 18:58:41 -07001736 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001737
1738 usage();
1739 return 1;
1740}
1741
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001742static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
David Pursell70ef7b42015-09-30 13:35:42 -07001743 std::string cmd = "pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001744
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001745 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001746 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001747 }
1748
David Pursell70ef7b42015-09-30 13:35:42 -07001749 // TODO(dpursell): add command-line arguments to install/uninstall to
1750 // manually disable shell protocol if needed.
1751 return send_shell_command(transport, serial, cmd, false);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001752}
1753
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001754static int uninstall_app(TransportType transport, const char* serial, int argc, const char** argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001755 /* if the user choose the -k option, we refuse to do it until devices are
1756 out with the option to uninstall the remaining data somehow (adb/ui) */
1757 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1758 {
1759 printf(
1760 "The -k option uninstalls the application while retaining the data/cache.\n"
1761 "At the moment, there is no way to remove the remaining data.\n"
1762 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1763 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1764 return -1;
1765 }
1766
1767 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1768 return pm_command(transport, serial, argc, argv);
1769}
1770
Elliott Hughes5c742702015-07-30 17:42:01 -07001771static int delete_file(TransportType transport, const char* serial, const std::string& filename) {
David Pursell70ef7b42015-09-30 13:35:42 -07001772 std::string cmd = "rm -f " + escape_arg(filename);
1773 return send_shell_command(transport, serial, cmd, false);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001774}
1775
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001776static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
Dan Albert286bb6d2015-07-09 20:35:09 +00001777 static const char *const DATA_DEST = "/data/local/tmp/%s";
1778 static const char *const SD_DEST = "/sdcard/tmp/%s";
Kenny Root597ea5b2011-08-05 11:19:45 -07001779 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001780 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001781 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001782
1783 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001784 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001785 where = SD_DEST;
1786 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001787 }
1788
Jeff Sharkey960df972014-06-09 17:30:57 -07001789 // Find last APK argument.
1790 // All other arguments passed through verbatim.
1791 int last_apk = -1;
1792 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001793 const char* file = argv[i];
Elliott Hughes3e7048c2015-07-27 21:21:39 -07001794 const char* dot = strrchr(file, '.');
Jeff Sharkey960df972014-06-09 17:30:57 -07001795 if (dot && !strcasecmp(dot, ".apk")) {
1796 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1797 fprintf(stderr, "Invalid APK file: %s\n", file);
1798 return -1;
1799 }
1800
1801 last_apk = i;
1802 break;
1803 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001804 }
1805
Jeff Sharkey960df972014-06-09 17:30:57 -07001806 if (last_apk == -1) {
1807 fprintf(stderr, "Missing APK file\n");
1808 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001809 }
1810
Elliott Hughesaa245492015-08-03 10:38:08 -07001811 int result = -1;
Josh Gao05786772015-10-30 16:57:19 -07001812 std::vector<const char*> apk_file = {argv[last_apk]};
1813 std::string apk_dest = android::base::StringPrintf(
1814 where, adb_basename(argv[last_apk]).c_str());
Elliott Hughesb708d162015-10-27 16:03:15 -07001815 if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
Elliott Hughesaa245492015-08-03 10:38:08 -07001816 argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
1817 result = pm_command(transport, serial, argc, argv);
Kenny Root597ea5b2011-08-05 11:19:45 -07001818
Kenny Root60733e92012-03-26 16:14:02 -07001819cleanup_apk:
Dan Albert286bb6d2015-07-09 20:35:09 +00001820 delete_file(transport, serial, apk_dest);
Elliott Hughesaa245492015-08-03 10:38:08 -07001821 return result;
Jeff Sharkey960df972014-06-09 17:30:57 -07001822}
1823
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001824static int install_multiple_app(TransportType transport, const char* serial, int argc,
Elliott Hughes58305772015-04-17 13:57:15 -07001825 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001826{
Jeff Sharkey960df972014-06-09 17:30:57 -07001827 int i;
1828 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001829 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001830
1831 // Find all APK arguments starting at end.
1832 // All other arguments passed through verbatim.
1833 int first_apk = -1;
1834 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001835 const char* file = argv[i];
Elliott Hughes3e7048c2015-07-27 21:21:39 -07001836 const char* dot = strrchr(file, '.');
Jeff Sharkey960df972014-06-09 17:30:57 -07001837 if (dot && !strcasecmp(dot, ".apk")) {
1838 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1839 fprintf(stderr, "Invalid APK file: %s\n", file);
1840 return -1;
1841 }
1842
1843 total_size += sb.st_size;
1844 first_apk = i;
1845 } else {
1846 break;
1847 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001848 }
1849
Jeff Sharkey960df972014-06-09 17:30:57 -07001850 if (first_apk == -1) {
1851 fprintf(stderr, "Missing APK file\n");
1852 return 1;
1853 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001854
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001855 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Jeff Sharkey960df972014-06-09 17:30:57 -07001856 for (i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001857 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001858 }
1859
1860 // Create install session
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001861 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001862 int fd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001863 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001864 fprintf(stderr, "Connect error for create: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001865 return -1;
1866 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001867 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001868 read_status_line(fd, buf, sizeof(buf));
1869 adb_close(fd);
1870
1871 int session_id = -1;
1872 if (!strncmp("Success", buf, 7)) {
1873 char* start = strrchr(buf, '[');
1874 char* end = strrchr(buf, ']');
1875 if (start && end) {
1876 *end = '\0';
1877 session_id = strtol(start + 1, NULL, 10);
1878 }
1879 }
1880 if (session_id < 0) {
1881 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001882 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001883 return -1;
1884 }
1885
1886 // Valid session, now stream the APKs
1887 int success = 1;
1888 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001889 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001890 if (stat(file, &sb) == -1) {
1891 fprintf(stderr, "Failed to stat %s\n", file);
1892 success = 0;
1893 goto finalize_session;
1894 }
1895
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001896 std::string cmd = android::base::StringPrintf(
1897 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
Elliott Hughes5c742702015-07-30 17:42:01 -07001898 static_cast<uint64_t>(sb.st_size), session_id, i, adb_basename(file).c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001899
1900 int localFd = adb_open(file, O_RDONLY);
1901 if (localFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001902 fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
Jeff Sharkey960df972014-06-09 17:30:57 -07001903 success = 0;
1904 goto finalize_session;
1905 }
1906
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001907 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001908 int remoteFd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001909 if (remoteFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001910 fprintf(stderr, "Connect error for write: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001911 adb_close(localFd);
1912 success = 0;
1913 goto finalize_session;
1914 }
1915
1916 copy_to_file(localFd, remoteFd);
1917 read_status_line(remoteFd, buf, sizeof(buf));
1918
1919 adb_close(localFd);
1920 adb_close(remoteFd);
1921
1922 if (strncmp("Success", buf, 7)) {
1923 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001924 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001925 success = 0;
1926 goto finalize_session;
1927 }
1928 }
1929
1930finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001931 // Commit session if we streamed everything okay; otherwise abandon
Elliott Hughes6452a892015-04-29 12:28:13 -07001932 std::string service =
1933 android::base::StringPrintf("exec:pm install-%s %d",
1934 success ? "commit" : "abandon", session_id);
1935 fd = adb_connect(service, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001936 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001937 fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001938 return -1;
1939 }
1940 read_status_line(fd, buf, sizeof(buf));
1941 adb_close(fd);
1942
1943 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001944 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001945 return 0;
1946 } else {
1947 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001948 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001949 return -1;
1950 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001951}