blob: 73569ffda33bdf2dcd45bc6189e02f711c55fff3 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dan Albert33134262015-03-19 15:21:08 -070017#define TRACE_TAG TRACE_ADB
18
19#include "sysdeps.h"
20
Dan Albert76649012015-02-24 15:51:19 -080021#include <assert.h>
22#include <ctype.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023#include <errno.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080024#include <limits.h>
25#include <stdarg.h>
Dan Albert76649012015-02-24 15:51:19 -080026#include <stdint.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080030#include <sys/stat.h>
Dan Albert76649012015-02-24 15:51:19 -080031#include <sys/types.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080032
Elliott Hughes2baae3a2015-04-17 10:59:34 -070033#include <string>
34
35#include <base/stringprintf.h>
36
Yabin Cuid325e862014-11-17 14:48:25 -080037#if !defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080038#include <termios.h>
Dan Albert76649012015-02-24 15:51:19 -080039#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080040#endif
41
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080042#include "adb.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080043#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080044#include "adb_client.h"
45#include "adb_io.h"
Elliott Hughes58305772015-04-17 13:57:15 -070046#include "adb_utils.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080047#include "file_sync_service.h"
48
Dan Albertbac34742015-02-25 17:51:28 -080049static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050
Elliott Hughes58305772015-04-17 13:57:15 -070051static int install_app(transport_type transport, const char* serial, int argc,
52 const char** argv);
53static int install_multiple_app(transport_type transport, const char* serial, int argc,
54 const char** argv);
55static int uninstall_app(transport_type transport, const char* serial, int argc,
Dan Albertbac34742015-02-25 17:51:28 -080056 const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080057
Elliott Hughes58305772015-04-17 13:57:15 -070058static std::string gProductOutPath;
Matt Gumbeld7b33082012-11-14 10:16:17 -080059extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080060
Elliott Hughes58305772015-04-17 13:57:15 -070061static std::string product_file(const char *extra) {
62 if (gProductOutPath.empty()) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080063 fprintf(stderr, "adb: Product directory not specified; "
64 "use -p or define ANDROID_PRODUCT_OUT\n");
65 exit(1);
66 }
67
Elliott Hughes58305772015-04-17 13:57:15 -070068 return android::base::StringPrintf("%s%s%s",
69 gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080070}
71
Elliott Hughes58305772015-04-17 13:57:15 -070072static void version(FILE* out) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080073 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
Elliott Hughes58305772015-04-17 13:57:15 -070074 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080075}
76
Elliott Hughes58305772015-04-17 13:57:15 -070077static void help() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080078 version(stderr);
79
80 fprintf(stderr,
81 "\n"
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"
Mark Lindner76f2a932014-03-11 17:55:59 -0700108 " adb push [-p] <local> <remote>\n"
109 " - copy file/dir to device\n"
110 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700111 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700112 " - copy file/dir from device\n"
113 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700114 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800115 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600116 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800117 " (see 'adb help all')\n"
118 " adb shell - run remote shell interactively\n"
119 " adb shell <command> - run remote shell command\n"
120 " adb emu <command> - run emulator console command\n"
121 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100122 " adb forward --list - list all forward socket connections.\n"
123 " the format is a list of lines with the following format:\n"
124 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800125 " adb forward <local> <remote> - forward socket connections\n"
126 " forward specs are one of: \n"
127 " tcp:<port>\n"
128 " localabstract:<unix domain socket name>\n"
129 " localreserved:<unix domain socket name>\n"
130 " localfilesystem:<unix domain socket name>\n"
131 " dev:<character device name>\n"
132 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100133 " adb forward --no-rebind <local> <remote>\n"
134 " - same as 'adb forward <local> <remote>' but fails\n"
135 " if <local> is already forwarded\n"
136 " adb forward --remove <local> - remove a specific forward socket connection\n"
137 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100138 " adb reverse --list - list all reverse socket connections from device\n"
139 " adb reverse <remote> <local> - reverse socket connections\n"
140 " reverse specs are one of:\n"
141 " tcp:<port>\n"
142 " localabstract:<unix domain socket name>\n"
143 " localreserved:<unix domain socket name>\n"
144 " localfilesystem:<unix domain socket name>\n"
145 " adb reverse --norebind <remote> <local>\n"
146 " - same as 'adb reverse <remote> <local>' but fails\n"
147 " if <remote> is already reversed.\n"
148 " adb reverse --remove <remote>\n"
149 " - remove a specific reversed socket connection\n"
150 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800151 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700152 " adb install [-lrtsd] <file>\n"
153 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700154 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700155 " (-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 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800161 " adb uninstall [-k] <package> - remove this app package from the device\n"
162 " ('-k' means keep the data and cache directories)\n"
163 " adb bugreport - return all information from the device\n"
164 " that should be included in a bug report.\n"
165 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800166 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700167 " - write an archive of the device's data to <file>.\n"
168 " If no -f option is supplied then the data is written\n"
169 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700170 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700171 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800172 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
173 " (aka .obb) files associated with each application; the default\n"
174 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700175 " (-shared|-noshared enable/disable backup of the device's\n"
176 " shared storage / SD card contents; the default is noshared.)\n"
177 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700178 " (-system|-nosystem toggles whether -all automatically includes\n"
179 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700180 " (<packages...> is the list of applications to be backed up. If\n"
181 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700182 " list is optional. Applications explicitly given on the\n"
183 " command line will be included even if -nosystem would\n"
184 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700185 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700186 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700187 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800188 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
189 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800190 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
191 " and the public key is stored in <file>.pub. Any existing files\n"
192 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800193 " adb help - show this help message\n"
194 " adb version - show version num\n"
195 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800196 "scripting:\n"
197 " adb wait-for-device - block until device is online\n"
198 " adb start-server - ensure that there is a server running\n"
199 " adb kill-server - kill the server if it is running\n"
200 " adb get-state - prints: offline | bootloader | device\n"
201 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700202 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800203 " adb status-window - continuously print device status for a specified device\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000204 " 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 -0700205 " adb reboot [bootloader|recovery]\n"
206 " - reboots the device, optionally into the bootloader or recovery program.\n"
207 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
208 " adb reboot sideload-auto-reboot\n"
209 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Romain Guy311add42009-12-14 14:42:17 -0800210 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700211 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500212 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800213 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000214 " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800215 "networking:\n"
216 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500217 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800218 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
219 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
220 "\n"
221 "adb sync notes: adb sync [ <directory> ]\n"
222 " <localdir> can be interpreted in several ways:\n"
223 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000224 " - 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 -0800225 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000226 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800227 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000228 "\n"
229 "environmental variables:\n"
230 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
231 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
232 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
233 " 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 -0800234 );
235}
236
Elliott Hughes58305772015-04-17 13:57:15 -0700237static int usage() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800238 help();
239 return 1;
240}
241
Yabin Cuid325e862014-11-17 14:48:25 -0800242#if defined(_WIN32)
243
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700244// Implemented in sysdeps_win32.cpp.
Spencer Low50184062015-03-01 15:06:21 -0800245void stdin_raw_init(int fd);
246void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800247
248#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100249static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800250
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100251static void stdin_raw_init(int fd) {
252 if (tcgetattr(fd, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800253
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100254 termios tio;
255 if (tcgetattr(fd, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800256
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100257 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800258
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100259 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800260 tio.c_cc[VTIME] = 0;
261 tio.c_cc[VMIN] = 1;
262
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100263 tcsetattr(fd, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800264}
265
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100266static void stdin_raw_restore(int fd) {
267 tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800268}
269#endif
270
271static void read_and_dump(int fd)
272{
273 char buf[4096];
274 int len;
275
276 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700277 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800278 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700279 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800280 if(len == 0) {
281 break;
282 }
283
284 if(len < 0) {
285 if(errno == EINTR) continue;
286 break;
287 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400288 fwrite(buf, 1, len, stdout);
289 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800290 }
291}
292
Jeff Sharkey960df972014-06-09 17:30:57 -0700293static void read_status_line(int fd, char* buf, size_t count)
294{
295 count--;
296 while (count > 0) {
297 int len = adb_read(fd, buf, count);
298 if (len == 0) {
299 break;
300 } else if (len < 0) {
301 if (errno == EINTR) continue;
302 break;
303 }
304
305 buf += len;
306 count -= len;
307 }
308 *buf = '\0';
309}
310
Christopher Tated2f54152011-04-21 12:53:28 -0700311static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700312 const size_t BUFSIZE = 32 * 1024;
313 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700314 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700315 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700316
317 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800318
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700319 if (inFd == STDIN_FILENO) {
320 stdin_raw_init(STDIN_FILENO);
321 }
Yabin Cuid325e862014-11-17 14:48:25 -0800322
Christopher Tated2f54152011-04-21 12:53:28 -0700323 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700324 if (inFd == STDIN_FILENO) {
325 len = unix_read(inFd, buf, BUFSIZE);
326 } else {
327 len = adb_read(inFd, buf, BUFSIZE);
328 }
Christopher Tated2f54152011-04-21 12:53:28 -0700329 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700330 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700331 break;
332 }
333 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700334 if (errno == EINTR) {
335 D("copy_to_file() : EINTR, retrying\n");
336 continue;
337 }
Christopher Tated2f54152011-04-21 12:53:28 -0700338 D("copy_to_file() : error %d\n", errno);
339 break;
340 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700341 if (outFd == STDOUT_FILENO) {
342 fwrite(buf, 1, len, stdout);
343 fflush(stdout);
344 } else {
345 adb_write(outFd, buf, len);
346 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700347 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700348 }
Yabin Cuid325e862014-11-17 14:48:25 -0800349
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700350 if (inFd == STDIN_FILENO) {
351 stdin_raw_restore(STDIN_FILENO);
352 }
Yabin Cuid325e862014-11-17 14:48:25 -0800353
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700354 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700355 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700356}
357
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800358static void *stdin_read_thread(void *x)
359{
360 int fd, fdi;
361 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800362 int r, n;
363 int state = 0;
364
365 int *fds = (int*) x;
366 fd = fds[0];
367 fdi = fds[1];
368 free(fds);
369
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800370 for(;;) {
371 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700372 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800373 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700374 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800375 if(r == 0) break;
376 if(r < 0) {
377 if(errno == EINTR) continue;
378 break;
379 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400380 for(n = 0; n < r; n++){
381 switch(buf[n]) {
382 case '\n':
383 state = 1;
384 break;
385 case '\r':
386 state = 1;
387 break;
388 case '~':
389 if(state == 1) state++;
390 break;
391 case '.':
392 if(state == 2) {
393 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400394 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400395 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800396 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400397 default:
398 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800399 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800400 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800401 r = adb_write(fd, buf, r);
402 if(r <= 0) {
403 break;
404 }
405 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800406 return 0;
407}
408
Elliott Hughes58305772015-04-17 13:57:15 -0700409static int interactive_shell() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800410 adb_thread_t thr;
411 int fdi, fd;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800412
413 fd = adb_connect("shell:");
414 if(fd < 0) {
415 fprintf(stderr,"error: %s\n", adb_error());
416 return 1;
417 }
418 fdi = 0; //dup(0);
419
Dan Albertbac34742015-02-25 17:51:28 -0800420 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800421 fds[0] = fd;
422 fds[1] = fdi;
423
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800424 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800425 adb_thread_create(&thr, stdin_read_thread, fds);
426 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800427 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800428 return 0;
429}
430
431
432static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
433{
434 if (serial) {
435 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
436 } else {
437 const char* prefix = "host";
438 if (ttype == kTransportUsb)
439 prefix = "host-usb";
440 else if (ttype == kTransportLocal)
441 prefix = "host-local";
442
443 snprintf(buffer, buflen, "%s:%s", prefix, command);
444 }
445}
446
Elliott Hughes58305772015-04-17 13:57:15 -0700447static int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
448 unsigned progress)
Doug Zongker447f0612012-01-09 14:54:53 -0800449{
450 char buf[4096];
451 unsigned total;
452 int fd;
Doug Zongker447f0612012-01-09 14:54:53 -0800453
454 sprintf(buf,"%s:%d", service, sz);
455 fd = adb_connect(buf);
456 if(fd < 0) {
457 fprintf(stderr,"error: %s\n", adb_error());
458 return -1;
459 }
460
461 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800462 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800463
464 total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800465 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800466
467 if(progress) {
468 char *x = strrchr(service, ':');
469 if(x) service = x + 1;
470 }
471
472 while(sz > 0) {
473 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800474 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800475 adb_status(fd);
476 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
477 return -1;
478 }
479 sz -= xfer;
480 ptr += xfer;
481 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100482 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800483 fflush(stdout);
484 }
485 }
486 if(progress) {
487 printf("\n");
488 }
489
Dan Albertcc731cc2015-02-24 21:26:58 -0800490 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800491 fprintf(stderr,"* error reading response *\n");
492 adb_close(fd);
493 return -1;
494 }
495 if(memcmp(buf, "OKAY", 4)) {
496 buf[4] = 0;
497 fprintf(stderr,"* error response '%s' *\n", buf);
498 adb_close(fd);
499 return -1;
500 }
501
502 adb_close(fd);
503 return 0;
504}
505
Doug Zongker71fe5842014-06-26 15:35:36 -0700506#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
507
508/*
509 * The sideload-host protocol serves the data in a file (given on the
510 * command line) to the client, using a simple protocol:
511 *
512 * - The connect message includes the total number of bytes in the
513 * file and a block size chosen by us.
514 *
515 * - The other side sends the desired block number as eight decimal
516 * digits (eg "00000023" for block 23). Blocks are numbered from
517 * zero.
518 *
519 * - We send back the data of the requested block. The last block is
520 * likely to be partial; when the last block is requested we only
521 * send the part of the block that exists, it's not padded up to the
522 * block size.
523 *
524 * - When the other side sends "DONEDONE" instead of a block number,
525 * we hang up.
526 */
Elliott Hughes58305772015-04-17 13:57:15 -0700527static int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700528 unsigned sz;
529 size_t xfer = 0;
530 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800531 int last_percent = -1;
532 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700533
534 printf("loading: '%s'", fn);
535 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800536 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700537 if (data == 0) {
538 printf("\n");
539 fprintf(stderr, "* cannot read '%s' *\n", fn);
540 return -1;
541 }
542
543 char buf[100];
544 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
545 int fd = adb_connect(buf);
546 if (fd < 0) {
547 // Try falling back to the older sideload method. Maybe this
548 // is an older device that doesn't support sideload-host.
549 printf("\n");
550 status = adb_download_buffer("sideload", fn, data, sz, 1);
551 goto done;
552 }
553
Spencer Lowf055c192015-01-25 14:40:16 -0800554 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700555
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700556 for (;;) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800557 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700558 fprintf(stderr, "* failed to read command: %s\n", adb_error());
559 status = -1;
560 goto done;
561 }
562
563 if (strncmp("DONEDONE", buf, 8) == 0) {
564 status = 0;
565 break;
566 }
567
568 buf[8] = '\0';
569 int block = strtol(buf, NULL, 10);
570
571 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
572 if (offset >= sz) {
573 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
574 status = -1;
575 goto done;
576 }
577 uint8_t* start = data + offset;
578 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
579 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
580 if (offset_end > sz) {
581 to_write = sz - offset;
582 }
583
Dan Albertcc731cc2015-02-24 21:26:58 -0800584 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700585 adb_status(fd);
586 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
587 status = -1;
588 goto done;
589 }
590 xfer += to_write;
591
592 // For normal OTA packages, we expect to transfer every byte
593 // twice, plus a bit of overhead (one read during
594 // verification, one read of each byte for installation, plus
595 // extra access to things like the zip central directory).
596 // This estimate of the completion becomes 100% when we've
597 // transferred ~2.13 (=100/47) times the package size.
598 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
599 if (percent != last_percent) {
600 printf("\rserving: '%s' (~%d%%) ", fn, percent);
601 fflush(stdout);
602 last_percent = percent;
603 }
604 }
605
Colin Cross6d6a8982014-07-07 14:12:41 -0700606 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700607
608 done:
609 if (fd >= 0) adb_close(fd);
610 free(data);
611 return status;
612}
613
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800614static void status_window(transport_type ttype, const char* serial)
615{
616 char command[4096];
617 char *state = 0;
618 char *laststate = 0;
619
620 /* silence stderr */
621#ifdef _WIN32
622 /* XXX: TODO */
623#else
624 int fd;
625 fd = unix_open("/dev/null", O_WRONLY);
626 dup2(fd, 2);
627 adb_close(fd);
628#endif
629
630 format_host_command(command, sizeof command, "get-state", ttype, serial);
631
632 for(;;) {
633 adb_sleep_ms(250);
634
635 if(state) {
636 free(state);
637 state = 0;
638 }
639
640 state = adb_query(command);
641
642 if(state) {
643 if(laststate && !strcmp(state,laststate)){
644 continue;
645 } else {
646 if(laststate) free(laststate);
647 laststate = strdup(state);
648 }
649 }
650
651 printf("%c[2J%c[2H", 27, 27);
652 printf("Android Debug Bridge\n");
653 printf("State: %s\n", state ? state : "offline");
654 fflush(stdout);
655 }
656}
657
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800658/**
659 * Run ppp in "notty" mode against a resource listed as the first parameter
660 * eg:
661 *
662 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
663 *
664 */
Elliott Hughes58305772015-04-17 13:57:15 -0700665static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800666#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800667 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
668 return -1;
669#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800670 pid_t pid;
671 int fd;
672
673 if (argc < 2) {
674 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
675 argv[0]);
676
677 return 1;
678 }
679
Dan Albertbac34742015-02-25 17:51:28 -0800680 const char* adb_service_name = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800681 fd = adb_connect(adb_service_name);
682
683 if(fd < 0) {
684 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
685 adb_service_name, adb_error());
686 return 1;
687 }
688
689 pid = fork();
690
691 if (pid < 0) {
692 perror("from fork()");
693 return 1;
694 } else if (pid == 0) {
695 int err;
696 int i;
697 const char **ppp_args;
698
699 // copy args
700 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
701 ppp_args[0] = "pppd";
702 for (i = 2 ; i < argc ; i++) {
703 //argv[2] and beyond become ppp_args[1] and beyond
704 ppp_args[i - 1] = argv[i];
705 }
706 ppp_args[i-1] = NULL;
707
708 // child side
709
710 dup2(fd, STDIN_FILENO);
711 dup2(fd, STDOUT_FILENO);
712 adb_close(STDERR_FILENO);
713 adb_close(fd);
714
715 err = execvp("pppd", (char * const *)ppp_args);
716
717 if (err < 0) {
718 perror("execing pppd");
719 }
720 exit(-1);
721 } else {
722 // parent side
723
724 adb_close(fd);
725 return 0;
726 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800727#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800728}
729
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700730static int send_shell_command(transport_type transport, const char* serial,
731 const std::string& command) {
732 int fd;
733 while (true) {
734 fd = adb_connect(command.c_str());
735 if (fd >= 0)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800736 break;
737 fprintf(stderr,"- waiting for device -\n");
738 adb_sleep_ms(1000);
739 do_cmd(transport, serial, "wait-for-device", 0);
740 }
741
742 read_and_dump(fd);
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700743 int rc = adb_close(fd);
744 if (rc) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800745 perror("close");
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700746 }
747 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800748}
749
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700750static int logcat(transport_type transport, const char* serial, int argc, const char** argv) {
751 char* log_tags = getenv("ANDROID_LOG_TAGS");
752 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800753
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700754 std::string cmd = "shell:export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800755
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700756 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700757 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -0800758 }
759
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800760 argc -= 1;
761 argv += 1;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700762 while (argc-- > 0) {
763 cmd += " ";
764 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800765 }
766
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700767 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800768 return 0;
769}
770
Mark Salyzyn60299df2014-04-30 09:10:31 -0700771static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800772{
773 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700774 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800775
776 for(;;) {
777 x = adb_dirstart(x);
778 if(x == 0) return 0;
779 *x = 0;
780 ret = adb_mkdir(path, 0775);
781 *x = OS_PATH_SEPARATOR;
782 if((ret < 0) && (errno != EEXIST)) {
783 return ret;
784 }
785 x++;
786 }
787 return 0;
788}
789
Dan Albertbac34742015-02-25 17:51:28 -0800790static int backup(int argc, const char** argv) {
Christopher Tated2f54152011-04-21 12:53:28 -0700791 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800792 char default_name[32];
793 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700794 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700795 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700796
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700797 /* find, extract, and use any -f argument */
798 for (i = 1; i < argc; i++) {
799 if (!strcmp("-f", argv[i])) {
800 if (i == argc-1) {
801 fprintf(stderr, "adb: -f passed with no filename\n");
802 return usage();
803 }
804 filename = argv[i+1];
805 for (j = i+2; j <= argc; ) {
806 argv[i++] = argv[j++];
807 }
808 argc -= 2;
809 argv[argc] = NULL;
810 }
Christopher Tated2f54152011-04-21 12:53:28 -0700811 }
812
Christopher Tatebb86bc52011-08-22 17:12:08 -0700813 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
814 if (argc < 2) return usage();
815
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800816 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700817 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800818 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700819 if (outFd < 0) {
820 fprintf(stderr, "adb: unable to open file %s\n", filename);
821 return -1;
822 }
823
824 snprintf(buf, sizeof(buf), "backup");
825 for (argc--, argv++; argc; argc--, argv++) {
826 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
827 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
828 }
829
830 D("backup. filename=%s buf=%s\n", filename, buf);
831 fd = adb_connect(buf);
832 if (fd < 0) {
833 fprintf(stderr, "adb: unable to connect for backup\n");
834 adb_close(outFd);
835 return -1;
836 }
837
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800838 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700839 copy_to_file(fd, outFd);
840
841 adb_close(fd);
842 adb_close(outFd);
843 return 0;
844}
845
Dan Albertbac34742015-02-25 17:51:28 -0800846static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700847 const char* filename;
848 int fd, tarFd;
849
850 if (argc != 2) return usage();
851
852 filename = argv[1];
853 tarFd = adb_open(filename, O_RDONLY);
854 if (tarFd < 0) {
855 fprintf(stderr, "adb: unable to open file %s\n", filename);
856 return -1;
857 }
858
859 fd = adb_connect("restore:");
860 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700861 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700862 adb_close(tarFd);
863 return -1;
864 }
865
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800866 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700867 copy_to_file(tarFd, fd);
868
869 adb_close(fd);
870 adb_close(tarFd);
871 return 0;
872}
873
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800874#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
875static int top_works(const char *top)
876{
877 if (top != NULL && adb_is_absolute_host_path(top)) {
878 char path_buf[PATH_MAX];
879 snprintf(path_buf, sizeof(path_buf),
880 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
881 return access(path_buf, F_OK) == 0;
882 }
883 return 0;
884}
885
886static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
887{
888 strcpy(path_buf, indir);
889 while (1) {
890 if (top_works(path_buf)) {
891 return path_buf;
892 }
893 char *s = adb_dirstop(path_buf);
894 if (s != NULL) {
895 *s = '\0';
896 } else {
897 path_buf[0] = '\0';
898 return NULL;
899 }
900 }
901}
902
903static char *find_top(char path_buf[PATH_MAX])
904{
905 char *top = getenv("ANDROID_BUILD_TOP");
906 if (top != NULL && top[0] != '\0') {
907 if (!top_works(top)) {
908 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
909 return NULL;
910 }
911 } else {
912 top = getenv("TOP");
913 if (top != NULL && top[0] != '\0') {
914 if (!top_works(top)) {
915 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
916 return NULL;
917 }
918 } else {
919 top = NULL;
920 }
921 }
922
923 if (top != NULL) {
924 /* The environment pointed to a top directory that works.
925 */
926 strcpy(path_buf, top);
927 return path_buf;
928 }
929
930 /* The environment didn't help. Walk up the tree from the CWD
931 * to see if we can find the top.
932 */
933 char dir[PATH_MAX];
934 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
935 if (top == NULL) {
936 /* If the CWD isn't under a good-looking top, see if the
937 * executable is.
938 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100939 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800940 top = find_top_from(dir, path_buf);
941 }
942 return top;
943}
944
945/* <hint> may be:
946 * - A simple product name
947 * e.g., "sooner"
948TODO: debug? sooner-debug, sooner:debug?
949 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
950 * e.g., "out/target/product/sooner"
951 * - An absolute path to the PRODUCT_OUT dir
952 * e.g., "/src/device/out/target/product/sooner"
953 *
954 * Given <hint>, try to construct an absolute path to the
955 * ANDROID_PRODUCT_OUT dir.
956 */
Elliott Hughes58305772015-04-17 13:57:15 -0700957static std::string find_product_out_path(const char* hint) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800958 if (hint == NULL || hint[0] == '\0') {
Elliott Hughes58305772015-04-17 13:57:15 -0700959 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800960 }
961
Elliott Hughes58305772015-04-17 13:57:15 -0700962 // If it's already absolute, don't bother doing any work.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800963 if (adb_is_absolute_host_path(hint)) {
Elliott Hughes58305772015-04-17 13:57:15 -0700964 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800965 }
966
Elliott Hughes58305772015-04-17 13:57:15 -0700967 // If there are any slashes in it, assume it's a relative path;
968 // make it absolute.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800969 if (adb_dirstart(hint) != NULL) {
Elliott Hughes58305772015-04-17 13:57:15 -0700970 char cwd[PATH_MAX];
971 if (getcwd(cwd, sizeof(cwd)) == NULL) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800972 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -0700973 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800974 }
Elliott Hughes58305772015-04-17 13:57:15 -0700975 return android::base::StringPrintf("%s%s%s", cwd, OS_PATH_SEPARATOR_STR, hint);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800976 }
977
Elliott Hughes58305772015-04-17 13:57:15 -0700978 // It's a string without any slashes. Try to do something with it.
979 //
980 // Try to find the root of the build tree, and build a PRODUCT_OUT
981 // path from there.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800982 char top_buf[PATH_MAX];
Elliott Hughes58305772015-04-17 13:57:15 -0700983 const char* top = find_top(top_buf);
984 if (top == nullptr) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800985 fprintf(stderr, "adb: Couldn't find top of build tree\n");
Elliott Hughes58305772015-04-17 13:57:15 -0700986 return "";
987 }
988 std::string path = top_buf;
989 path += OS_PATH_SEPARATOR_STR;
990 path += "out";
991 path += OS_PATH_SEPARATOR_STR;
992 path += "target";
993 path += OS_PATH_SEPARATOR_STR;
994 path += "product";
995 path += OS_PATH_SEPARATOR_STR;
996 path += hint;
997 if (!directory_exists(path)) {
998 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
999 "\"%s\" doesn't exist\n", hint, path.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001000 return NULL;
1001 }
Elliott Hughes58305772015-04-17 13:57:15 -07001002 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001003}
1004
Dan Albertbac34742015-02-25 17:51:28 -08001005static void parse_push_pull_args(const char **arg, int narg, char const **path1,
1006 char const **path2, int *show_progress,
1007 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001008 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001009 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001010
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001011 while (narg > 0) {
1012 if (!strcmp(*arg, "-p")) {
1013 *show_progress = 1;
1014 } else if (!strcmp(*arg, "-a")) {
1015 *copy_attrs = 1;
1016 } else {
1017 break;
1018 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001019 ++arg;
1020 --narg;
1021 }
1022
1023 if (narg > 0) {
1024 *path1 = *arg;
1025 ++arg;
1026 --narg;
1027 }
1028
1029 if (narg > 0) {
1030 *path2 = *arg;
1031 }
1032}
1033
Tao Bao175b7bb2015-03-29 11:22:34 -07001034static int adb_connect_command(const char* command) {
1035 int fd = adb_connect(command);
1036 if (fd != -1) {
1037 read_and_dump(fd);
1038 adb_close(fd);
1039 return 0;
1040 }
1041 fprintf(stderr, "Error: %s\n", adb_error());
1042 return 1;
1043}
1044
Dan Albertbac34742015-02-25 17:51:28 -08001045int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001046{
1047 char buf[4096];
1048 int no_daemon = 0;
1049 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001050 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001051 int persist = 0;
1052 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001053 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -08001054 const char* serial = NULL;
1055 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001056
Elliott Hughes58305772015-04-17 13:57:15 -07001057 // If defined, this should be an absolute path to
1058 // the directory containing all of the various system images
1059 // for a particular product. If not defined, and the adb
1060 // command requires this information, then the user must
1061 // specify the path using "-p".
1062 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
1063 if (ANDROID_PRODUCT_OUT != nullptr) {
1064 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001065 }
1066 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1067
Nick Pellydb449262009-05-07 12:48:03 -07001068 serial = getenv("ANDROID_SERIAL");
1069
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001070 /* Validate and assign the server port */
1071 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1072 int server_port = DEFAULT_ADB_PORT;
1073 if (server_port_str && strlen(server_port_str) > 0) {
1074 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001075 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001076 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001077 "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n",
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001078 server_port_str);
1079 return usage();
1080 }
1081 }
1082
1083 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001084 while (argc > 0) {
1085 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001086 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001087 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001088 no_daemon = 1;
1089 } else if (!strcmp(argv[0], "fork-server")) {
1090 /* this is a special flag used only when the ADB client launches the ADB Server */
1091 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001092 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001093 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001094 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001095 const char *product = NULL;
1096 if (argv[0][2] == '\0') {
1097 if (argc < 2) return usage();
1098 product = argv[1];
1099 argc--;
1100 argv++;
1101 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001102 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001103 }
1104 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -07001105 if (gProductOutPath.empty()) {
1106 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001107 return usage();
1108 }
1109 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1110 if (isdigit(argv[0][2])) {
1111 serial = argv[0] + 2;
1112 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001113 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001114 serial = argv[1];
1115 argc--;
1116 argv++;
1117 }
1118 } else if (!strcmp(argv[0],"-d")) {
1119 ttype = kTransportUsb;
1120 } else if (!strcmp(argv[0],"-e")) {
1121 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001122 } else if (!strcmp(argv[0],"-a")) {
1123 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001124 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001125 const char *hostname = NULL;
1126 if (argv[0][2] == '\0') {
1127 if (argc < 2) return usage();
1128 hostname = argv[1];
1129 argc--;
1130 argv++;
1131 } else {
1132 hostname = argv[0] + 2;
1133 }
1134 adb_set_tcp_name(hostname);
1135
Riley Andrews98f58e82014-12-05 17:37:24 -08001136 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001137 if (argv[0][2] == '\0') {
1138 if (argc < 2) return usage();
1139 server_port_str = argv[1];
1140 argc--;
1141 argv++;
1142 } else {
1143 server_port_str = argv[0] + 2;
1144 }
1145 if (strlen(server_port_str) > 0) {
1146 server_port = (int) strtol(server_port_str, NULL, 0);
1147 if (server_port <= 0 || server_port > 65535) {
1148 fprintf(stderr,
1149 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1150 server_port_str);
1151 return usage();
1152 }
1153 } else {
1154 fprintf(stderr,
1155 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1156 return usage();
1157 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001158 } else {
1159 /* out of recognized modifiers and flags */
1160 break;
1161 }
1162 argc--;
1163 argv++;
1164 }
1165
1166 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001167 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001168
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001169 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001170 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001171 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001172 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001173 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001174 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001175 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001176 fprintf(stderr,"* could not start server *\n");
1177 }
1178 return r;
1179 }
1180
Riley Andrews98f58e82014-12-05 17:37:24 -08001181 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001182 return usage();
1183 }
1184
Riley Andrewsc8514c82014-12-05 17:32:46 -08001185 /* handle wait-for-* prefix */
1186 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001187 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001188 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1189 if (ttype == kTransportUsb) {
1190 service = "wait-for-usb";
1191 } else if (ttype == kTransportLocal) {
1192 service = "wait-for-local";
1193 } else {
1194 service = "wait-for-any";
1195 }
1196 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001197
Riley Andrewsc8514c82014-12-05 17:32:46 -08001198 format_host_command(buf, sizeof buf, service, ttype, serial);
1199
1200 if (adb_command(buf)) {
1201 D("failure: %s *\n",adb_error());
1202 fprintf(stderr,"error: %s\n", adb_error());
1203 return 1;
1204 }
1205
1206 /* Allow a command to be run after wait-for-device,
1207 * e.g. 'adb wait-for-device shell'.
1208 */
1209 if (argc == 1) {
1210 return 0;
1211 }
1212
1213 /* Fall through */
1214 argc--;
1215 argv++;
1216 }
1217
1218 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001219 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001220 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001221 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001222 if (argc < 2)
1223 listopt = "";
1224 else if (argc == 2 && !strcmp(argv[1], "-l"))
1225 listopt = argv[1];
1226 else {
1227 fprintf(stderr, "Usage: adb devices [-l]\n");
1228 return 1;
1229 }
1230 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001231 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001232 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001233 printf("List of devices attached \n");
1234 printf("%s\n", tmp);
1235 return 0;
1236 } else {
1237 return 1;
1238 }
1239 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001240 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001241 char *tmp;
1242 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001243 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001244 return 1;
1245 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001246 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1247 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001248 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001249 printf("%s\n", tmp);
1250 return 0;
1251 } else {
1252 return 1;
1253 }
1254 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001255 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001256 char *tmp;
1257 if (argc > 2) {
1258 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1259 return 1;
1260 }
1261 if (argc == 2) {
1262 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1263 } else {
1264 snprintf(buf, sizeof buf, "host:disconnect:");
1265 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001266 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001267 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001268 printf("%s\n", tmp);
1269 return 0;
1270 } else {
1271 return 1;
1272 }
1273 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001274 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001275 return adb_send_emulator_command(argc, argv);
1276 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001277 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001278 char h = (argv[0][0] == 'h');
1279
1280 if (h) {
1281 printf("\x1b[41;33m");
1282 fflush(stdout);
1283 }
1284
Riley Andrews98f58e82014-12-05 17:37:24 -08001285 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001286 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001287 r = interactive_shell();
1288 if (h) {
1289 printf("\x1b[0m");
1290 fflush(stdout);
1291 }
1292 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001293 }
1294
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001295 std::string cmd = "shell:";
1296 cmd += argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001297 argc -= 2;
1298 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001299 while (argc-- > 0) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001300 cmd += " ";
1301 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001302 }
1303
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001304 while (true) {
1305 D("interactive shell loop. cmd=%s\n", cmd.c_str());
1306 int fd = adb_connect(cmd.c_str());
1307 int r;
Riley Andrews98f58e82014-12-05 17:37:24 -08001308 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001309 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001310 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001311 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001312 adb_close(fd);
1313 r = 0;
1314 } else {
1315 fprintf(stderr,"error: %s\n", adb_error());
1316 r = -1;
1317 }
1318
Riley Andrews98f58e82014-12-05 17:37:24 -08001319 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001320 fprintf(stderr,"\n- waiting for device -\n");
1321 adb_sleep_ms(1000);
1322 do_cmd(ttype, serial, "wait-for-device", 0);
1323 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001324 if (h) {
1325 printf("\x1b[0m");
1326 fflush(stdout);
1327 }
JP Abgrall408fa572011-03-16 15:57:42 -07001328 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001329 return r;
1330 }
1331 }
1332 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001333 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001334 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001335
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001336 std::string cmd = "exec:";
1337 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001338 argc -= 2;
1339 argv += 2;
1340 while (argc-- > 0) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001341 cmd += " ";
1342 cmd += escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001343 }
1344
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001345 int fd = adb_connect(cmd.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001346 if (fd < 0) {
1347 fprintf(stderr, "error: %s\n", adb_error());
1348 return -1;
1349 }
1350
1351 if (exec_in) {
1352 copy_to_file(STDIN_FILENO, fd);
1353 } else {
1354 copy_to_file(fd, STDOUT_FILENO);
1355 }
1356
1357 adb_close(fd);
1358 return 0;
1359 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001360 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001361 int fd;
1362 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001363 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001364 fprintf(stderr,"* server not running *\n");
1365 return 1;
1366 }
1367 return 0;
1368 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001369 else if (!strcmp(argv[0], "sideload")) {
1370 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001371 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001372 return 1;
1373 } else {
1374 return 0;
1375 }
1376 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001377 else if (!strcmp(argv[0], "remount") ||
1378 !strcmp(argv[0], "reboot") ||
1379 !strcmp(argv[0], "reboot-bootloader") ||
1380 !strcmp(argv[0], "tcpip") ||
1381 !strcmp(argv[0], "usb") ||
1382 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001383 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001384 !strcmp(argv[0], "disable-verity") ||
1385 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001386 char command[100];
Tao Bao175b7bb2015-03-29 11:22:34 -07001387 if (!strcmp(argv[0], "reboot-bootloader")) {
Romain Guy311add42009-12-14 14:42:17 -08001388 snprintf(command, sizeof(command), "reboot:bootloader");
Tao Bao175b7bb2015-03-29 11:22:34 -07001389 } else if (argc > 1) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001390 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001391 } else {
Mike Lockwoodff196702009-08-24 15:58:40 -07001392 snprintf(command, sizeof(command), "%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001393 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001394 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001395 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001396 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001397 if (argc != 1) return usage();
1398 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001399 return 0;
1400 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001401 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001402 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001403 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001404 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001405 char remove = 0;
1406 char remove_all = 0;
1407 char list = 0;
1408 char no_rebind = 0;
1409
1410 // Parse options here.
1411 while (argc > 1 && argv[1][0] == '-') {
1412 if (!strcmp(argv[1], "--list"))
1413 list = 1;
1414 else if (!strcmp(argv[1], "--remove"))
1415 remove = 1;
1416 else if (!strcmp(argv[1], "--remove-all"))
1417 remove_all = 1;
1418 else if (!strcmp(argv[1], "--no-rebind"))
1419 no_rebind = 1;
1420 else {
1421 return usage();
1422 }
1423 argc--;
1424 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001425 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001426
1427 // Ensure we can only use one option at a time.
1428 if (list + remove + remove_all + no_rebind > 1) {
1429 return usage();
1430 }
1431
1432 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001433 if (reverse) {
1434 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001435 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001436 if (serial) {
1437 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1438 serial);
1439 } else if (ttype == kTransportUsb) {
1440 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1441 } else if (ttype == kTransportLocal) {
1442 snprintf(host_prefix, sizeof host_prefix, "host-local");
1443 } else {
1444 snprintf(host_prefix, sizeof host_prefix, "host");
1445 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001446 }
1447
1448 // Implement forward --list
1449 if (list) {
1450 if (argc != 1)
1451 return usage();
1452 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1453 char* forwards = adb_query(buf);
1454 if (forwards == NULL) {
1455 fprintf(stderr, "error: %s\n", adb_error());
1456 return 1;
1457 }
1458 printf("%s", forwards);
1459 free(forwards);
1460 return 0;
1461 }
1462
1463 // Implement forward --remove-all
1464 else if (remove_all) {
1465 if (argc != 1)
1466 return usage();
1467 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1468 }
1469
1470 // Implement forward --remove <local>
1471 else if (remove) {
1472 if (argc != 2)
1473 return usage();
1474 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1475 }
1476 // Or implement one of:
1477 // forward <local> <remote>
1478 // forward --no-rebind <local> <remote>
1479 else
1480 {
1481 if (argc != 3)
1482 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001483 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001484 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1485 }
1486
Riley Andrews98f58e82014-12-05 17:37:24 -08001487 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001488 fprintf(stderr,"error: %s\n", adb_error());
1489 return 1;
1490 }
1491 return 0;
1492 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001493 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001494 else if (!strcmp(argv[0], "ls")) {
1495 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001496 return do_sync_ls(argv[1]);
1497 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001498 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001499 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001500 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001501 const char* lpath = NULL, *rpath = NULL;
1502
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001503 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001504
1505 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001506 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001507 }
1508
1509 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001510 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001511 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001512 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001513 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001514 const char* rpath = NULL, *lpath = ".";
1515
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001516 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001517
1518 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001519 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001520 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001521
1522 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001523 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001524 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001525 if (argc < 2) return usage();
1526 return install_app(ttype, serial, argc, argv);
1527 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001528 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001529 if (argc < 2) return usage();
1530 return install_multiple_app(ttype, serial, argc, argv);
1531 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001532 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001533 if (argc < 2) return usage();
1534 return uninstall_app(ttype, serial, argc, argv);
1535 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001536 else if (!strcmp(argv[0], "sync")) {
Elliott Hughes58305772015-04-17 13:57:15 -07001537 std::string src_arg;
1538 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001539 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001540 // No local path was specified.
1541 src_arg = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001542 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughes58305772015-04-17 13:57:15 -07001543 list_only = 1;
Anthony Newnam705c9442010-02-22 08:36:49 -06001544 if (argc == 3) {
Elliott Hughes58305772015-04-17 13:57:15 -07001545 src_arg = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001546 } else {
Elliott Hughes58305772015-04-17 13:57:15 -07001547 src_arg = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001548 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001549 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001550 // A local path or "android"/"data" arg was specified.
1551 src_arg = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001552 } else {
1553 return usage();
1554 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001555
Elliott Hughes58305772015-04-17 13:57:15 -07001556 if (src_arg != "" &&
1557 src_arg != "system" && src_arg != "data" && src_arg != "vendor" && src_arg != "oem") {
1558 return usage();
1559 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001560
Elliott Hughes58305772015-04-17 13:57:15 -07001561 std::string system_src_path = product_file("system");
1562 std::string data_src_path = product_file("data");
1563 std::string vendor_src_path = product_file("vendor");
1564 std::string oem_src_path = product_file("oem");
1565 if (!directory_exists(vendor_src_path)) {
1566 vendor_src_path = "";
1567 }
1568 if (!directory_exists(oem_src_path)) {
1569 oem_src_path = "";
1570 }
1571
1572 int rc = 0;
1573 if (rc == 0 && (src_arg.empty() || src_arg == "system")) {
1574 rc = do_sync_sync(system_src_path.c_str(), "/system", list_only);
1575 }
1576 if (rc == 0 && (src_arg.empty() || src_arg == "vendor")) {
1577 rc = do_sync_sync(vendor_src_path.c_str(), "/vendor", list_only);
1578 }
1579 if(rc == 0 && (src_arg.empty() || src_arg == "oem")) {
1580 rc = do_sync_sync(oem_src_path.c_str(), "/oem", list_only);
1581 }
1582 if (rc == 0 && (src_arg.empty() || src_arg == "data")) {
1583 rc = do_sync_sync(data_src_path.c_str(), "/data", list_only);
1584 }
1585 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001586 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001587 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001588 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001589 !strcmp(argv[0],"get-serialno") ||
1590 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001591 {
1592 char *tmp;
1593
1594 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1595 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001596 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001597 printf("%s\n", tmp);
1598 return 0;
1599 } else {
1600 return 1;
1601 }
1602 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001603 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001604 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001605 status_window(ttype, serial);
1606 return 0;
1607 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001608 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001609 return logcat(ttype, serial, argc, argv);
1610 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001611 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001612 return ppp(argc, argv);
1613 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001614 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001615 return adb_connect("host:start-server");
1616 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001617 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001618 return backup(argc, argv);
1619 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001620 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001621 return restore(argc, argv);
1622 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001623 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001624 if (argc < 2) return usage();
1625 return adb_auth_keygen(argv[1]);
1626 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001627 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001628 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001629 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001630 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001631 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001632 help();
1633 return 0;
1634 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001635 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001636 version(stdout);
1637 return 0;
1638 }
1639
1640 usage();
1641 return 1;
1642}
1643
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001644#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001645static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001646{
Dan Albertbac34742015-02-25 17:51:28 -08001647 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001648 int argc;
1649 va_list ap;
1650
1651 va_start(ap, cmd);
1652 argc = 0;
1653
1654 if (serial) {
1655 argv[argc++] = "-s";
1656 argv[argc++] = serial;
1657 } else if (ttype == kTransportUsb) {
1658 argv[argc++] = "-d";
1659 } else if (ttype == kTransportLocal) {
1660 argv[argc++] = "-e";
1661 }
1662
1663 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001664 while(argc < MAX_ARGV_LENGTH &&
1665 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1666 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001667 va_end(ap);
1668
1669#if 0
1670 int n;
1671 fprintf(stderr,"argc = %d\n",argc);
1672 for(n = 0; n < argc; n++) {
1673 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1674 }
1675#endif
1676
1677 return adb_commandline(argc, argv);
1678}
1679
Dan Albertbac34742015-02-25 17:51:28 -08001680static int pm_command(transport_type transport, const char* serial,
1681 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001682{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001683 std::string cmd = "shell:pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001684
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001685 while (argc-- > 0) {
1686 cmd += " ";
1687 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001688 }
1689
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001690 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001691 return 0;
1692}
1693
Elliott Hughes58305772015-04-17 13:57:15 -07001694static int uninstall_app(transport_type transport, const char* serial, int argc,
1695 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001696{
1697 /* if the user choose the -k option, we refuse to do it until devices are
1698 out with the option to uninstall the remaining data somehow (adb/ui) */
1699 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1700 {
1701 printf(
1702 "The -k option uninstalls the application while retaining the data/cache.\n"
1703 "At the moment, there is no way to remove the remaining data.\n"
1704 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1705 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1706 return -1;
1707 }
1708
1709 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1710 return pm_command(transport, serial, argc, argv);
1711}
1712
Dan Albertbac34742015-02-25 17:51:28 -08001713static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001714{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001715 std::string cmd = "shell:rm -f " + escape_arg(filename);
1716 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001717 return 0;
1718}
1719
Kenny Root597ea5b2011-08-05 11:19:45 -07001720static const char* get_basename(const char* filename)
1721{
1722 const char* basename = adb_dirstop(filename);
1723 if (basename) {
1724 basename++;
1725 return basename;
1726 } else {
1727 return filename;
1728 }
1729}
1730
Elliott Hughes58305772015-04-17 13:57:15 -07001731static int install_app(transport_type transport, const char* serial, int argc,
1732 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001733{
1734 static const char *const DATA_DEST = "/data/local/tmp/%s";
1735 static const char *const SD_DEST = "/sdcard/tmp/%s";
1736 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001737 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001738 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001739
1740 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001741 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001742 where = SD_DEST;
1743 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001744 }
1745
Jeff Sharkey960df972014-06-09 17:30:57 -07001746 // Find last APK argument.
1747 // All other arguments passed through verbatim.
1748 int last_apk = -1;
1749 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001750 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001751 char* dot = strrchr(file, '.');
1752 if (dot && !strcasecmp(dot, ".apk")) {
1753 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1754 fprintf(stderr, "Invalid APK file: %s\n", file);
1755 return -1;
1756 }
1757
1758 last_apk = i;
1759 break;
1760 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001761 }
1762
Jeff Sharkey960df972014-06-09 17:30:57 -07001763 if (last_apk == -1) {
1764 fprintf(stderr, "Missing APK file\n");
1765 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001766 }
1767
Dan Albertbac34742015-02-25 17:51:28 -08001768 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001769 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001770 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001771 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001772 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001773 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001774 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001775 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001776 }
1777
1778 pm_command(transport, serial, argc, argv);
1779
Kenny Root60733e92012-03-26 16:14:02 -07001780cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001781 delete_file(transport, serial, apk_dest);
1782 return err;
1783}
1784
Elliott Hughes58305772015-04-17 13:57:15 -07001785static int install_multiple_app(transport_type transport, const char* serial, int argc,
1786 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001787{
Jeff Sharkey960df972014-06-09 17:30:57 -07001788 int i;
1789 struct stat sb;
1790 unsigned long long total_size = 0;
1791
1792 // Find all APK arguments starting at end.
1793 // All other arguments passed through verbatim.
1794 int first_apk = -1;
1795 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001796 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001797 char* dot = strrchr(file, '.');
1798 if (dot && !strcasecmp(dot, ".apk")) {
1799 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1800 fprintf(stderr, "Invalid APK file: %s\n", file);
1801 return -1;
1802 }
1803
1804 total_size += sb.st_size;
1805 first_apk = i;
1806 } else {
1807 break;
1808 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001809 }
1810
Jeff Sharkey960df972014-06-09 17:30:57 -07001811 if (first_apk == -1) {
1812 fprintf(stderr, "Missing APK file\n");
1813 return 1;
1814 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001815
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001816 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %lld", total_size);
Jeff Sharkey960df972014-06-09 17:30:57 -07001817 for (i = 1; i < first_apk; i++) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001818 cmd += " ";
1819 cmd += escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001820 }
1821
1822 // Create install session
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001823 int fd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001824 if (fd < 0) {
1825 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1826 return -1;
1827 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001828 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001829 read_status_line(fd, buf, sizeof(buf));
1830 adb_close(fd);
1831
1832 int session_id = -1;
1833 if (!strncmp("Success", buf, 7)) {
1834 char* start = strrchr(buf, '[');
1835 char* end = strrchr(buf, ']');
1836 if (start && end) {
1837 *end = '\0';
1838 session_id = strtol(start + 1, NULL, 10);
1839 }
1840 }
1841 if (session_id < 0) {
1842 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001843 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001844 return -1;
1845 }
1846
1847 // Valid session, now stream the APKs
1848 int success = 1;
1849 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001850 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001851 if (stat(file, &sb) == -1) {
1852 fprintf(stderr, "Failed to stat %s\n", file);
1853 success = 0;
1854 goto finalize_session;
1855 }
1856
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001857 std::string cmd = android::base::StringPrintf("exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07001858 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001859
1860 int localFd = adb_open(file, O_RDONLY);
1861 if (localFd < 0) {
1862 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
1863 success = 0;
1864 goto finalize_session;
1865 }
1866
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001867 int remoteFd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001868 if (remoteFd < 0) {
1869 fprintf(stderr, "Connect error for write: %s\n", adb_error());
1870 adb_close(localFd);
1871 success = 0;
1872 goto finalize_session;
1873 }
1874
1875 copy_to_file(localFd, remoteFd);
1876 read_status_line(remoteFd, buf, sizeof(buf));
1877
1878 adb_close(localFd);
1879 adb_close(remoteFd);
1880
1881 if (strncmp("Success", buf, 7)) {
1882 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001883 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001884 success = 0;
1885 goto finalize_session;
1886 }
1887 }
1888
1889finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001890 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07001891 if (success) {
1892 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
1893 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001894 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07001895 }
1896
1897 fd = adb_connect(buf);
1898 if (fd < 0) {
1899 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
1900 return -1;
1901 }
1902 read_status_line(fd, buf, sizeof(buf));
1903 adb_close(fd);
1904
1905 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001906 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001907 return 0;
1908 } else {
1909 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001910 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001911 return -1;
1912 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001913}