Merge "adb: win32: fix adb emu command"
diff --git a/adb/Android.mk b/adb/Android.mk
index 7d6238c..1aed2cb 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -96,6 +96,9 @@
ifeq ($(HOST_OS),windows)
LOCAL_C_INCLUDES += development/host/windows/usb/api/
+ # Windows.h defines an awful ERROR macro that collides with base/logging.h.
+ # Suppress it with NOGDI.
+ LOCAL_CFLAGS += -DNOGDI
endif
include $(BUILD_HOST_STATIC_LIBRARY)
@@ -152,18 +155,21 @@
include $(CLEAR_VARS)
ifeq ($(HOST_OS),linux)
- LOCAL_LDLIBS += -lrt -ldl -lpthread
- LOCAL_CFLAGS += -DWORKAROUND_BUG6558362
+ LOCAL_LDLIBS += -lrt -ldl -lpthread
+ LOCAL_CFLAGS += -DWORKAROUND_BUG6558362
endif
ifeq ($(HOST_OS),darwin)
- LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
- LOCAL_CFLAGS += -Wno-sizeof-pointer-memaccess -Wno-unused-parameter
+ LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
+ LOCAL_CFLAGS += -Wno-sizeof-pointer-memaccess -Wno-unused-parameter
endif
ifeq ($(HOST_OS),windows)
- LOCAL_LDLIBS += -lws2_32 -lgdi32
- EXTRA_STATIC_LIBS := AdbWinApi
+ # Windows.h defines an awful ERROR macro that collides with base/logging.h.
+ # Suppress it with NOGDI.
+ LOCAL_CFLAGS += -DNOGDI
+ LOCAL_LDLIBS += -lws2_32 -lgdi32
+ EXTRA_STATIC_LIBS := AdbWinApi
endif
LOCAL_CLANG := $(adb_host_clang)
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index 510dcc2..e4658f5 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -16,6 +16,11 @@
#define TRACE_TAG TRACE_AUTH
+#ifdef _WIN32
+// This blocks some definitions we need on Windows.
+#undef NOGDI
+#endif
+
#include "sysdeps.h"
#include "adb_auth.h"
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 18e14de..532af45 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -80,36 +80,6 @@
__adb_server_name = hostname;
}
-int adb_get_emulator_console_port() {
- if (__adb_serial) {
- // The user specified a serial number; is it an emulator?
- int port;
- return (sscanf(__adb_serial, "emulator-%d", &port) == 1) ? port : -1;
- }
-
- // No specific device was given, so get the list of connected
- // devices and search for emulators. If there's one, we'll
- // take it. If there are more than one, that's an error.
- std::string devices;
- std::string error;
- if (!adb_query("host:devices", &devices, &error)) {
- printf("no emulator connected: %s\n", error.c_str());
- return -1;
- }
-
- int port;
- size_t emulator_count = 0;
- for (auto& device : android::base::Split(devices, "\n")) {
- if (sscanf(device.c_str(), "emulator-%d", &port) == 1) {
- if (++emulator_count > 1) {
- return -2;
- }
- }
- }
- if (emulator_count == 0) return -1;
- return port;
-}
-
static int switch_socket_transport(int fd, std::string* error) {
std::string service;
if (__adb_serial) {
diff --git a/adb/adb_client.h b/adb/adb_client.h
index de5c2db..9895c49 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#ifndef _ADB_CLIENT_H_
#define _ADB_CLIENT_H_
@@ -5,16 +21,13 @@
#include <string>
-/* connect to adb, connect to the named service, and return
-** a valid fd for interacting with that service upon success
-** or a negative number on failure
-*/
+// Connect to adb, connect to the named service, and return a valid fd for
+// interacting with that service upon success or a negative number on failure.
int adb_connect(const std::string& service, std::string* error);
int _adb_connect(const std::string& service, std::string* error);
-/* connect to adb, connect to the named service, return 0 if
-** the connection succeeded AND the service returned OKAY
-*/
+// Connect to adb, connect to the named service, return 0 if the connection
+// succeeded AND the service returned OKAY.
int adb_command(const std::string& service, std::string* error);
// Connects to the named adb service and fills 'result' with the response.
@@ -24,29 +37,19 @@
// Set the preferred transport to connect to.
void adb_set_transport(TransportType type, const char* serial);
-/* Set TCP specifics of the transport to use
-*/
+// Set TCP specifics of the transport to use.
void adb_set_tcp_specifics(int server_port);
-/* Set TCP Hostname of the transport to use
-*/
+// Set TCP Hostname of the transport to use.
void adb_set_tcp_name(const char* hostname);
-/* Return the console port of the currently connected emulator (if any)
- * of -1 if there is no emulator, and -2 if there is more than one.
- * assumes adb_set_transport() was alled previously...
- */
-int adb_get_emulator_console_port(void);
+// Send commands to the current emulator instance. Will fail if there is not
+// exactly one emulator connected (or if you use -s <serial> with a <serial>
+// that does not designate an emulator).
+int adb_send_emulator_command(int argc, const char** argv, const char* serial);
-/* send commands to the current emulator instance. will fail if there
- * is zero, or more than one emulator connected (or if you use -s <serial>
- * with a <serial> that does not designate an emulator)
- */
-int adb_send_emulator_command(int argc, const char** argv);
-
-// Reads a standard adb status response (OKAY|FAIL) and
-// returns true in the event of OKAY, false in the event of FAIL
-// or protocol error.
+// Reads a standard adb status response (OKAY|FAIL) and returns true in the
+// event of OKAY, false in the event of FAIL or protocol error.
bool adb_status(int fd, std::string* error);
#endif
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 76eb8c0..27ab7b4 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -1136,7 +1136,7 @@
return adb_query_command(query);
}
else if (!strcmp(argv[0], "emu")) {
- return adb_send_emulator_command(argc, argv);
+ return adb_send_emulator_command(argc, argv, serial);
}
else if (!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {
char h = (argv[0][0] == 'h');
diff --git a/adb/console.cpp b/adb/console.cpp
index 452ee41..0707960 100644
--- a/adb/console.cpp
+++ b/adb/console.cpp
@@ -1,44 +1,115 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#include "sysdeps.h"
-#include "adb.h"
-#include "adb_client.h"
+
#include <stdio.h>
-static int connect_to_console(void)
-{
- int fd, port;
+#include "base/file.h"
+#include "base/logging.h"
+#include "base/strings.h"
- port = adb_get_emulator_console_port();
- if (port < 0) {
- if (port == -2)
- fprintf(stderr, "error: more than one emulator detected. use -s option\n");
- else
- fprintf(stderr, "error: no emulator detected\n");
+#include "adb.h"
+#include "adb_client.h"
+
+// Return the console port of the currently connected emulator (if any) or -1 if
+// there is no emulator, and -2 if there is more than one.
+static int adb_get_emulator_console_port(const char* serial) {
+ if (serial) {
+ // The user specified a serial number; is it an emulator?
+ int port;
+ return (sscanf(serial, "emulator-%d", &port) == 1) ? port : -1;
+ }
+
+ // No specific device was given, so get the list of connected devices and
+ // search for emulators. If there's one, we'll take it. If there are more
+ // than one, that's an error.
+ std::string devices;
+ std::string error;
+ if (!adb_query("host:devices", &devices, &error)) {
+ fprintf(stderr, "error: no emulator connected: %s\n", error.c_str());
return -1;
}
- fd = socket_loopback_client( port, SOCK_STREAM );
- if (fd < 0) {
+
+ int port;
+ size_t emulator_count = 0;
+ for (const auto& device : android::base::Split(devices, "\n")) {
+ if (sscanf(device.c_str(), "emulator-%d", &port) == 1) {
+ if (++emulator_count > 1) {
+ fprintf(
+ stderr, "error: more than one emulator detected; use -s\n");
+ return -1;
+ }
+ }
+ }
+
+ if (emulator_count == 0) {
+ fprintf(stderr, "error: no emulator detected\n");
+ return -1;
+ }
+
+ return port;
+}
+
+static int connect_to_console(const char* serial) {
+ int port = adb_get_emulator_console_port(serial);
+ if (port == -1) {
+ return -1;
+ }
+
+ int fd = socket_loopback_client(port, SOCK_STREAM);
+ if (fd == -1) {
fprintf(stderr, "error: could not connect to TCP port %d\n", port);
return -1;
}
- return fd;
+ return fd;
}
-
-int adb_send_emulator_command(int argc, const char** argv)
-{
- int fd, nn;
-
- fd = connect_to_console();
- if (fd < 0)
+int adb_send_emulator_command(int argc, const char** argv, const char* serial) {
+ int fd = connect_to_console(serial);
+ if (fd == -1) {
return 1;
-
-#define QUIT "quit\n"
-
- for (nn = 1; nn < argc; nn++) {
- adb_write( fd, argv[nn], strlen(argv[nn]) );
- adb_write( fd, (nn == argc-1) ? "\n" : " ", 1 );
}
- adb_write( fd, QUIT, sizeof(QUIT)-1 );
+
+ for (int i = 1; i < argc; i++) {
+ adb_write(fd, argv[i], strlen(argv[i]));
+ adb_write(fd, i == argc - 1 ? "\n" : " ", 1);
+ }
+
+ const char disconnect_command[] = "quit\n";
+ if (adb_write(fd, disconnect_command, sizeof(disconnect_command) - 1) == -1) {
+ LOG(FATAL) << "Could not finalize emulator command";
+ }
+
+ // Drain output that the emulator console has sent us to prevent a problem
+ // on Windows where if adb closes the socket without reading all the data,
+ // the emulator's next call to recv() will have an ECONNABORTED error,
+ // preventing the emulator from reading the command that adb has sent.
+ // https://code.google.com/p/android/issues/detail?id=21021
+ int result;
+ do {
+ char buf[BUFSIZ];
+ result = adb_read(fd, buf, sizeof(buf));
+ // Keep reading until zero bytes (EOF) or an error. If 'adb emu kill'
+ // is executed, the emulator calls exit() which causes adb to get
+ // ECONNRESET. Any other emu command is followed by the quit command
+ // that we sent above, and that causes the emulator to close the socket
+ // which should cause zero bytes (EOF) to be returned.
+ } while (result > 0);
+
adb_close(fd);
return 0;
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index a21272f..b7962b9 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -16,6 +16,9 @@
#define TRACE_TAG TRACE_SYSDEPS
+// For whatever reason this blocks the definition of ToAscii...
+#undef NOGDI
+
#include "sysdeps.h"
#include <winsock2.h> /* winsock.h *must* be included before windows.h. */
diff --git a/base/include/base/logging.h b/base/include/base/logging.h
index 84ec538..4a15f43 100644
--- a/base/include/base/logging.h
+++ b/base/include/base/logging.h
@@ -23,8 +23,10 @@
#endif
#ifdef _WIN32
+#ifndef NOGDI
#define NOGDI // Suppress the evil ERROR macro.
#endif
+#endif
#include <functional>
#include <memory>