blob: 17c4432dcb3854233ffeb95360da634febfd8a15 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dan Albert33134262015-03-19 15:21:08 -070017#define TRACE_TAG TRACE_ADB
18
19#include "sysdeps.h"
20
Dan Albert76649012015-02-24 15:51:19 -080021#include <assert.h>
22#include <ctype.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023#include <errno.h>
Elliott Hughes2940ccf2015-04-17 14:07:52 -070024#include <inttypes.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080025#include <limits.h>
26#include <stdarg.h>
Dan Albert76649012015-02-24 15:51:19 -080027#include <stdint.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080031#include <sys/stat.h>
Dan Albert76649012015-02-24 15:51:19 -080032#include <sys/types.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080033
Elliott Hughes2baae3a2015-04-17 10:59:34 -070034#include <string>
35
36#include <base/stringprintf.h>
37
Yabin Cuid325e862014-11-17 14:48:25 -080038#if !defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080039#include <termios.h>
Dan Albert76649012015-02-24 15:51:19 -080040#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080041#endif
42
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043#include "adb.h"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -080044#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080045#include "adb_client.h"
46#include "adb_io.h"
Elliott Hughes58305772015-04-17 13:57:15 -070047#include "adb_utils.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048#include "file_sync_service.h"
49
Elliott Hughes3bd73c12015-05-05 13:10:43 -070050static int install_app(TransportType t, const char* serial, int argc, const char** argv);
51static int install_multiple_app(TransportType t, const char* serial, int argc, const char** argv);
52static int uninstall_app(TransportType t, const char* serial, int argc, const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080053
Elliott Hughes58305772015-04-17 13:57:15 -070054static std::string gProductOutPath;
Matt Gumbeld7b33082012-11-14 10:16:17 -080055extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080056
Elliott Hughes58305772015-04-17 13:57:15 -070057static std::string product_file(const char *extra) {
58 if (gProductOutPath.empty()) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080059 fprintf(stderr, "adb: Product directory not specified; "
60 "use -p or define ANDROID_PRODUCT_OUT\n");
61 exit(1);
62 }
63
Elliott Hughes58305772015-04-17 13:57:15 -070064 return android::base::StringPrintf("%s%s%s",
65 gProductOutPath.c_str(), OS_PATH_SEPARATOR_STR, extra);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080066}
67
Elliott Hughes58305772015-04-17 13:57:15 -070068static void version(FILE* out) {
Elliott Hughesf3bbfa62015-05-07 21:56:31 -070069 fprintf(out, "Android Debug Bridge version %d.%d.%d\nRevision %s\n",
70 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION, ADB_REVISION);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080071}
72
Elliott Hughes58305772015-04-17 13:57:15 -070073static void help() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080074 version(stderr);
75
76 fprintf(stderr,
77 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080078 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080079 " -d - directs command to the only connected USB device\n"
80 " returns an error if more than one USB device is present.\n"
81 " -e - directs command to the only running emulator.\n"
82 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070083 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070084 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -070085 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080086 " -p <product name or path> - simple product name like 'sooner', or\n"
87 " a relative/absolute path to a product\n"
88 " out directory like 'out/target/product/sooner'.\n"
89 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
90 " environment variable is used, which must\n"
91 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080092 " -H - Name of adb server host (default: localhost)\n"
93 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -070094 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070095 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -040096 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
97 " Port 5555 is used by default if no port number is specified.\n"
98 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
99 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200100 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400101 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800102 "\n"
103 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700104 " adb push [-p] <local> <remote>\n"
105 " - copy file/dir to device\n"
106 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700107 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700108 " - copy file/dir from device\n"
109 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700110 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800111 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600112 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800113 " (see 'adb help all')\n"
114 " adb shell - run remote shell interactively\n"
115 " adb shell <command> - run remote shell command\n"
116 " adb emu <command> - run emulator console command\n"
117 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100118 " adb forward --list - list all forward socket connections.\n"
119 " the format is a list of lines with the following format:\n"
120 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800121 " adb forward <local> <remote> - forward socket connections\n"
122 " forward specs are one of: \n"
123 " tcp:<port>\n"
124 " localabstract:<unix domain socket name>\n"
125 " localreserved:<unix domain socket name>\n"
126 " localfilesystem:<unix domain socket name>\n"
127 " dev:<character device name>\n"
128 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100129 " adb forward --no-rebind <local> <remote>\n"
130 " - same as 'adb forward <local> <remote>' but fails\n"
131 " if <local> is already forwarded\n"
132 " adb forward --remove <local> - remove a specific forward socket connection\n"
133 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100134 " adb reverse --list - list all reverse socket connections from device\n"
135 " adb reverse <remote> <local> - reverse socket connections\n"
136 " reverse specs are one of:\n"
137 " tcp:<port>\n"
138 " localabstract:<unix domain socket name>\n"
139 " localreserved:<unix domain socket name>\n"
140 " localfilesystem:<unix domain socket name>\n"
141 " adb reverse --norebind <remote> <local>\n"
142 " - same as 'adb reverse <remote> <local>' but fails\n"
143 " if <remote> is already reversed.\n"
144 " adb reverse --remove <remote>\n"
145 " - remove a specific reversed socket connection\n"
146 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800147 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900148 " adb install [-lrtsdg] <file>\n"
Svetoslav23d84072015-06-01 16:02:50 -0700149 " - push this package file to the device and install it\n"
150 " (-l: forward lock application)\n"
151 " (-r: replace existing application)\n"
152 " (-t: allow test packages)\n"
153 " (-s: install application on sdcard)\n"
154 " (-d: allow version code downgrade)\n"
155 " (-g: grant all runtime permissions)\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900156 " adb install-multiple [-lrtsdpg] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700157 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700158 " (-l: forward lock application)\n"
159 " (-r: replace existing application)\n"
160 " (-t: allow test packages)\n"
161 " (-s: install application on sdcard)\n"
162 " (-d: allow version code downgrade)\n"
163 " (-p: partial application install)\n"
Lorenzo Colitti0b3baac2015-05-28 12:03:44 +0900164 " (-g: grant all runtime permissions)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800165 " adb uninstall [-k] <package> - remove this app package from the device\n"
166 " ('-k' means keep the data and cache directories)\n"
167 " adb bugreport - return all information from the device\n"
168 " that should be included in a bug report.\n"
169 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800170 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700171 " - write an archive of the device's data to <file>.\n"
172 " If no -f option is supplied then the data is written\n"
173 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700174 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700175 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800176 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
177 " (aka .obb) files associated with each application; the default\n"
178 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700179 " (-shared|-noshared enable/disable backup of the device's\n"
180 " shared storage / SD card contents; the default is noshared.)\n"
181 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700182 " (-system|-nosystem toggles whether -all automatically includes\n"
183 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700184 " (<packages...> is the list of applications to be backed up. If\n"
185 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700186 " list is optional. Applications explicitly given on the\n"
187 " command line will be included even if -nosystem would\n"
188 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700189 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700190 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700191 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800192 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
193 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800194 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
195 " and the public key is stored in <file>.pub. Any existing files\n"
196 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800197 " adb help - show this help message\n"
198 " adb version - show version num\n"
199 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800200 "scripting:\n"
201 " adb wait-for-device - block until device is online\n"
202 " adb start-server - ensure that there is a server running\n"
203 " adb kill-server - kill the server if it is running\n"
204 " adb get-state - prints: offline | bootloader | device\n"
205 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700206 " adb get-devpath - prints: <device-path>\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000207 " 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 -0700208 " adb reboot [bootloader|recovery]\n"
209 " - reboots the device, optionally into the bootloader or recovery program.\n"
210 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
211 " adb reboot sideload-auto-reboot\n"
212 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Romain Guy311add42009-12-14 14:42:17 -0800213 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700214 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500215 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800216 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000217 " 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 -0800218 "networking:\n"
219 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500220 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800221 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
222 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
223 "\n"
224 "adb sync notes: adb sync [ <directory> ]\n"
225 " <localdir> can be interpreted in several ways:\n"
226 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000227 " - 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 -0800228 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000229 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800230 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000231 "\n"
232 "environmental variables:\n"
233 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
234 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
235 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
236 " 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 -0800237 );
238}
239
Elliott Hughes58305772015-04-17 13:57:15 -0700240static int usage() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800241 help();
242 return 1;
243}
244
Yabin Cuid325e862014-11-17 14:48:25 -0800245#if defined(_WIN32)
246
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700247// Implemented in sysdeps_win32.cpp.
Spencer Low50184062015-03-01 15:06:21 -0800248void stdin_raw_init(int fd);
249void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800250
251#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100252static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800253
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100254static void stdin_raw_init(int fd) {
255 if (tcgetattr(fd, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800256
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100257 termios tio;
258 if (tcgetattr(fd, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800259
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100260 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800261
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100262 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800263 tio.c_cc[VTIME] = 0;
264 tio.c_cc[VMIN] = 1;
265
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100266 tcsetattr(fd, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800267}
268
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100269static void stdin_raw_restore(int fd) {
270 tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800271}
272#endif
273
Elliott Hughes5677c232015-05-07 23:37:40 -0700274static void read_and_dump(int fd) {
275 while (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700276 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
Elliott Hughes5677c232015-05-07 23:37:40 -0700277 char buf[BUFSIZ];
278 int len = adb_read(fd, buf, sizeof(buf));
JP Abgrall408fa572011-03-16 15:57:42 -0700279 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
Elliott Hughes5677c232015-05-07 23:37:40 -0700280 if (len <= 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800281 break;
282 }
283
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400284 fwrite(buf, 1, len, stdout);
285 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800286 }
287}
288
Jeff Sharkey960df972014-06-09 17:30:57 -0700289static void read_status_line(int fd, char* buf, size_t count)
290{
291 count--;
292 while (count > 0) {
293 int len = adb_read(fd, buf, count);
294 if (len == 0) {
295 break;
296 } else if (len < 0) {
297 if (errno == EINTR) continue;
298 break;
299 }
300
301 buf += len;
302 count -= len;
303 }
304 *buf = '\0';
305}
306
Christopher Tated2f54152011-04-21 12:53:28 -0700307static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700308 const size_t BUFSIZE = 32 * 1024;
309 char* buf = (char*) malloc(BUFSIZE);
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700310 if (buf == nullptr) fatal("couldn't allocate buffer for copy_to_file");
Christopher Tated2f54152011-04-21 12:53:28 -0700311 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700312 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700313
314 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800315
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700316 if (inFd == STDIN_FILENO) {
317 stdin_raw_init(STDIN_FILENO);
318 }
Yabin Cuid325e862014-11-17 14:48:25 -0800319
Elliott Hughesa7090b92015-04-17 17:03:59 -0700320 while (true) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700321 if (inFd == STDIN_FILENO) {
322 len = unix_read(inFd, buf, BUFSIZE);
323 } else {
324 len = adb_read(inFd, buf, BUFSIZE);
325 }
Christopher Tated2f54152011-04-21 12:53:28 -0700326 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700327 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700328 break;
329 }
330 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700331 if (errno == EINTR) {
332 D("copy_to_file() : EINTR, retrying\n");
333 continue;
334 }
Christopher Tated2f54152011-04-21 12:53:28 -0700335 D("copy_to_file() : error %d\n", errno);
336 break;
337 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700338 if (outFd == STDOUT_FILENO) {
339 fwrite(buf, 1, len, stdout);
340 fflush(stdout);
341 } else {
342 adb_write(outFd, buf, len);
343 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700344 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700345 }
Yabin Cuid325e862014-11-17 14:48:25 -0800346
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700347 if (inFd == STDIN_FILENO) {
348 stdin_raw_restore(STDIN_FILENO);
349 }
Yabin Cuid325e862014-11-17 14:48:25 -0800350
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700351 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700352 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700353}
354
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800355static void *stdin_read_thread(void *x)
356{
357 int fd, fdi;
358 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800359 int r, n;
360 int state = 0;
361
362 int *fds = (int*) x;
363 fd = fds[0];
364 fdi = fds[1];
365 free(fds);
366
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800367 for(;;) {
368 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700369 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800370 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700371 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800372 if(r == 0) break;
373 if(r < 0) {
374 if(errno == EINTR) continue;
375 break;
376 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400377 for(n = 0; n < r; n++){
378 switch(buf[n]) {
379 case '\n':
380 state = 1;
381 break;
382 case '\r':
383 state = 1;
384 break;
385 case '~':
386 if(state == 1) state++;
387 break;
388 case '.':
389 if(state == 2) {
390 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400391 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400392 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800393 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400394 default:
395 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800396 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800397 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800398 r = adb_write(fd, buf, r);
399 if(r <= 0) {
400 break;
401 }
402 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800403 return 0;
404}
405
Elliott Hughes58305772015-04-17 13:57:15 -0700406static int interactive_shell() {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700407 int fdi;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800408
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700409 std::string error;
410 int fd = adb_connect("shell:", &error);
411 if (fd < 0) {
412 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800413 return 1;
414 }
415 fdi = 0; //dup(0);
416
Dan Albertbac34742015-02-25 17:51:28 -0800417 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700418 if (fds == nullptr) {
419 fprintf(stderr, "couldn't allocate fds array: %s\n", strerror(errno));
420 return 1;
421 }
422
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800423 fds[0] = fd;
424 fds[1] = fdi;
425
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800426 stdin_raw_init(fdi);
Elliott Hughes9b0f3542015-05-05 13:41:21 -0700427
428 adb_thread_create(stdin_read_thread, fds);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800429 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800430 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800431 return 0;
432}
433
434
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700435static std::string format_host_command(const char* command, TransportType type, const char* serial) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800436 if (serial) {
Elliott Hughes6452a892015-04-29 12:28:13 -0700437 return android::base::StringPrintf("host-serial:%s:%s", serial, command);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700439
440 const char* prefix = "host";
441 if (type == kTransportUsb) {
442 prefix = "host-usb";
443 } else if (type == kTransportLocal) {
444 prefix = "host-local";
445 }
446 return android::base::StringPrintf("%s:%s", prefix, command);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800447}
448
Elliott Hughes6452a892015-04-29 12:28:13 -0700449static int adb_download_buffer(const char *service, const char *fn, const void* data, unsigned sz,
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700450 bool show_progress)
Doug Zongker447f0612012-01-09 14:54:53 -0800451{
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700452 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700453 int fd = adb_connect(android::base::StringPrintf("%s:%d", service, sz), &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700454 if (fd < 0) {
455 fprintf(stderr,"error: %s\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800456 return -1;
457 }
458
459 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800460 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800461
Elliott Hughes6452a892015-04-29 12:28:13 -0700462 unsigned total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800463 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800464
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700465 if (show_progress) {
Doug Zongker447f0612012-01-09 14:54:53 -0800466 char *x = strrchr(service, ':');
467 if(x) service = x + 1;
468 }
469
Elliott Hughes6452a892015-04-29 12:28:13 -0700470 while (sz > 0) {
Doug Zongker447f0612012-01-09 14:54:53 -0800471 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700472 if (!WriteFdExactly(fd, ptr, xfer)) {
473 std::string error;
474 adb_status(fd, &error);
475 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800476 return -1;
477 }
478 sz -= xfer;
479 ptr += xfer;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700480 if (show_progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100481 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800482 fflush(stdout);
483 }
484 }
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700485 if (show_progress) {
Doug Zongker447f0612012-01-09 14:54:53 -0800486 printf("\n");
487 }
488
Elliott Hughese67f1f82015-04-30 17:32:03 -0700489 if (!adb_status(fd, &error)) {
490 fprintf(stderr,"* error response '%s' *\n", error.c_str());
Doug Zongker447f0612012-01-09 14:54:53 -0800491 return -1;
492 }
493
494 adb_close(fd);
495 return 0;
496}
497
Doug Zongker71fe5842014-06-26 15:35:36 -0700498#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
499
500/*
501 * The sideload-host protocol serves the data in a file (given on the
502 * command line) to the client, using a simple protocol:
503 *
504 * - The connect message includes the total number of bytes in the
505 * file and a block size chosen by us.
506 *
507 * - The other side sends the desired block number as eight decimal
508 * digits (eg "00000023" for block 23). Blocks are numbered from
509 * zero.
510 *
511 * - We send back the data of the requested block. The last block is
512 * likely to be partial; when the last block is requested we only
513 * send the part of the block that exists, it's not padded up to the
514 * block size.
515 *
516 * - When the other side sends "DONEDONE" instead of a block number,
517 * we hang up.
518 */
Elliott Hughes58305772015-04-17 13:57:15 -0700519static int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700520 unsigned sz;
521 size_t xfer = 0;
522 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800523 int last_percent = -1;
524 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700525
526 printf("loading: '%s'", fn);
527 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800528 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700529 if (data == 0) {
530 printf("\n");
531 fprintf(stderr, "* cannot read '%s' *\n", fn);
532 return -1;
533 }
534
Elliott Hughes6452a892015-04-29 12:28:13 -0700535 std::string service =
536 android::base::StringPrintf("sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700537 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700538 int fd = adb_connect(service, &error);
Doug Zongker71fe5842014-06-26 15:35:36 -0700539 if (fd < 0) {
540 // Try falling back to the older sideload method. Maybe this
541 // is an older device that doesn't support sideload-host.
542 printf("\n");
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700543 status = adb_download_buffer("sideload", fn, data, sz, true);
Doug Zongker71fe5842014-06-26 15:35:36 -0700544 goto done;
545 }
546
Spencer Lowf055c192015-01-25 14:40:16 -0800547 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700548
Elliott Hughesa7090b92015-04-17 17:03:59 -0700549 while (true) {
Elliott Hughes6452a892015-04-29 12:28:13 -0700550 char buf[9];
Dan Albertcc731cc2015-02-24 21:26:58 -0800551 if (!ReadFdExactly(fd, buf, 8)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700552 fprintf(stderr, "* failed to read command: %s\n", strerror(errno));
Doug Zongker71fe5842014-06-26 15:35:36 -0700553 status = -1;
554 goto done;
555 }
Elliott Hughes6452a892015-04-29 12:28:13 -0700556 buf[8] = '\0';
Doug Zongker71fe5842014-06-26 15:35:36 -0700557
Elliott Hughes6452a892015-04-29 12:28:13 -0700558 if (strcmp("DONEDONE", buf) == 0) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700559 status = 0;
560 break;
561 }
562
Doug Zongker71fe5842014-06-26 15:35:36 -0700563 int block = strtol(buf, NULL, 10);
564
565 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
566 if (offset >= sz) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700567 fprintf(stderr, "* attempt to read block %d past end\n", block);
Doug Zongker71fe5842014-06-26 15:35:36 -0700568 status = -1;
569 goto done;
570 }
571 uint8_t* start = data + offset;
572 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
573 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
574 if (offset_end > sz) {
575 to_write = sz - offset;
576 }
577
Dan Albertcc731cc2015-02-24 21:26:58 -0800578 if(!WriteFdExactly(fd, start, to_write)) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700579 adb_status(fd, &error);
580 fprintf(stderr,"* failed to write data '%s' *\n", error.c_str());
Doug Zongker71fe5842014-06-26 15:35:36 -0700581 status = -1;
582 goto done;
583 }
584 xfer += to_write;
585
586 // For normal OTA packages, we expect to transfer every byte
587 // twice, plus a bit of overhead (one read during
588 // verification, one read of each byte for installation, plus
589 // extra access to things like the zip central directory).
590 // This estimate of the completion becomes 100% when we've
591 // transferred ~2.13 (=100/47) times the package size.
592 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
593 if (percent != last_percent) {
594 printf("\rserving: '%s' (~%d%%) ", fn, percent);
595 fflush(stdout);
596 last_percent = percent;
597 }
598 }
599
Colin Cross6d6a8982014-07-07 14:12:41 -0700600 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700601
602 done:
603 if (fd >= 0) adb_close(fd);
604 free(data);
605 return status;
606}
607
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800608/**
609 * Run ppp in "notty" mode against a resource listed as the first parameter
610 * eg:
611 *
612 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
613 *
614 */
Elliott Hughes58305772015-04-17 13:57:15 -0700615static int ppp(int argc, const char** argv) {
Yabin Cuie77b6a02014-11-11 09:24:11 -0800616#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800617 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
618 return -1;
619#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800620 if (argc < 2) {
621 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
622 argv[0]);
623
624 return 1;
625 }
626
Dan Albertbac34742015-02-25 17:51:28 -0800627 const char* adb_service_name = argv[1];
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700628 std::string error;
629 int fd = adb_connect(adb_service_name, &error);
630 if (fd < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800631 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700632 adb_service_name, error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800633 return 1;
634 }
635
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700636 pid_t pid = fork();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800637
638 if (pid < 0) {
639 perror("from fork()");
640 return 1;
641 } else if (pid == 0) {
642 int err;
643 int i;
644 const char **ppp_args;
645
646 // copy args
647 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
648 ppp_args[0] = "pppd";
649 for (i = 2 ; i < argc ; i++) {
650 //argv[2] and beyond become ppp_args[1] and beyond
651 ppp_args[i - 1] = argv[i];
652 }
653 ppp_args[i-1] = NULL;
654
655 // child side
656
657 dup2(fd, STDIN_FILENO);
658 dup2(fd, STDOUT_FILENO);
659 adb_close(STDERR_FILENO);
660 adb_close(fd);
661
662 err = execvp("pppd", (char * const *)ppp_args);
663
664 if (err < 0) {
665 perror("execing pppd");
666 }
667 exit(-1);
668 } else {
669 // parent side
670
671 adb_close(fd);
672 return 0;
673 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800674#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800675}
676
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700677static bool wait_for_device(const char* service, TransportType t, const char* serial) {
Elliott Hughes2b101112015-05-04 19:29:32 -0700678 // Was the caller vague about what they'd like us to wait for?
679 // If so, check they weren't more specific in their choice of transport type.
680 if (strcmp(service, "wait-for-device") == 0) {
681 if (t == kTransportUsb) {
682 service = "wait-for-usb";
683 } else if (t == kTransportLocal) {
684 service = "wait-for-local";
685 } else {
686 service = "wait-for-any";
687 }
688 }
689
690 std::string cmd = format_host_command(service, t, serial);
Elliott Hughes424af022015-05-29 17:55:19 -0700691 return adb_command(cmd);
Elliott Hughes2b101112015-05-04 19:29:32 -0700692}
693
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700694static int send_shell_command(TransportType transport_type, const char* serial,
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700695 const std::string& command) {
696 int fd;
697 while (true) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700698 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700699 fd = adb_connect(command, &error);
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700700 if (fd >= 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800701 break;
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700702 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800703 fprintf(stderr,"- waiting for device -\n");
704 adb_sleep_ms(1000);
Elliott Hughes2b101112015-05-04 19:29:32 -0700705 wait_for_device("wait-for-device", transport_type, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800706 }
707
708 read_and_dump(fd);
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700709 int rc = adb_close(fd);
710 if (rc) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800711 perror("close");
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700712 }
713 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800714}
715
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700716static int logcat(TransportType transport, const char* serial, int argc, const char** argv) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700717 char* log_tags = getenv("ANDROID_LOG_TAGS");
718 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800719
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700720 std::string cmd = "shell:export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800721
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700722 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700723 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -0800724 }
725
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700726 --argc;
727 ++argv;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700728 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700729 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800730 }
731
Elliott Hughes15551472015-04-21 17:58:55 -0700732 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800733}
734
Mark Salyzyn60299df2014-04-30 09:10:31 -0700735static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800736{
737 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700738 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800739
740 for(;;) {
741 x = adb_dirstart(x);
742 if(x == 0) return 0;
743 *x = 0;
744 ret = adb_mkdir(path, 0775);
745 *x = OS_PATH_SEPARATOR;
746 if((ret < 0) && (errno != EEXIST)) {
747 return ret;
748 }
749 x++;
750 }
751 return 0;
752}
753
Dan Albertbac34742015-02-25 17:51:28 -0800754static int backup(int argc, const char** argv) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700755 const char* filename = "./backup.ab";
Christopher Tated2f54152011-04-21 12:53:28 -0700756
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700757 /* find, extract, and use any -f argument */
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700758 for (int i = 1; i < argc; i++) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700759 if (!strcmp("-f", argv[i])) {
760 if (i == argc-1) {
761 fprintf(stderr, "adb: -f passed with no filename\n");
762 return usage();
763 }
764 filename = argv[i+1];
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700765 for (int j = i+2; j <= argc; ) {
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700766 argv[i++] = argv[j++];
767 }
768 argc -= 2;
769 argv[argc] = NULL;
770 }
Christopher Tated2f54152011-04-21 12:53:28 -0700771 }
772
Christopher Tatebb86bc52011-08-22 17:12:08 -0700773 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
774 if (argc < 2) return usage();
775
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800776 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700777 mkdirs(filename);
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700778 int outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700779 if (outFd < 0) {
780 fprintf(stderr, "adb: unable to open file %s\n", filename);
781 return -1;
782 }
783
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700784 std::string cmd = "backup:";
785 --argc;
786 ++argv;
787 while (argc-- > 0) {
788 cmd += " " + escape_arg(*argv++);
Christopher Tated2f54152011-04-21 12:53:28 -0700789 }
790
Elliott Hughes6c34bba2015-04-17 20:11:08 -0700791 D("backup. filename=%s cmd=%s\n", filename, cmd.c_str());
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700792 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -0700793 int fd = adb_connect(cmd, &error);
Christopher Tated2f54152011-04-21 12:53:28 -0700794 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700795 fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
Christopher Tated2f54152011-04-21 12:53:28 -0700796 adb_close(outFd);
797 return -1;
798 }
799
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800800 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700801 copy_to_file(fd, outFd);
802
803 adb_close(fd);
804 adb_close(outFd);
805 return 0;
806}
807
Dan Albertbac34742015-02-25 17:51:28 -0800808static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700809 if (argc != 2) return usage();
810
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700811 const char* filename = argv[1];
812 int tarFd = adb_open(filename, O_RDONLY);
Christopher Tate702967a2011-05-17 15:52:54 -0700813 if (tarFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700814 fprintf(stderr, "adb: unable to open file %s: %s\n", filename, strerror(errno));
Christopher Tate702967a2011-05-17 15:52:54 -0700815 return -1;
816 }
817
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700818 std::string error;
819 int fd = adb_connect("restore:", &error);
Christopher Tate702967a2011-05-17 15:52:54 -0700820 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700821 fprintf(stderr, "adb: unable to connect for restore: %s\n", error.c_str());
Christopher Tate702967a2011-05-17 15:52:54 -0700822 adb_close(tarFd);
823 return -1;
824 }
825
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800826 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700827 copy_to_file(tarFd, fd);
828
829 adb_close(fd);
830 adb_close(tarFd);
831 return 0;
832}
833
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800834/* <hint> may be:
835 * - A simple product name
836 * e.g., "sooner"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800837 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
838 * e.g., "out/target/product/sooner"
839 * - An absolute path to the PRODUCT_OUT dir
840 * e.g., "/src/device/out/target/product/sooner"
841 *
842 * Given <hint>, try to construct an absolute path to the
843 * ANDROID_PRODUCT_OUT dir.
844 */
Elliott Hughes58305772015-04-17 13:57:15 -0700845static std::string find_product_out_path(const char* hint) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800846 if (hint == NULL || hint[0] == '\0') {
Elliott Hughes58305772015-04-17 13:57:15 -0700847 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800848 }
849
Elliott Hughes58305772015-04-17 13:57:15 -0700850 // If it's already absolute, don't bother doing any work.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800851 if (adb_is_absolute_host_path(hint)) {
Elliott Hughes58305772015-04-17 13:57:15 -0700852 return hint;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800853 }
854
Elliott Hughes58305772015-04-17 13:57:15 -0700855 // If there are any slashes in it, assume it's a relative path;
856 // make it absolute.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700857 if (adb_dirstart(hint) != nullptr) {
858 std::string cwd;
859 if (!getcwd(&cwd)) {
860 fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
Elliott Hughes58305772015-04-17 13:57:15 -0700861 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800862 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700863 return android::base::StringPrintf("%s%s%s", cwd.c_str(), OS_PATH_SEPARATOR_STR, hint);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800864 }
865
Elliott Hughes58305772015-04-17 13:57:15 -0700866 // It's a string without any slashes. Try to do something with it.
867 //
868 // Try to find the root of the build tree, and build a PRODUCT_OUT
869 // path from there.
Elliott Hughesa7090b92015-04-17 17:03:59 -0700870 char* top = getenv("ANDROID_BUILD_TOP");
Elliott Hughes58305772015-04-17 13:57:15 -0700871 if (top == nullptr) {
Elliott Hughesa7090b92015-04-17 17:03:59 -0700872 fprintf(stderr, "adb: ANDROID_BUILD_TOP not set!\n");
Elliott Hughes58305772015-04-17 13:57:15 -0700873 return "";
874 }
Elliott Hughesa7090b92015-04-17 17:03:59 -0700875
876 std::string path = top;
Elliott Hughes58305772015-04-17 13:57:15 -0700877 path += OS_PATH_SEPARATOR_STR;
878 path += "out";
879 path += OS_PATH_SEPARATOR_STR;
880 path += "target";
881 path += OS_PATH_SEPARATOR_STR;
882 path += "product";
883 path += OS_PATH_SEPARATOR_STR;
884 path += hint;
885 if (!directory_exists(path)) {
886 fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
887 "\"%s\" doesn't exist\n", hint, path.c_str());
Elliott Hughesa7090b92015-04-17 17:03:59 -0700888 return "";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800889 }
Elliott Hughes58305772015-04-17 13:57:15 -0700890 return path;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800891}
892
Dan Albertbac34742015-02-25 17:51:28 -0800893static void parse_push_pull_args(const char **arg, int narg, char const **path1,
894 char const **path2, int *show_progress,
895 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -0700896 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700897 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -0700898
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700899 while (narg > 0) {
900 if (!strcmp(*arg, "-p")) {
901 *show_progress = 1;
902 } else if (!strcmp(*arg, "-a")) {
903 *copy_attrs = 1;
904 } else {
905 break;
906 }
Mark Lindner76f2a932014-03-11 17:55:59 -0700907 ++arg;
908 --narg;
909 }
910
911 if (narg > 0) {
912 *path1 = *arg;
913 ++arg;
914 --narg;
915 }
916
917 if (narg > 0) {
918 *path2 = *arg;
919 }
920}
921
Elliott Hughes6452a892015-04-29 12:28:13 -0700922static int adb_connect_command(const std::string& command) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -0700923 std::string error;
924 int fd = adb_connect(command, &error);
Elliott Hughes5677c232015-05-07 23:37:40 -0700925 if (fd < 0) {
926 fprintf(stderr, "error: %s\n", error.c_str());
927 return 1;
Tao Bao175b7bb2015-03-29 11:22:34 -0700928 }
Elliott Hughes5677c232015-05-07 23:37:40 -0700929 read_and_dump(fd);
930 adb_close(fd);
931 return 0;
Tao Bao175b7bb2015-03-29 11:22:34 -0700932}
933
Elliott Hughes6452a892015-04-29 12:28:13 -0700934static int adb_query_command(const std::string& command) {
935 std::string result;
936 std::string error;
937 if (!adb_query(command, &result, &error)) {
938 fprintf(stderr, "error: %s\n", error.c_str());
939 return 1;
940 }
941 printf("%s\n", result.c_str());
942 return 0;
943}
944
Elliott Hughesab52c182015-05-01 17:04:38 -0700945int adb_commandline(int argc, const char **argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800946 int no_daemon = 0;
947 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100948 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800949 int r;
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700950 TransportType transport_type = kTransportAny;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800951
Elliott Hughes58305772015-04-17 13:57:15 -0700952 // If defined, this should be an absolute path to
953 // the directory containing all of the various system images
954 // for a particular product. If not defined, and the adb
955 // command requires this information, then the user must
956 // specify the path using "-p".
957 char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
958 if (ANDROID_PRODUCT_OUT != nullptr) {
959 gProductOutPath = ANDROID_PRODUCT_OUT;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800960 }
961 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
962
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700963 const char* serial = getenv("ANDROID_SERIAL");
Nick Pellydb449262009-05-07 12:48:03 -0700964
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100965 /* Validate and assign the server port */
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700966 const char* server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100967 int server_port = DEFAULT_ADB_PORT;
968 if (server_port_str && strlen(server_port_str) > 0) {
969 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -0800970 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100971 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -0800972 "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 +0100973 server_port_str);
974 return usage();
975 }
976 }
977
978 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -0800979 while (argc > 0) {
980 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +0100981 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -0800982 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800983 no_daemon = 1;
984 } else if (!strcmp(argv[0], "fork-server")) {
985 /* this is a special flag used only when the ADB client launches the ADB Server */
986 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -0800987 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800988 const char *product = NULL;
989 if (argv[0][2] == '\0') {
990 if (argc < 2) return usage();
991 product = argv[1];
992 argc--;
993 argv++;
994 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -0700995 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800996 }
997 gProductOutPath = find_product_out_path(product);
Elliott Hughes58305772015-04-17 13:57:15 -0700998 if (gProductOutPath.empty()) {
999 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001000 return usage();
1001 }
1002 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1003 if (isdigit(argv[0][2])) {
1004 serial = argv[0] + 2;
1005 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001006 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001007 serial = argv[1];
1008 argc--;
1009 argv++;
1010 }
1011 } else if (!strcmp(argv[0],"-d")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001012 transport_type = kTransportUsb;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001013 } else if (!strcmp(argv[0],"-e")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001014 transport_type = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001015 } else if (!strcmp(argv[0],"-a")) {
1016 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001017 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001018 const char *hostname = NULL;
1019 if (argv[0][2] == '\0') {
1020 if (argc < 2) return usage();
1021 hostname = argv[1];
1022 argc--;
1023 argv++;
1024 } else {
1025 hostname = argv[0] + 2;
1026 }
1027 adb_set_tcp_name(hostname);
1028
Riley Andrews98f58e82014-12-05 17:37:24 -08001029 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001030 if (argv[0][2] == '\0') {
1031 if (argc < 2) return usage();
1032 server_port_str = argv[1];
1033 argc--;
1034 argv++;
1035 } else {
1036 server_port_str = argv[0] + 2;
1037 }
1038 if (strlen(server_port_str) > 0) {
1039 server_port = (int) strtol(server_port_str, NULL, 0);
1040 if (server_port <= 0 || server_port > 65535) {
1041 fprintf(stderr,
1042 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1043 server_port_str);
1044 return usage();
1045 }
1046 } else {
1047 fprintf(stderr,
1048 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1049 return usage();
1050 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001051 } else {
1052 /* out of recognized modifiers and flags */
1053 break;
1054 }
1055 argc--;
1056 argv++;
1057 }
1058
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001059 adb_set_transport(transport_type, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001060 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001061
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001062 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001063 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001064 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001065 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001066 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001067 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001068 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001069 fprintf(stderr,"* could not start server *\n");
1070 }
1071 return r;
1072 }
1073
Riley Andrews98f58e82014-12-05 17:37:24 -08001074 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001075 return usage();
1076 }
1077
Riley Andrewsc8514c82014-12-05 17:32:46 -08001078 /* handle wait-for-* prefix */
1079 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001080 const char* service = argv[0];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001081
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001082 if (!wait_for_device(service, transport_type, serial)) {
Riley Andrewsc8514c82014-12-05 17:32:46 -08001083 return 1;
1084 }
1085
Elliott Hughes2b101112015-05-04 19:29:32 -07001086 // Allow a command to be run after wait-for-device,
1087 // e.g. 'adb wait-for-device shell'.
Riley Andrewsc8514c82014-12-05 17:32:46 -08001088 if (argc == 1) {
1089 return 0;
1090 }
1091
1092 /* Fall through */
1093 argc--;
1094 argv++;
1095 }
1096
1097 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001098 if (!strcmp(argv[0], "devices")) {
Dan Albertbac34742015-02-25 17:51:28 -08001099 const char *listopt;
Elliott Hughes6452a892015-04-29 12:28:13 -07001100 if (argc < 2) {
Scott Andersone109d262012-04-20 11:21:14 -07001101 listopt = "";
Elliott Hughes6452a892015-04-29 12:28:13 -07001102 } else if (argc == 2 && !strcmp(argv[1], "-l")) {
Scott Andersone109d262012-04-20 11:21:14 -07001103 listopt = argv[1];
Elliott Hughes6452a892015-04-29 12:28:13 -07001104 } else {
Scott Andersone109d262012-04-20 11:21:14 -07001105 fprintf(stderr, "Usage: adb devices [-l]\n");
1106 return 1;
1107 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001108
1109 std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
1110 printf("List of devices attached\n");
1111 return adb_query_command(query);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001112 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001113 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001114 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001115 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001116 return 1;
1117 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001118
1119 std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
1120 return adb_query_command(query);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001121 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001122 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001123 if (argc > 2) {
1124 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1125 return 1;
1126 }
Elliott Hughes6452a892015-04-29 12:28:13 -07001127
1128 std::string query = android::base::StringPrintf("host:disconnect:%s",
1129 (argc == 2) ? argv[1] : "");
1130 return adb_query_command(query);
Mike Lockwoodff196702009-08-24 15:58:40 -07001131 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001132 else if (!strcmp(argv[0], "emu")) {
Spencer Low142ec752015-05-06 16:13:42 -07001133 return adb_send_emulator_command(argc, argv, serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001134 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001135 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001136 char h = (argv[0][0] == 'h');
1137
1138 if (h) {
1139 printf("\x1b[41;33m");
1140 fflush(stdout);
1141 }
1142
Riley Andrews98f58e82014-12-05 17:37:24 -08001143 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001144 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001145 r = interactive_shell();
1146 if (h) {
1147 printf("\x1b[0m");
1148 fflush(stdout);
1149 }
1150 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001151 }
1152
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001153 std::string cmd = "shell:";
Elliott Hughes2b101112015-05-04 19:29:32 -07001154 --argc;
1155 ++argv;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001156 while (argc-- > 0) {
Elliott Hughes2b101112015-05-04 19:29:32 -07001157 // We don't escape here, just like ssh(1). http://b/20564385.
1158 cmd += *argv++;
1159 if (*argv) cmd += " ";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001160 }
1161
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001162 while (true) {
1163 D("interactive shell loop. cmd=%s\n", cmd.c_str());
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001164 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001165 int fd = adb_connect(cmd, &error);
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001166 int r;
Riley Andrews98f58e82014-12-05 17:37:24 -08001167 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001168 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001169 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001170 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001171 adb_close(fd);
1172 r = 0;
1173 } else {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001174 fprintf(stderr,"error: %s\n", error.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001175 r = -1;
1176 }
1177
Elliott Hughes32687be2015-05-05 12:50:26 -07001178 if (h) {
1179 printf("\x1b[0m");
1180 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001181 }
Elliott Hughes32687be2015-05-05 12:50:26 -07001182 D("interactive shell loop. return r=%d\n", r);
1183 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001184 }
1185 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001186 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001187 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001188
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001189 std::string cmd = "exec:";
1190 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001191 argc -= 2;
1192 argv += 2;
1193 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001194 cmd += " " + escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001195 }
1196
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001197 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001198 int fd = adb_connect(cmd, &error);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001199 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001200 fprintf(stderr, "error: %s\n", error.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001201 return -1;
1202 }
1203
1204 if (exec_in) {
1205 copy_to_file(STDIN_FILENO, fd);
1206 } else {
1207 copy_to_file(fd, STDOUT_FILENO);
1208 }
1209
1210 adb_close(fd);
1211 return 0;
1212 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001213 else if (!strcmp(argv[0], "kill-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001214 std::string error;
1215 int fd = _adb_connect("host:kill", &error);
Riley Andrews98f58e82014-12-05 17:37:24 -08001216 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001217 fprintf(stderr,"* server not running *\n");
1218 return 1;
1219 }
1220 return 0;
1221 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001222 else if (!strcmp(argv[0], "sideload")) {
1223 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001224 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001225 return 1;
1226 } else {
1227 return 0;
1228 }
1229 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001230 else if (!strcmp(argv[0], "remount") ||
1231 !strcmp(argv[0], "reboot") ||
1232 !strcmp(argv[0], "reboot-bootloader") ||
1233 !strcmp(argv[0], "tcpip") ||
1234 !strcmp(argv[0], "usb") ||
1235 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001236 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001237 !strcmp(argv[0], "disable-verity") ||
1238 !strcmp(argv[0], "enable-verity")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001239 std::string command;
Tao Bao175b7bb2015-03-29 11:22:34 -07001240 if (!strcmp(argv[0], "reboot-bootloader")) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001241 command = "reboot:bootloader";
Tao Bao175b7bb2015-03-29 11:22:34 -07001242 } else if (argc > 1) {
Elliott Hughes5677c232015-05-07 23:37:40 -07001243 command = android::base::StringPrintf("%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001244 } else {
Elliott Hughes5677c232015-05-07 23:37:40 -07001245 command = android::base::StringPrintf("%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001246 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001247 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001248 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001249 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001250 if (argc != 1) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001251 return send_shell_command(transport_type, serial, "shell:bugreport");
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001252 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001253 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
Elliott Hughes424af022015-05-29 17:55:19 -07001254 bool reverse = !strcmp(argv[0], "reverse");
1255 ++argv;
1256 --argc;
1257 if (argc < 1) return usage();
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001258
1259 // Determine the <host-prefix> for this command.
Elliott Hughes424af022015-05-29 17:55:19 -07001260 std::string host_prefix;
David 'Digit' Turner25258692013-03-21 21:07:42 +01001261 if (reverse) {
Elliott Hughes424af022015-05-29 17:55:19 -07001262 host_prefix = "reverse";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001263 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001264 if (serial) {
Elliott Hughes424af022015-05-29 17:55:19 -07001265 host_prefix = android::base::StringPrintf("host-serial:%s", serial);
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001266 } else if (transport_type == kTransportUsb) {
Elliott Hughes424af022015-05-29 17:55:19 -07001267 host_prefix = "host-usb";
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001268 } else if (transport_type == kTransportLocal) {
Elliott Hughes424af022015-05-29 17:55:19 -07001269 host_prefix = "host-local";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001270 } else {
Elliott Hughes424af022015-05-29 17:55:19 -07001271 host_prefix = "host";
David 'Digit' Turner25258692013-03-21 21:07:42 +01001272 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001273 }
1274
Elliott Hughes424af022015-05-29 17:55:19 -07001275 std::string cmd;
1276 if (strcmp(argv[0], "--list") == 0) {
Elliott Hughesab52c182015-05-01 17:04:38 -07001277 if (argc != 1) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001278 return adb_query_command(host_prefix + ":list-forward");
1279 } else if (strcmp(argv[0], "--remove-all") == 0) {
1280 if (argc != 1) return usage();
1281 cmd = host_prefix + ":killforward-all";
1282 } else if (strcmp(argv[0], "--remove") == 0) {
1283 // forward --remove <local>
Elliott Hughesab52c182015-05-01 17:04:38 -07001284 if (argc != 2) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001285 cmd = host_prefix + ":killforward:" + argv[1];
1286 } else if (strcmp(argv[0], "--no-rebind") == 0) {
1287 // forward --no-rebind <local> <remote>
Elliott Hughesab52c182015-05-01 17:04:38 -07001288 if (argc != 3) return usage();
Elliott Hughes424af022015-05-29 17:55:19 -07001289 cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
1290 } else {
1291 // forward <local> <remote>
1292 if (argc != 2) return usage();
1293 cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001294 }
1295
Elliott Hughes424af022015-05-29 17:55:19 -07001296 return adb_command(cmd) ? 0 : 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001297 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001298 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001299 else if (!strcmp(argv[0], "ls")) {
1300 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001301 return do_sync_ls(argv[1]);
1302 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001303 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001304 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001305 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001306 const char* lpath = NULL, *rpath = NULL;
1307
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001308 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001309
1310 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001311 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001312 }
1313
1314 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001315 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001316 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001317 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001318 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001319 const char* rpath = NULL, *lpath = ".";
1320
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001321 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001322
1323 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001324 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001325 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001326
1327 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001328 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001329 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001330 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001331 return install_app(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001332 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001333 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001334 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001335 return install_multiple_app(transport_type, serial, argc, argv);
Jeff Sharkey960df972014-06-09 17:30:57 -07001336 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001337 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001338 if (argc < 2) return usage();
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001339 return uninstall_app(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001340 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001341 else if (!strcmp(argv[0], "sync")) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001342 std::string src;
Elliott Hughes58305772015-04-17 13:57:15 -07001343 bool list_only = false;
Riley Andrews98f58e82014-12-05 17:37:24 -08001344 if (argc < 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001345 // No local path was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001346 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001347 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001348 list_only = true;
Anthony Newnam705c9442010-02-22 08:36:49 -06001349 if (argc == 3) {
Elliott Hughesd236d072015-04-21 10:17:07 -07001350 src = argv[2];
Anthony Newnam705c9442010-02-22 08:36:49 -06001351 } else {
Elliott Hughesd236d072015-04-21 10:17:07 -07001352 src = "";
Anthony Newnam705c9442010-02-22 08:36:49 -06001353 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001354 } else if (argc == 2) {
Elliott Hughes58305772015-04-17 13:57:15 -07001355 // A local path or "android"/"data" arg was specified.
Elliott Hughesd236d072015-04-21 10:17:07 -07001356 src = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001357 } else {
1358 return usage();
1359 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001360
Elliott Hughesd236d072015-04-21 10:17:07 -07001361 if (src != "" &&
1362 src != "system" && src != "data" && src != "vendor" && src != "oem") {
Elliott Hughes58305772015-04-17 13:57:15 -07001363 return usage();
1364 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001365
Elliott Hughes58305772015-04-17 13:57:15 -07001366 std::string system_src_path = product_file("system");
1367 std::string data_src_path = product_file("data");
1368 std::string vendor_src_path = product_file("vendor");
1369 std::string oem_src_path = product_file("oem");
Elliott Hughes58305772015-04-17 13:57:15 -07001370
1371 int rc = 0;
Elliott Hughesd236d072015-04-21 10:17:07 -07001372 if (rc == 0 && (src.empty() || src == "system")) {
1373 rc = do_sync_sync(system_src_path, "/system", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001374 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001375 if (rc == 0 && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
1376 rc = do_sync_sync(vendor_src_path, "/vendor", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001377 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001378 if (rc == 0 && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
1379 rc = do_sync_sync(oem_src_path, "/oem", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001380 }
Elliott Hughesd236d072015-04-21 10:17:07 -07001381 if (rc == 0 && (src.empty() || src == "data")) {
1382 rc = do_sync_sync(data_src_path, "/data", list_only);
Elliott Hughes58305772015-04-17 13:57:15 -07001383 }
1384 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001385 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001386 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001387 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001388 !strcmp(argv[0],"get-serialno") ||
1389 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001390 {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001391 return adb_query_command(format_host_command(argv[0], transport_type, serial));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001392 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001393 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001394 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001395 return logcat(transport_type, serial, argc, argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001396 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001397 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001398 return ppp(argc, argv);
1399 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001400 else if (!strcmp(argv[0], "start-server")) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001401 std::string error;
1402 return adb_connect("host:start-server", &error);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001403 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001404 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001405 return backup(argc, argv);
1406 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001407 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001408 return restore(argc, argv);
1409 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001410 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001411 if (argc < 2) return usage();
1412 return adb_auth_keygen(argv[1]);
1413 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001414 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001415 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001416 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001417 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001418 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001419 help();
1420 return 0;
1421 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001422 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001423 version(stdout);
1424 return 0;
1425 }
1426
1427 usage();
1428 return 1;
1429}
1430
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001431static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001432 std::string cmd = "shell:pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001433
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001434 while (argc-- > 0) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001435 cmd += " " + escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001436 }
1437
Elliott Hughes15551472015-04-21 17:58:55 -07001438 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001439}
1440
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001441static int uninstall_app(TransportType transport, const char* serial, int argc, const char** argv) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001442 /* if the user choose the -k option, we refuse to do it until devices are
1443 out with the option to uninstall the remaining data somehow (adb/ui) */
1444 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1445 {
1446 printf(
1447 "The -k option uninstalls the application while retaining the data/cache.\n"
1448 "At the moment, there is no way to remove the remaining data.\n"
1449 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1450 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1451 return -1;
1452 }
1453
1454 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1455 return pm_command(transport, serial, argc, argv);
1456}
1457
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001458static int delete_file(TransportType transport, const char* serial, char* filename) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001459 std::string cmd = "shell:rm -f " + escape_arg(filename);
Elliott Hughes15551472015-04-21 17:58:55 -07001460 return send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001461}
1462
Kenny Root597ea5b2011-08-05 11:19:45 -07001463static const char* get_basename(const char* filename)
1464{
1465 const char* basename = adb_dirstop(filename);
1466 if (basename) {
1467 basename++;
1468 return basename;
1469 } else {
1470 return filename;
1471 }
1472}
1473
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001474static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001475 static const char *const DATA_DEST = "/data/local/tmp/%s";
1476 static const char *const SD_DEST = "/sdcard/tmp/%s";
1477 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001478 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001479 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001480
1481 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001482 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001483 where = SD_DEST;
1484 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001485 }
1486
Jeff Sharkey960df972014-06-09 17:30:57 -07001487 // Find last APK argument.
1488 // All other arguments passed through verbatim.
1489 int last_apk = -1;
1490 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001491 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001492 char* dot = strrchr(file, '.');
1493 if (dot && !strcasecmp(dot, ".apk")) {
1494 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1495 fprintf(stderr, "Invalid APK file: %s\n", file);
1496 return -1;
1497 }
1498
1499 last_apk = i;
1500 break;
1501 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001502 }
1503
Jeff Sharkey960df972014-06-09 17:30:57 -07001504 if (last_apk == -1) {
1505 fprintf(stderr, "Missing APK file\n");
1506 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001507 }
1508
Dan Albertbac34742015-02-25 17:51:28 -08001509 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001510 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001511 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001512 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001513 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001514 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001515 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001516 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001517 }
1518
Elliott Hughes15551472015-04-21 17:58:55 -07001519 err = pm_command(transport, serial, argc, argv);
Kenny Root597ea5b2011-08-05 11:19:45 -07001520
Kenny Root60733e92012-03-26 16:14:02 -07001521cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001522 delete_file(transport, serial, apk_dest);
1523 return err;
1524}
1525
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001526static int install_multiple_app(TransportType transport, const char* serial, int argc,
Elliott Hughes58305772015-04-17 13:57:15 -07001527 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001528{
Jeff Sharkey960df972014-06-09 17:30:57 -07001529 int i;
1530 struct stat sb;
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001531 uint64_t total_size = 0;
Jeff Sharkey960df972014-06-09 17:30:57 -07001532
1533 // Find all APK arguments starting at end.
1534 // All other arguments passed through verbatim.
1535 int first_apk = -1;
1536 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001537 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001538 char* dot = strrchr(file, '.');
1539 if (dot && !strcasecmp(dot, ".apk")) {
1540 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1541 fprintf(stderr, "Invalid APK file: %s\n", file);
1542 return -1;
1543 }
1544
1545 total_size += sb.st_size;
1546 first_apk = i;
1547 } else {
1548 break;
1549 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001550 }
1551
Jeff Sharkey960df972014-06-09 17:30:57 -07001552 if (first_apk == -1) {
1553 fprintf(stderr, "Missing APK file\n");
1554 return 1;
1555 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001556
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001557 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size);
Jeff Sharkey960df972014-06-09 17:30:57 -07001558 for (i = 1; i < first_apk; i++) {
Elliott Hughes6c34bba2015-04-17 20:11:08 -07001559 cmd += " " + escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001560 }
1561
1562 // Create install session
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001563 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001564 int fd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001565 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001566 fprintf(stderr, "Connect error for create: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001567 return -1;
1568 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001569 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001570 read_status_line(fd, buf, sizeof(buf));
1571 adb_close(fd);
1572
1573 int session_id = -1;
1574 if (!strncmp("Success", buf, 7)) {
1575 char* start = strrchr(buf, '[');
1576 char* end = strrchr(buf, ']');
1577 if (start && end) {
1578 *end = '\0';
1579 session_id = strtol(start + 1, NULL, 10);
1580 }
1581 }
1582 if (session_id < 0) {
1583 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001584 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001585 return -1;
1586 }
1587
1588 // Valid session, now stream the APKs
1589 int success = 1;
1590 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001591 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001592 if (stat(file, &sb) == -1) {
1593 fprintf(stderr, "Failed to stat %s\n", file);
1594 success = 0;
1595 goto finalize_session;
1596 }
1597
Elliott Hughes2940ccf2015-04-17 14:07:52 -07001598 std::string cmd = android::base::StringPrintf(
1599 "exec:pm install-write -S %" PRIu64 " %d %d_%s -",
1600 static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001601
1602 int localFd = adb_open(file, O_RDONLY);
1603 if (localFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001604 fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
Jeff Sharkey960df972014-06-09 17:30:57 -07001605 success = 0;
1606 goto finalize_session;
1607 }
1608
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001609 std::string error;
Elliott Hughes6452a892015-04-29 12:28:13 -07001610 int remoteFd = adb_connect(cmd, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001611 if (remoteFd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001612 fprintf(stderr, "Connect error for write: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001613 adb_close(localFd);
1614 success = 0;
1615 goto finalize_session;
1616 }
1617
1618 copy_to_file(localFd, remoteFd);
1619 read_status_line(remoteFd, buf, sizeof(buf));
1620
1621 adb_close(localFd);
1622 adb_close(remoteFd);
1623
1624 if (strncmp("Success", buf, 7)) {
1625 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001626 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001627 success = 0;
1628 goto finalize_session;
1629 }
1630 }
1631
1632finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07001633 // Commit session if we streamed everything okay; otherwise abandon
Elliott Hughes6452a892015-04-29 12:28:13 -07001634 std::string service =
1635 android::base::StringPrintf("exec:pm install-%s %d",
1636 success ? "commit" : "abandon", session_id);
1637 fd = adb_connect(service, &error);
Jeff Sharkey960df972014-06-09 17:30:57 -07001638 if (fd < 0) {
Elliott Hughes078f0fc2015-04-29 08:35:59 -07001639 fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001640 return -1;
1641 }
1642 read_status_line(fd, buf, sizeof(buf));
1643 adb_close(fd);
1644
1645 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07001646 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001647 return 0;
1648 } else {
1649 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001650 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001651 return -1;
1652 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001653}