Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Unified Diff: tools/android/forwarder2/device_controller.cc

Issue 19478003: Remove Thread wrapper class in forwarder2. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Marcus' comments Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/android/forwarder2/device_controller.h ('k') | tools/android/forwarder2/device_forwarder_main.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/android/forwarder2/device_controller.cc
diff --git a/tools/android/forwarder2/device_controller.cc b/tools/android/forwarder2/device_controller.cc
index e9ce9cb7c37eb9f331b6ed670a3d432daae1816b..87d0e17143d22e6b1c81c3c823bfdeddea14ae35 100644
--- a/tools/android/forwarder2/device_controller.cc
+++ b/tools/android/forwarder2/device_controller.cc
@@ -4,139 +4,151 @@
#include "tools/android/forwarder2/device_controller.h"
-#include <errno.h>
-#include <stdlib.h>
+#include <utility>
+#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
-#include "base/safe_strerror_posix.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/single_thread_task_runner.h"
#include "tools/android/forwarder2/command.h"
#include "tools/android/forwarder2/device_listener.h"
#include "tools/android/forwarder2/socket.h"
namespace forwarder2 {
-DeviceController::DeviceController(int exit_notifier_fd)
- : exit_notifier_fd_(exit_notifier_fd) {
- kickstart_adb_socket_.AddEventFd(exit_notifier_fd);
+// static
+scoped_ptr<DeviceController> DeviceController::Create(
+ const std::string& adb_unix_socket,
+ int exit_notifier_fd) {
+ scoped_ptr<DeviceController> device_controller;
+ scoped_ptr<Socket> host_socket(new Socket());
+ if (!host_socket->BindUnix(adb_unix_socket)) {
+ PLOG(ERROR) << "Could not BindAndListen DeviceController socket on port "
+ << adb_unix_socket << ": ";
+ return device_controller.Pass();
+ }
+ LOG(INFO) << "Listening on Unix Domain Socket " << adb_unix_socket;
+ device_controller.reset(
+ new DeviceController(host_socket.Pass(), exit_notifier_fd));
+ return device_controller.Pass();
}
DeviceController::~DeviceController() {
- KillAllListeners();
- CleanUpDeadListeners();
- CHECK_EQ(0, listeners_.size());
+ DCHECK(construction_task_runner_->RunsTasksOnCurrentThread());
}
-void DeviceController::CleanUpDeadListeners() {
- // Clean up dead listeners.
- for (ListenersMap::iterator it(&listeners_); !it.IsAtEnd(); it.Advance()) {
- if (!it.GetCurrentValue()->is_alive())
- // Remove deletes the listener.
- listeners_.Remove(it.GetCurrentKey());
- }
+void DeviceController::Start() {
+ AcceptHostCommandSoon();
}
-void DeviceController::KillAllListeners() {
- for (ListenersMap::iterator it(&listeners_); !it.IsAtEnd(); it.Advance())
- it.GetCurrentValue()->ForceExit();
- for (ListenersMap::iterator it(&listeners_); !it.IsAtEnd(); it.Advance()) {
- it.GetCurrentValue()->Join();
- CHECK(!it.GetCurrentValue()->is_alive());
- }
+DeviceController::DeviceController(scoped_ptr<Socket> host_socket,
+ int exit_notifier_fd)
+ : host_socket_(host_socket.Pass()),
+ exit_notifier_fd_(exit_notifier_fd),
+ construction_task_runner_(base::MessageLoopProxy::current()),
+ weak_ptr_factory_(this) {
+ host_socket_->AddEventFd(exit_notifier_fd);
}
-bool DeviceController::Init(const std::string& adb_unix_socket) {
- if (!kickstart_adb_socket_.BindUnix(adb_unix_socket)) {
- LOG(ERROR) << "Could not BindAndListen DeviceController socket on port "
- << adb_unix_socket << ": " << safe_strerror(errno);
- return false;
- }
- LOG(INFO) << "Listening on Unix Domain Socket " << adb_unix_socket;
- return true;
+void DeviceController::AcceptHostCommandSoon() {
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&DeviceController::AcceptHostCommandInternal,
+ base::Unretained(this)));
}
-void DeviceController::Start() {
- while (true) {
- CleanUpDeadListeners();
- scoped_ptr<Socket> socket(new Socket);
- if (!kickstart_adb_socket_.Accept(socket.get())) {
- if (!kickstart_adb_socket_.DidReceiveEvent()) {
- LOG(ERROR) << "Could not Accept DeviceController socket: "
- << safe_strerror(errno);
- } else {
- LOG(INFO) << "Received exit notification";
+void DeviceController::AcceptHostCommandInternal() {
+ scoped_ptr<Socket> socket(new Socket);
+ if (!host_socket_->Accept(socket.get())) {
+ if (!host_socket_->DidReceiveEvent())
+ PLOG(ERROR) << "Could not Accept DeviceController socket";
+ else
+ LOG(INFO) << "Received exit notification";
+ return;
+ }
+ base::ScopedClosureRunner accept_next_client(
+ base::Bind(&DeviceController::AcceptHostCommandSoon,
+ base::Unretained(this)));
+ // So that |socket| doesn't block on read if it has notifications.
+ socket->AddEventFd(exit_notifier_fd_);
+ int port;
+ command::Type command;
+ if (!ReadCommand(socket.get(), &port, &command)) {
+ LOG(ERROR) << "Invalid command received.";
+ return;
+ }
+ const ListenersMap::iterator listener_it = listeners_.find(port);
+ DeviceListener* const listener = listener_it == listeners_.end()
+ ? static_cast<DeviceListener*>(NULL) : listener_it->second.get();
+ switch (command) {
+ case command::LISTEN: {
+ if (listener != NULL) {
+ LOG(WARNING) << "Already forwarding port " << port
+ << ". Attempting to restart the listener.\n";
+ // Note that this deletes the listener object.
+ listeners_.erase(listener_it);
}
+ scoped_ptr<DeviceListener> new_listener(
+ DeviceListener::Create(
+ socket.Pass(), port, base::Bind(&DeviceController::DeleteListener,
+ weak_ptr_factory_.GetWeakPtr())));
+ if (!new_listener)
+ return;
+ new_listener->Start();
+ // |port| can be zero, to allow dynamically allocated port, so instead, we
+ // call DeviceListener::listener_port() to retrieve the currently
+ // allocated port to this new listener.
+ const int listener_port = new_listener->listener_port();
+ listeners_.insert(
+ std::make_pair(listener_port,
+ linked_ptr<DeviceListener>(new_listener.release())));
+ LOG(INFO) << "Forwarding device port " << listener_port << " to host.";
break;
}
- // So that |socket| doesn't block on read if it has notifications.
- socket->AddEventFd(exit_notifier_fd_);
- int port;
- command::Type command;
- if (!ReadCommand(socket.get(), &port, &command)) {
- LOG(ERROR) << "Invalid command received.";
- continue;
- }
- DeviceListener* listener = listeners_.Lookup(port);
- switch (command) {
- case command::LISTEN: {
- if (listener != NULL) {
- LOG(WARNING) << "Already forwarding port " << port
- << ". Attempting to restart the listener.\n";
- listener->ForceExit();
- listener->Join();
- CHECK(!listener->is_alive());
- // Remove deletes the listener object.
- listeners_.Remove(port);
- }
- scoped_ptr<DeviceListener> new_listener(
- new DeviceListener(socket.Pass(), port));
- if (!new_listener->BindListenerSocket())
- continue;
- new_listener->Start();
- // |port| can be zero, to allow dynamically allocated port, so instead,
- // we call DeviceListener::listener_port() to retrieve the currently
- // allocated port to this new listener, which has been set by the
- // BindListenerSocket() method in case of success.
- const int listener_port = new_listener->listener_port();
- // |new_listener| is now owned by listeners_ map.
- listeners_.AddWithID(new_listener.release(), listener_port);
- LOG(INFO) << "Forwarding device port " << listener_port << " to host.";
+ case command::DATA_CONNECTION:
+ if (listener == NULL) {
+ LOG(ERROR) << "Data Connection command received, but "
+ << "listener has not been set up yet for port " << port;
+ // After this point it is assumed that, once we close our Adb Data
+ // socket, the Adb forwarder command will propagate the closing of
+ // sockets all the way to the host side.
break;
}
- case command::DATA_CONNECTION:
- if (listener == NULL) {
- LOG(ERROR) << "Data Connection command received, but "
- << "listener has not been set up yet for port " << port;
- // After this point it is assumed that, once we close our Adb Data
- // socket, the Adb forwarder command will propagate the closing of
- // sockets all the way to the host side.
- continue;
- } else if (!listener->SetAdbDataSocket(socket.Pass())) {
- LOG(ERROR) << "Could not set Adb Data Socket for port: " << port;
- // Same assumption as above, but in this case the socket is closed
- // inside SetAdbDataSocket.
- continue;
- }
- break;
- case command::UNMAP_PORT:
- if (!listener) {
- SendCommand(command::UNMAP_PORT_ERROR, port, socket.get());
- break;
- }
- listener->ForceExit();
- listener->Join();
- CHECK(!listener->is_alive());
- listeners_.Remove(port);
- SendCommand(command::UNMAP_PORT_SUCCESS, port, socket.get());
+ listener->SetAdbDataSocket(socket.Pass());
+ break;
+ case command::UNLISTEN:
+ if (!listener) {
+ SendCommand(command::UNLISTEN_ERROR, port, socket.get());
break;
- default:
- // TODO(felipeg): add a KillAllListeners command.
- LOG(ERROR) << "Invalid command received. Port: " << port
- << " Command: " << command;
- }
+ }
+ listeners_.erase(listener_it);
+ SendCommand(command::UNLISTEN_SUCCESS, port, socket.get());
+ break;
+ default:
+ // TODO(felipeg): add a KillAllListeners command.
+ LOG(ERROR) << "Invalid command received. Port: " << port
+ << " Command: " << command;
}
- KillAllListeners();
- CleanUpDeadListeners();
+}
+
+// static
+void DeviceController::DeleteListener(
+ const base::WeakPtr<DeviceController>& device_controller_ptr,
+ int listener_port) {
+ DeviceController* const controller = device_controller_ptr.get();
+ if (!controller)
+ return;
+ DCHECK(controller->construction_task_runner_->RunsTasksOnCurrentThread());
+ const ListenersMap::iterator listener_it = controller->listeners_.find(
+ listener_port);
+ if (listener_it == controller->listeners_.end())
+ return;
+ const linked_ptr<DeviceListener> listener = listener_it->second;
+ // Note that the listener is removed from the map before it gets destroyed in
+ // case its destructor would access the map.
+ controller->listeners_.erase(listener_it);
}
} // namespace forwarder
« no previous file with comments | « tools/android/forwarder2/device_controller.h ('k') | tools/android/forwarder2/device_forwarder_main.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698