1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/test/chromedriver/chrome/device_manager.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/callback.h"
13 #include "base/logging.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/stringprintf.h"
16 #include "chrome/test/chromedriver/chrome/adb.h"
17 #include "chrome/test/chromedriver/chrome/status.h"
20 const std::string& device_serial, Adb* adb,
21 base::Callback<void()> release_callback)
22 : serial_(device_serial),
24 release_callback_(release_callback) {}
27 release_callback_.Run();
30 Status Device::StartApp(const std::string& package,
31 const std::string& activity,
32 const std::string& process,
33 const std::string& args,
35 if (!active_package_.empty())
36 return Status(kUnknownError,
37 active_package_ + " was launched and has not been quit");
39 Status status = adb_->CheckAppInstalled(serial_, package);
43 status = adb_->ClearAppData(serial_, package);
47 std::string known_activity;
48 std::string device_socket;
49 std::string command_line_file;
50 std::string exec_name;
51 if (package.compare("org.chromium.content_shell_apk") == 0) {
52 known_activity = ".ContentShellActivity";
53 device_socket = "content_shell_devtools_remote";
54 command_line_file = "/data/local/tmp/content-shell-command-line";
55 exec_name = "content_shell";
56 } else if (package.compare("org.chromium.chrome.testshell") == 0) {
57 known_activity = ".ChromiumTestShellActivity";
58 device_socket = "chromium_testshell_devtools_remote";
59 command_line_file = "/data/local/tmp/chromium-testshell-command-line";
60 exec_name = "chromium_testshell";
61 } else if (package.find("chrome") != std::string::npos) {
62 known_activity = "com.google.android.apps.chrome.Main";
63 device_socket = "chrome_devtools_remote";
64 command_line_file = "/data/local/chrome-command-line";
68 if (!known_activity.empty()) {
69 if (!activity.empty() || !process.empty())
70 return Status(kUnknownError, "known package " + package +
71 " does not accept activity/process");
72 } else if (activity.empty()) {
73 return Status(kUnknownError, "WebView apps require activity name");
76 if (!command_line_file.empty()) {
77 status = adb_->SetCommandLineFile(serial_, command_line_file, exec_name,
83 status = adb_->Launch(serial_, package,
84 known_activity.empty() ? activity : known_activity);
87 active_package_ = package;
89 if (device_socket.empty()) {
90 // Assume this is a WebView app.
92 status = adb_->GetPidByName(serial_, process.empty() ? package : process,
97 "process name must be specified if not equal to package name");
100 device_socket = base::StringPrintf("webview_devtools_remote_%d", pid);
103 return adb_->ForwardPort(serial_, port, device_socket);
106 Status Device::StopApp() {
107 if (!active_package_.empty()) {
108 std::string response;
109 Status status = adb_->ForceStop(serial_, active_package_);
112 active_package_ = "";
117 DeviceManager::DeviceManager(Adb* adb) : adb_(adb) {
121 DeviceManager::~DeviceManager() {}
123 Status DeviceManager::AcquireDevice(scoped_ptr<Device>* device) {
124 std::vector<std::string> devices;
125 Status status = adb_->GetDevices(&devices);
130 return Status(kUnknownError, "There are no devices online");
132 base::AutoLock lock(devices_lock_);
133 status = Status(kUnknownError, "All devices are in use (" +
134 base::IntToString(devices.size()) + " online)");
135 std::vector<std::string>::iterator iter;
136 for (iter = devices.begin(); iter != devices.end(); iter++) {
137 if (!IsDeviceLocked(*iter)) {
138 device->reset(LockDevice(*iter));
139 status = Status(kOk);
146 Status DeviceManager::AcquireSpecificDevice(
147 const std::string& device_serial, scoped_ptr<Device>* device) {
148 std::vector<std::string> devices;
149 Status status = adb_->GetDevices(&devices);
153 if (std::find(devices.begin(), devices.end(), device_serial) == devices.end())
154 return Status(kUnknownError,
155 "Device " + device_serial + " is not online");
157 base::AutoLock lock(devices_lock_);
158 if (IsDeviceLocked(device_serial)) {
159 status = Status(kUnknownError,
160 "Device " + device_serial + " is already in use");
162 device->reset(LockDevice(device_serial));
163 status = Status(kOk);
168 void DeviceManager::ReleaseDevice(const std::string& device_serial) {
169 base::AutoLock lock(devices_lock_);
170 active_devices_.remove(device_serial);
173 Device* DeviceManager::LockDevice(const std::string& device_serial) {
174 active_devices_.push_back(device_serial);
175 return new Device(device_serial, adb_,
176 base::Bind(&DeviceManager::ReleaseDevice, base::Unretained(this),
180 bool DeviceManager::IsDeviceLocked(const std::string& device_serial) {
181 return std::find(active_devices_.begin(), active_devices_.end(),
182 device_serial) != active_devices_.end();