/*
* Copyright (C) 2010 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.
*/
package com.android.monkeyrunner.adb;
import com.google.common.collect.Lists;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.IDevice;
import com.android.monkeyrunner.MonkeyDevice;
import com.android.monkeyrunner.MonkeyRunnerBackend;
import com.android.sdklib.SdkConstants;
import java.io.File;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
/**
* Backend implementation that works over ADB to talk to the device.
*/
public class AdbBackend implements MonkeyRunnerBackend {
private static Logger LOG = Logger.getLogger(AdbBackend.class.getCanonicalName());
// How long to wait each time we check for the device to be connected.
private static final int CONNECTION_ITERATION_TIMEOUT_MS = 200;
private final List<AdbMonkeyDevice> devices = Lists.newArrayList();
private final AndroidDebugBridge bridge;
public AdbBackend() {
// [try to] ensure ADB is running
String adbLocation = findAdb();
AndroidDebugBridge.init(false /* debugger support */);
bridge = AndroidDebugBridge.createBridge(
adbLocation, true /* forceNewBridge */);
}
private String findAdb() {
String mrParentLocation =
System.getProperty("com.android.monkeyrunner.bindir"); //$NON-NLS-1$
// in the new SDK, adb is in the platform-tools, but when run from the command line
// in the Android source tree, then adb is next to monkeyrunner.
if (mrParentLocation != null && mrParentLocation.length() != 0) {
// check if there's a platform-tools folder
File platformTools = new File(new File(mrParentLocation).getParent(),
SdkConstants.FD_PLATFORM_TOOLS);
if (platformTools.isDirectory()) {
return platformTools.getAbsolutePath() + File.separator + SdkConstants.FN_ADB;
}
return mrParentLocation + File.separator + SdkConstants.FN_ADB;
}
return SdkConstants.FN_ADB;
}
/**
* Checks the attached devices looking for one whose device id matches the specified regex.
*
* @param deviceIdRegex the regular expression to match against
* @return the Device (if found), or null (if not found).
*/
private IDevice findAttacedDevice(String deviceIdRegex) {
Pattern pattern = Pattern.compile(deviceIdRegex);
for (IDevice device : bridge.getDevices()) {
String serialNumber = device.getSerialNumber();
if (pattern.matcher(serialNumber).matches()) {
return device;
}
}
return null;
}
public MonkeyDevice waitForConnection() {
return waitForConnection(Integer.MAX_VALUE, ".*");
}
public MonkeyDevice waitForConnection(long timeoutMs, String deviceIdRegex) {
do {
IDevice device = findAttacedDevice(deviceIdRegex);
// Only return the device when it is online
if (device != null && device.getState() == IDevice.DeviceState.ONLINE) {
AdbMonkeyDevice amd = new AdbMonkeyDevice(device);
devices.add(amd);
return amd;
}
try {
Thread.sleep(CONNECTION_ITERATION_TIMEOUT_MS);
} catch (InterruptedException e) {
LOG.log(Level.SEVERE, "Error sleeping", e);
}
timeoutMs -= CONNECTION_ITERATION_TIMEOUT_MS;
} while (timeoutMs > 0);
// Timeout. Give up.
return null;
}
public void shutdown() {
for (AdbMonkeyDevice device : devices) {
device.dispose();
}
AndroidDebugBridge.terminate();
}
}