blob: 78d43e51c91484b356d8743a2a5d0b209d772b7d [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"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080046#include "file_sync_service.h"
47
Dan Albertbac34742015-02-25 17:51:28 -080048static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080049
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050int find_sync_dirs(const char *srcarg,
Elliott Hughesec7a6672015-03-16 21:58:32 +000051 char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
52 char **oem_srcdir_out);
Dan Albertbac34742015-02-25 17:51:28 -080053int install_app(transport_type transport, const char* serial, int argc,
54 const char** argv);
55int install_multiple_app(transport_type transport, const char* serial, int argc,
56 const char** argv);
57int uninstall_app(transport_type transport, const char* serial, int argc,
58 const char** argv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080059
60static const char *gProductOutPath = NULL;
Matt Gumbeld7b33082012-11-14 10:16:17 -080061extern int gListenAll;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080062
63static char *product_file(const char *extra)
64{
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080065 if (gProductOutPath == NULL) {
66 fprintf(stderr, "adb: Product directory not specified; "
67 "use -p or define ANDROID_PRODUCT_OUT\n");
68 exit(1);
69 }
70
Dan Albertbac34742015-02-25 17:51:28 -080071 int n = strlen(gProductOutPath) + strlen(extra) + 2;
72 char* x = reinterpret_cast<char*>(malloc(n));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080073 if (x == 0) {
74 fprintf(stderr, "adb: Out of memory (product_file())\n");
75 exit(1);
76 }
77
78 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra);
79 return x;
80}
81
82void version(FILE * out) {
83 fprintf(out, "Android Debug Bridge version %d.%d.%d\n",
84 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION);
85}
86
87void help()
88{
89 version(stderr);
90
91 fprintf(stderr,
92 "\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -080093 " -a - directs adb to listen on all interfaces for a connection\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080094 " -d - directs command to the only connected USB device\n"
95 " returns an error if more than one USB device is present.\n"
96 " -e - directs command to the only running emulator.\n"
97 " returns an error if more than one emulator is running.\n"
Scott Andersone109d262012-04-20 11:21:14 -070098 " -s <specific device> - directs command to the device or emulator with the given\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -070099 " serial number or qualifier. Overrides ANDROID_SERIAL\n"
Elliott Hughes31dbed72009-10-07 15:38:53 -0700100 " environment variable.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800101 " -p <product name or path> - simple product name like 'sooner', or\n"
102 " a relative/absolute path to a product\n"
103 " out directory like 'out/target/product/sooner'.\n"
104 " If -p is not specified, the ANDROID_PRODUCT_OUT\n"
105 " environment variable is used, which must\n"
106 " be an absolute path.\n"
Matt Gumbeld7b33082012-11-14 10:16:17 -0800107 " -H - Name of adb server host (default: localhost)\n"
108 " -P - Port of adb server (default: 5037)\n"
Scott Andersone109d262012-04-20 11:21:14 -0700109 " devices [-l] - list all connected devices\n"
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700110 " ('-l' will also list device qualifiers)\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400111 " connect <host>[:<port>] - connect to a device via TCP/IP\n"
112 " Port 5555 is used by default if no port number is specified.\n"
113 " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
114 " Port 5555 is used by default if no port number is specified.\n"
Bernhard Reutner-Fischer6715a432011-04-26 12:46:05 +0200115 " Using this command with no additional arguments\n"
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400116 " will disconnect from all connected TCP/IP devices.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800117 "\n"
118 "device commands:\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700119 " adb push [-p] <local> <remote>\n"
120 " - copy file/dir to device\n"
121 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700122 " adb pull [-p] [-a] <remote> [<local>]\n"
Mark Lindner76f2a932014-03-11 17:55:59 -0700123 " - copy file/dir from device\n"
124 " ('-p' to display the transfer progress)\n"
Lajos Molnarde8ff4a2013-04-19 12:41:09 -0700125 " ('-a' means copy timestamp and mode)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800126 " adb sync [ <directory> ] - copy host->device only if changed\n"
Anthony Newnam705c9442010-02-22 08:36:49 -0600127 " (-l means list but don't copy)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800128 " (see 'adb help all')\n"
129 " adb shell - run remote shell interactively\n"
130 " adb shell <command> - run remote shell command\n"
131 " adb emu <command> - run emulator console command\n"
132 " adb logcat [ <filter-spec> ] - View device log\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100133 " adb forward --list - list all forward socket connections.\n"
134 " the format is a list of lines with the following format:\n"
135 " <serial> \" \" <local> \" \" <remote> \"\\n\"\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800136 " adb forward <local> <remote> - forward socket connections\n"
137 " forward specs are one of: \n"
138 " tcp:<port>\n"
139 " localabstract:<unix domain socket name>\n"
140 " localreserved:<unix domain socket name>\n"
141 " localfilesystem:<unix domain socket name>\n"
142 " dev:<character device name>\n"
143 " jdwp:<process pid> (remote only)\n"
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +0100144 " adb forward --no-rebind <local> <remote>\n"
145 " - same as 'adb forward <local> <remote>' but fails\n"
146 " if <local> is already forwarded\n"
147 " adb forward --remove <local> - remove a specific forward socket connection\n"
148 " adb forward --remove-all - remove all forward socket connections\n"
David 'Digit' Turner25258692013-03-21 21:07:42 +0100149 " adb reverse --list - list all reverse socket connections from device\n"
150 " adb reverse <remote> <local> - reverse socket connections\n"
151 " reverse specs are one of:\n"
152 " tcp:<port>\n"
153 " localabstract:<unix domain socket name>\n"
154 " localreserved:<unix domain socket name>\n"
155 " localfilesystem:<unix domain socket name>\n"
156 " adb reverse --norebind <remote> <local>\n"
157 " - same as 'adb reverse <remote> <local>' but fails\n"
158 " if <remote> is already reversed.\n"
159 " adb reverse --remove <remote>\n"
160 " - remove a specific reversed socket connection\n"
161 " adb reverse --remove-all - remove all reversed socket connections from device\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800162 " adb jdwp - list PIDs of processes hosting a JDWP transport\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700163 " adb install [-lrtsd] <file>\n"
164 " adb install-multiple [-lrtsdp] <file...>\n"
Anonymous Coward4474ac42012-04-24 10:43:41 -0700165 " - push this package file to the device and install it\n"
Jeff Sharkey960df972014-06-09 17:30:57 -0700166 " (-l: forward lock application)\n"
167 " (-r: replace existing application)\n"
168 " (-t: allow test packages)\n"
169 " (-s: install application on sdcard)\n"
170 " (-d: allow version code downgrade)\n"
171 " (-p: partial application install)\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800172 " adb uninstall [-k] <package> - remove this app package from the device\n"
173 " ('-k' means keep the data and cache directories)\n"
174 " adb bugreport - return all information from the device\n"
175 " that should be included in a bug report.\n"
176 "\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800177 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
Christopher Tate56885092011-10-03 18:27:01 -0700178 " - write an archive of the device's data to <file>.\n"
179 " If no -f option is supplied then the data is written\n"
180 " to \"backup.ab\" in the current directory.\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700181 " (-apk|-noapk enable/disable backup of the .apks themselves\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700182 " in the archive; the default is noapk.)\n"
Christopher Tate0c06eb52013-03-06 16:40:52 -0800183 " (-obb|-noobb enable/disable backup of any installed apk expansion\n"
184 " (aka .obb) files associated with each application; the default\n"
185 " is noobb.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700186 " (-shared|-noshared enable/disable backup of the device's\n"
187 " shared storage / SD card contents; the default is noshared.)\n"
188 " (-all means to back up all installed applications)\n"
Christopher Tate56885092011-10-03 18:27:01 -0700189 " (-system|-nosystem toggles whether -all automatically includes\n"
190 " system applications; the default is to include system apps)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700191 " (<packages...> is the list of applications to be backed up. If\n"
192 " the -all or -shared flags are passed, then the package\n"
Christopher Tate56885092011-10-03 18:27:01 -0700193 " list is optional. Applications explicitly given on the\n"
194 " command line will be included even if -nosystem would\n"
195 " ordinarily cause them to be omitted.)\n"
Christopher Tated2f54152011-04-21 12:53:28 -0700196 "\n"
Christopher Tatede034ec2011-08-09 17:05:29 -0700197 " adb restore <file> - restore device contents from the <file> backup archive\n"
Christopher Tate702967a2011-05-17 15:52:54 -0700198 "\n"
Paul Lawrence982089d2014-12-03 15:31:57 -0800199 " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
200 " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800201 " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
202 " and the public key is stored in <file>.pub. Any existing files\n"
203 " are overwritten.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800204 " adb help - show this help message\n"
205 " adb version - show version num\n"
206 "\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800207 "scripting:\n"
208 " adb wait-for-device - block until device is online\n"
209 " adb start-server - ensure that there is a server running\n"
210 " adb kill-server - kill the server if it is running\n"
211 " adb get-state - prints: offline | bootloader | device\n"
212 " adb get-serialno - prints: <serial-number>\n"
Scott Andersone109d262012-04-20 11:21:14 -0700213 " adb get-devpath - prints: <device-path>\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800214 " adb status-window - continuously print device status for a specified device\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000215 " 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 -0700216 " adb reboot [bootloader|recovery]\n"
217 " - reboots the device, optionally into the bootloader or recovery program.\n"
218 " adb reboot sideload - reboots the device into the sideload mode in recovery program (adb root required).\n"
219 " adb reboot sideload-auto-reboot\n"
220 " - reboots into the sideload mode, then reboots automatically after the sideload regardless of the result.\n"
Romain Guy311add42009-12-14 14:42:17 -0800221 " adb reboot-bootloader - reboots the device into the bootloader\n"
Mike Lockwoodff196702009-08-24 15:58:40 -0700222 " adb root - restarts the adbd daemon with root permissions\n"
Dan Pasanen98858812014-10-06 12:57:20 -0500223 " adb unroot - restarts the adbd daemon without root permissions\n"
Romain Guy311add42009-12-14 14:42:17 -0800224 " adb usb - restarts the adbd daemon listening on USB\n"
Paul Lawrenceec900bb2014-10-09 14:22:49 +0000225 " 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 -0800226 "networking:\n"
227 " adb ppp <tty> [parameters] - Run PPP over USB.\n"
Kenny Rootc9891992009-06-08 14:40:30 -0500228 " Note: you should not automatically start a PPP connection.\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800229 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n"
230 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n"
231 "\n"
232 "adb sync notes: adb sync [ <directory> ]\n"
233 " <localdir> can be interpreted in several ways:\n"
234 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000235 " - 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 -0800236 "\n"
Elliott Hughesec7a6672015-03-16 21:58:32 +0000237 " - If it is \"system\", \"vendor\", \"oem\" or \"data\", only the corresponding partition\n"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800238 " is updated.\n"
Timcd643152010-02-16 20:18:29 +0000239 "\n"
240 "environmental variables:\n"
241 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
242 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
243 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
244 " 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 -0800245 );
246}
247
248int usage()
249{
250 help();
251 return 1;
252}
253
Yabin Cuid325e862014-11-17 14:48:25 -0800254#if defined(_WIN32)
255
Elliott Hughesa2f2e562015-04-16 16:47:02 -0700256// Implemented in sysdeps_win32.cpp.
Spencer Low50184062015-03-01 15:06:21 -0800257void stdin_raw_init(int fd);
258void stdin_raw_restore(int fd);
Yabin Cuid325e862014-11-17 14:48:25 -0800259
260#else
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100261static termios g_saved_terminal_state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800262
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100263static void stdin_raw_init(int fd) {
264 if (tcgetattr(fd, &g_saved_terminal_state)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800265
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100266 termios tio;
267 if (tcgetattr(fd, &tio)) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800268
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100269 cfmakeraw(&tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800270
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100271 // No timeout but request at least one character per read.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800272 tio.c_cc[VTIME] = 0;
273 tio.c_cc[VMIN] = 1;
274
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100275 tcsetattr(fd, TCSAFLUSH, &tio);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800276}
277
Alistair Buxtondfa09fd2013-03-01 22:16:41 +0100278static void stdin_raw_restore(int fd) {
279 tcsetattr(fd, TCSAFLUSH, &g_saved_terminal_state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800280}
281#endif
282
283static void read_and_dump(int fd)
284{
285 char buf[4096];
286 int len;
287
288 while(fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700289 D("read_and_dump(): pre adb_read(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800290 len = adb_read(fd, buf, 4096);
JP Abgrall408fa572011-03-16 15:57:42 -0700291 D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800292 if(len == 0) {
293 break;
294 }
295
296 if(len < 0) {
297 if(errno == EINTR) continue;
298 break;
299 }
Mike Lockwooddd6b36e2009-09-22 01:18:40 -0400300 fwrite(buf, 1, len, stdout);
301 fflush(stdout);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800302 }
303}
304
Jeff Sharkey960df972014-06-09 17:30:57 -0700305static void read_status_line(int fd, char* buf, size_t count)
306{
307 count--;
308 while (count > 0) {
309 int len = adb_read(fd, buf, count);
310 if (len == 0) {
311 break;
312 } else if (len < 0) {
313 if (errno == EINTR) continue;
314 break;
315 }
316
317 buf += len;
318 count -= len;
319 }
320 *buf = '\0';
321}
322
Christopher Tated2f54152011-04-21 12:53:28 -0700323static void copy_to_file(int inFd, int outFd) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700324 const size_t BUFSIZE = 32 * 1024;
325 char* buf = (char*) malloc(BUFSIZE);
Christopher Tated2f54152011-04-21 12:53:28 -0700326 int len;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700327 long total = 0;
Christopher Tated2f54152011-04-21 12:53:28 -0700328
329 D("copy_to_file(%d -> %d)\n", inFd, outFd);
Yabin Cuid325e862014-11-17 14:48:25 -0800330
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700331 if (inFd == STDIN_FILENO) {
332 stdin_raw_init(STDIN_FILENO);
333 }
Yabin Cuid325e862014-11-17 14:48:25 -0800334
Christopher Tated2f54152011-04-21 12:53:28 -0700335 for (;;) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700336 if (inFd == STDIN_FILENO) {
337 len = unix_read(inFd, buf, BUFSIZE);
338 } else {
339 len = adb_read(inFd, buf, BUFSIZE);
340 }
Christopher Tated2f54152011-04-21 12:53:28 -0700341 if (len == 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700342 D("copy_to_file() : read 0 bytes; exiting\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700343 break;
344 }
345 if (len < 0) {
Christopher Tate5b811fa2011-06-10 11:38:37 -0700346 if (errno == EINTR) {
347 D("copy_to_file() : EINTR, retrying\n");
348 continue;
349 }
Christopher Tated2f54152011-04-21 12:53:28 -0700350 D("copy_to_file() : error %d\n", errno);
351 break;
352 }
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700353 if (outFd == STDOUT_FILENO) {
354 fwrite(buf, 1, len, stdout);
355 fflush(stdout);
356 } else {
357 adb_write(outFd, buf, len);
358 }
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700359 total += len;
Christopher Tated2f54152011-04-21 12:53:28 -0700360 }
Yabin Cuid325e862014-11-17 14:48:25 -0800361
Jeff Sharkey5d9d4342014-05-26 18:30:43 -0700362 if (inFd == STDIN_FILENO) {
363 stdin_raw_restore(STDIN_FILENO);
364 }
Yabin Cuid325e862014-11-17 14:48:25 -0800365
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700366 D("copy_to_file() finished after %lu bytes\n", total);
Christopher Tate5b811fa2011-06-10 11:38:37 -0700367 free(buf);
Christopher Tated2f54152011-04-21 12:53:28 -0700368}
369
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800370static void *stdin_read_thread(void *x)
371{
372 int fd, fdi;
373 unsigned char buf[1024];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800374 int r, n;
375 int state = 0;
376
377 int *fds = (int*) x;
378 fd = fds[0];
379 fdi = fds[1];
380 free(fds);
381
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800382 for(;;) {
383 /* fdi is really the client's stdin, so use read, not adb_read here */
JP Abgrall408fa572011-03-16 15:57:42 -0700384 D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800385 r = unix_read(fdi, buf, 1024);
JP Abgrall408fa572011-03-16 15:57:42 -0700386 D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800387 if(r == 0) break;
388 if(r < 0) {
389 if(errno == EINTR) continue;
390 break;
391 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400392 for(n = 0; n < r; n++){
393 switch(buf[n]) {
394 case '\n':
395 state = 1;
396 break;
397 case '\r':
398 state = 1;
399 break;
400 case '~':
401 if(state == 1) state++;
402 break;
403 case '.':
404 if(state == 2) {
405 fprintf(stderr,"\n* disconnect *\n");
Mike Lockwood67d53582010-05-25 13:40:15 -0400406 stdin_raw_restore(fdi);
Mike Lockwood67d53582010-05-25 13:40:15 -0400407 exit(0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800408 }
Mike Lockwood67d53582010-05-25 13:40:15 -0400409 default:
410 state = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800411 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800412 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800413 r = adb_write(fd, buf, r);
414 if(r <= 0) {
415 break;
416 }
417 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800418 return 0;
419}
420
421int interactive_shell(void)
422{
423 adb_thread_t thr;
424 int fdi, fd;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800425
426 fd = adb_connect("shell:");
427 if(fd < 0) {
428 fprintf(stderr,"error: %s\n", adb_error());
429 return 1;
430 }
431 fdi = 0; //dup(0);
432
Dan Albertbac34742015-02-25 17:51:28 -0800433 int* fds = reinterpret_cast<int*>(malloc(sizeof(int) * 2));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800434 fds[0] = fd;
435 fds[1] = fdi;
436
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800437 stdin_raw_init(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438 adb_thread_create(&thr, stdin_read_thread, fds);
439 read_and_dump(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800440 stdin_raw_restore(fdi);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800441 return 0;
442}
443
444
445static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial)
446{
447 if (serial) {
448 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command);
449 } else {
450 const char* prefix = "host";
451 if (ttype == kTransportUsb)
452 prefix = "host-usb";
453 else if (ttype == kTransportLocal)
454 prefix = "host-local";
455
456 snprintf(buffer, buflen, "%s:%s", prefix, command);
457 }
458}
459
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100460int adb_download_buffer(const char *service, const char *fn, const void* data, int sz,
Doug Zongker447f0612012-01-09 14:54:53 -0800461 unsigned progress)
462{
463 char buf[4096];
464 unsigned total;
465 int fd;
Doug Zongker447f0612012-01-09 14:54:53 -0800466
467 sprintf(buf,"%s:%d", service, sz);
468 fd = adb_connect(buf);
469 if(fd < 0) {
470 fprintf(stderr,"error: %s\n", adb_error());
471 return -1;
472 }
473
474 int opt = CHUNK_SIZE;
Spencer Lowf055c192015-01-25 14:40:16 -0800475 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker447f0612012-01-09 14:54:53 -0800476
477 total = sz;
Dan Albertbac34742015-02-25 17:51:28 -0800478 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
Doug Zongker447f0612012-01-09 14:54:53 -0800479
480 if(progress) {
481 char *x = strrchr(service, ':');
482 if(x) service = x + 1;
483 }
484
485 while(sz > 0) {
486 unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz;
Dan Albertcc731cc2015-02-24 21:26:58 -0800487 if(!WriteFdExactly(fd, ptr, xfer)) {
Doug Zongker447f0612012-01-09 14:54:53 -0800488 adb_status(fd);
489 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
490 return -1;
491 }
492 sz -= xfer;
493 ptr += xfer;
494 if(progress) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100495 printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total))));
Doug Zongker447f0612012-01-09 14:54:53 -0800496 fflush(stdout);
497 }
498 }
499 if(progress) {
500 printf("\n");
501 }
502
Dan Albertcc731cc2015-02-24 21:26:58 -0800503 if(!ReadFdExactly(fd, buf, 4)){
Doug Zongker447f0612012-01-09 14:54:53 -0800504 fprintf(stderr,"* error reading response *\n");
505 adb_close(fd);
506 return -1;
507 }
508 if(memcmp(buf, "OKAY", 4)) {
509 buf[4] = 0;
510 fprintf(stderr,"* error response '%s' *\n", buf);
511 adb_close(fd);
512 return -1;
513 }
514
515 adb_close(fd);
516 return 0;
517}
518
519
520int adb_download(const char *service, const char *fn, unsigned progress)
521{
522 void *data;
523 unsigned sz;
524
525 data = load_file(fn, &sz);
526 if(data == 0) {
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100527 fprintf(stderr,"* cannot read '%s' *\n", fn);
Doug Zongker447f0612012-01-09 14:54:53 -0800528 return -1;
529 }
530
Magnus Eriksson86ae6d52013-03-05 07:37:32 +0100531 int status = adb_download_buffer(service, fn, data, sz, progress);
Doug Zongker447f0612012-01-09 14:54:53 -0800532 free(data);
533 return status;
534}
535
Doug Zongker71fe5842014-06-26 15:35:36 -0700536#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
537
538/*
539 * The sideload-host protocol serves the data in a file (given on the
540 * command line) to the client, using a simple protocol:
541 *
542 * - The connect message includes the total number of bytes in the
543 * file and a block size chosen by us.
544 *
545 * - The other side sends the desired block number as eight decimal
546 * digits (eg "00000023" for block 23). Blocks are numbered from
547 * zero.
548 *
549 * - We send back the data of the requested block. The last block is
550 * likely to be partial; when the last block is requested we only
551 * send the part of the block that exists, it's not padded up to the
552 * block size.
553 *
554 * - When the other side sends "DONEDONE" instead of a block number,
555 * we hang up.
556 */
557int adb_sideload_host(const char* fn) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700558 unsigned sz;
559 size_t xfer = 0;
560 int status;
Dan Albertbac34742015-02-25 17:51:28 -0800561 int last_percent = -1;
562 int opt = SIDELOAD_HOST_BLOCK_SIZE;
Doug Zongker71fe5842014-06-26 15:35:36 -0700563
564 printf("loading: '%s'", fn);
565 fflush(stdout);
Dan Albertbac34742015-02-25 17:51:28 -0800566 uint8_t* data = reinterpret_cast<uint8_t*>(load_file(fn, &sz));
Doug Zongker71fe5842014-06-26 15:35:36 -0700567 if (data == 0) {
568 printf("\n");
569 fprintf(stderr, "* cannot read '%s' *\n", fn);
570 return -1;
571 }
572
573 char buf[100];
574 sprintf(buf, "sideload-host:%d:%d", sz, SIDELOAD_HOST_BLOCK_SIZE);
575 int fd = adb_connect(buf);
576 if (fd < 0) {
577 // Try falling back to the older sideload method. Maybe this
578 // is an older device that doesn't support sideload-host.
579 printf("\n");
580 status = adb_download_buffer("sideload", fn, data, sz, 1);
581 goto done;
582 }
583
Spencer Lowf055c192015-01-25 14:40:16 -0800584 opt = adb_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const void *) &opt, sizeof(opt));
Doug Zongker71fe5842014-06-26 15:35:36 -0700585
Doug Zongker4b39c6a2014-07-07 15:28:43 -0700586 for (;;) {
Dan Albertcc731cc2015-02-24 21:26:58 -0800587 if (!ReadFdExactly(fd, buf, 8)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700588 fprintf(stderr, "* failed to read command: %s\n", adb_error());
589 status = -1;
590 goto done;
591 }
592
593 if (strncmp("DONEDONE", buf, 8) == 0) {
594 status = 0;
595 break;
596 }
597
598 buf[8] = '\0';
599 int block = strtol(buf, NULL, 10);
600
601 size_t offset = block * SIDELOAD_HOST_BLOCK_SIZE;
602 if (offset >= sz) {
603 fprintf(stderr, "* attempt to read past end: %s\n", adb_error());
604 status = -1;
605 goto done;
606 }
607 uint8_t* start = data + offset;
608 size_t offset_end = offset + SIDELOAD_HOST_BLOCK_SIZE;
609 size_t to_write = SIDELOAD_HOST_BLOCK_SIZE;
610 if (offset_end > sz) {
611 to_write = sz - offset;
612 }
613
Dan Albertcc731cc2015-02-24 21:26:58 -0800614 if(!WriteFdExactly(fd, start, to_write)) {
Doug Zongker71fe5842014-06-26 15:35:36 -0700615 adb_status(fd);
616 fprintf(stderr,"* failed to write data '%s' *\n", adb_error());
617 status = -1;
618 goto done;
619 }
620 xfer += to_write;
621
622 // For normal OTA packages, we expect to transfer every byte
623 // twice, plus a bit of overhead (one read during
624 // verification, one read of each byte for installation, plus
625 // extra access to things like the zip central directory).
626 // This estimate of the completion becomes 100% when we've
627 // transferred ~2.13 (=100/47) times the package size.
628 int percent = (int)(xfer * 47LL / (sz ? sz : 1));
629 if (percent != last_percent) {
630 printf("\rserving: '%s' (~%d%%) ", fn, percent);
631 fflush(stdout);
632 last_percent = percent;
633 }
634 }
635
Colin Cross6d6a8982014-07-07 14:12:41 -0700636 printf("\rTotal xfer: %.2fx%*s\n", (double)xfer / (sz ? sz : 1), (int)strlen(fn)+10, "");
Doug Zongker71fe5842014-06-26 15:35:36 -0700637
638 done:
639 if (fd >= 0) adb_close(fd);
640 free(data);
641 return status;
642}
643
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800644static void status_window(transport_type ttype, const char* serial)
645{
646 char command[4096];
647 char *state = 0;
648 char *laststate = 0;
649
650 /* silence stderr */
651#ifdef _WIN32
652 /* XXX: TODO */
653#else
654 int fd;
655 fd = unix_open("/dev/null", O_WRONLY);
656 dup2(fd, 2);
657 adb_close(fd);
658#endif
659
660 format_host_command(command, sizeof command, "get-state", ttype, serial);
661
662 for(;;) {
663 adb_sleep_ms(250);
664
665 if(state) {
666 free(state);
667 state = 0;
668 }
669
670 state = adb_query(command);
671
672 if(state) {
673 if(laststate && !strcmp(state,laststate)){
674 continue;
675 } else {
676 if(laststate) free(laststate);
677 laststate = strdup(state);
678 }
679 }
680
681 printf("%c[2J%c[2H", 27, 27);
682 printf("Android Debug Bridge\n");
683 printf("State: %s\n", state ? state : "offline");
684 fflush(stdout);
685 }
686}
687
Brian Carlstrom46a8ffe2014-08-05 22:51:18 -0700688static int should_escape(const char c)
Jeff Sharkeyd0eee742014-08-05 16:53:08 -0700689{
690 return (c == ' ' || c == '\'' || c == '"' || c == '\\' || c == '(' || c == ')');
691}
692
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700693static std::string escape_arg(const std::string& s) {
694 // Preserve empty arguments.
695 if (s.empty()) return "\"\"";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800696
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700697 std::string result(s);
698 for (auto it = result.begin(); it != result.end(); ++it) {
699 if (should_escape(*it)) {
700 it = result.insert(it, '\\') + 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800701 }
702 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700703 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800704}
705
706/**
707 * Run ppp in "notty" mode against a resource listed as the first parameter
708 * eg:
709 *
710 * ppp dev:/dev/omap_csmi_tty0 <ppp options>
711 *
712 */
Dan Albertbac34742015-02-25 17:51:28 -0800713int ppp(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800714{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800715#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800716 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
717 return -1;
718#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800719 pid_t pid;
720 int fd;
721
722 if (argc < 2) {
723 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
724 argv[0]);
725
726 return 1;
727 }
728
Dan Albertbac34742015-02-25 17:51:28 -0800729 const char* adb_service_name = argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800730 fd = adb_connect(adb_service_name);
731
732 if(fd < 0) {
733 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
734 adb_service_name, adb_error());
735 return 1;
736 }
737
738 pid = fork();
739
740 if (pid < 0) {
741 perror("from fork()");
742 return 1;
743 } else if (pid == 0) {
744 int err;
745 int i;
746 const char **ppp_args;
747
748 // copy args
749 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
750 ppp_args[0] = "pppd";
751 for (i = 2 ; i < argc ; i++) {
752 //argv[2] and beyond become ppp_args[1] and beyond
753 ppp_args[i - 1] = argv[i];
754 }
755 ppp_args[i-1] = NULL;
756
757 // child side
758
759 dup2(fd, STDIN_FILENO);
760 dup2(fd, STDOUT_FILENO);
761 adb_close(STDERR_FILENO);
762 adb_close(fd);
763
764 err = execvp("pppd", (char * const *)ppp_args);
765
766 if (err < 0) {
767 perror("execing pppd");
768 }
769 exit(-1);
770 } else {
771 // parent side
772
773 adb_close(fd);
774 return 0;
775 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800776#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800777}
778
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700779static int send_shell_command(transport_type transport, const char* serial,
780 const std::string& command) {
781 int fd;
782 while (true) {
783 fd = adb_connect(command.c_str());
784 if (fd >= 0)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800785 break;
786 fprintf(stderr,"- waiting for device -\n");
787 adb_sleep_ms(1000);
788 do_cmd(transport, serial, "wait-for-device", 0);
789 }
790
791 read_and_dump(fd);
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700792 int rc = adb_close(fd);
793 if (rc) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800794 perror("close");
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700795 }
796 return rc;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800797}
798
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700799static int logcat(transport_type transport, const char* serial, int argc, const char** argv) {
800 char* log_tags = getenv("ANDROID_LOG_TAGS");
801 std::string quoted = escape_arg(log_tags == nullptr ? "" : log_tags);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800802
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700803 std::string cmd = "shell:export ANDROID_LOG_TAGS=\"" + quoted + "\"; exec logcat";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800804
Jeff Sharkeyfd546e82014-06-10 11:31:24 -0700805 if (!strcmp(argv[0], "longcat")) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700806 cmd += " -v long";
Christopher Tatedb0a8802011-11-30 13:00:33 -0800807 }
808
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800809 argc -= 1;
810 argv += 1;
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700811 while (argc-- > 0) {
812 cmd += " ";
813 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800814 }
815
Elliott Hughes2baae3a2015-04-17 10:59:34 -0700816 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800817 return 0;
818}
819
Mark Salyzyn60299df2014-04-30 09:10:31 -0700820static int mkdirs(const char *path)
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800821{
822 int ret;
Mark Salyzyn60299df2014-04-30 09:10:31 -0700823 char *x = (char *)path + 1;
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800824
825 for(;;) {
826 x = adb_dirstart(x);
827 if(x == 0) return 0;
828 *x = 0;
829 ret = adb_mkdir(path, 0775);
830 *x = OS_PATH_SEPARATOR;
831 if((ret < 0) && (errno != EEXIST)) {
832 return ret;
833 }
834 x++;
835 }
836 return 0;
837}
838
Dan Albertbac34742015-02-25 17:51:28 -0800839static int backup(int argc, const char** argv) {
Christopher Tated2f54152011-04-21 12:53:28 -0700840 char buf[4096];
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800841 char default_name[32];
842 const char* filename = strcpy(default_name, "./backup.ab");
Christopher Tated2f54152011-04-21 12:53:28 -0700843 int fd, outFd;
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700844 int i, j;
Christopher Tated2f54152011-04-21 12:53:28 -0700845
Christopher Tatec9cd3b92011-06-01 17:56:23 -0700846 /* find, extract, and use any -f argument */
847 for (i = 1; i < argc; i++) {
848 if (!strcmp("-f", argv[i])) {
849 if (i == argc-1) {
850 fprintf(stderr, "adb: -f passed with no filename\n");
851 return usage();
852 }
853 filename = argv[i+1];
854 for (j = i+2; j <= argc; ) {
855 argv[i++] = argv[j++];
856 }
857 argc -= 2;
858 argv[argc] = NULL;
859 }
Christopher Tated2f54152011-04-21 12:53:28 -0700860 }
861
Christopher Tatebb86bc52011-08-22 17:12:08 -0700862 /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
863 if (argc < 2) return usage();
864
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800865 adb_unlink(filename);
Mark Salyzyn60299df2014-04-30 09:10:31 -0700866 mkdirs(filename);
Christopher Tateb1dfffe2011-12-08 19:04:34 -0800867 outFd = adb_creat(filename, 0640);
Christopher Tated2f54152011-04-21 12:53:28 -0700868 if (outFd < 0) {
869 fprintf(stderr, "adb: unable to open file %s\n", filename);
870 return -1;
871 }
872
873 snprintf(buf, sizeof(buf), "backup");
874 for (argc--, argv++; argc; argc--, argv++) {
875 strncat(buf, ":", sizeof(buf) - strlen(buf) - 1);
876 strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1);
877 }
878
879 D("backup. filename=%s buf=%s\n", filename, buf);
880 fd = adb_connect(buf);
881 if (fd < 0) {
882 fprintf(stderr, "adb: unable to connect for backup\n");
883 adb_close(outFd);
884 return -1;
885 }
886
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800887 printf("Now unlock your device and confirm the backup operation.\n");
Christopher Tated2f54152011-04-21 12:53:28 -0700888 copy_to_file(fd, outFd);
889
890 adb_close(fd);
891 adb_close(outFd);
892 return 0;
893}
894
Dan Albertbac34742015-02-25 17:51:28 -0800895static int restore(int argc, const char** argv) {
Christopher Tate702967a2011-05-17 15:52:54 -0700896 const char* filename;
897 int fd, tarFd;
898
899 if (argc != 2) return usage();
900
901 filename = argv[1];
902 tarFd = adb_open(filename, O_RDONLY);
903 if (tarFd < 0) {
904 fprintf(stderr, "adb: unable to open file %s\n", filename);
905 return -1;
906 }
907
908 fd = adb_connect("restore:");
909 if (fd < 0) {
Brian Carlstrom93c91fa2013-10-18 13:58:48 -0700910 fprintf(stderr, "adb: unable to connect for restore\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700911 adb_close(tarFd);
912 return -1;
913 }
914
Christopher Tatebffa4ca2012-01-06 15:43:03 -0800915 printf("Now unlock your device and confirm the restore operation.\n");
Christopher Tate702967a2011-05-17 15:52:54 -0700916 copy_to_file(tarFd, fd);
917
918 adb_close(fd);
919 adb_close(tarFd);
920 return 0;
921}
922
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800923#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
924static int top_works(const char *top)
925{
926 if (top != NULL && adb_is_absolute_host_path(top)) {
927 char path_buf[PATH_MAX];
928 snprintf(path_buf, sizeof(path_buf),
929 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top);
930 return access(path_buf, F_OK) == 0;
931 }
932 return 0;
933}
934
935static char *find_top_from(const char *indir, char path_buf[PATH_MAX])
936{
937 strcpy(path_buf, indir);
938 while (1) {
939 if (top_works(path_buf)) {
940 return path_buf;
941 }
942 char *s = adb_dirstop(path_buf);
943 if (s != NULL) {
944 *s = '\0';
945 } else {
946 path_buf[0] = '\0';
947 return NULL;
948 }
949 }
950}
951
952static char *find_top(char path_buf[PATH_MAX])
953{
954 char *top = getenv("ANDROID_BUILD_TOP");
955 if (top != NULL && top[0] != '\0') {
956 if (!top_works(top)) {
957 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top);
958 return NULL;
959 }
960 } else {
961 top = getenv("TOP");
962 if (top != NULL && top[0] != '\0') {
963 if (!top_works(top)) {
964 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top);
965 return NULL;
966 }
967 } else {
968 top = NULL;
969 }
970 }
971
972 if (top != NULL) {
973 /* The environment pointed to a top directory that works.
974 */
975 strcpy(path_buf, top);
976 return path_buf;
977 }
978
979 /* The environment didn't help. Walk up the tree from the CWD
980 * to see if we can find the top.
981 */
982 char dir[PATH_MAX];
983 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf);
984 if (top == NULL) {
985 /* If the CWD isn't under a good-looking top, see if the
986 * executable is.
987 */
Alexey Tarasov31664102009-10-22 02:55:00 +1100988 get_my_path(dir, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800989 top = find_top_from(dir, path_buf);
990 }
991 return top;
992}
993
994/* <hint> may be:
995 * - A simple product name
996 * e.g., "sooner"
997TODO: debug? sooner-debug, sooner:debug?
998 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
999 * e.g., "out/target/product/sooner"
1000 * - An absolute path to the PRODUCT_OUT dir
1001 * e.g., "/src/device/out/target/product/sooner"
1002 *
1003 * Given <hint>, try to construct an absolute path to the
1004 * ANDROID_PRODUCT_OUT dir.
1005 */
1006static const char *find_product_out_path(const char *hint)
1007{
1008 static char path_buf[PATH_MAX];
1009
1010 if (hint == NULL || hint[0] == '\0') {
1011 return NULL;
1012 }
1013
1014 /* If it's already absolute, don't bother doing any work.
1015 */
1016 if (adb_is_absolute_host_path(hint)) {
1017 strcpy(path_buf, hint);
1018 return path_buf;
1019 }
1020
1021 /* If there are any slashes in it, assume it's a relative path;
1022 * make it absolute.
1023 */
1024 if (adb_dirstart(hint) != NULL) {
1025 if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
1026 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno));
1027 return NULL;
1028 }
1029 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
1030 fprintf(stderr, "adb: Couldn't assemble path\n");
1031 return NULL;
1032 }
1033 strcat(path_buf, OS_PATH_SEPARATOR_STR);
1034 strcat(path_buf, hint);
1035 return path_buf;
1036 }
1037
1038 /* It's a string without any slashes. Try to do something with it.
1039 *
1040 * Try to find the root of the build tree, and build a PRODUCT_OUT
1041 * path from there.
1042 */
1043 char top_buf[PATH_MAX];
1044 const char *top = find_top(top_buf);
1045 if (top == NULL) {
1046 fprintf(stderr, "adb: Couldn't find top of build tree\n");
1047 return NULL;
1048 }
1049//TODO: if we have a way to indicate debug, look in out/debug/target/...
1050 snprintf(path_buf, sizeof(path_buf),
1051 "%s" OS_PATH_SEPARATOR_STR
1052 "out" OS_PATH_SEPARATOR_STR
1053 "target" OS_PATH_SEPARATOR_STR
1054 "product" OS_PATH_SEPARATOR_STR
1055 "%s", top_buf, hint);
1056 if (access(path_buf, F_OK) < 0) {
1057 fprintf(stderr, "adb: Couldn't find a product dir "
1058 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
1059 return NULL;
1060 }
1061 return path_buf;
1062}
1063
Dan Albertbac34742015-02-25 17:51:28 -08001064static void parse_push_pull_args(const char **arg, int narg, char const **path1,
1065 char const **path2, int *show_progress,
1066 int *copy_attrs) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001067 *show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001068 *copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001069
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001070 while (narg > 0) {
1071 if (!strcmp(*arg, "-p")) {
1072 *show_progress = 1;
1073 } else if (!strcmp(*arg, "-a")) {
1074 *copy_attrs = 1;
1075 } else {
1076 break;
1077 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001078 ++arg;
1079 --narg;
1080 }
1081
1082 if (narg > 0) {
1083 *path1 = *arg;
1084 ++arg;
1085 --narg;
1086 }
1087
1088 if (narg > 0) {
1089 *path2 = *arg;
1090 }
1091}
1092
Tao Bao175b7bb2015-03-29 11:22:34 -07001093static int adb_connect_command(const char* command) {
1094 int fd = adb_connect(command);
1095 if (fd != -1) {
1096 read_and_dump(fd);
1097 adb_close(fd);
1098 return 0;
1099 }
1100 fprintf(stderr, "Error: %s\n", adb_error());
1101 return 1;
1102}
1103
Dan Albertbac34742015-02-25 17:51:28 -08001104int adb_commandline(int argc, const char **argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001105{
1106 char buf[4096];
1107 int no_daemon = 0;
1108 int is_daemon = 0;
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001109 int is_server = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001110 int persist = 0;
1111 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001112 transport_type ttype = kTransportAny;
Dan Albertbac34742015-02-25 17:51:28 -08001113 const char* serial = NULL;
1114 const char* server_port_str = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001115
1116 /* If defined, this should be an absolute path to
1117 * the directory containing all of the various system images
1118 * for a particular product. If not defined, and the adb
1119 * command requires this information, then the user must
1120 * specify the path using "-p".
1121 */
1122 gProductOutPath = getenv("ANDROID_PRODUCT_OUT");
1123 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') {
1124 gProductOutPath = NULL;
1125 }
1126 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint
1127
Nick Pellydb449262009-05-07 12:48:03 -07001128 serial = getenv("ANDROID_SERIAL");
1129
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001130 /* Validate and assign the server port */
1131 server_port_str = getenv("ANDROID_ADB_SERVER_PORT");
1132 int server_port = DEFAULT_ADB_PORT;
1133 if (server_port_str && strlen(server_port_str) > 0) {
1134 server_port = (int) strtol(server_port_str, NULL, 0);
Matt Gumbeld7b33082012-11-14 10:16:17 -08001135 if (server_port <= 0 || server_port > 65535) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001136 fprintf(stderr,
Matt Gumbeld7b33082012-11-14 10:16:17 -08001137 "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 +01001138 server_port_str);
1139 return usage();
1140 }
1141 }
1142
1143 /* modifiers and flags */
Riley Andrews98f58e82014-12-05 17:37:24 -08001144 while (argc > 0) {
1145 if (!strcmp(argv[0],"server")) {
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001146 is_server = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001147 } else if (!strcmp(argv[0],"nodaemon")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001148 no_daemon = 1;
1149 } else if (!strcmp(argv[0], "fork-server")) {
1150 /* this is a special flag used only when the ADB client launches the ADB Server */
1151 is_daemon = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001152 } else if (!strcmp(argv[0],"persist")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001153 persist = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001154 } else if (!strncmp(argv[0], "-p", 2)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001155 const char *product = NULL;
1156 if (argv[0][2] == '\0') {
1157 if (argc < 2) return usage();
1158 product = argv[1];
1159 argc--;
1160 argv++;
1161 } else {
Vairavan Srinivasan81273232012-08-04 16:40:50 -07001162 product = argv[0] + 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001163 }
1164 gProductOutPath = find_product_out_path(product);
1165 if (gProductOutPath == NULL) {
1166 fprintf(stderr, "adb: could not resolve \"-p %s\"\n",
1167 product);
1168 return usage();
1169 }
1170 } else if (argv[0][0]=='-' && argv[0][1]=='s') {
1171 if (isdigit(argv[0][2])) {
1172 serial = argv[0] + 2;
1173 } else {
Riley Andrews98f58e82014-12-05 17:37:24 -08001174 if (argc < 2 || argv[0][2] != '\0') return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001175 serial = argv[1];
1176 argc--;
1177 argv++;
1178 }
1179 } else if (!strcmp(argv[0],"-d")) {
1180 ttype = kTransportUsb;
1181 } else if (!strcmp(argv[0],"-e")) {
1182 ttype = kTransportLocal;
Matt Gumbeld7b33082012-11-14 10:16:17 -08001183 } else if (!strcmp(argv[0],"-a")) {
1184 gListenAll = 1;
Riley Andrews98f58e82014-12-05 17:37:24 -08001185 } else if (!strncmp(argv[0], "-H", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001186 const char *hostname = NULL;
1187 if (argv[0][2] == '\0') {
1188 if (argc < 2) return usage();
1189 hostname = argv[1];
1190 argc--;
1191 argv++;
1192 } else {
1193 hostname = argv[0] + 2;
1194 }
1195 adb_set_tcp_name(hostname);
1196
Riley Andrews98f58e82014-12-05 17:37:24 -08001197 } else if (!strncmp(argv[0], "-P", 2)) {
Matt Gumbeld7b33082012-11-14 10:16:17 -08001198 if (argv[0][2] == '\0') {
1199 if (argc < 2) return usage();
1200 server_port_str = argv[1];
1201 argc--;
1202 argv++;
1203 } else {
1204 server_port_str = argv[0] + 2;
1205 }
1206 if (strlen(server_port_str) > 0) {
1207 server_port = (int) strtol(server_port_str, NULL, 0);
1208 if (server_port <= 0 || server_port > 65535) {
1209 fprintf(stderr,
1210 "adb: port number must be a positive number less than 65536. Got \"%s\"\n",
1211 server_port_str);
1212 return usage();
1213 }
1214 } else {
1215 fprintf(stderr,
1216 "adb: port number must be a positive number less than 65536. Got empty string.\n");
1217 return usage();
1218 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001219 } else {
1220 /* out of recognized modifiers and flags */
1221 break;
1222 }
1223 argc--;
1224 argv++;
1225 }
1226
1227 adb_set_transport(ttype, serial);
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001228 adb_set_tcp_specifics(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001229
David 'Digit' Turner305b4b02011-01-31 14:23:56 +01001230 if (is_server) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001231 if (no_daemon || is_daemon) {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001232 r = adb_main(is_daemon, server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001233 } else {
Stefan Hilzingera84a42e2010-04-19 12:21:12 +01001234 r = launch_server(server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001235 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001236 if (r) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001237 fprintf(stderr,"* could not start server *\n");
1238 }
1239 return r;
1240 }
1241
Riley Andrews98f58e82014-12-05 17:37:24 -08001242 if (argc == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001243 return usage();
1244 }
1245
Riley Andrewsc8514c82014-12-05 17:32:46 -08001246 /* handle wait-for-* prefix */
1247 if (!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
Dan Albertbac34742015-02-25 17:51:28 -08001248 const char* service = argv[0];
Riley Andrewsc8514c82014-12-05 17:32:46 -08001249 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) {
1250 if (ttype == kTransportUsb) {
1251 service = "wait-for-usb";
1252 } else if (ttype == kTransportLocal) {
1253 service = "wait-for-local";
1254 } else {
1255 service = "wait-for-any";
1256 }
1257 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001258
Riley Andrewsc8514c82014-12-05 17:32:46 -08001259 format_host_command(buf, sizeof buf, service, ttype, serial);
1260
1261 if (adb_command(buf)) {
1262 D("failure: %s *\n",adb_error());
1263 fprintf(stderr,"error: %s\n", adb_error());
1264 return 1;
1265 }
1266
1267 /* Allow a command to be run after wait-for-device,
1268 * e.g. 'adb wait-for-device shell'.
1269 */
1270 if (argc == 1) {
1271 return 0;
1272 }
1273
1274 /* Fall through */
1275 argc--;
1276 argv++;
1277 }
1278
1279 /* adb_connect() commands */
Riley Andrews98f58e82014-12-05 17:37:24 -08001280 if (!strcmp(argv[0], "devices")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001281 char *tmp;
Dan Albertbac34742015-02-25 17:51:28 -08001282 const char *listopt;
Scott Andersone109d262012-04-20 11:21:14 -07001283 if (argc < 2)
1284 listopt = "";
1285 else if (argc == 2 && !strcmp(argv[1], "-l"))
1286 listopt = argv[1];
1287 else {
1288 fprintf(stderr, "Usage: adb devices [-l]\n");
1289 return 1;
1290 }
1291 snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001292 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001293 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001294 printf("List of devices attached \n");
1295 printf("%s\n", tmp);
1296 return 0;
1297 } else {
1298 return 1;
1299 }
1300 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001301 else if (!strcmp(argv[0], "connect")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001302 char *tmp;
1303 if (argc != 2) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001304 fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
Mike Lockwoodff196702009-08-24 15:58:40 -07001305 return 1;
1306 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001307 snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
1308 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001309 if (tmp) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001310 printf("%s\n", tmp);
1311 return 0;
1312 } else {
1313 return 1;
1314 }
1315 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001316 else if (!strcmp(argv[0], "disconnect")) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001317 char *tmp;
1318 if (argc > 2) {
1319 fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
1320 return 1;
1321 }
1322 if (argc == 2) {
1323 snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
1324 } else {
1325 snprintf(buf, sizeof buf, "host:disconnect:");
1326 }
Mike Lockwoodff196702009-08-24 15:58:40 -07001327 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001328 if (tmp) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001329 printf("%s\n", tmp);
1330 return 0;
1331 } else {
1332 return 1;
1333 }
1334 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001335 else if (!strcmp(argv[0], "emu")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001336 return adb_send_emulator_command(argc, argv);
1337 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001338 else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001339 char h = (argv[0][0] == 'h');
1340
1341 if (h) {
1342 printf("\x1b[41;33m");
1343 fflush(stdout);
1344 }
1345
Riley Andrews98f58e82014-12-05 17:37:24 -08001346 if (argc < 2) {
JP Abgrall408fa572011-03-16 15:57:42 -07001347 D("starting interactive shell\n");
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001348 r = interactive_shell();
1349 if (h) {
1350 printf("\x1b[0m");
1351 fflush(stdout);
1352 }
1353 return r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001354 }
1355
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001356 std::string cmd = "shell:";
1357 cmd += argv[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001358 argc -= 2;
1359 argv += 2;
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001360 while (argc-- > 0) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001361 cmd += " ";
1362 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001363 }
1364
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001365 while (true) {
1366 D("interactive shell loop. cmd=%s\n", cmd.c_str());
1367 int fd = adb_connect(cmd.c_str());
1368 int r;
Riley Andrews98f58e82014-12-05 17:37:24 -08001369 if (fd >= 0) {
JP Abgrall408fa572011-03-16 15:57:42 -07001370 D("about to read_and_dump(fd=%d)\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001371 read_and_dump(fd);
JP Abgrall408fa572011-03-16 15:57:42 -07001372 D("read_and_dump() done.\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001373 adb_close(fd);
1374 r = 0;
1375 } else {
1376 fprintf(stderr,"error: %s\n", adb_error());
1377 r = -1;
1378 }
1379
Riley Andrews98f58e82014-12-05 17:37:24 -08001380 if (persist) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001381 fprintf(stderr,"\n- waiting for device -\n");
1382 adb_sleep_ms(1000);
1383 do_cmd(ttype, serial, "wait-for-device", 0);
1384 } else {
Daniel Sandlerff91ab82010-08-19 01:10:18 -04001385 if (h) {
1386 printf("\x1b[0m");
1387 fflush(stdout);
1388 }
JP Abgrall408fa572011-03-16 15:57:42 -07001389 D("interactive shell loop. return r=%d\n", r);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001390 return r;
1391 }
1392 }
1393 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001394 else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001395 int exec_in = !strcmp(argv[0], "exec-in");
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001396
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001397 std::string cmd = "exec:";
1398 cmd += argv[1];
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001399 argc -= 2;
1400 argv += 2;
1401 while (argc-- > 0) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001402 cmd += " ";
1403 cmd += escape_arg(*argv++);
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001404 }
1405
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001406 int fd = adb_connect(cmd.c_str());
Jeff Sharkey5d9d4342014-05-26 18:30:43 -07001407 if (fd < 0) {
1408 fprintf(stderr, "error: %s\n", adb_error());
1409 return -1;
1410 }
1411
1412 if (exec_in) {
1413 copy_to_file(STDIN_FILENO, fd);
1414 } else {
1415 copy_to_file(fd, STDOUT_FILENO);
1416 }
1417
1418 adb_close(fd);
1419 return 0;
1420 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001421 else if (!strcmp(argv[0], "kill-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001422 int fd;
1423 fd = _adb_connect("host:kill");
Riley Andrews98f58e82014-12-05 17:37:24 -08001424 if (fd == -1) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001425 fprintf(stderr,"* server not running *\n");
1426 return 1;
1427 }
1428 return 0;
1429 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001430 else if (!strcmp(argv[0], "sideload")) {
1431 if (argc != 2) return usage();
Doug Zongker71fe5842014-06-26 15:35:36 -07001432 if (adb_sideload_host(argv[1])) {
Doug Zongker447f0612012-01-09 14:54:53 -08001433 return 1;
1434 } else {
1435 return 0;
1436 }
1437 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001438 else if (!strcmp(argv[0], "remount") ||
1439 !strcmp(argv[0], "reboot") ||
1440 !strcmp(argv[0], "reboot-bootloader") ||
1441 !strcmp(argv[0], "tcpip") ||
1442 !strcmp(argv[0], "usb") ||
1443 !strcmp(argv[0], "root") ||
Dan Pasanen98858812014-10-06 12:57:20 -05001444 !strcmp(argv[0], "unroot") ||
Riley Andrewsc8514c82014-12-05 17:32:46 -08001445 !strcmp(argv[0], "disable-verity") ||
1446 !strcmp(argv[0], "enable-verity")) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001447 char command[100];
Tao Bao175b7bb2015-03-29 11:22:34 -07001448 if (!strcmp(argv[0], "reboot-bootloader")) {
Romain Guy311add42009-12-14 14:42:17 -08001449 snprintf(command, sizeof(command), "reboot:bootloader");
Tao Bao175b7bb2015-03-29 11:22:34 -07001450 } else if (argc > 1) {
Mike Lockwoodff196702009-08-24 15:58:40 -07001451 snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
Tao Bao175b7bb2015-03-29 11:22:34 -07001452 } else {
Mike Lockwoodff196702009-08-24 15:58:40 -07001453 snprintf(command, sizeof(command), "%s:", argv[0]);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001454 }
Tao Bao175b7bb2015-03-29 11:22:34 -07001455 return adb_connect_command(command);
The Android Open Source Projecte037fd72009-03-13 13:04:37 -07001456 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001457 else if (!strcmp(argv[0], "bugreport")) {
Dan Egnorc130ea72010-01-20 13:50:36 -08001458 if (argc != 1) return usage();
1459 do_cmd(ttype, serial, "shell", "bugreport", 0);
Mike Lockwoodf56d1b52009-09-03 14:54:58 -04001460 return 0;
1461 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001462 /* adb_command() wrapper commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001463 else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001464 char host_prefix[64];
David 'Digit' Turner25258692013-03-21 21:07:42 +01001465 char reverse = (char) !strcmp(argv[0], "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001466 char remove = 0;
1467 char remove_all = 0;
1468 char list = 0;
1469 char no_rebind = 0;
1470
1471 // Parse options here.
1472 while (argc > 1 && argv[1][0] == '-') {
1473 if (!strcmp(argv[1], "--list"))
1474 list = 1;
1475 else if (!strcmp(argv[1], "--remove"))
1476 remove = 1;
1477 else if (!strcmp(argv[1], "--remove-all"))
1478 remove_all = 1;
1479 else if (!strcmp(argv[1], "--no-rebind"))
1480 no_rebind = 1;
1481 else {
1482 return usage();
1483 }
1484 argc--;
1485 argv++;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001486 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001487
1488 // Ensure we can only use one option at a time.
1489 if (list + remove + remove_all + no_rebind > 1) {
1490 return usage();
1491 }
1492
1493 // Determine the <host-prefix> for this command.
David 'Digit' Turner25258692013-03-21 21:07:42 +01001494 if (reverse) {
1495 snprintf(host_prefix, sizeof host_prefix, "reverse");
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001496 } else {
David 'Digit' Turner25258692013-03-21 21:07:42 +01001497 if (serial) {
1498 snprintf(host_prefix, sizeof host_prefix, "host-serial:%s",
1499 serial);
1500 } else if (ttype == kTransportUsb) {
1501 snprintf(host_prefix, sizeof host_prefix, "host-usb");
1502 } else if (ttype == kTransportLocal) {
1503 snprintf(host_prefix, sizeof host_prefix, "host-local");
1504 } else {
1505 snprintf(host_prefix, sizeof host_prefix, "host");
1506 }
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001507 }
1508
1509 // Implement forward --list
1510 if (list) {
1511 if (argc != 1)
1512 return usage();
1513 snprintf(buf, sizeof buf, "%s:list-forward", host_prefix);
1514 char* forwards = adb_query(buf);
1515 if (forwards == NULL) {
1516 fprintf(stderr, "error: %s\n", adb_error());
1517 return 1;
1518 }
1519 printf("%s", forwards);
1520 free(forwards);
1521 return 0;
1522 }
1523
1524 // Implement forward --remove-all
1525 else if (remove_all) {
1526 if (argc != 1)
1527 return usage();
1528 snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix);
1529 }
1530
1531 // Implement forward --remove <local>
1532 else if (remove) {
1533 if (argc != 2)
1534 return usage();
1535 snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]);
1536 }
1537 // Or implement one of:
1538 // forward <local> <remote>
1539 // forward --no-rebind <local> <remote>
1540 else
1541 {
1542 if (argc != 3)
1543 return usage();
David 'Digit' Turnerf0e0c2e2015-01-22 09:07:41 +01001544 const char* command = no_rebind ? "forward:norebind" : "forward";
David 'Digit' Turner0d82fbf2012-11-14 15:01:55 +01001545 snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, argv[1], argv[2]);
1546 }
1547
Riley Andrews98f58e82014-12-05 17:37:24 -08001548 if (adb_command(buf)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001549 fprintf(stderr,"error: %s\n", adb_error());
1550 return 1;
1551 }
1552 return 0;
1553 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001554 /* do_sync_*() commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001555 else if (!strcmp(argv[0], "ls")) {
1556 if (argc != 2) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001557 return do_sync_ls(argv[1]);
1558 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001559 else if (!strcmp(argv[0], "push")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001560 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001561 int copy_attrs = 0; // unused
Mark Lindner76f2a932014-03-11 17:55:59 -07001562 const char* lpath = NULL, *rpath = NULL;
1563
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001564 parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001565
1566 if ((lpath != NULL) && (rpath != NULL)) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001567 return do_sync_push(lpath, rpath, show_progress);
Mark Lindner76f2a932014-03-11 17:55:59 -07001568 }
1569
1570 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001571 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001572 else if (!strcmp(argv[0], "pull")) {
Mark Lindner76f2a932014-03-11 17:55:59 -07001573 int show_progress = 0;
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001574 int copy_attrs = 0;
Mark Lindner76f2a932014-03-11 17:55:59 -07001575 const char* rpath = NULL, *lpath = ".";
1576
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001577 parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
Mark Lindner76f2a932014-03-11 17:55:59 -07001578
1579 if (rpath != NULL) {
Lajos Molnarde8ff4a2013-04-19 12:41:09 -07001580 return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
Joe Onorato00c0eea2010-01-05 13:42:25 -08001581 }
Mark Lindner76f2a932014-03-11 17:55:59 -07001582
1583 return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001584 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001585 else if (!strcmp(argv[0], "install")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001586 if (argc < 2) return usage();
1587 return install_app(ttype, serial, argc, argv);
1588 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001589 else if (!strcmp(argv[0], "install-multiple")) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001590 if (argc < 2) return usage();
1591 return install_multiple_app(ttype, serial, argc, argv);
1592 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001593 else if (!strcmp(argv[0], "uninstall")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001594 if (argc < 2) return usage();
1595 return uninstall_app(ttype, serial, argc, argv);
1596 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001597 else if (!strcmp(argv[0], "sync")) {
Dan Albertbac34742015-02-25 17:51:28 -08001598 const char* srcarg;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001599 char *system_srcpath, *data_srcpath, *vendor_srcpath, *oem_srcpath;
1600
Anthony Newnam705c9442010-02-22 08:36:49 -06001601 int listonly = 0;
1602
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001603 int ret;
Riley Andrews98f58e82014-12-05 17:37:24 -08001604 if (argc < 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001605 /* No local path was specified. */
1606 srcarg = NULL;
Anthony Newnam705c9442010-02-22 08:36:49 -06001607 } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) {
1608 listonly = 1;
1609 if (argc == 3) {
1610 srcarg = argv[2];
1611 } else {
1612 srcarg = NULL;
1613 }
Riley Andrews98f58e82014-12-05 17:37:24 -08001614 } else if (argc == 2) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001615 /* A local path or "android"/"data" arg was specified. */
1616 srcarg = argv[1];
1617 } else {
1618 return usage();
1619 }
Elliott Hughesec7a6672015-03-16 21:58:32 +00001620 ret = find_sync_dirs(srcarg, &system_srcpath, &data_srcpath, &vendor_srcpath,
1621 &oem_srcpath);
Riley Andrews98f58e82014-12-05 17:37:24 -08001622 if (ret != 0) return usage();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001623
Elliott Hughesec7a6672015-03-16 21:58:32 +00001624 if (system_srcpath != NULL)
1625 ret = do_sync_sync(system_srcpath, "/system", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001626 if (ret == 0 && vendor_srcpath != NULL)
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001627 ret = do_sync_sync(vendor_srcpath, "/vendor", listonly);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001628 if(ret == 0 && oem_srcpath != NULL)
1629 ret = do_sync_sync(oem_srcpath, "/oem", listonly);
Riley Andrews98f58e82014-12-05 17:37:24 -08001630 if (ret == 0 && data_srcpath != NULL)
Anthony Newnam705c9442010-02-22 08:36:49 -06001631 ret = do_sync_sync(data_srcpath, "/data", listonly);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001632
Elliott Hughesec7a6672015-03-16 21:58:32 +00001633 free(system_srcpath);
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001634 free(vendor_srcpath);
Elliott Hughesec7a6672015-03-16 21:58:32 +00001635 free(oem_srcpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001636 free(data_srcpath);
1637 return ret;
1638 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001639 /* passthrough commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001640 else if (!strcmp(argv[0],"get-state") ||
Scott Andersone109d262012-04-20 11:21:14 -07001641 !strcmp(argv[0],"get-serialno") ||
1642 !strcmp(argv[0],"get-devpath"))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001643 {
1644 char *tmp;
1645
1646 format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1647 tmp = adb_query(buf);
Riley Andrews98f58e82014-12-05 17:37:24 -08001648 if (tmp) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001649 printf("%s\n", tmp);
1650 return 0;
1651 } else {
1652 return 1;
1653 }
1654 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001655 /* other commands */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001656 else if (!strcmp(argv[0],"status-window")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001657 status_window(ttype, serial);
1658 return 0;
1659 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001660 else if (!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat") || !strcmp(argv[0],"longcat")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001661 return logcat(ttype, serial, argc, argv);
1662 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001663 else if (!strcmp(argv[0],"ppp")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001664 return ppp(argc, argv);
1665 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001666 else if (!strcmp(argv[0], "start-server")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001667 return adb_connect("host:start-server");
1668 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001669 else if (!strcmp(argv[0], "backup")) {
Christopher Tated2f54152011-04-21 12:53:28 -07001670 return backup(argc, argv);
1671 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001672 else if (!strcmp(argv[0], "restore")) {
Christopher Tate702967a2011-05-17 15:52:54 -07001673 return restore(argc, argv);
1674 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001675 else if (!strcmp(argv[0], "keygen")) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -08001676 if (argc < 2) return usage();
1677 return adb_auth_keygen(argv[1]);
1678 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001679 else if (!strcmp(argv[0], "jdwp")) {
Tao Bao175b7bb2015-03-29 11:22:34 -07001680 return adb_connect_command("jdwp");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001681 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001682 /* "adb /?" is a common idiom under Windows */
Riley Andrewsc8514c82014-12-05 17:32:46 -08001683 else if (!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001684 help();
1685 return 0;
1686 }
Riley Andrewsc8514c82014-12-05 17:32:46 -08001687 else if (!strcmp(argv[0], "version")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001688 version(stdout);
1689 return 0;
1690 }
1691
1692 usage();
1693 return 1;
1694}
1695
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001696#define MAX_ARGV_LENGTH 16
Dan Albertbac34742015-02-25 17:51:28 -08001697static int do_cmd(transport_type ttype, const char* serial, const char *cmd, ...)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001698{
Dan Albertbac34742015-02-25 17:51:28 -08001699 const char *argv[MAX_ARGV_LENGTH];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001700 int argc;
1701 va_list ap;
1702
1703 va_start(ap, cmd);
1704 argc = 0;
1705
1706 if (serial) {
1707 argv[argc++] = "-s";
1708 argv[argc++] = serial;
1709 } else if (ttype == kTransportUsb) {
1710 argv[argc++] = "-d";
1711 } else if (ttype == kTransportLocal) {
1712 argv[argc++] = "-e";
1713 }
1714
1715 argv[argc++] = cmd;
Alexander Ivchenko678bd2e2014-08-06 14:51:40 +04001716 while(argc < MAX_ARGV_LENGTH &&
1717 (argv[argc] = va_arg(ap, char*)) != 0) argc++;
1718 assert(argc < MAX_ARGV_LENGTH);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001719 va_end(ap);
1720
1721#if 0
1722 int n;
1723 fprintf(stderr,"argc = %d\n",argc);
1724 for(n = 0; n < argc; n++) {
1725 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1726 }
1727#endif
1728
1729 return adb_commandline(argc, argv);
1730}
1731
1732int find_sync_dirs(const char *srcarg,
Elliott Hughesec7a6672015-03-16 21:58:32 +00001733 char **system_srcdir_out, char **data_srcdir_out, char **vendor_srcdir_out,
1734 char **oem_srcdir_out)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001735{
Elliott Hughesec7a6672015-03-16 21:58:32 +00001736 char *system_srcdir = NULL, *data_srcdir = NULL, *vendor_srcdir = NULL, *oem_srcdir = NULL;
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001737 struct stat st;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001738
1739 if(srcarg == NULL) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001740 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001741 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001742 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001743 oem_srcdir = product_file("oem");
1744 // Check if vendor partition exists.
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001745 if (lstat(vendor_srcdir, &st) || !S_ISDIR(st.st_mode))
1746 vendor_srcdir = NULL;
Elliott Hughesec7a6672015-03-16 21:58:32 +00001747 // Check if oem partition exists.
1748 if (lstat(oem_srcdir, &st) || !S_ISDIR(st.st_mode))
1749 oem_srcdir = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001750 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001751 // srcarg may be "data", "system", "vendor", "oem" or NULL.
1752 // If srcarg is NULL, then all partitions are synced.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001753 if(strcmp(srcarg, "system") == 0) {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001754 system_srcdir = product_file("system");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001755 } else if(strcmp(srcarg, "data") == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001756 data_srcdir = product_file("data");
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001757 } else if(strcmp(srcarg, "vendor") == 0) {
1758 vendor_srcdir = product_file("vendor");
Elliott Hughesec7a6672015-03-16 21:58:32 +00001759 } else if(strcmp(srcarg, "oem") == 0) {
1760 oem_srcdir = product_file("oem");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001761 } else {
Elliott Hughesec7a6672015-03-16 21:58:32 +00001762 // It's not "system", "data", "vendor", or "oem".
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001763 return 1;
1764 }
1765 }
1766
Elliott Hughesec7a6672015-03-16 21:58:32 +00001767 if(system_srcdir_out != NULL)
1768 *system_srcdir_out = system_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001769 else
Elliott Hughesec7a6672015-03-16 21:58:32 +00001770 free(system_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001771
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001772 if(vendor_srcdir_out != NULL)
1773 *vendor_srcdir_out = vendor_srcdir;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001774 else
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001775 free(vendor_srcdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001776
Elliott Hughesec7a6672015-03-16 21:58:32 +00001777 if(oem_srcdir_out != NULL)
1778 *oem_srcdir_out = oem_srcdir;
1779 else
1780 free(oem_srcdir);
1781
Daniel Rosenberg686bce62014-06-30 20:29:40 -07001782 if(data_srcdir_out != NULL)
Elliott Hughesec7a6672015-03-16 21:58:32 +00001783 *data_srcdir_out = data_srcdir;
1784 else
1785 free(data_srcdir);
1786
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001787 return 0;
1788}
1789
Dan Albertbac34742015-02-25 17:51:28 -08001790static int pm_command(transport_type transport, const char* serial,
1791 int argc, const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001792{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001793 std::string cmd = "shell:pm";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001794
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001795 while (argc-- > 0) {
1796 cmd += " ";
1797 cmd += escape_arg(*argv++);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001798 }
1799
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001800 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001801 return 0;
1802}
1803
Dan Albertbac34742015-02-25 17:51:28 -08001804int uninstall_app(transport_type transport, const char* serial, int argc,
1805 const char** argv)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001806{
1807 /* if the user choose the -k option, we refuse to do it until devices are
1808 out with the option to uninstall the remaining data somehow (adb/ui) */
1809 if (argc == 3 && strcmp(argv[1], "-k") == 0)
1810 {
1811 printf(
1812 "The -k option uninstalls the application while retaining the data/cache.\n"
1813 "At the moment, there is no way to remove the remaining data.\n"
1814 "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1815 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1816 return -1;
1817 }
1818
1819 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1820 return pm_command(transport, serial, argc, argv);
1821}
1822
Dan Albertbac34742015-02-25 17:51:28 -08001823static int delete_file(transport_type transport, const char* serial, char* filename)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001824{
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001825 std::string cmd = "shell:rm -f " + escape_arg(filename);
1826 send_shell_command(transport, serial, cmd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001827 return 0;
1828}
1829
Kenny Root597ea5b2011-08-05 11:19:45 -07001830static const char* get_basename(const char* filename)
1831{
1832 const char* basename = adb_dirstop(filename);
1833 if (basename) {
1834 basename++;
1835 return basename;
1836 } else {
1837 return filename;
1838 }
1839}
1840
Dan Albertbac34742015-02-25 17:51:28 -08001841int install_app(transport_type transport, const char* serial, int argc,
1842 const char** argv)
Kenny Root597ea5b2011-08-05 11:19:45 -07001843{
1844 static const char *const DATA_DEST = "/data/local/tmp/%s";
1845 static const char *const SD_DEST = "/sdcard/tmp/%s";
1846 const char* where = DATA_DEST;
Kenny Root597ea5b2011-08-05 11:19:45 -07001847 int i;
Jeff Sharkey960df972014-06-09 17:30:57 -07001848 struct stat sb;
Kenny Root597ea5b2011-08-05 11:19:45 -07001849
1850 for (i = 1; i < argc; i++) {
Jeff Sharkey960df972014-06-09 17:30:57 -07001851 if (!strcmp(argv[i], "-s")) {
Kenny Root597ea5b2011-08-05 11:19:45 -07001852 where = SD_DEST;
1853 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001854 }
1855
Jeff Sharkey960df972014-06-09 17:30:57 -07001856 // Find last APK argument.
1857 // All other arguments passed through verbatim.
1858 int last_apk = -1;
1859 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001860 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001861 char* dot = strrchr(file, '.');
1862 if (dot && !strcasecmp(dot, ".apk")) {
1863 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1864 fprintf(stderr, "Invalid APK file: %s\n", file);
1865 return -1;
1866 }
1867
1868 last_apk = i;
1869 break;
1870 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001871 }
1872
Jeff Sharkey960df972014-06-09 17:30:57 -07001873 if (last_apk == -1) {
1874 fprintf(stderr, "Missing APK file\n");
1875 return -1;
Kenny Root597ea5b2011-08-05 11:19:45 -07001876 }
1877
Dan Albertbac34742015-02-25 17:51:28 -08001878 const char* apk_file = argv[last_apk];
Jeff Sharkey960df972014-06-09 17:30:57 -07001879 char apk_dest[PATH_MAX];
Kenny Root597ea5b2011-08-05 11:19:45 -07001880 snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001881 int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
Kenny Root597ea5b2011-08-05 11:19:45 -07001882 if (err) {
Kenny Root60733e92012-03-26 16:14:02 -07001883 goto cleanup_apk;
Kenny Root597ea5b2011-08-05 11:19:45 -07001884 } else {
Jeff Sharkey960df972014-06-09 17:30:57 -07001885 argv[last_apk] = apk_dest; /* destination name, not source location */
Kenny Root597ea5b2011-08-05 11:19:45 -07001886 }
1887
1888 pm_command(transport, serial, argc, argv);
1889
Kenny Root60733e92012-03-26 16:14:02 -07001890cleanup_apk:
Jeff Sharkey960df972014-06-09 17:30:57 -07001891 delete_file(transport, serial, apk_dest);
1892 return err;
1893}
1894
Dan Albertbac34742015-02-25 17:51:28 -08001895int install_multiple_app(transport_type transport, const char* serial, int argc,
1896 const char** argv)
Jeff Sharkey960df972014-06-09 17:30:57 -07001897{
Jeff Sharkey960df972014-06-09 17:30:57 -07001898 int i;
1899 struct stat sb;
1900 unsigned long long total_size = 0;
1901
1902 // Find all APK arguments starting at end.
1903 // All other arguments passed through verbatim.
1904 int first_apk = -1;
1905 for (i = argc - 1; i >= 0; i--) {
Dan Albertbac34742015-02-25 17:51:28 -08001906 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001907 char* dot = strrchr(file, '.');
1908 if (dot && !strcasecmp(dot, ".apk")) {
1909 if (stat(file, &sb) == -1 || !S_ISREG(sb.st_mode)) {
1910 fprintf(stderr, "Invalid APK file: %s\n", file);
1911 return -1;
1912 }
1913
1914 total_size += sb.st_size;
1915 first_apk = i;
1916 } else {
1917 break;
1918 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001919 }
1920
Jeff Sharkey960df972014-06-09 17:30:57 -07001921 if (first_apk == -1) {
1922 fprintf(stderr, "Missing APK file\n");
1923 return 1;
1924 }
Kenny Root597ea5b2011-08-05 11:19:45 -07001925
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001926 std::string cmd = android::base::StringPrintf("exec:pm install-create -S %lld", total_size);
Jeff Sharkey960df972014-06-09 17:30:57 -07001927 for (i = 1; i < first_apk; i++) {
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001928 cmd += " ";
1929 cmd += escape_arg(argv[i]);
Jeff Sharkey960df972014-06-09 17:30:57 -07001930 }
1931
1932 // Create install session
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001933 int fd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001934 if (fd < 0) {
1935 fprintf(stderr, "Connect error for create: %s\n", adb_error());
1936 return -1;
1937 }
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001938 char buf[BUFSIZ];
Jeff Sharkey960df972014-06-09 17:30:57 -07001939 read_status_line(fd, buf, sizeof(buf));
1940 adb_close(fd);
1941
1942 int session_id = -1;
1943 if (!strncmp("Success", buf, 7)) {
1944 char* start = strrchr(buf, '[');
1945 char* end = strrchr(buf, ']');
1946 if (start && end) {
1947 *end = '\0';
1948 session_id = strtol(start + 1, NULL, 10);
1949 }
1950 }
1951 if (session_id < 0) {
1952 fprintf(stderr, "Failed to create session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07001953 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001954 return -1;
1955 }
1956
1957 // Valid session, now stream the APKs
1958 int success = 1;
1959 for (i = first_apk; i < argc; i++) {
Dan Albertbac34742015-02-25 17:51:28 -08001960 const char* file = argv[i];
Jeff Sharkey960df972014-06-09 17:30:57 -07001961 if (stat(file, &sb) == -1) {
1962 fprintf(stderr, "Failed to stat %s\n", file);
1963 success = 0;
1964 goto finalize_session;
1965 }
1966
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001967 std::string cmd = android::base::StringPrintf("exec:pm install-write -S %lld %d %d_%s -",
Jeff Sharkeyc03064e2014-07-14 13:57:54 -07001968 (long long int) sb.st_size, session_id, i, get_basename(file));
Jeff Sharkey960df972014-06-09 17:30:57 -07001969
1970 int localFd = adb_open(file, O_RDONLY);
1971 if (localFd < 0) {
1972 fprintf(stderr, "Failed to open %s: %s\n", file, adb_error());
1973 success = 0;
1974 goto finalize_session;
1975 }
1976
Elliott Hughes2baae3a2015-04-17 10:59:34 -07001977 int remoteFd = adb_connect(cmd.c_str());
Jeff Sharkey960df972014-06-09 17:30:57 -07001978 if (remoteFd < 0) {
1979 fprintf(stderr, "Connect error for write: %s\n", adb_error());
1980 adb_close(localFd);
1981 success = 0;
1982 goto finalize_session;
1983 }
1984
1985 copy_to_file(localFd, remoteFd);
1986 read_status_line(remoteFd, buf, sizeof(buf));
1987
1988 adb_close(localFd);
1989 adb_close(remoteFd);
1990
1991 if (strncmp("Success", buf, 7)) {
1992 fprintf(stderr, "Failed to write %s\n", file);
Christopher Tate71bbc672014-07-14 16:45:13 -07001993 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07001994 success = 0;
1995 goto finalize_session;
1996 }
1997 }
1998
1999finalize_session:
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002000 // Commit session if we streamed everything okay; otherwise abandon
Jeff Sharkey960df972014-06-09 17:30:57 -07002001 if (success) {
2002 snprintf(buf, sizeof(buf), "exec:pm install-commit %d", session_id);
2003 } else {
Jeff Sharkeyac77e1f2014-07-25 09:58:25 -07002004 snprintf(buf, sizeof(buf), "exec:pm install-abandon %d", session_id);
Jeff Sharkey960df972014-06-09 17:30:57 -07002005 }
2006
2007 fd = adb_connect(buf);
2008 if (fd < 0) {
2009 fprintf(stderr, "Connect error for finalize: %s\n", adb_error());
2010 return -1;
2011 }
2012 read_status_line(fd, buf, sizeof(buf));
2013 adb_close(fd);
2014
2015 if (!strncmp("Success", buf, 7)) {
Christopher Tate71bbc672014-07-14 16:45:13 -07002016 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002017 return 0;
2018 } else {
2019 fprintf(stderr, "Failed to finalize session\n");
Christopher Tate71bbc672014-07-14 16:45:13 -07002020 fputs(buf, stderr);
Jeff Sharkey960df972014-06-09 17:30:57 -07002021 return -1;
2022 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002023}