blob: 3d418cb92351ddb5bd74e8dbea517cffc547a31d [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Yabin Cuiaed3c612015-09-22 15:52:57 -070017#define TRACE_TAG SERVICES
Dan Albert33134262015-03-19 15:21:08 -070018
19#include "sysdeps.h"
20
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080021#include <errno.h>
Dan Albert76649012015-02-24 15:51:19 -080022#include <stddef.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27#ifndef _WIN32
28#include <netdb.h>
29#include <netinet/in.h>
30#include <sys/ioctl.h>
31#include <unistd.h>
32#endif
33
Josh Gaoe1dacfc2017-04-12 17:00:49 -070034#include <thread>
35
Elliott Hughes4f713192015-12-04 22:00:26 -080036#include <android-base/file.h>
David Pursell706955f2016-01-21 08:40:59 -080037#include <android-base/parsenetaddress.h>
Elliott Hughes4f713192015-12-04 22:00:26 -080038#include <android-base/stringprintf.h>
39#include <android-base/strings.h>
Luis Hector Chavez095792c2018-07-18 19:40:12 -070040#include <android-base/unique_fd.h>
Elliott Hughes381cfa92015-07-23 17:12:58 -070041#include <cutils/sockets.h>
Elliott Hughes6c34bba2015-04-17 20:11:08 -070042
Dan Albert76649012015-02-24 15:51:19 -080043#if !ADB_HOST
Elliott Hughesffdec182016-09-23 15:40:03 -070044#include <android-base/properties.h>
Tao Bao40e0ec92017-01-05 18:01:01 -080045#include <bootloader_message/bootloader_message.h>
Mark Salyzyn97787a02016-03-28 15:52:13 -070046#include <cutils/android_reboot.h>
Steven Morelandd73be1b2017-04-13 23:48:57 -070047#include <log/log_properties.h>
Dan Albert76649012015-02-24 15:51:19 -080048#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080049
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050#include "adb.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080051#include "adb_io.h"
Elliott Hughes3d5f60d2015-07-18 12:21:30 -070052#include "adb_utils.h"
Luis Hector Chavez095792c2018-07-18 19:40:12 -070053#if !ADB_HOST
54#include "daemon/framebuffer_service.h"
55#include "daemon/set_verity_enable_state_service.h"
56#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080057#include "file_sync_service.h"
Elliott Hughesec7a6672015-03-16 21:58:32 +000058#include "remount_service.h"
David Pursell70ef7b42015-09-30 13:35:42 -070059#include "services.h"
David Pursell80f67022015-08-28 15:08:49 -070060#include "shell_service.h"
Josh Gaocfb21412016-08-24 18:38:44 -070061#include "socket_spec.h"
Josh Gao09855472016-02-19 10:42:40 -080062#include "sysdeps.h"
Dan Albert76649012015-02-24 15:51:19 -080063#include "transport.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080064
Luis Hector Chavez095792c2018-07-18 19:40:12 -070065namespace {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080066
Luis Hector Chavez095792c2018-07-18 19:40:12 -070067void service_bootstrap_func(std::string service_name,
68 std::function<void(android::base::unique_fd)> func,
69 android::base::unique_fd fd) {
70 adb_thread_setname(android::base::StringPrintf("%s svc %d", service_name.c_str(), fd.get()));
71 func(std::move(fd));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080072}
73
Benoit Goby9470c2f2013-02-20 15:04:53 -080074#if !ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080075
Luis Hector Chavez095792c2018-07-18 19:40:12 -070076void restart_root_service(android::base::unique_fd fd) {
The Android Open Source Projecte037fd72009-03-13 13:04:37 -070077 if (getuid() == 0) {
Luis Hector Chavez095792c2018-07-18 19:40:12 -070078 WriteFdExactly(fd.get(), "adbd is already running as root\n");
79 return;
The Android Open Source Projecte037fd72009-03-13 13:04:37 -070080 }
Luis Hector Chavez095792c2018-07-18 19:40:12 -070081 if (!__android_log_is_debuggable()) {
82 WriteFdExactly(fd.get(), "adbd cannot run as root in production builds\n");
83 return;
84 }
85
86 android::base::SetProperty("service.adb.root", "1");
87 WriteFdExactly(fd.get(), "restarting adbd as root\n");
The Android Open Source Projecte037fd72009-03-13 13:04:37 -070088}
89
Luis Hector Chavez095792c2018-07-18 19:40:12 -070090void restart_unroot_service(android::base::unique_fd fd) {
Dan Pasanen98858812014-10-06 12:57:20 -050091 if (getuid() != 0) {
Luis Hector Chavez095792c2018-07-18 19:40:12 -070092 WriteFdExactly(fd.get(), "adbd not running as root\n");
93 return;
Dan Pasanen98858812014-10-06 12:57:20 -050094 }
Luis Hector Chavez095792c2018-07-18 19:40:12 -070095 android::base::SetProperty("service.adb.root", "0");
96 WriteFdExactly(fd.get(), "restarting adbd as non root\n");
Dan Pasanen98858812014-10-06 12:57:20 -050097}
98
Luis Hector Chavez095792c2018-07-18 19:40:12 -070099void restart_tcp_service(android::base::unique_fd fd, int port) {
Mike Lockwoodff196702009-08-24 15:58:40 -0700100 if (port <= 0) {
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700101 WriteFdFmt(fd.get(), "invalid port %d\n", port);
Mike Lockwoodff196702009-08-24 15:58:40 -0700102 return;
103 }
104
Elliott Hughesffdec182016-09-23 15:40:03 -0700105 android::base::SetProperty("service.adb.tcp.port", android::base::StringPrintf("%d", port));
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700106 WriteFdFmt(fd.get(), "restarting in TCP mode port: %d\n", port);
Mike Lockwoodff196702009-08-24 15:58:40 -0700107}
108
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700109void restart_usb_service(android::base::unique_fd fd) {
Elliott Hughesffdec182016-09-23 15:40:03 -0700110 android::base::SetProperty("service.adb.tcp.port", "0");
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700111 WriteFdExactly(fd.get(), "restarting in USB mode\n");
Mike Lockwoodff196702009-08-24 15:58:40 -0700112}
113
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700114bool reboot_service_impl(android::base::unique_fd fd, const std::string& arg) {
115 std::string reboot_arg = arg;
Tao Bao175b7bb2015-03-29 11:22:34 -0700116 bool auto_reboot = false;
117
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700118 if (reboot_arg == "sideload-auto-reboot") {
Tao Bao175b7bb2015-03-29 11:22:34 -0700119 auto_reboot = true;
120 reboot_arg = "sideload";
121 }
122
Tao Bao175b7bb2015-03-29 11:22:34 -0700123 // It reboots into sideload mode by setting "--sideload" or "--sideload_auto_reboot"
124 // in the command file.
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700125 if (reboot_arg == "sideload") {
Tao Bao175b7bb2015-03-29 11:22:34 -0700126 if (getuid() != 0) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700127 WriteFdExactly(fd, "'adb root' is required for 'adb reboot sideload'.\n");
Tao Bao175b7bb2015-03-29 11:22:34 -0700128 return false;
129 }
130
Tao Bao40e0ec92017-01-05 18:01:01 -0800131 const std::vector<std::string> options = {
132 auto_reboot ? "--sideload_auto_reboot" : "--sideload"
133 };
134 std::string err;
135 if (!write_bootloader_message(options, &err)) {
136 D("Failed to set bootloader message: %s", err.c_str());
Tao Bao175b7bb2015-03-29 11:22:34 -0700137 return false;
138 }
139
140 reboot_arg = "recovery";
141 }
Mike Lockwoodee156622009-08-04 20:37:51 -0400142
143 sync();
Mike Lockwoodd969faa2010-02-24 16:07:23 -0500144
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700145 if (reboot_arg.empty()) reboot_arg = "adb";
146 std::string reboot_string = android::base::StringPrintf("reboot,%s", reboot_arg.c_str());
Elliott Hughesffdec182016-09-23 15:40:03 -0700147 if (!android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_string)) {
148 WriteFdFmt(fd, "reboot (%s) failed\n", reboot_string.c_str());
Tao Bao175b7bb2015-03-29 11:22:34 -0700149 return false;
Mike Lockwoodee156622009-08-04 20:37:51 -0400150 }
Tao Bao175b7bb2015-03-29 11:22:34 -0700151
152 return true;
153}
154
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700155void reboot_service(android::base::unique_fd fd, const std::string& arg) {
156 if (!reboot_service_impl(std::move(fd), arg)) {
157 return;
Tao Bao175b7bb2015-03-29 11:22:34 -0700158 }
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700159 // Don't return early. Give the reboot command time to take effect
160 // to avoid messing up scripts which do "adb reboot && adb wait-for-device"
161 while (true) {
162 pause();
163 }
Mike Lockwoodee156622009-08-04 20:37:51 -0400164}
165
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700166void reconnect_service(android::base::unique_fd fd, atransport* t) {
Yabin Cui1f4ec192016-04-05 13:50:44 -0700167 WriteFdExactly(fd, "done");
Yabin Cui1f4ec192016-04-05 13:50:44 -0700168 kick_transport(t);
169}
170
Josh Gao44899ee2018-04-13 12:17:03 -0700171int reverse_service(const char* command, atransport* transport) {
Yabin Cuifbfa8402015-10-30 18:37:26 -0700172 int s[2];
173 if (adb_socketpair(s)) {
174 PLOG(ERROR) << "cannot create service socket pair.";
175 return -1;
David 'Digit' Turner25258692013-03-21 21:07:42 +0100176 }
Yabin Cuifbfa8402015-10-30 18:37:26 -0700177 VLOG(SERVICES) << "service socketpair: " << s[0] << ", " << s[1];
Josh Gao44899ee2018-04-13 12:17:03 -0700178 if (handle_forward_request(command, transport, s[1]) < 0) {
Yabin Cuifbfa8402015-10-30 18:37:26 -0700179 SendFail(s[1], "not a reverse forwarding command");
180 }
181 adb_close(s[1]);
182 return s[0];
David 'Digit' Turner25258692013-03-21 21:07:42 +0100183}
184
David Pursell4e2fd362015-09-22 10:43:08 -0700185// Shell service string can look like:
David Pursell70ef7b42015-09-30 13:35:42 -0700186// shell[,arg1,arg2,...]:[command]
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700187int ShellService(const std::string& args, const atransport* transport) {
David Pursell4e2fd362015-09-22 10:43:08 -0700188 size_t delimiter_index = args.find(':');
189 if (delimiter_index == std::string::npos) {
190 LOG(ERROR) << "No ':' found in shell service arguments: " << args;
191 return -1;
192 }
David Pursell70ef7b42015-09-30 13:35:42 -0700193
David Pursell4e2fd362015-09-22 10:43:08 -0700194 const std::string service_args = args.substr(0, delimiter_index);
195 const std::string command = args.substr(delimiter_index + 1);
196
David Pursell70ef7b42015-09-30 13:35:42 -0700197 // Defaults:
198 // PTY for interactive, raw for non-interactive.
199 // No protocol.
Elliott Hughes18ddf5c2015-11-16 10:55:34 -0800200 // $TERM set to "dumb".
David Pursell70ef7b42015-09-30 13:35:42 -0700201 SubprocessType type(command.empty() ? SubprocessType::kPty
202 : SubprocessType::kRaw);
203 SubprocessProtocol protocol = SubprocessProtocol::kNone;
Elliott Hughes18ddf5c2015-11-16 10:55:34 -0800204 std::string terminal_type = "dumb";
David Pursell4e2fd362015-09-22 10:43:08 -0700205
David Pursell70ef7b42015-09-30 13:35:42 -0700206 for (const std::string& arg : android::base::Split(service_args, ",")) {
207 if (arg == kShellServiceArgRaw) {
208 type = SubprocessType::kRaw;
209 } else if (arg == kShellServiceArgPty) {
210 type = SubprocessType::kPty;
211 } else if (arg == kShellServiceArgShellProtocol) {
212 protocol = SubprocessProtocol::kShell;
Elliott Hughes18ddf5c2015-11-16 10:55:34 -0800213 } else if (android::base::StartsWith(arg, "TERM=")) {
214 terminal_type = arg.substr(5);
215 } else if (!arg.empty()) {
216 // This is not an error to allow for future expansion.
217 LOG(WARNING) << "Ignoring unknown shell service argument: " << arg;
David Pursell70ef7b42015-09-30 13:35:42 -0700218 }
219 }
David Pursell4e2fd362015-09-22 10:43:08 -0700220
Elliott Hughes18ddf5c2015-11-16 10:55:34 -0800221 return StartSubprocess(command.c_str(), terminal_type.c_str(), type, protocol);
David Pursell4e2fd362015-09-22 10:43:08 -0700222}
223
224#endif // !ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800225
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700226android::base::unique_fd create_service_thread(const char* service_name,
227 std::function<void(android::base::unique_fd)> func) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800228 int s[2];
Dan Albertbac34742015-02-25 17:51:28 -0800229 if (adb_socketpair(s)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800230 printf("cannot create service socket pair\n");
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700231 return android::base::unique_fd();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800232 }
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700233 D("socketpair: (%d,%d)", s[0], s[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800234
Jerry Zhang2f8c60b2017-02-10 17:45:27 -0800235#if !ADB_HOST
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700236 if (strcmp(service_name, "sync") == 0) {
Jerry Zhang2f8c60b2017-02-10 17:45:27 -0800237 // Set file sync service socket to maximum size
238 int max_buf = LINUX_MAX_SOCKET_SIZE;
239 adb_setsockopt(s[0], SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(max_buf));
240 adb_setsockopt(s[1], SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(max_buf));
241 }
242#endif // !ADB_HOST
243
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700244 std::thread(service_bootstrap_func, service_name, func, android::base::unique_fd(s[1])).detach();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800245
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700246 D("service thread started, %d:%d",s[0], s[1]);
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700247 return android::base::unique_fd(s[0]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800248}
249
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700250} // namespace
251
Josh Gao44899ee2018-04-13 12:17:03 -0700252int service_to_fd(const char* name, atransport* transport) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800253 int ret = -1;
254
Josh Gaocfb21412016-08-24 18:38:44 -0700255 if (is_socket_spec(name)) {
256 std::string error;
257 ret = socket_spec_connect(name, &error);
258 if (ret < 0) {
259 LOG(ERROR) << "failed to connect to socket '" << name << "': " << error;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800260 }
Benoit Goby9470c2f2013-02-20 15:04:53 -0800261#if !ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800262 } else if(!strncmp("dev:", name, 4)) {
Nick Kralevichfe8d7f42014-07-18 20:57:35 -0700263 ret = unix_open(name + 4, O_RDWR | O_CLOEXEC);
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700264 } else if (!strncmp(name, "framebuffer:", 12)) {
265 ret = create_service_thread("fb", framebuffer_service).release();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800266 } else if (!strncmp(name, "jdwp:", 5)) {
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700267 ret = create_jdwp_connection_fd(atoi(name + 5));
268 } else if (!strncmp(name, "shell", 5)) {
David Pursell4e2fd362015-09-22 10:43:08 -0700269 ret = ShellService(name + 5, transport);
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700270 } else if (!strncmp(name, "exec:", 5)) {
Elliott Hughes18ddf5c2015-11-16 10:55:34 -0800271 ret = StartSubprocess(name + 5, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700272 } else if (!strncmp(name, "sync:", 5)) {
273 ret = create_service_thread("sync", file_sync_service).release();
274 } else if (!strncmp(name, "remount:", 8)) {
275 std::string options(name + strlen("remount:"));
276 ret = create_service_thread("remount",
277 std::bind(remount_service, std::placeholders::_1, options))
278 .release();
279 } else if (!strncmp(name, "reboot:", 7)) {
280 std::string arg(name + strlen("reboot:"));
281 ret = create_service_thread("reboot", std::bind(reboot_service, std::placeholders::_1, arg))
282 .release();
283 } else if (!strncmp(name, "root:", 5)) {
284 ret = create_service_thread("root", restart_root_service).release();
285 } else if (!strncmp(name, "unroot:", 7)) {
286 ret = create_service_thread("unroot", restart_unroot_service).release();
287 } else if (!strncmp(name, "backup:", 7)) {
288 ret = StartSubprocess(
289 android::base::StringPrintf("/system/bin/bu backup %s", (name + 7)).c_str(),
290 nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
291 } else if (!strncmp(name, "restore:", 8)) {
Elliott Hughes18ddf5c2015-11-16 10:55:34 -0800292 ret = StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw,
David Pursell0955c662015-08-31 10:42:13 -0700293 SubprocessProtocol::kNone);
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700294 } else if (!strncmp(name, "tcpip:", 6)) {
Mike Lockwoodff196702009-08-24 15:58:40 -0700295 int port;
Spencer Low943ef232015-01-25 17:38:36 -0800296 if (sscanf(name + 6, "%d", &port) != 1) {
Elliott Hughes19d80b82015-07-21 16:13:40 -0700297 return -1;
Mike Lockwoodff196702009-08-24 15:58:40 -0700298 }
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700299 ret = create_service_thread("tcp",
300 std::bind(restart_tcp_service, std::placeholders::_1, port))
301 .release();
302 } else if (!strncmp(name, "usb:", 4)) {
303 ret = create_service_thread("usb", restart_usb_service).release();
David 'Digit' Turner25258692013-03-21 21:07:42 +0100304 } else if (!strncmp(name, "reverse:", 8)) {
Josh Gao44899ee2018-04-13 12:17:03 -0700305 ret = reverse_service(name + 8, transport);
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700306 } else if (!strncmp(name, "disable-verity:", 15)) {
307 ret = create_service_thread("verity-on", std::bind(set_verity_enabled_state_service,
308 std::placeholders::_1, false))
309 .release();
310 } else if (!strncmp(name, "enable-verity:", 15)) {
311 ret = create_service_thread("verity-off", std::bind(set_verity_enabled_state_service,
312 std::placeholders::_1, true))
313 .release();
Yabin Cui1f4ec192016-04-05 13:50:44 -0700314 } else if (!strcmp(name, "reconnect")) {
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700315 ret = create_service_thread("reconnect",
316 std::bind(reconnect_service, std::placeholders::_1, transport))
317 .release();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800318#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800319 }
320 if (ret >= 0) {
321 close_on_exec(ret);
322 }
323 return ret;
324}
325
326#if ADB_HOST
327struct state_info {
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700328 TransportType transport_type;
Leo Sartre1fbc9db2015-11-27 18:56:48 +0100329 std::string serial;
Josh Gaob122b172017-08-16 16:57:01 -0700330 TransportId transport_id;
Dan Albertdcd78a12015-05-18 16:43:57 -0700331 ConnectionState state;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800332};
333
Leo Sartre1fbc9db2015-11-27 18:56:48 +0100334static void wait_for_state(int fd, void* data) {
335 std::unique_ptr<state_info> sinfo(reinterpret_cast<state_info*>(data));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800336
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700337 D("wait_for_state %d", sinfo->state);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800338
Elliott Hughes8d28e192015-10-07 14:55:10 -0700339 while (true) {
340 bool is_ambiguous = false;
341 std::string error = "unknown error";
Yi Kongaed415c2018-07-13 18:15:16 -0700342 const char* serial = sinfo->serial.length() ? sinfo->serial.c_str() : nullptr;
Josh Gaob122b172017-08-16 16:57:01 -0700343 atransport* t = acquire_one_transport(sinfo->transport_type, serial, sinfo->transport_id,
344 &is_ambiguous, &error);
Yabin Cuib5e11412017-03-10 16:01:01 -0800345 if (t != nullptr && (sinfo->state == kCsAny || sinfo->state == t->GetConnectionState())) {
Elliott Hughes8d28e192015-10-07 14:55:10 -0700346 SendOkay(fd);
347 break;
348 } else if (!is_ambiguous) {
Josh Gao09855472016-02-19 10:42:40 -0800349 adb_pollfd pfd = {.fd = fd, .events = POLLIN };
350 int rc = adb_poll(&pfd, 1, 1000);
351 if (rc < 0) {
352 SendFail(fd, error);
353 break;
354 } else if (rc > 0 && (pfd.revents & POLLHUP) != 0) {
355 // The other end of the socket is closed, probably because the other side was
356 // terminated, bail out.
357 break;
358 }
359
Elliott Hughes8d28e192015-10-07 14:55:10 -0700360 // Try again...
361 } else {
362 SendFail(fd, error);
363 break;
364 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800365 }
366
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800367 adb_close(fd);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700368 D("wait_for_state is done");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800369}
Benoit Goby1c45ee92013-03-29 18:22:36 -0700370
Elliott Hughese67f1f82015-04-30 17:32:03 -0700371void connect_emulator(const std::string& port_spec, std::string* response) {
372 std::vector<std::string> pieces = android::base::Split(port_spec, ",");
373 if (pieces.size() != 2) {
374 *response = android::base::StringPrintf("unable to parse '%s' as <console port>,<adb port>",
375 port_spec.c_str());
Benoit Goby1c45ee92013-03-29 18:22:36 -0700376 return;
377 }
378
Yi Kongaed415c2018-07-13 18:15:16 -0700379 int console_port = strtol(pieces[0].c_str(), nullptr, 0);
380 int adb_port = strtol(pieces[1].c_str(), nullptr, 0);
Elliott Hughese67f1f82015-04-30 17:32:03 -0700381 if (console_port <= 0 || adb_port <= 0) {
382 *response = android::base::StringPrintf("Invalid port numbers: %s", port_spec.c_str());
Benoit Goby1c45ee92013-03-29 18:22:36 -0700383 return;
384 }
385
Elliott Hughese67f1f82015-04-30 17:32:03 -0700386 // Check if the emulator is already known.
387 // Note: There's a small but harmless race condition here: An emulator not
388 // present just yet could be registered by another invocation right
389 // after doing this check here. However, local_connect protects
390 // against double-registration too. From here, a better error message
391 // can be produced. In the case of the race condition, the very specific
392 // error message won't be shown, but the data doesn't get corrupted.
Benoit Goby1c45ee92013-03-29 18:22:36 -0700393 atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port);
Elliott Hughese67f1f82015-04-30 17:32:03 -0700394 if (known_emulator != nullptr) {
395 *response = android::base::StringPrintf("Emulator already registered on port %d", adb_port);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700396 return;
397 }
398
Elliott Hughese67f1f82015-04-30 17:32:03 -0700399 // Preconditions met, try to connect to the emulator.
Elliott Hughes381cfa92015-07-23 17:12:58 -0700400 std::string error;
401 if (!local_connect_arbitrary_ports(console_port, adb_port, &error)) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700402 *response = android::base::StringPrintf("Connected to emulator on ports %d,%d",
403 console_port, adb_port);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700404 } else {
Elliott Hughes381cfa92015-07-23 17:12:58 -0700405 *response = android::base::StringPrintf("Could not connect to emulator on ports %d,%d: %s",
406 console_port, adb_port, error.c_str());
Benoit Goby1c45ee92013-03-29 18:22:36 -0700407 }
408}
409
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700410static void connect_service(android::base::unique_fd fd, std::string host) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700411 std::string response;
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700412 if (!strncmp(host.c_str(), "emu:", 4)) {
413 connect_emulator(host.c_str() + 4, &response);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700414 } else {
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700415 connect_device(host.c_str(), &response);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700416 }
417
418 // Send response for emulator and device
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700419 SendProtocolString(fd.get(), response);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700420}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800421#endif
422
423#if ADB_HOST
Josh Gaob122b172017-08-16 16:57:01 -0700424asocket* host_service_to_socket(const char* name, const char* serial, TransportId transport_id) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800425 if (!strcmp(name,"track-devices")) {
Josh Gaob0c18022017-08-14 18:57:54 -0700426 return create_device_tracker(false);
427 } else if (!strcmp(name, "track-devices-l")) {
428 return create_device_tracker(true);
Leo Sartre1fbc9db2015-11-27 18:56:48 +0100429 } else if (android::base::StartsWith(name, "wait-for-")) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800430 name += strlen("wait-for-");
431
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700432 std::unique_ptr<state_info> sinfo = std::make_unique<state_info>();
Leo Sartre1fbc9db2015-11-27 18:56:48 +0100433 if (sinfo == nullptr) {
434 fprintf(stderr, "couldn't allocate state_info: %s", strerror(errno));
435 return nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800436 }
437
Leo Sartre1fbc9db2015-11-27 18:56:48 +0100438 if (serial) sinfo->serial = serial;
Josh Gaob122b172017-08-16 16:57:01 -0700439 sinfo->transport_id = transport_id;
Leo Sartre1fbc9db2015-11-27 18:56:48 +0100440
441 if (android::base::StartsWith(name, "local")) {
442 name += strlen("local");
443 sinfo->transport_type = kTransportLocal;
444 } else if (android::base::StartsWith(name, "usb")) {
445 name += strlen("usb");
446 sinfo->transport_type = kTransportUsb;
447 } else if (android::base::StartsWith(name, "any")) {
448 name += strlen("any");
449 sinfo->transport_type = kTransportAny;
450 } else {
451 return nullptr;
452 }
453
454 if (!strcmp(name, "-device")) {
455 sinfo->state = kCsDevice;
456 } else if (!strcmp(name, "-recovery")) {
457 sinfo->state = kCsRecovery;
458 } else if (!strcmp(name, "-sideload")) {
459 sinfo->state = kCsSideload;
460 } else if (!strcmp(name, "-bootloader")) {
461 sinfo->state = kCsBootloader;
Josh Gao86441c32016-04-13 12:18:58 -0700462 } else if (!strcmp(name, "-any")) {
463 sinfo->state = kCsAny;
Leo Sartre1fbc9db2015-11-27 18:56:48 +0100464 } else {
465 return nullptr;
466 }
467
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700468 int fd = create_service_thread(
469 "wait", std::bind(wait_for_state, std::placeholders::_1, sinfo.get()))
470 .release();
Ting-Yuan Huangf26cf6d2017-08-15 15:07:21 -0700471 if (fd != -1) {
472 sinfo.release();
473 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800474 return create_local_socket(fd);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700475 } else if (!strncmp(name, "connect:", 8)) {
Luis Hector Chavez095792c2018-07-18 19:40:12 -0700476 std::string host(name + strlen("connect:"));
477 int fd = create_service_thread("connect",
478 std::bind(connect_service, std::placeholders::_1, host))
479 .release();
Benoit Goby1c45ee92013-03-29 18:22:36 -0700480 return create_local_socket(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800481 }
Yi Kongaed415c2018-07-13 18:15:16 -0700482 return nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800483}
484#endif /* ADB_HOST */