blob: ed9b73668be45b345a64caaabec5af5b46f6050c [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 Hughes0fbf9612015-11-04 13:07:47 -080044#include <sys/ioctl.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);
Todd Kennedy6fa848a2015-11-03 16:53:08 -080062static int install_app_legacy(TransportType t, const char* serial, int argc, const char** argv);
63static int uninstall_app_legacy(TransportType t, const char* serial, int argc, const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080064
Elliott Hughes58305772015-04-17 13:57:15 -070065static std::string gProductOutPath;
Matt Gumbeld7b33082012-11-14 10:16:17 -080066extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080067
Elliott Hughes58305772015-04-17 13:57:15 -070068static std::string product_file(const char *extra) {
69 if (gProductOutPath.empty()) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080070 fprintf(stderr, "adb: Product directory not specified; "
71 "use -p or define ANDROID_PRODUCT_OUT\n");
72 exit(1);
73 }
74
Elliott Hughes58305772015-04-17 13:57:15 -070075 return android::base::StringPrintf("%s%s%s",
76 gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080077}
78
Elliott Hughes58305772015-04-17 13:57:15 -070079static void help() {
Elliott Hughes42ae2602015-08-12 08:32:10 -070080 fprintf(stderr, "%s\n", adb_version().c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080081 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -080082 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080083 " -d - directs command to the only connected USB device\n"
84 " returns an error if more than one USB device is present.\n"
85 " -e - directs command to the only running emulator.\n"
86 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070087 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070088 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070089 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080090 " -p <product name or path> - simple product name like 'sooner', or\n"
91 " a relative/absolute path to a product\n"
92 " out directory like 'out/target/product/sooner'.\n"
93 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
94 " environment variable is used, which must\n"
95 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080096 " -H - Name of adb server host (default: localhost)\n"
97 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -070098 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070099 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400100 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
101 " Port 5555 is used by default if no port number is specified.\n"
102 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
103 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200104 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400105 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800106 "\n"
107 "device commands:\n"
Josh Gao05786772015-10-30 16:57:19 -0700108 " adb push <local>... <remote>\n"
109 " - copy files/dirs to device\n"
110 " adb pull [-a] <remote>... <local>\n"
111 " - copy files/dirs from device\n"
112 " (-a preserves file timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800113 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600114 " (-l means list but don't copy)\n"
Elliott Hughes0e42c2a2015-11-10 10:54:44 -0800115 " adb shell [-e escape] [-Tt] [-x] [command]\n"
116 " - run remote shell command (interactive shell if no command given)\n"
117 " (-e: choose escape character, or \"none\"; default '~')\n"
118 " (-T: disable PTY allocation)\n"
119 " (-t: force PTY allocation)\n"
120 " (-x: disable remote exit codes and stdout/stderr separation)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800121 " adb emu <command> - run emulator console command\n"
122 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100123 " adb forward --list - list all forward socket connections.\n"
124 " the format is a list of lines with the following format:\n"
125 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800126 " adb forward <local> <remote> - forward socket connections\n"
127 " forward specs are one of: \n"
128 " tcp:<port>\n"
129 " localabstract:<unix domain socket name>\n"
130 " localreserved:<unix domain socket name>\n"
131 " localfilesystem:<unix domain socket name>\n"
132 " dev:<character device name>\n"
133 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100134 " adb forward --no-rebind <local> <remote>\n"
135 " - same as 'adb forward <local> <remote>' but fails\n"
136 " if <local> is already forwarded\n"
137 " adb forward --remove <local> - remove a specific forward socket connection\n"
138 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100139 " adb reverse --list - list all reverse socket connections from device\n"
140 " adb reverse <remote> <local> - reverse socket connections\n"
141 " reverse specs are one of:\n"
142 " tcp:<port>\n"
143 " localabstract:<unix domain socket name>\n"
144 " localreserved:<unix domain socket name>\n"
145 " localfilesystem:<unix domain socket name>\n"
Spencer Low587ea202015-11-02 17:34:49 -0800146 " adb reverse --no-rebind <remote> <local>\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100147 " - same as 'adb reverse <remote> <local>' but fails\n"
148 " if <remote> is already reversed.\n"
149 " adb reverse --remove <remote>\n"
150 " - remove a specific reversed socket connection\n"
151 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800152 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900153 " adb install [-lrtsdg] <file>\n"
Svetoslav23d84072015-06-01 16:02:50 -0700154 " - push this package file to the device and install it\n"
155 " (-l: forward lock application)\n"
156 " (-r: replace existing application)\n"
157 " (-t: allow test packages)\n"
158 " (-s: install application on sdcard)\n"
159 " (-d: allow version code downgrade)\n"
160 " (-g: grant all runtime permissions)\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900161 " adb install-multiple [-lrtsdpg] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700162 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700163 " (-l: forward lock application)\n"
164 " (-r: replace existing application)\n"
165 " (-t: allow test packages)\n"
166 " (-s: install application on sdcard)\n"
167 " (-d: allow version code downgrade)\n"
168 " (-p: partial application install)\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900169 " (-g: grant all runtime permissions)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800170 " adb uninstall [-k] <package> - remove this app package from the device\n"
171 " ('-k' means keep the data and cache directories)\n"
172 " adb bugreport - return all information from the device\n"
173 " that should be included in a bug report.\n"
174 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800175 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700176 " - write an archive of the device's data to <file>.\n"
177 " If no -f option is supplied then the data is written\n"
178 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700179 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700180 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800181 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
182 " (aka .obb) files associated with each application; the default\n"
183 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700184 " (-shared|-noshared enable/disable backup of the device's\n"
185 " shared storage / SD card contents; the default is noshared.)\n"
186 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700187 " (-system|-nosystem toggles whether -all automatically includes\n"
188 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700189 " (<packages...> is the list of applications to be backed up. If\n"
190 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700191 " list is optional. Applications explicitly given on the\n"
192 " command line will be included even if -nosystem would\n"
193 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700194 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700195 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700196 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800197 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
198 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800199 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
200 " and the public key is stored in <file>.pub. Any existing files\n"
201 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800202 " adb help - show this help message\n"
203 " adb version - show version num\n"
204 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800205 "scripting:\n"
206 " adb wait-for-device - block until device is online\n"
207 " adb start-server - ensure that there is a server running\n"
208 " adb kill-server - kill the server if it is running\n"
209 " adb get-state - prints: offline | bootloader | device\n"
210 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700211 " adb get-devpath - prints: <device-path>\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000212 " 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 -0700213 " adb reboot [bootloader|recovery]\n"
214 " - reboots the device, optionally into the bootloader or recovery program.\n"
215 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
216 " adb reboot sideload-auto-reboot\n"
217 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700218 " adb sideload <file> - sideloads the given package\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700219 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500220 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800221 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000222 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700223 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800224 "networking:\n"
225 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500226 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800227 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
228 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
229 "\n"
230 "adb sync notes: adb sync [ <directory> ]\n"
231 " <localdir> can be interpreted in several ways:\n"
232 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000233 " - 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 -0800234 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000235 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800236 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000237 "\n"
Elliott Hughes7e067cf2015-06-12 14:26:29 -0700238 "environment variables:\n"
Timcd643152010-02-16 20:18:29 +0000239 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
240 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
241 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
242 " 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 -0800243 );
244}
245
Elliott Hughes58305772015-04-17 13:57:15 -0700246static int usage() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800247 help();
248 return 1;
249}
250
Yabin Cuid325e862014-11-17 14:48:25 -0800251#if defined(_WIN32)
252
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700253// Implemented in sysdeps_win32.cpp.
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800254void stdin_raw_init();
255void stdin_raw_restore();
Yabin Cuid325e862014-11-17 14:48:25 -0800256
257#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100258static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800259
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800260static void stdin_raw_init() {
261 if (tcgetattr(STDIN_FILENO, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800262
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100263 termios tio;
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800264 if (tcgetattr(STDIN_FILENO, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800265
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100266 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800267
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100268 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800269 tio.c_cc[VTIME] = 0;
270 tio.c_cc[VMIN] = 1;
271
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800272 tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800273}
274
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800275static void stdin_raw_restore() {
276 tcsetattr(STDIN_FILENO, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800277}
278#endif
279
David Pursell606835a2015-09-08 17:17:02 -0700280// Reads from |fd| and prints received data. If |use_shell_protocol| is true
281// this expects that incoming data will use the shell protocol, in which case
282// stdout/stderr are routed independently and the remote exit code will be
283// returned.
284static int read_and_dump(int fd, bool use_shell_protocol=false) {
285 int exit_code = 0;
286 std::unique_ptr<ShellProtocol> protocol;
287 int length = 0;
288 FILE* outfile = stdout;
289
290 char raw_buffer[BUFSIZ];
291 char* buffer_ptr = raw_buffer;
292 if (use_shell_protocol) {
293 protocol.reset(new ShellProtocol(fd));
294 if (!protocol) {
295 LOG(ERROR) << "failed to allocate memory for ShellProtocol object";
296 return 1;
297 }
298 buffer_ptr = protocol->data();
299 }
300
Elliott Hughes5677c232015-05-07 23:37:40 -0700301 while (fd >= 0) {
David Pursell606835a2015-09-08 17:17:02 -0700302 if (use_shell_protocol) {
303 if (!protocol->Read()) {
304 break;
305 }
306 switch (protocol->id()) {
307 case ShellProtocol::kIdStdout:
308 outfile = stdout;
309 break;
310 case ShellProtocol::kIdStderr:
311 outfile = stderr;
312 break;
313 case ShellProtocol::kIdExit:
314 exit_code = protocol->data()[0];
315 continue;
316 default:
317 continue;
318 }
319 length = protocol->data_length();
320 } else {
321 D("read_and_dump(): pre adb_read(fd=%d)", fd);
322 length = adb_read(fd, raw_buffer, sizeof(raw_buffer));
323 D("read_and_dump(): post adb_read(fd=%d): length=%d", fd, length);
324 if (length <= 0) {
325 break;
326 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800327 }
328
David Pursell606835a2015-09-08 17:17:02 -0700329 fwrite(buffer_ptr, 1, length, outfile);
330 fflush(outfile);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800331 }
David Pursell606835a2015-09-08 17:17:02 -0700332
333 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800334}
335
Jeff Sharkey960df972014-06-09 17:30:57 -0700336static void read_status_line(int fd, char* buf, size_t count)
337{
338 count--;
339 while (count > 0) {
340 int len = adb_read(fd, buf, count);
Elliott Hughes8fcd8bc2015-08-25 10:59:45 -0700341 if (len <= 0) {
Jeff Sharkey960df972014-06-09 17:30:57 -0700342 break;
343 }
344
345 buf += len;
346 count -= len;
347 }
348 *buf = '\0';
349}
350
Christopher Tated2f54152011-04-21 12:53:28 -0700351static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700352 const size_t BUFSIZE = 32 * 1024;
353 char* buf = (char*) malloc(BUFSIZE);
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700354 if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
Christopher Tated2f54152011-04-21 12:53:28 -0700355 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700356 long total = 0;
Spencer Lowb7dfb792015-05-22 16:48:31 -0700357#ifdef _WIN32
358 int old_stdin_mode = -1;
359 int old_stdout_mode = -1;
360#endif
Christopher Tated2f54152011-04-21 12:53:28 -0700361
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700362 D("copy_to_file(%d -> %d)", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800363
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700364 if (inFd == STDIN_FILENO) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800365 stdin_raw_init();
Spencer Lowb7dfb792015-05-22 16:48:31 -0700366#ifdef _WIN32
367 old_stdin_mode = _setmode(STDIN_FILENO, _O_BINARY);
368 if (old_stdin_mode == -1) {
369 fatal_errno("could not set stdin to binary");
370 }
371#endif
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700372 }
Yabin Cuid325e862014-11-17 14:48:25 -0800373
Spencer Lowb7dfb792015-05-22 16:48:31 -0700374#ifdef _WIN32
375 if (outFd == STDOUT_FILENO) {
376 old_stdout_mode = _setmode(STDOUT_FILENO, _O_BINARY);
377 if (old_stdout_mode == -1) {
378 fatal_errno("could not set stdout to binary");
379 }
380 }
381#endif
382
Elliott Hughesa7090b92015-04-17 17:03:59 -0700383 while (true) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700384 if (inFd == STDIN_FILENO) {
385 len = unix_read(inFd, buf, BUFSIZE);
386 } else {
387 len = adb_read(inFd, buf, BUFSIZE);
388 }
Christopher Tated2f54152011-04-21 12:53:28 -0700389 if (len == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700390 D("copy_to_file() : read 0 bytes; exiting");
Christopher Tated2f54152011-04-21 12:53:28 -0700391 break;
392 }
393 if (len < 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700394 D("copy_to_file(): read failed: %s", strerror(errno));
Christopher Tated2f54152011-04-21 12:53:28 -0700395 break;
396 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700397 if (outFd == STDOUT_FILENO) {
398 fwrite(buf, 1, len, stdout);
399 fflush(stdout);
400 } else {
401 adb_write(outFd, buf, len);
402 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700403 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700404 }
Yabin Cuid325e862014-11-17 14:48:25 -0800405
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700406 if (inFd == STDIN_FILENO) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800407 stdin_raw_restore();
Spencer Lowb7dfb792015-05-22 16:48:31 -0700408#ifdef _WIN32
409 if (_setmode(STDIN_FILENO, old_stdin_mode) == -1) {
410 fatal_errno("could not restore stdin mode");
411 }
412#endif
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700413 }
Yabin Cuid325e862014-11-17 14:48:25 -0800414
Spencer Lowb7dfb792015-05-22 16:48:31 -0700415#ifdef _WIN32
416 if (outFd == STDOUT_FILENO) {
417 if (_setmode(STDOUT_FILENO, old_stdout_mode) == -1) {
418 fatal_errno("could not restore stdout mode");
419 }
420 }
421#endif
422
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700423 D("copy_to_file() finished after %lu bytes", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700424 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700425}
426
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800427static std::string format_host_command(const char* command,
428 TransportType type, const char* serial) {
429 if (serial) {
430 return android::base::StringPrintf("host-serial:%s:%s", serial, command);
431 }
432
433 const char* prefix = "host";
434 if (type == kTransportUsb) {
435 prefix = "host-usb";
436 } else if (type == kTransportLocal) {
437 prefix = "host-local";
438 }
439 return android::base::StringPrintf("%s:%s", prefix, command);
440}
441
442// Returns the FeatureSet for the indicated transport.
443static FeatureSet GetFeatureSet(TransportType transport_type, const char* serial) {
444 std::string result, error;
445 if (adb_query(format_host_command("features", transport_type, serial), &result, &error)) {
446 return StringToFeatureSet(result);
447 }
448 return FeatureSet();
449}
450
451static void send_window_size_change(int fd, std::unique_ptr<ShellProtocol>& shell) {
452#if !defined(_WIN32)
453 // Old devices can't handle window size changes.
454 if (shell == nullptr) return;
455
456 winsize ws;
457 if (ioctl(fd, TIOCGWINSZ, &ws) == -1) return;
458
459 // Send the new window size as human-readable ASCII for debugging convenience.
460 size_t l = snprintf(shell->data(), shell->data_capacity(), "%dx%d,%dx%d",
461 ws.ws_row, ws.ws_col, ws.ws_xpixel, ws.ws_ypixel);
462 shell->Write(ShellProtocol::kIdWindowSizeChange, l + 1);
463#endif
464}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800465
David Pursell606835a2015-09-08 17:17:02 -0700466// Used to pass multiple values to the stdin read thread.
467struct StdinReadArgs {
468 int stdin_fd, write_fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700469 bool raw_stdin;
David Pursell606835a2015-09-08 17:17:02 -0700470 std::unique_ptr<ShellProtocol> protocol;
471};
472
David Pursell606835a2015-09-08 17:17:02 -0700473// Loops to read from stdin and push the data to the given FD.
474// The argument should be a pointer to a StdinReadArgs object. This function
475// will take ownership of the object and delete it when finished.
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800476static void* stdin_read_thread_loop(void* x) {
David Pursell606835a2015-09-08 17:17:02 -0700477 std::unique_ptr<StdinReadArgs> args(reinterpret_cast<StdinReadArgs*>(x));
478 int state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800479
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800480#if !defined(_WIN32)
481 // Mask SIGTTIN in case we're in a backgrounded process.
Josh Gao8dcdb572015-10-23 15:03:31 -0700482 sigset_t sigset;
483 sigemptyset(&sigset);
484 sigaddset(&sigset, SIGTTIN);
485 pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
486#endif
487
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800488#if !defined(_WIN32)
489 // Unblock SIGWINCH for this thread, so our read(2) below will be
490 // interrupted if the window size changes.
491 sigset_t mask;
492 sigemptyset(&mask);
493 sigaddset(&mask, SIGWINCH);
494 pthread_sigmask(SIG_UNBLOCK, &mask, nullptr);
495#endif
496
497 // Set up the initial window size.
498 send_window_size_change(args->stdin_fd, args->protocol);
499
David Pursell606835a2015-09-08 17:17:02 -0700500 char raw_buffer[1024];
501 char* buffer_ptr = raw_buffer;
502 size_t buffer_size = sizeof(raw_buffer);
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800503 if (args->protocol != nullptr) {
David Pursell606835a2015-09-08 17:17:02 -0700504 buffer_ptr = args->protocol->data();
505 buffer_size = args->protocol->data_capacity();
506 }
507
Elliott Hughesaa245492015-08-03 10:38:08 -0700508 while (true) {
David Pursell606835a2015-09-08 17:17:02 -0700509 // Use unix_read() rather than adb_read() for stdin.
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800510 D("stdin_read_thread_loop(): pre unix_read(fdi=%d,...)", args->stdin_fd);
511#if !defined(_WIN32)
512#undef read
513 int r = read(args->stdin_fd, buffer_ptr, buffer_size);
514 if (r == -1 && errno == EINTR) {
515 send_window_size_change(args->stdin_fd, args->protocol);
516 continue;
517 }
518#define read ___xxx_read
519#else
David Pursell606835a2015-09-08 17:17:02 -0700520 int r = unix_read(args->stdin_fd, buffer_ptr, buffer_size);
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800521#endif
522 D("stdin_read_thread_loop(): post unix_read(fdi=%d,...)", args->stdin_fd);
David Pursell1ed57f02015-10-06 15:30:03 -0700523 if (r <= 0) {
524 // Only devices using the shell protocol know to close subprocess
525 // stdin. For older devices we want to just leave the connection
526 // open, otherwise an unpredictable amount of return data could
527 // be lost due to the FD closing before all data has been received.
528 if (args->protocol) {
529 args->protocol->Write(ShellProtocol::kIdCloseStdin, 0);
530 }
531 break;
532 }
533 // If we made stdin raw, check input for the "~." escape sequence. In
534 // this situation signals like Ctrl+C are sent remotely rather than
535 // interpreted locally so this provides an emergency out if the remote
536 // process starts ignoring the signal. SSH also does this, see the
537 // "escape characters" section on the ssh man page for more info.
538 if (args->raw_stdin) {
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800539 for (int n = 0; n < r; n++) {
540 switch (buffer_ptr[n]) {
David Pursell1ed57f02015-10-06 15:30:03 -0700541 case '\n':
542 state = 1;
543 break;
544 case '\r':
545 state = 1;
546 break;
547 case '~':
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800548 if (state == 1) {
David Pursell08a27092015-10-20 14:19:36 -0700549 state++;
550 } else {
551 state = 0;
552 }
David Pursell1ed57f02015-10-06 15:30:03 -0700553 break;
554 case '.':
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800555 if (state == 2) {
556 fprintf(stderr,"\r\n* disconnect *\r\n");
557 stdin_raw_restore();
David Pursell1ed57f02015-10-06 15:30:03 -0700558 exit(0);
559 }
560 default:
561 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800562 }
563 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800564 }
David Pursell606835a2015-09-08 17:17:02 -0700565 if (args->protocol) {
566 if (!args->protocol->Write(ShellProtocol::kIdStdin, r)) {
567 break;
568 }
569 } else {
570 if (!WriteFdExactly(args->write_fd, buffer_ptr, r)) {
571 break;
572 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800573 }
574 }
David Pursell606835a2015-09-08 17:17:02 -0700575
576 return nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800577}
578
David Pursell1ed57f02015-10-06 15:30:03 -0700579// Returns a shell service string with the indicated arguments and command.
580static std::string ShellServiceString(bool use_shell_protocol,
581 const std::string& type_arg,
582 const std::string& command) {
583 std::vector<std::string> args;
584 if (use_shell_protocol) {
585 args.push_back(kShellServiceArgShellProtocol);
586 }
587 if (!type_arg.empty()) {
588 args.push_back(type_arg);
589 }
590
591 // Shell service string can look like: shell[,arg1,arg2,...]:[command].
592 return android::base::StringPrintf("shell%s%s:%s",
593 args.empty() ? "" : ",",
594 android::base::Join(args, ',').c_str(),
595 command.c_str());
596}
597
598// Connects to a shell on the device and read/writes data.
599//
600// Note: currently this function doesn't properly clean up resources; the
601// FD connected to the adb server is never closed and the stdin read thread
602// may never exit.
603//
604// On success returns the remote exit code if |use_shell_protocol| is true,
605// 0 otherwise. On failure returns 1.
606static int RemoteShell(bool use_shell_protocol, const std::string& type_arg,
607 const std::string& command) {
608 std::string service_string = ShellServiceString(use_shell_protocol,
609 type_arg, command);
610
611 // Make local stdin raw if the device allocates a PTY, which happens if:
612 // 1. We are explicitly asking for a PTY shell, or
613 // 2. We don't specify shell type and are starting an interactive session.
614 bool raw_stdin = (type_arg == kShellServiceArgPty ||
615 (type_arg.empty() && command.empty()));
616
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700617 std::string error;
David Pursell4e2fd362015-09-22 10:43:08 -0700618 int fd = adb_connect(service_string, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700619 if (fd < 0) {
620 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800621 return 1;
622 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800623
David Pursell606835a2015-09-08 17:17:02 -0700624 StdinReadArgs* args = new StdinReadArgs;
625 if (!args) {
626 LOG(ERROR) << "couldn't allocate StdinReadArgs object";
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700627 return 1;
628 }
David Pursell1ed57f02015-10-06 15:30:03 -0700629 args->stdin_fd = STDIN_FILENO;
David Pursell606835a2015-09-08 17:17:02 -0700630 args->write_fd = fd;
David Pursell1ed57f02015-10-06 15:30:03 -0700631 args->raw_stdin = raw_stdin;
David Pursell606835a2015-09-08 17:17:02 -0700632 if (use_shell_protocol) {
633 args->protocol.reset(new ShellProtocol(args->write_fd));
634 }
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700635
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800636 if (raw_stdin) stdin_raw_init();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800637
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800638#if !defined(_WIN32)
639 // Ensure our process is notified if the local window size changes.
640 // We use sigaction(2) to ensure that the SA_RESTART flag is not set,
641 // because the whole reason we're sending signals is to unblock the read(2)!
642 // That also means we don't need to do anything in the signal handler:
643 // the side effect of delivering the signal is all we need.
644 struct sigaction sa;
645 memset(&sa, 0, sizeof(sa));
646 sa.sa_handler = [](int) {};
647 sa.sa_flags = 0;
648 sigaction(SIGWINCH, &sa, nullptr);
649
650 // Now block SIGWINCH in this thread (the main thread) and all threads spawned
651 // from it. The stdin read thread will unblock this signal to ensure that it's
652 // the thread that receives the signal.
653 sigset_t mask;
654 sigemptyset(&mask);
655 sigaddset(&mask, SIGWINCH);
656 pthread_sigmask(SIG_BLOCK, &mask, nullptr);
657#endif
658
659 // TODO: combine read_and_dump with stdin_read_thread to make life simpler?
660 int exit_code = 1;
661 if (!adb_thread_create(stdin_read_thread_loop, args)) {
David Pursell606835a2015-09-08 17:17:02 -0700662 PLOG(ERROR) << "error starting stdin read thread";
David Pursell606835a2015-09-08 17:17:02 -0700663 delete args;
664 } else {
665 exit_code = read_and_dump(fd, use_shell_protocol);
666 }
Elliott Hughes9b0f3542015-05-05 13:41:21 -0700667
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800668 // TODO: properly exit stdin_read_thread_loop and close |fd|.
David Pursell1ed57f02015-10-06 15:30:03 -0700669
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800670 // TODO: we should probably install signal handlers for this.
671 // TODO: can we use atexit? even on Windows?
672 if (raw_stdin) stdin_raw_restore();
David Pursell1ed57f02015-10-06 15:30:03 -0700673
David Pursell606835a2015-09-08 17:17:02 -0700674 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800675}
676
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800677static int adb_shell(int argc, const char** argv,
678 TransportType transport_type, const char* serial) {
679 FeatureSet features = GetFeatureSet(transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800680
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800681 bool use_shell_protocol = CanUseFeature(features, kFeatureShell2);
682 if (!use_shell_protocol) {
683 D("shell protocol not supported, using raw data transfer");
684 } else {
685 D("using shell protocol");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800686 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700687
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800688 // Parse shell-specific command-line options.
689 // argv[0] is always "shell".
690 --argc;
691 ++argv;
692 int t_arg_count = 0;
693 while (argc) {
694 if (!strcmp(argv[0], "-T") || !strcmp(argv[0], "-t")) {
695 if (!CanUseFeature(features, kFeatureShell2)) {
696 fprintf(stderr, "error: target doesn't support PTY args -Tt\n");
697 return 1;
698 }
699 // Like ssh, -t arguments are cumulative so that multiple -t's
700 // are needed to force a PTY.
701 if (argv[0][1] == 't') {
702 ++t_arg_count;
703 } else {
704 t_arg_count = -1;
705 }
706 --argc;
707 ++argv;
708 } else if (!strcmp(argv[0], "-x")) {
709 use_shell_protocol = false;
710 --argc;
711 ++argv;
712 } else {
713 break;
714 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700715 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800716
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800717 std::string shell_type_arg;
718 if (CanUseFeature(features, kFeatureShell2)) {
719 if (t_arg_count < 0) {
720 shell_type_arg = kShellServiceArgRaw;
721 } else if (t_arg_count == 0) {
722 // If stdin isn't a TTY, default to a raw shell; this lets
723 // things like `adb shell < my_script.sh` work as expected.
724 // Otherwise leave |shell_type_arg| blank which uses PTY for
725 // interactive shells and raw for non-interactive.
726 if (!unix_isatty(STDIN_FILENO)) {
727 shell_type_arg = kShellServiceArgRaw;
728 }
729 } else if (t_arg_count == 1) {
730 // A single -t arg isn't enough to override implicit -T.
731 if (!unix_isatty(STDIN_FILENO)) {
732 fprintf(stderr,
733 "Remote PTY will not be allocated because stdin is not a terminal.\n"
734 "Use multiple -t options to force remote PTY allocation.\n");
735 shell_type_arg = kShellServiceArgRaw;
736 } else {
737 shell_type_arg = kShellServiceArgPty;
738 }
739 } else {
740 shell_type_arg = kShellServiceArgPty;
741 }
David Pursell71c83122015-09-14 15:33:50 -0700742 }
Elliott Hughesc15b17f2015-11-03 11:18:40 -0800743
744 std::string command;
745 if (argc) {
746 // We don't escape here, just like ssh(1). http://b/20564385.
747 command = android::base::Join(std::vector<const char*>(argv, argv + argc), ' ');
748 }
749
750 return RemoteShell(use_shell_protocol, shell_type_arg, command);
David Pursell71c83122015-09-14 15:33:50 -0700751}
752
Elliott Hughes6452a892015-04-29 12:28:13 -0700753static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700754 bool show_progress)
Doug Zongker447f0612012-01-09 14:54:53 -0800755{
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700756 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700757 int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700758 if (fd < 0) {
759 fprintf(stderr,"error: %s\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800760 return -1;
761 }
762
763 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800764 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800765
Elliott Hughes6452a892015-04-29 12:28:13 -0700766 unsigned total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800767 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800768
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700769 if (show_progress) {
Elliott Hughes3e7048c2015-07-27 21:21:39 -0700770 const char* x = strrchr(service, ':');
771 if (x) service = x + 1;
Doug Zongker447f0612012-01-09 14:54:53 -0800772 }
773
Elliott Hughes6452a892015-04-29 12:28:13 -0700774 while (sz > 0) {
Doug Zongker447f0612012-01-09 14:54:53 -0800775 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700776 if (!WriteFdExactly(fd, ptr, xfer)) {
777 std::string error;
778 adb_status(fd, &error);
779 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Spencer Low351ecd12015-10-14 17:32:44 -0700780 adb_close(fd);
Doug Zongker447f0612012-01-09 14:54:53 -0800781 return -1;
782 }
783 sz -= xfer;
784 ptr += xfer;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700785 if (show_progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100786 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800787 fflush(stdout);
788 }
789 }
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700790 if (show_progress) {
Doug Zongker447f0612012-01-09 14:54:53 -0800791 printf("\n");
792 }
793
Elliott Hughese67f1f82015-04-30 17:32:03 -0700794 if (!adb_status(fd, &error)) {
795 fprintf(stderr,"* error response '%s' *\n", error.c_str());
Spencer Low351ecd12015-10-14 17:32:44 -0700796 adb_close(fd);
Doug Zongker447f0612012-01-09 14:54:53 -0800797 return -1;
798 }
799
800 adb_close(fd);
801 return 0;
802}
803
Doug Zongker71fe5842014-06-26 15:35:36 -0700804#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
805
806/*
807 * The sideload-host protocol serves the data in a file (given on the
808 * command line) to the client, using a simple protocol:
809 *
810 * - The connect message includes the total number of bytes in the
811 * file and a block size chosen by us.
812 *
813 * - The other side sends the desired block number as eight decimal
814 * digits (eg "00000023" for block 23). Blocks are numbered from
815 * zero.
816 *
817 * - We send back the data of the requested block. The last block is
818 * likely to be partial; when the last block is requested we only
819 * send the part of the block that exists, it's not padded up to the
820 * block size.
821 *
822 * - When the other side sends "DONEDONE" instead of a block number,
823 * we hang up.
824 */
Elliott Hughes58305772015-04-17 13:57:15 -0700825static int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700826 unsigned sz;
827 size_t xfer = 0;
828 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800829 int last_percent = -1;
830 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700831
832 printf("loading: '%s'", fn);
833 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800834 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700835 if (data == 0) {
836 printf("\n");
837 fprintf(stderr, "* cannot read '%s' *\n", fn);
838 return -1;
839 }
840
Elliott Hughes6452a892015-04-29 12:28:13 -0700841 std::string service =
842 android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700843 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700844 int fd = adb_connect(service, &error);
Doug Zongker71fe5842014-06-26 15:35:36 -0700845 if (fd < 0) {
846 // Try falling back to the older sideload method. Maybe this
847 // is an older device that doesn't support sideload-host.
848 printf("\n");
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700849 status = adb_download_buffer("sideload", fn, data, sz, true);
Doug Zongker71fe5842014-06-26 15:35:36 -0700850 goto done;
851 }
852
Spencer Lowf055c192015-01-25 14:40:16 -0800853 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700854
Elliott Hughesa7090b92015-04-17 17:03:59 -0700855 while (true) {
Elliott Hughes6452a892015-04-29 12:28:13 -0700856 char buf[9];
Dan Albertcc731cc2015-02-24 21:26:58 -0800857 if (!ReadFdExactly(fd, buf, 8)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700858 fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
Doug Zongker71fe5842014-06-26 15:35:36 -0700859 status = -1;
860 goto done;
861 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700862 buf[8] = '\0';
Doug Zongker71fe5842014-06-26 15:35:36 -0700863
Elliott Hughes6452a892015-04-29 12:28:13 -0700864 if (strcmp("DONEDONE", buf) == 0) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700865 status = 0;
866 break;
867 }
868
Doug Zongker71fe5842014-06-26 15:35:36 -0700869 int block = strtol(buf, NULL, 10);
870
871 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
872 if (offset >= sz) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700873 fprintf(stderr, "* attempt to read block %d past end\n", block);
Doug Zongker71fe5842014-06-26 15:35:36 -0700874 status = -1;
875 goto done;
876 }
877 uint8_t* start = data + offset;
878 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
879 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
880 if (offset_end > sz) {
881 to_write = sz - offset;
882 }
883
Dan Albertcc731cc2015-02-24 21:26:58 -0800884 if(!WriteFdExactly(fd, start, to_write)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700885 adb_status(fd, &error);
886 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Doug Zongker71fe5842014-06-26 15:35:36 -0700887 status = -1;
888 goto done;
889 }
890 xfer += to_write;
891
892 // For normal OTA packages, we expect to transfer every byte
893 // twice, plus a bit of overhead (one read during
894 // verification, one read of each byte for installation, plus
895 // extra access to things like the zip central directory).
896 // This estimate of the completion becomes 100% when we've
897 // transferred ~2.13 (=100/47) times the package size.
898 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
899 if (percent != last_percent) {
900 printf("\rserving: '%s' (~%d%%) ", fn, percent);
901 fflush(stdout);
902 last_percent = percent;
903 }
904 }
905
Colin Cross6d6a8982014-07-07 14:12:41 -0700906 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700907
908 done:
909 if (fd >= 0) adb_close(fd);
910 free(data);
911 return status;
912}
913
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800914/**
915 * Run ppp in "notty" mode against a resource listed as the first parameter
916 * eg:
917 *
918 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
919 *
920 */
Elliott Hughes58305772015-04-17 13:57:15 -0700921static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800922#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800923 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
924 return -1;
925#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800926 if (argc < 2) {
927 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
928 argv[0]);
929
930 return 1;
931 }
932
Dan Albertbac34742015-02-25 17:51:28 -0800933 const char* adb_service_name = argv[1];
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700934 std::string error;
935 int fd = adb_connect(adb_service_name, &error);
936 if (fd < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800937 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700938 adb_service_name, error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800939 return 1;
940 }
941
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700942 pid_t pid = fork();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800943
944 if (pid < 0) {
945 perror("from fork()");
946 return 1;
947 } else if (pid == 0) {
948 int err;
949 int i;
950 const char **ppp_args;
951
952 // copy args
953 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
954 ppp_args[0] = "pppd";
955 for (i = 2 ; i < argc ; i++) {
956 //argv[2] and beyond become ppp_args[1] and beyond
957 ppp_args[i - 1] = argv[i];
958 }
959 ppp_args[i-1] = NULL;
960
961 // child side
962
963 dup2(fd, STDIN_FILENO);
964 dup2(fd, STDOUT_FILENO);
965 adb_close(STDERR_FILENO);
966 adb_close(fd);
967
968 err = execvp("pppd", (char * const *)ppp_args);
969
970 if (err < 0) {
971 perror("execing pppd");
972 }
973 exit(-1);
974 } else {
975 // parent side
976
977 adb_close(fd);
978 return 0;
979 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800980#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800981}
982
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700983static bool wait_for_device(const char* service, TransportType t, const char* serial) {
Elliott Hughes2b101112015-05-04 19:29:32 -0700984 // Was the caller vague about what they'd like us to wait for?
985 // If so, check they weren't more specific in their choice of transport type.
986 if (strcmp(service, "wait-for-device") == 0) {
987 if (t == kTransportUsb) {
988 service = "wait-for-usb";
989 } else if (t == kTransportLocal) {
990 service = "wait-for-local";
991 } else {
992 service = "wait-for-any";
993 }
994 }
995
996 std::string cmd = format_host_command(service, t, serial);
Elliott Hughes424af022015-05-29 17:55:19 -0700997 return adb_command(cmd);
Elliott Hughes2b101112015-05-04 19:29:32 -0700998}
999
David Pursell70ef7b42015-09-30 13:35:42 -07001000// Connects to the device "shell" service with |command| and prints the
1001// resulting output.
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001002static int send_shell_command(TransportType transport_type, const char* serial,
David Pursell70ef7b42015-09-30 13:35:42 -07001003 const std::string& command,
1004 bool disable_shell_protocol) {
1005 // Only use shell protocol if it's supported and the caller doesn't want
1006 // to explicitly disable it.
1007 bool use_shell_protocol = false;
1008 if (!disable_shell_protocol) {
1009 FeatureSet features = GetFeatureSet(transport_type, serial);
1010 use_shell_protocol = CanUseFeature(features, kFeatureShell2);
1011 }
1012
1013 std::string service_string = ShellServiceString(use_shell_protocol, "",
1014 command);
1015
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001016 int fd;
1017 while (true) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001018 std::string error;
David Pursell70ef7b42015-09-30 13:35:42 -07001019 fd = adb_connect(service_string, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001020 if (fd >= 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001021 break;
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001022 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001023 fprintf(stderr,"- waiting for device -\n");
1024 adb_sleep_ms(1000);
Elliott Hughes2b101112015-05-04 19:29:32 -07001025 wait_for_device("wait-for-device", transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001026 }
1027
David Pursell70ef7b42015-09-30 13:35:42 -07001028 int exit_code = read_and_dump(fd, use_shell_protocol);
David Pursell71c83122015-09-14 15:33:50 -07001029
1030 if (adb_close(fd) < 0) {
1031 PLOG(ERROR) << "failure closing FD " << fd;
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001032 }
David Pursell71c83122015-09-14 15:33:50 -07001033
1034 return exit_code;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001035}
1036
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001037static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001038 char* log_tags = getenv("ANDROID_LOG_TAGS");
1039 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001040
David Pursell70ef7b42015-09-30 13:35:42 -07001041 std::string cmd = "export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001042
Jeff Sharkeyfd546e82014-06-10 11:31:24 -07001043 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001044 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -08001045 }
1046
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001047 --argc;
1048 ++argv;
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001049 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001050 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001051 }
1052
David Pursell70ef7b42015-09-30 13:35:42 -07001053 // No need for shell protocol with logcat, always disable for simplicity.
1054 return send_shell_command(transport, serial, cmd, true);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001055}
1056
Dan Albertbac34742015-02-25 17:51:28 -08001057static int backup(int argc, const char** argv) {
Elliott Hughes24f165f2015-08-21 20:31:31 -07001058 const char* filename = "backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -07001059
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001060 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001061 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001062 if (!strcmp("-f", argv[i])) {
1063 if (i == argc-1) {
1064 fprintf(stderr, "adb: -f passed with no filename\n");
1065 return usage();
1066 }
1067 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001068 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -07001069 argv[i++] = argv[j++];
1070 }
1071 argc -= 2;
1072 argv[argc] = NULL;
1073 }
Christopher Tated2f54152011-04-21 12:53:28 -07001074 }
1075
Christopher Tatebb86bc52011-08-22 17:12:08 -07001076 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
1077 if (argc < 2) return usage();
1078
Christopher Tateb1dfffe2011-12-08 19:04:34 -08001079 adb_unlink(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001080 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -07001081 if (outFd < 0) {
1082 fprintf(stderr, "adb: unable to open file %s\n", filename);
1083 return -1;
1084 }
1085
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001086 std::string cmd = "backup:";
1087 --argc;
1088 ++argv;
1089 while (argc-- > 0) {
1090 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -07001091 }
1092
Yabin Cui7a3f8d62015-09-02 17:44:28 -07001093 D("backup. filename=%s cmd=%s", filename, cmd.c_str());
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001094 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001095 int fd = adb_connect(cmd, &error);
Christopher Tated2f54152011-04-21 12:53:28 -07001096 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001097 fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -07001098 adb_close(outFd);
1099 return -1;
1100 }
1101
Christopher Tatebffa4ca2012-01-06 15:43:03 -08001102 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -07001103 copy_to_file(fd, outFd);
1104
1105 adb_close(fd);
1106 adb_close(outFd);
1107 return 0;
1108}
1109
Dan Albertbac34742015-02-25 17:51:28 -08001110static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -07001111 if (argc != 2) return usage();
1112
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001113 const char* filename = argv[1];
1114 int tarFd = adb_open(filename, O_RDONLY);
Christopher Tate702967a2011-05-17 15:52:54 -07001115 if (tarFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001116 fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
Christopher Tate702967a2011-05-17 15:52:54 -07001117 return -1;
1118 }
1119
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001120 std::string error;
1121 int fd = adb_connect("restore:", &error);
Christopher Tate702967a2011-05-17 15:52:54 -07001122 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001123 fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
Christopher Tate702967a2011-05-17 15:52:54 -07001124 adb_close(tarFd);
1125 return -1;
1126 }
1127
Christopher Tatebffa4ca2012-01-06 15:43:03 -08001128 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -07001129 copy_to_file(tarFd, fd);
1130
1131 adb_close(fd);
1132 adb_close(tarFd);
1133 return 0;
1134}
1135
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001136/* <hint> may be:
1137 * - A simple product name
1138 * e.g., "sooner"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001139 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
1140 * e.g., "out/target/product/sooner"
1141 * - An absolute path to the PRODUCT_OUT dir
1142 * e.g., "/src/device/out/target/product/sooner"
1143 *
1144 * Given <hint>, try to construct an absolute path to the
1145 * ANDROID_PRODUCT_OUT dir.
1146 */
Elliott Hughes5c742702015-07-30 17:42:01 -07001147static std::string find_product_out_path(const std::string& hint) {
1148 if (hint.empty()) {
Elliott Hughes58305772015-04-17 13:57:15 -07001149 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001150 }
1151
Elliott Hughes58305772015-04-17 13:57:15 -07001152 // If it's already absolute, don't bother doing any work.
Elliott Hughes5c742702015-07-30 17:42:01 -07001153 if (adb_is_absolute_host_path(hint.c_str())) {
Elliott Hughes58305772015-04-17 13:57:15 -07001154 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001155 }
1156
Elliott Hughes58305772015-04-17 13:57:15 -07001157 // If there are any slashes in it, assume it's a relative path;
1158 // make it absolute.
Elliott Hughes5c742702015-07-30 17:42:01 -07001159 if (hint.find_first_of(OS_PATH_SEPARATORS) != std::string::npos) {
Elliott Hughesa7090b92015-04-17 17:03:59 -07001160 std::string cwd;
1161 if (!getcwd(&cwd)) {
1162 fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -07001163 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001164 }
Elliott Hughes5c742702015-07-30 17:42:01 -07001165 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 -08001166 }
1167
Elliott Hughes58305772015-04-17 13:57:15 -07001168 // It's a string without any slashes. Try to do something with it.
1169 //
1170 // Try to find the root of the build tree, and build a PRODUCT_OUT
1171 // path from there.
Elliott Hughesa7090b92015-04-17 17:03:59 -07001172 char* top = getenv("ANDROID_BUILD_TOP");
Elliott Hughes58305772015-04-17 13:57:15 -07001173 if (top == nullptr) {
Elliott Hughesa7090b92015-04-17 17:03:59 -07001174 fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
Elliott Hughes58305772015-04-17 13:57:15 -07001175 return "";
1176 }
Elliott Hughesa7090b92015-04-17 17:03:59 -07001177
1178 std::string path = top;
Elliott Hughes58305772015-04-17 13:57:15 -07001179 path += OS_PATH_SEPARATOR_STR;
1180 path += "out";
1181 path += OS_PATH_SEPARATOR_STR;
1182 path += "target";
1183 path += OS_PATH_SEPARATOR_STR;
1184 path += "product";
1185 path += OS_PATH_SEPARATOR_STR;
1186 path += hint;
1187 if (!directory_exists(path)) {
1188 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
Elliott Hughes5c742702015-07-30 17:42:01 -07001189 "\"%s\" doesn't exist\n", hint.c_str(), path.c_str());
Elliott Hughesa7090b92015-04-17 17:03:59 -07001190 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001191 }
Elliott Hughes58305772015-04-17 13:57:15 -07001192 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001193}
1194
Josh Gao05786772015-10-30 16:57:19 -07001195static void parse_push_pull_args(const char** arg, int narg,
1196 std::vector<const char*>* srcs,
1197 const char** dst, bool* copy_attrs) {
1198 *copy_attrs = false;
Mark Lindner76f2a932014-03-11 17:55:59 -07001199
Josh Gao05786772015-10-30 16:57:19 -07001200 srcs->clear();
1201 bool ignore_flags = false;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001202 while (narg > 0) {
Josh Gao05786772015-10-30 16:57:19 -07001203 if (ignore_flags || *arg[0] != '-') {
1204 srcs->push_back(*arg);
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001205 } else {
Josh Gao05786772015-10-30 16:57:19 -07001206 if (!strcmp(*arg, "-p")) {
1207 // Silently ignore for backwards compatibility.
1208 } else if (!strcmp(*arg, "-a")) {
1209 *copy_attrs = true;
1210 } else if (!strcmp(*arg, "--")) {
1211 ignore_flags = true;
1212 } else {
1213 fprintf(stderr, "adb: unrecognized option '%s'\n", *arg);
1214 exit(1);
1215 }
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001216 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001217 ++arg;
1218 --narg;
1219 }
1220
Josh Gao05786772015-10-30 16:57:19 -07001221 if (srcs->size() > 1) {
1222 *dst = srcs->back();
1223 srcs->pop_back();
Mark Lindner76f2a932014-03-11 17:55:59 -07001224 }
1225}
1226
Elliott Hughes6452a892015-04-29 12:28:13 -07001227static int adb_connect_command(const std::string& command) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001228 std::string error;
1229 int fd = adb_connect(command, &error);
Elliott Hughes5677c232015-05-07 23:37:40 -07001230 if (fd < 0) {
1231 fprintf(stderr, "error: %s\n", error.c_str());
1232 return 1;
Tao Bao175b7bb2015-03-29 11:22:34 -07001233 }
Elliott Hughes5677c232015-05-07 23:37:40 -07001234 read_and_dump(fd);
1235 adb_close(fd);
1236 return 0;
Tao Bao175b7bb2015-03-29 11:22:34 -07001237}
1238
Elliott Hughes6452a892015-04-29 12:28:13 -07001239static int adb_query_command(const std::string& command) {
1240 std::string result;
1241 std::string error;
1242 if (!adb_query(command, &result, &error)) {
1243 fprintf(stderr, "error: %s\n", error.c_str());
1244 return 1;
1245 }
1246 printf("%s\n", result.c_str());
1247 return 0;
1248}
1249
Spencer Lowa13df302015-09-07 16:20:13 -07001250// Disallow stdin, stdout, and stderr.
1251static bool _is_valid_ack_reply_fd(const int ack_reply_fd) {
1252#ifdef _WIN32
1253 const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
1254 return (GetStdHandle(STD_INPUT_HANDLE) != ack_reply_handle) &&
1255 (GetStdHandle(STD_OUTPUT_HANDLE) != ack_reply_handle) &&
1256 (GetStdHandle(STD_ERROR_HANDLE) != ack_reply_handle);
1257#else
1258 return ack_reply_fd > 2;
1259#endif
1260}
1261
Elliott Hughesab52c182015-05-01 17:04:38 -07001262int adb_commandline(int argc, const char **argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001263 int no_daemon = 0;
1264 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001265 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001266 int r;
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001267 TransportType transport_type = kTransportAny;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001268 int ack_reply_fd = -1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001269
Elliott Hughes58305772015-04-17 13:57:15 -07001270 // If defined, this should be an absolute path to
1271 // the directory containing all of the various system images
1272 // for a particular product. If not defined, and the adb
1273 // command requires this information, then the user must
1274 // specify the path using "-p".
1275 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
1276 if (ANDROID_PRODUCT_OUT != nullptr) {
1277 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001278 }
1279 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1280
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001281 /* Validate and assign the server port */
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001282 const char* server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001283 int server_port = DEFAULT_ADB_PORT;
1284 if (server_port_str && strlen(server_port_str) > 0) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001285 server_port = strtol(server_port_str, nullptr, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001286 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001287 fprintf(stderr,
Spencer Lowf18fc082015-08-11 17:05:02 -07001288 "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 +01001289 server_port_str);
1290 return usage();
1291 }
1292 }
1293
Elliott Hughes8d28e192015-10-07 14:55:10 -07001294 // We need to check for -d and -e before we look at $ANDROID_SERIAL.
1295 const char* serial = nullptr;
1296
Riley Andrews98f58e82014-12-05 17:37:24 -08001297 while (argc > 0) {
1298 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001299 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001300 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001301 no_daemon = 1;
1302 } else if (!strcmp(argv[0], "fork-server")) {
1303 /* this is a special flag used only when the ADB client launches the ADB Server */
1304 is_daemon = 1;
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001305 } else if (!strcmp(argv[0], "--reply-fd")) {
1306 if (argc < 2) return usage();
1307 const char* reply_fd_str = argv[1];
1308 argc--;
1309 argv++;
1310 ack_reply_fd = strtol(reply_fd_str, nullptr, 10);
Spencer Lowa13df302015-09-07 16:20:13 -07001311 if (!_is_valid_ack_reply_fd(ack_reply_fd)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001312 fprintf(stderr, "adb: invalid reply fd \"%s\"\n", reply_fd_str);
1313 return usage();
1314 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001315 } else if (!strncmp(argv[0], "-p", 2)) {
Elliott Hughes048b27c2015-07-31 13:18:22 -07001316 const char* product = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001317 if (argv[0][2] == '\0') {
1318 if (argc < 2) return usage();
1319 product = argv[1];
1320 argc--;
1321 argv++;
1322 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001323 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001324 }
Elliott Hughes048b27c2015-07-31 13:18:22 -07001325 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -07001326 if (gProductOutPath.empty()) {
1327 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001328 return usage();
1329 }
1330 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1331 if (isdigit(argv[0][2])) {
1332 serial = argv[0] + 2;
1333 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001334 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001335 serial = argv[1];
1336 argc--;
1337 argv++;
1338 }
1339 } else if (!strcmp(argv[0],"-d")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001340 transport_type = kTransportUsb;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001341 } else if (!strcmp(argv[0],"-e")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001342 transport_type = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001343 } else if (!strcmp(argv[0],"-a")) {
1344 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001345 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001346 const char *hostname = NULL;
1347 if (argv[0][2] == '\0') {
1348 if (argc < 2) return usage();
1349 hostname = argv[1];
1350 argc--;
1351 argv++;
1352 } else {
1353 hostname = argv[0] + 2;
1354 }
1355 adb_set_tcp_name(hostname);
1356
Riley Andrews98f58e82014-12-05 17:37:24 -08001357 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001358 if (argv[0][2] == '\0') {
1359 if (argc < 2) return usage();
1360 server_port_str = argv[1];
1361 argc--;
1362 argv++;
1363 } else {
1364 server_port_str = argv[0] + 2;
1365 }
1366 if (strlen(server_port_str) > 0) {
1367 server_port = (int) strtol(server_port_str, NULL, 0);
1368 if (server_port <= 0 || server_port > 65535) {
1369 fprintf(stderr,
1370 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1371 server_port_str);
1372 return usage();
1373 }
1374 } else {
1375 fprintf(stderr,
1376 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1377 return usage();
1378 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001379 } else {
1380 /* out of recognized modifiers and flags */
1381 break;
1382 }
1383 argc--;
1384 argv++;
1385 }
1386
Elliott Hughes8d28e192015-10-07 14:55:10 -07001387 // If none of -d, -e, or -s were specified, try $ANDROID_SERIAL.
1388 if (transport_type == kTransportAny && serial == nullptr) {
1389 serial = getenv("ANDROID_SERIAL");
1390 }
1391
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001392 adb_set_transport(transport_type, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001393 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001394
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001395 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001396 if (no_daemon || is_daemon) {
Spencer Low5c398d22015-08-08 15:07:07 -07001397 if (is_daemon && (ack_reply_fd == -1)) {
Siva Velusamy9f2d1a92015-08-07 10:10:29 -07001398 fprintf(stderr, "reply fd for adb server to client communication not specified.\n");
1399 return usage();
1400 }
1401 r = adb_main(is_daemon, server_port, ack_reply_fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001402 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001403 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001404 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001405 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001406 fprintf(stderr,"* could not start server *\n");
1407 }
1408 return r;
1409 }
1410
Riley Andrews98f58e82014-12-05 17:37:24 -08001411 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001412 return usage();
1413 }
1414
Riley Andrewsc8514c82014-12-05 17:32:46 -08001415 /* handle wait-for-* prefix */
1416 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001417 const char* service = argv[0];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001418
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001419 if (!wait_for_device(service, transport_type, serial)) {
Riley Andrewsc8514c82014-12-05 17:32:46 -08001420 return 1;
1421 }
1422
Elliott Hughes2b101112015-05-04 19:29:32 -07001423 // Allow a command to be run after wait-for-device,
1424 // e.g. 'adb wait-for-device shell'.
Riley Andrewsc8514c82014-12-05 17:32:46 -08001425 if (argc == 1) {
1426 return 0;
1427 }
1428
1429 /* Fall through */
1430 argc--;
1431 argv++;
1432 }
1433
1434 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001435 if (!strcmp(argv[0], "devices")) {
Dan Albertbac34742015-02-25 17:51:28 -08001436 const char *listopt;
Elliott Hughes6452a892015-04-29 12:28:13 -07001437 if (argc < 2) {
Scott Andersone109d262012-04-20 11:21:14 -07001438 listopt = "";
Elliott Hughes6452a892015-04-29 12:28:13 -07001439 } else if (argc == 2 && !strcmp(argv[1], "-l")) {
Scott Andersone109d262012-04-20 11:21:14 -07001440 listopt = argv[1];
Elliott Hughes6452a892015-04-29 12:28:13 -07001441 } else {
Scott Andersone109d262012-04-20 11:21:14 -07001442 fprintf(stderr, "Usage: adb devices [-l]\n");
1443 return 1;
1444 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001445
1446 std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
1447 printf("List of devices attached\n");
1448 return adb_query_command(query);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001449 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001450 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001451 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001452 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001453 return 1;
1454 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001455
1456 std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
1457 return adb_query_command(query);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001458 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001459 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001460 if (argc > 2) {
1461 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1462 return 1;
1463 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001464
1465 std::string query = android::base::StringPrintf("host:disconnect:%s",
1466 (argc == 2) ? argv[1] : "");
1467 return adb_query_command(query);
Mike Lockwoodff196702009-08-24 15:58:40 -07001468 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001469 else if (!strcmp(argv[0], "emu")) {
Spencer Low142ec752015-05-06 16:13:42 -07001470 return adb_send_emulator_command(argc, argv, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001471 }
Elliott Hughesc15b17f2015-11-03 11:18:40 -08001472 else if (!strcmp(argv[0], "shell")) {
1473 return adb_shell(argc, argv, transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001474 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001475 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001476 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001477
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001478 std::string cmd = "exec:";
1479 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001480 argc -= 2;
1481 argv += 2;
1482 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001483 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001484 }
1485
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001486 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001487 int fd = adb_connect(cmd, &error);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001488 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001489 fprintf(stderr, "error: %s\n", error.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001490 return -1;
1491 }
1492
1493 if (exec_in) {
1494 copy_to_file(STDIN_FILENO, fd);
1495 } else {
1496 copy_to_file(fd, STDOUT_FILENO);
1497 }
1498
1499 adb_close(fd);
1500 return 0;
1501 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001502 else if (!strcmp(argv[0], "kill-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001503 std::string error;
1504 int fd = _adb_connect("host:kill", &error);
Spencer Lowf18fc082015-08-11 17:05:02 -07001505 if (fd == -2) {
1506 // Failed to make network connection to server. Don't output the
1507 // network error since that is expected.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001508 fprintf(stderr,"* server not running *\n");
Spencer Lowf18fc082015-08-11 17:05:02 -07001509 // Successful exit code because the server is already "killed".
1510 return 0;
1511 } else if (fd == -1) {
1512 // Some other error.
1513 fprintf(stderr, "error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001514 return 1;
Spencer Lowf18fc082015-08-11 17:05:02 -07001515 } else {
1516 // Successfully connected, kill command sent, okay status came back.
1517 // Server should exit() in a moment, if not already.
Spencer Low351ecd12015-10-14 17:32:44 -07001518 ReadOrderlyShutdown(fd);
Spencer Lowf18fc082015-08-11 17:05:02 -07001519 adb_close(fd);
1520 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001521 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001522 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001523 else if (!strcmp(argv[0], "sideload")) {
1524 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001525 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001526 return 1;
1527 } else {
1528 return 0;
1529 }
1530 }
Elliott Hughes19d80b82015-07-21 16:13:40 -07001531 else if (!strcmp(argv[0], "tcpip") && argc > 1) {
1532 return adb_connect_command(android::base::StringPrintf("tcpip:%s", argv[1]));
1533 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001534 else if (!strcmp(argv[0], "remount") ||
1535 !strcmp(argv[0], "reboot") ||
1536 !strcmp(argv[0], "reboot-bootloader") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001537 !strcmp(argv[0], "usb") ||
1538 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001539 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001540 !strcmp(argv[0], "disable-verity") ||
1541 !strcmp(argv[0], "enable-verity")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001542 std::string command;
Tao Bao175b7bb2015-03-29 11:22:34 -07001543 if (!strcmp(argv[0], "reboot-bootloader")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001544 command = "reboot:bootloader";
Tao Bao175b7bb2015-03-29 11:22:34 -07001545 } else if (argc > 1) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001546 command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001547 } else {
Elliott Hughes5677c232015-05-07 23:37:40 -07001548 command = android::base::StringPrintf("%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001549 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001550 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001551 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001552 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001553 if (argc != 1) return usage();
David Pursell70ef7b42015-09-30 13:35:42 -07001554 // No need for shell protocol with bugreport, always disable for
1555 // simplicity.
1556 return send_shell_command(transport_type, serial, "bugreport", true);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001557 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001558 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
Elliott Hughes424af022015-05-29 17:55:19 -07001559 bool reverse = !strcmp(argv[0], "reverse");
1560 ++argv;
1561 --argc;
1562 if (argc < 1) return usage();
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001563
1564 // Determine the <host-prefix> for this command.
Elliott Hughes424af022015-05-29 17:55:19 -07001565 std::string host_prefix;
David 'Digit' Turner25258692013-03-21 21:07:42 +01001566 if (reverse) {
Elliott Hughes424af022015-05-29 17:55:19 -07001567 host_prefix = "reverse";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001568 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001569 if (serial) {
Elliott Hughes424af022015-05-29 17:55:19 -07001570 host_prefix = android::base::StringPrintf("host-serial:%s", serial);
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001571 } else if (transport_type == kTransportUsb) {
Elliott Hughes424af022015-05-29 17:55:19 -07001572 host_prefix = "host-usb";
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001573 } else if (transport_type == kTransportLocal) {
Elliott Hughes424af022015-05-29 17:55:19 -07001574 host_prefix = "host-local";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001575 } else {
Elliott Hughes424af022015-05-29 17:55:19 -07001576 host_prefix = "host";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001577 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001578 }
1579
Elliott Hughes424af022015-05-29 17:55:19 -07001580 std::string cmd;
1581 if (strcmp(argv[0], "--list") == 0) {
Elliott Hughesab52c182015-05-01 17:04:38 -07001582 if (argc != 1) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001583 return adb_query_command(host_prefix + ":list-forward");
1584 } else if (strcmp(argv[0], "--remove-all") == 0) {
1585 if (argc != 1) return usage();
1586 cmd = host_prefix + ":killforward-all";
1587 } else if (strcmp(argv[0], "--remove") == 0) {
1588 // forward --remove <local>
Elliott Hughesab52c182015-05-01 17:04:38 -07001589 if (argc != 2) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001590 cmd = host_prefix + ":killforward:" + argv[1];
1591 } else if (strcmp(argv[0], "--no-rebind") == 0) {
1592 // forward --no-rebind <local> <remote>
Elliott Hughesab52c182015-05-01 17:04:38 -07001593 if (argc != 3) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001594 cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
1595 } else {
1596 // forward <local> <remote>
1597 if (argc != 2) return usage();
1598 cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001599 }
1600
Elliott Hughes424af022015-05-29 17:55:19 -07001601 return adb_command(cmd) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001602 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001603 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001604 else if (!strcmp(argv[0], "ls")) {
1605 if (argc != 2) return usage();
Elliott Hughesaa245492015-08-03 10:38:08 -07001606 return do_sync_ls(argv[1]) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001607 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001608 else if (!strcmp(argv[0], "push")) {
Josh Gao05786772015-10-30 16:57:19 -07001609 bool copy_attrs = false;
1610 std::vector<const char*> srcs;
1611 const char* dst = nullptr;
Mark Lindner76f2a932014-03-11 17:55:59 -07001612
Josh Gao05786772015-10-30 16:57:19 -07001613 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
1614 if (srcs.empty() || !dst) return usage();
1615 return do_sync_push(srcs, dst) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001616 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001617 else if (!strcmp(argv[0], "pull")) {
Josh Gao05786772015-10-30 16:57:19 -07001618 bool copy_attrs = false;
1619 std::vector<const char*> srcs;
1620 const char* dst = ".";
Mark Lindner76f2a932014-03-11 17:55:59 -07001621
Josh Gao05786772015-10-30 16:57:19 -07001622 parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs);
1623 if (srcs.empty()) return usage();
1624 return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001625 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001626 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001627 if (argc < 2) return usage();
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001628 FeatureSet features = GetFeatureSet(transport_type, serial);
1629 if (CanUseFeature(features, kFeatureCmd)) {
1630 return install_app(transport_type, serial, argc, argv);
1631 }
1632 return install_app_legacy(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001633 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001634 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001635 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001636 return install_multiple_app(transport_type, serial, argc, argv);
Jeff Sharkey960df972014-06-09 17:30:57 -07001637 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001638 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001639 if (argc < 2) return usage();
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001640 FeatureSet features = GetFeatureSet(transport_type, serial);
1641 if (CanUseFeature(features, kFeatureCmd)) {
1642 return uninstall_app(transport_type, serial, argc, argv);
1643 }
1644 return uninstall_app_legacy(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001645 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001646 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001647 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001648 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001649 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001650 // No local path was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001651 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001652 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001653 list_only = true;
Anthony Newnam705c9442010-02-22 08:36:49 -06001654 if (argc == 3) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001655 src = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001656 } else {
Elliott Hughesd236d072015-04-21 10:17:07 -07001657 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001658 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001659 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001660 // A local path or "android"/"data" arg was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001661 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001662 } else {
1663 return usage();
1664 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001665
Elliott Hughesd236d072015-04-21 10:17:07 -07001666 if (src != "" &&
1667 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes58305772015-04-17 13:57:15 -07001668 return usage();
1669 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001670
Elliott Hughes58305772015-04-17 13:57:15 -07001671 std::string system_src_path = product_file("system");
1672 std::string data_src_path = product_file("data");
1673 std::string vendor_src_path = product_file("vendor");
1674 std::string oem_src_path = product_file("oem");
Elliott Hughes58305772015-04-17 13:57:15 -07001675
Elliott Hughesaa245492015-08-03 10:38:08 -07001676 bool okay = true;
1677 if (okay && (src.empty() || src == "system")) {
1678 okay = do_sync_sync(system_src_path, "/system", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001679 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001680 if (okay && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
1681 okay = do_sync_sync(vendor_src_path, "/vendor", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001682 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001683 if (okay && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
1684 okay = do_sync_sync(oem_src_path, "/oem", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001685 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001686 if (okay && (src.empty() || src == "data")) {
1687 okay = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001688 }
Elliott Hughesaa245492015-08-03 10:38:08 -07001689 return okay ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001690 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001691 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001692 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001693 !strcmp(argv[0],"get-serialno") ||
1694 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001695 {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001696 return adb_query_command(format_host_command(argv[0], transport_type, serial));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001697 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001698 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001699 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001700 return logcat(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001701 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001702 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001703 return ppp(argc, argv);
1704 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001705 else if (!strcmp(argv[0], "start-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001706 std::string error;
Spencer Lowf18fc082015-08-11 17:05:02 -07001707 const int result = adb_connect("host:start-server", &error);
1708 if (result < 0) {
1709 fprintf(stderr, "error: %s\n", error.c_str());
1710 }
1711 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001712 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001713 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001714 return backup(argc, argv);
1715 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001716 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001717 return restore(argc, argv);
1718 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001719 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001720 if (argc < 2) return usage();
Yabin Cuiaed3c612015-09-22 15:52:57 -07001721 // Always print key generation information for keygen command.
1722 adb_trace_enable(AUTH);
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001723 return adb_auth_keygen(argv[1]);
1724 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001725 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001726 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001727 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001728 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001729 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001730 help();
1731 return 0;
1732 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001733 else if (!strcmp(argv[0], "version")) {
Elliott Hughes42ae2602015-08-12 08:32:10 -07001734 fprintf(stdout, "%s", adb_version().c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001735 return 0;
1736 }
Dan Albert90d4b732015-05-20 18:58:41 -07001737 else if (!strcmp(argv[0], "features")) {
David Pursell4e2fd362015-09-22 10:43:08 -07001738 // Only list the features common to both the adb client and the device.
1739 FeatureSet features = GetFeatureSet(transport_type, serial);
1740 for (const std::string& name : features) {
David Pursell70ef7b42015-09-30 13:35:42 -07001741 if (CanUseFeature(features, name)) {
David Pursell4e2fd362015-09-22 10:43:08 -07001742 printf("%s\n", name.c_str());
1743 }
1744 }
1745 return 0;
Dan Albert90d4b732015-05-20 18:58:41 -07001746 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001747
1748 usage();
1749 return 1;
1750}
1751
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001752static int uninstall_app(TransportType transport, const char* serial, int argc, const char** argv) {
1753 // 'adb uninstall' takes the same arguments as 'cmd package uninstall' on device
1754 std::string cmd = "cmd package";
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001755 while (argc-- > 0) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001756 // deny the '-k' option until the remaining data/cache can be removed with adb/UI
1757 if (strcmp(*argv, "-k") == 0) {
1758 printf(
1759 "The -k option uninstalls the application while retaining the data/cache.\n"
1760 "At the moment, there is no way to remove the remaining data.\n"
1761 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1762 "If you truly wish to continue, execute 'adb shell cmd package uninstall -k'.\n");
1763 return EXIT_FAILURE;
1764 }
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001765 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001766 }
1767
David Pursell70ef7b42015-09-30 13:35:42 -07001768 return send_shell_command(transport, serial, cmd, false);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001769}
1770
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001771static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001772 // The last argument must be the APK file
1773 const char* file = argv[argc - 1];
1774 const char* dot = strrchr(file, '.');
1775 bool found_apk = false;
Jeff Sharkey960df972014-06-09 17:30:57 -07001776 struct stat sb;
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001777 if (dot && !strcasecmp(dot, ".apk")) {
1778 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1779 fprintf(stderr, "Invalid APK file: %s\n", file);
1780 return EXIT_FAILURE;
Kenny Root597ea5b2011-08-05 11:19:45 -07001781 }
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001782 found_apk = true;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001783 }
1784
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001785 if (!found_apk) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001786 fprintf(stderr, "Missing APK file\n");
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001787 return EXIT_FAILURE;
Kenny Root597ea5b2011-08-05 11:19:45 -07001788 }
1789
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001790 int localFd = adb_open(file, O_RDONLY);
1791 if (localFd < 0) {
1792 fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
1793 return 1;
1794 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001795
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001796 std::string error;
1797 std::string cmd = "exec:cmd package";
1798
1799 // don't copy the APK name, but, copy the rest of the arguments as-is
1800 while (argc-- > 1) {
1801 cmd += " " + escape_arg(std::string(*argv++));
1802 }
1803
1804 // add size parameter [required for streaming installs]
1805 // do last to override any user specified value
1806 cmd += " " + android::base::StringPrintf("-S %" PRIu64, static_cast<uint64_t>(sb.st_size));
1807
1808 int remoteFd = adb_connect(cmd, &error);
1809 if (remoteFd < 0) {
1810 fprintf(stderr, "Connect error for write: %s\n", error.c_str());
1811 adb_close(localFd);
1812 return 1;
1813 }
1814
1815 char buf[BUFSIZ];
1816 copy_to_file(localFd, remoteFd);
1817 read_status_line(remoteFd, buf, sizeof(buf));
1818
1819 adb_close(localFd);
1820 adb_close(remoteFd);
1821
1822 if (strncmp("Success", buf, 7)) {
1823 fprintf(stderr, "Failed to write %s\n", file);
1824 fputs(buf, stderr);
1825 return 1;
1826 }
1827 fputs(buf, stderr);
1828 return 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001829}
1830
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001831static int install_multiple_app(TransportType transport, const char* serial, int argc,
Elliott Hughes58305772015-04-17 13:57:15 -07001832 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001833{
Jeff Sharkey960df972014-06-09 17:30:57 -07001834 int i;
1835 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001836 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001837
1838 // Find all APK arguments starting at end.
1839 // All other arguments passed through verbatim.
1840 int first_apk = -1;
1841 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001842 const char* file = argv[i];
Elliott Hughes3e7048c2015-07-27 21:21:39 -07001843 const char* dot = strrchr(file, '.');
Jeff Sharkey960df972014-06-09 17:30:57 -07001844 if (dot && !strcasecmp(dot, ".apk")) {
1845 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1846 fprintf(stderr, "Invalid APK file: %s\n", file);
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001847 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001848 }
1849
1850 total_size += sb.st_size;
1851 first_apk = i;
1852 } else {
1853 break;
1854 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001855 }
1856
Jeff Sharkey960df972014-06-09 17:30:57 -07001857 if (first_apk == -1) {
1858 fprintf(stderr, "Missing APK file\n");
1859 return 1;
1860 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001861
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001862 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Jeff Sharkey960df972014-06-09 17:30:57 -07001863 for (i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001864 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001865 }
1866
1867 // Create install session
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001868 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001869 int fd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001870 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001871 fprintf(stderr, "Connect error for create: %s\n", error.c_str());
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001872 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001873 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001874 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001875 read_status_line(fd, buf, sizeof(buf));
1876 adb_close(fd);
1877
1878 int session_id = -1;
1879 if (!strncmp("Success", buf, 7)) {
1880 char* start = strrchr(buf, '[');
1881 char* end = strrchr(buf, ']');
1882 if (start && end) {
1883 *end = '\0';
1884 session_id = strtol(start + 1, NULL, 10);
1885 }
1886 }
1887 if (session_id < 0) {
1888 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001889 fputs(buf, stderr);
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001890 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001891 }
1892
1893 // Valid session, now stream the APKs
1894 int success = 1;
1895 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001896 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001897 if (stat(file, &sb) == -1) {
1898 fprintf(stderr, "Failed to stat %s\n", file);
1899 success = 0;
1900 goto finalize_session;
1901 }
1902
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001903 std::string cmd = android::base::StringPrintf(
1904 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
Elliott Hughes5c742702015-07-30 17:42:01 -07001905 static_cast<uint64_t>(sb.st_size), session_id, i, adb_basename(file).c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001906
1907 int localFd = adb_open(file, O_RDONLY);
1908 if (localFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001909 fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
Jeff Sharkey960df972014-06-09 17:30:57 -07001910 success = 0;
1911 goto finalize_session;
1912 }
1913
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001914 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001915 int remoteFd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001916 if (remoteFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001917 fprintf(stderr, "Connect error for write: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001918 adb_close(localFd);
1919 success = 0;
1920 goto finalize_session;
1921 }
1922
1923 copy_to_file(localFd, remoteFd);
1924 read_status_line(remoteFd, buf, sizeof(buf));
1925
1926 adb_close(localFd);
1927 adb_close(remoteFd);
1928
1929 if (strncmp("Success", buf, 7)) {
1930 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001931 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001932 success = 0;
1933 goto finalize_session;
1934 }
1935 }
1936
1937finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001938 // Commit session if we streamed everything okay; otherwise abandon
Elliott Hughes6452a892015-04-29 12:28:13 -07001939 std::string service =
1940 android::base::StringPrintf("exec:pm install-%s %d",
1941 success ? "commit" : "abandon", session_id);
1942 fd = adb_connect(service, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001943 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001944 fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001945 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001946 }
1947 read_status_line(fd, buf, sizeof(buf));
1948 adb_close(fd);
1949
1950 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001951 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001952 return 0;
1953 } else {
1954 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001955 fputs(buf, stderr);
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001956 return EXIT_FAILURE;
Jeff Sharkey960df972014-06-09 17:30:57 -07001957 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001958}
Todd Kennedy6fa848a2015-11-03 16:53:08 -08001959
1960static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
1961 std::string cmd = "pm";
1962
1963 while (argc-- > 0) {
1964 cmd += " " + escape_arg(*argv++);
1965 }
1966
1967 return send_shell_command(transport, serial, cmd, false);
1968}
1969
1970static int uninstall_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
1971 /* if the user choose the -k option, we refuse to do it until devices are
1972 out with the option to uninstall the remaining data somehow (adb/ui) */
1973 int i;
1974 for (i = 1; i < argc; i++) {
1975 if (!strcmp(argv[i], "-k")) {
1976 printf(
1977 "The -k option uninstalls the application while retaining the data/cache.\n"
1978 "At the moment, there is no way to remove the remaining data.\n"
1979 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1980 "If you truly wish to continue, execute 'adb shell pm uninstall -k'\n.");
1981 return EXIT_FAILURE;
1982 }
1983 }
1984
1985 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1986 return pm_command(transport, serial, argc, argv);
1987}
1988
1989static int delete_file(TransportType transport, const char* serial, const std::string& filename) {
1990 std::string cmd = "rm -f " + escape_arg(filename);
1991 return send_shell_command(transport, serial, cmd, false);
1992}
1993
1994static int install_app_legacy(TransportType transport, const char* serial, int argc, const char** argv) {
1995 static const char *const DATA_DEST = "/data/local/tmp/%s";
1996 static const char *const SD_DEST = "/sdcard/tmp/%s";
1997 const char* where = DATA_DEST;
1998 int i;
1999 struct stat sb;
2000
2001 for (i = 1; i < argc; i++) {
2002 if (!strcmp(argv[i], "-s")) {
2003 where = SD_DEST;
2004 }
2005 }
2006
2007 // Find last APK argument.
2008 // All other arguments passed through verbatim.
2009 int last_apk = -1;
2010 for (i = argc - 1; i >= 0; i--) {
2011 const char* file = argv[i];
2012 const char* dot = strrchr(file, '.');
2013 if (dot && !strcasecmp(dot, ".apk")) {
2014 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
2015 fprintf(stderr, "Invalid APK file: %s\n", file);
2016 return EXIT_FAILURE;
2017 }
2018
2019 last_apk = i;
2020 break;
2021 }
2022 }
2023
2024 if (last_apk == -1) {
2025 fprintf(stderr, "Missing APK file\n");
2026 return EXIT_FAILURE;
2027 }
2028
2029 int result = -1;
2030 std::vector<const char*> apk_file = {argv[last_apk]};
2031 std::string apk_dest = android::base::StringPrintf(
2032 where, adb_basename(argv[last_apk]).c_str());
2033 if (!do_sync_push(apk_file, apk_dest.c_str())) goto cleanup_apk;
2034 argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
2035 result = pm_command(transport, serial, argc, argv);
2036
2037cleanup_apk:
2038 delete_file(transport, serial, apk_dest);
2039 return result;
2040}