• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 
17 // Include qemu_pipe.h before sysdeps, since it has inlined references to open, read, write.
18 #include <qemu_pipe.h>
19 
20 #define TRACE_TAG TRANSPORT
21 #include "sysdeps.h"
22 #include "transport.h"
23 
24 #include <android-base/properties.h>
25 
26 #include "adb_io.h"
27 #include "adb_trace.h"
28 #include "adb_unique_fd.h"
29 
30 /* A worker thread that monitors host connections, and registers a transport for
31  * every new host connection. This thread replaces server_socket_thread on
32  * condition that adbd daemon runs inside the emulator, and emulator uses QEMUD
33  * pipe to communicate with adbd daemon inside the guest. This is done in order
34  * to provide more robust communication channel between ADB host and guest. The
35  * main issue with server_socket_thread approach is that it runs on top of TCP,
36  * and thus is sensitive to network disruptions. For instance, the
37  * ConnectionManager may decide to reset all network connections, in which case
38  * the connection between ADB host and guest will be lost. To make ADB traffic
39  * independent from the network, we use here 'adb' QEMUD service to transfer data
40  * between the host, and the guest. See external/qemu/android/adb-*.* that
41  * implements the emulator's side of the protocol. Another advantage of using
42  * QEMUD approach is that ADB will be up much sooner, since it doesn't depend
43  * anymore on network being set up.
44  * The guest side of the protocol contains the following phases:
45  * - Connect with adb QEMUD service. In this phase a handle to 'adb' QEMUD service
46  *   is opened, and it becomes clear whether or not emulator supports that
47  *   protocol.
48  * - Wait for the ADB host to create connection with the guest. This is done by
49  *   sending an 'accept' request to the adb QEMUD service, and waiting on
50  *   response.
51  * - When new ADB host connection is accepted, the connection with adb QEMUD
52  *   service is registered as the transport, and a 'start' request is sent to the
53  *   adb QEMUD service, indicating that the guest is ready to receive messages.
54  *   Note that the guest will ignore messages sent down from the emulator before
55  *   the transport registration is completed. That's why we need to send the
56  *   'start' request after the transport is registered.
57  */
qemu_socket_thread(int port)58 void qemu_socket_thread(int port) {
59     /* 'accept' request to the adb QEMUD service. */
60     static const char _accept_req[] = "accept";
61     /* 'start' request to the adb QEMUD service. */
62     static const char _start_req[] = "start";
63     /* 'ok' reply from the adb QEMUD service. */
64     static const char _ok_resp[] = "ok";
65 
66     char tmp[256];
67     char con_name[32];
68 
69     adb_thread_setname("qemu socket");
70     D("transport: qemu_socket_thread() starting");
71 
72     /* adb QEMUD service connection request. */
73     snprintf(con_name, sizeof(con_name), "pipe:qemud:adb:%d", port);
74 
75     /* Connect to the adb QEMUD service. */
76     unique_fd fd(qemu_pipe_open(con_name));
77     if (fd < 0) {
78         /* This could be an older version of the emulator, that doesn't
79          * implement adb QEMUD service. Fall back to the old TCP way. */
80         D("adb service is not available. Falling back to TCP socket.");
81         std::thread(server_socket_thread, tcp_listen_inaddr_any, port).detach();
82         return;
83     }
84 
85     while (true) {
86         /*
87          * Wait till the host creates a new connection.
88          */
89 
90         /* Send the 'accept' request. */
91         if (WriteFdExactly(fd.get(), _accept_req, strlen(_accept_req))) {
92             /* Wait for the response. In the response we expect 'ok' on success,
93              * or 'ko' on failure. */
94             if (!ReadFdExactly(fd.get(), tmp, 2) || memcmp(tmp, _ok_resp, 2)) {
95                 D("Accepting ADB host connection has failed.");
96             } else {
97                 /* Host is connected. Register the transport, and start the
98                  * exchange. */
99                 std::string serial = android::base::StringPrintf("host-%d", fd.get());
100                 WriteFdExactly(fd.get(), _start_req, strlen(_start_req));
101                 register_socket_transport(std::move(fd), std::move(serial), port, 1,
102                                           [](atransport*) { return ReconnectResult::Abort; });
103             }
104 
105             /* Prepare for accepting of the next ADB host connection. */
106             fd.reset(qemu_pipe_open(con_name));
107             if (fd < 0) {
108                 D("adb service become unavailable.");
109                 return;
110             }
111         } else {
112             D("Unable to send the '%s' request to ADB service.", _accept_req);
113             return;
114         }
115     }
116     D("transport: qemu_socket_thread() exiting");
117     return;
118 }
119 
120 // If adbd is running inside the emulator, it will normally use QEMUD pipe (aka
121 // goldfish) as the transport. This can either be explicitly set by the
122 // service.adb.transport property, or be inferred from ro.kernel.qemu that is
123 // set to "1" for ranchu/goldfish.
use_qemu_goldfish()124 bool use_qemu_goldfish() {
125     // Legacy way to detect if adbd should use the goldfish pipe is to check for
126     // ro.kernel.qemu, keep that behaviour for backward compatibility.
127     if (android::base::GetBoolProperty("ro.kernel.qemu", false)) {
128         return true;
129     }
130     // If service.adb.transport is present and is set to "goldfish", use the
131     // QEMUD pipe.
132     if (android::base::GetProperty("service.adb.transport", "") == "goldfish") {
133         return true;
134     }
135     return false;
136 }
137