190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/device_manager.h" 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <algorithm> 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <vector> 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/bind.h" 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/bind_helpers.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/callback.h" 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h" 14d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/strings/string_number_conversions.h" 15d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/strings/stringprintf.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/test/chromedriver/chrome/adb.h" 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/test/chromedriver/chrome/status.h" 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(craigdh): Remove once Chromedriver no longer supports pre-m33 Chrome. 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char* kChromeCmdLineFileBeforeM33 = "/data/local/chrome-command-line"; 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char* kChromeCmdLineFile = "/data/local/tmp/chrome-command-line"; 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Device::Device( 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& device_serial, Adb* adb, 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Callback<void()> release_callback) 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : serial_(device_serial), 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) adb_(adb), 28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) release_callback_(release_callback) {} 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Device::~Device() { 31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) release_callback_.Run(); 32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Status Device::SetUp(const std::string& package, 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& activity, 36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& process, 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& args, 38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool use_running_app, 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int port) { 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!active_package_.empty()) 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status(kUnknownError, 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) active_package_ + " was launched and has not been quit"); 43d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status status = adb_->CheckAppInstalled(serial_, package); 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.IsError()) 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return status; 47d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 48d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string known_activity; 49d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string command_line_file; 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string device_socket; 51d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string exec_name; 52d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (package.compare("org.chromium.content_shell_apk") == 0) { 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Chromium content shell. 54d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch known_activity = ".ContentShellActivity"; 55d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch device_socket = "content_shell_devtools_remote"; 56d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch command_line_file = "/data/local/tmp/content-shell-command-line"; 57d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch exec_name = "content_shell"; 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (package.compare("org.chromium.chrome.shell") == 0) { 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // ChromeShell 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) known_activity = ".ChromeShellActivity"; 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) device_socket = "chrome_shell_devtools_remote"; 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) command_line_file = "/data/local/tmp/chrome-shell-command-line"; 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) exec_name = "chrome_shell"; 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (package.find("chrome") != std::string::npos && 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) package.find("webview") == std::string::npos) { 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Chrome. 67d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch known_activity = "com.google.android.apps.chrome.Main"; 68d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch device_socket = "chrome_devtools_remote"; 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) command_line_file = kChromeCmdLineFileBeforeM33; 70d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch exec_name = "chrome"; 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) status = adb_->SetDebugApp(serial_, package); 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.IsError()) 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return status; 74d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 75d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!use_running_app) { 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) status = adb_->ClearAppData(serial_, package); 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.IsError()) 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return status; 80d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!known_activity.empty()) { 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!activity.empty() || 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) !process.empty()) 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return Status(kUnknownError, "known package " + package + 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) " does not accept activity/process"); 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else if (activity.empty()) { 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return Status(kUnknownError, "WebView apps require activity name"); 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!command_line_file.empty()) { 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If Chrome is set as the debug app it looks in /data/local/tmp/. 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // There's no way to know if this is set, so write to both locations. 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This can be removed once support for pre-M33 is no longer needed. 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (command_line_file == kChromeCmdLineFileBeforeM33) { 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) status = adb_->SetCommandLineFile( 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) serial_, kChromeCmdLineFileBeforeM33, exec_name, args); 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Status status2 = adb_->SetCommandLineFile( 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) serial_, kChromeCmdLineFile, exec_name, args); 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.IsError() && status2.IsError()) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return Status(kUnknownError, 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Failed to set Chrome's command line file on device " + serial_); 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) status = adb_->SetCommandLineFile( 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) serial_, command_line_file, exec_name, args); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.IsError()) 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return status; 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) status = adb_->Launch(serial_, package, 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) known_activity.empty() ? activity : known_activity); 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.IsError()) 113d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return status; 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) active_package_ = package; 116d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this->ForwardDevtoolsPort(package, process, device_socket, port); 118d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return status; 120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 121d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Status Device::ForwardDevtoolsPort(const std::string& package, 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& process, 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string& device_socket, 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int port) { 126d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (device_socket.empty()) { 127d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch // Assume this is a WebView app. 128d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch int pid; 129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) Status status = adb_->GetPidByName(serial_, 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) process.empty() ? package : process, 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &pid); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.IsError()) { 133d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (process.empty()) 134d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch status.AddDetails( 135d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch "process name must be specified if not equal to package name"); 136d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return status; 137d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 138d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch device_socket = base::StringPrintf("webview_devtools_remote_%d", pid); 139d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 140d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch 141d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return adb_->ForwardPort(serial_, port, device_socket); 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Status Device::TearDown() { 145d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch if (!active_package_.empty()) { 146d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch std::string response; 147d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch Status status = adb_->ForceStop(serial_, active_package_); 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.IsError()) 149d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return status; 150d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch active_package_ = ""; 151d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch } 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status(kOk); 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)DeviceManager::DeviceManager(Adb* adb) : adb_(adb) { 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(adb_); 15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)DeviceManager::~DeviceManager() {} 160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status DeviceManager::AcquireDevice(scoped_ptr<Device>* device) { 162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::vector<std::string> devices; 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status status = adb_->GetDevices(&devices); 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.IsError()) 16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return status; 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (devices.empty()) 1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return Status(kUnknownError, "There are no devices online"); 1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::AutoLock lock(devices_lock_); 1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) status = Status(kUnknownError, "All devices are in use (" + 1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::IntToString(devices.size()) + " online)"); 173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::vector<std::string>::iterator iter; 174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (iter = devices.begin(); iter != devices.end(); iter++) { 175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!IsDeviceLocked(*iter)) { 176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) device->reset(LockDevice(*iter)); 177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) status = Status(kOk); 178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return status; 18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status DeviceManager::AcquireSpecificDevice( 185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::string& device_serial, scoped_ptr<Device>* device) { 186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::vector<std::string> devices; 187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status status = adb_->GetDevices(&devices); 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status.IsError()) 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return status; 19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (std::find(devices.begin(), devices.end(), device_serial) == devices.end()) 192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status(kUnknownError, 1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "Device " + device_serial + " is not online"); 194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::AutoLock lock(devices_lock_); 196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (IsDeviceLocked(device_serial)) { 197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) status = Status(kUnknownError, 1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) "Device " + device_serial + " is already in use"); 199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) device->reset(LockDevice(device_serial)); 201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) status = Status(kOk); 20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return status; 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void DeviceManager::ReleaseDevice(const std::string& device_serial) { 207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::AutoLock lock(devices_lock_); 208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) active_devices_.remove(device_serial); 20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Device* DeviceManager::LockDevice(const std::string& device_serial) { 212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) active_devices_.push_back(device_serial); 213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return new Device(device_serial, adb_, 214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(&DeviceManager::ReleaseDevice, base::Unretained(this), 215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) device_serial)); 21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool DeviceManager::IsDeviceLocked(const std::string& device_serial) { 219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return std::find(active_devices_.begin(), active_devices_.end(), 220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) device_serial) != active_devices_.end(); 22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 223