package com.gorillalogic.monkeytalk.utils;
import java.io.File;
import java.util.Map;
import com.gorillalogic.monkeytalk.utils.exec.Exec;
import com.gorillalogic.monkeytalk.utils.exec.ExecResult;
import com.gorillalogic.monkeytalk.utils.exec.ExecStatus;
/**
* Helper class to find the path to the Android SDK, and other Android tools like ADB.
*/
public class AndroidUtils {
public static final String ADB_LOCATION = "platform-tools" + File.separator + "adb";
public static final long ADB_RETRY_TIME = 1000;
protected static final String SDK_PATH = null;
/**
* Helper to get the path to ADB if the ANDROID_SDK (or ANDROID_HOME) environment variable is
* set.
*
* @return the path to ADB, or {@code null}.
*/
public static File getAdb() {
return getAdb(getSdk());
}
/**
* Helper to get the path to ADB as a String if the ANDROID_SDK (or ANDROID_HOME) environment
* variable is set.
*
* @return the path to ADB as a String, or {@code null}.
*/
public static String getAdbPath() {
File adb = getAdb(getSdk());
return (adb != null ? adb.getAbsolutePath() : null);
}
/**
* Helper to get the path to ADB given the path to the Android SDK.
*
* @param sdk
* the path to the Android SDK
* @return the path to ADB, or {@code null}.
*/
public static File getAdb(File sdk) {
if (sdk != null && sdk.exists() && sdk.isDirectory()) {
File adb = new File(sdk, ADB_LOCATION);
if (adb.exists() && adb.isFile()) {
return adb;
}
}
return null;
}
/**
* Helper to get the path to the Android SDK if the ANDROID_SDK (or ANDROID_HOME) environment
* variable is set.
*
* @return the path to the Android SDK, or {@code null}.
*/
public static File getSdk() {
String path = getSdkPath();
if (path != null) {
File sdk = new File(path);
if (sdk != null && sdk.exists() && sdk.isDirectory()) {
return sdk;
}
}
return null;
}
/**
* Helper to get the path to the Android SDK as a String if the ANDROID_SDK (or ANDROID_HOME)
* environment variable is set.
*
* @return the path to the Android SDK as a String, or {@code null}.
*/
public static String getSdkPath() {
if (SDK_PATH!=null) {
return SDK_PATH;
}
Map<String, String> env = System.getenv();
if (env.containsKey("ANDROID_SDK")) {
return env.get("ANDROID_SDK");
} else if (env.containsKey("ANDROID_HOME")) {
return env.get("ANDROID_HOME");
}
return null;
}
protected ExecResult runAdbCommand(String[] cmd) {
return runAdbCommand(cmd, null, 0);
}
protected ExecResult runAdbCommand(String[] cmd, Long timeout) {
return runAdbCommand(cmd, timeout, 0);
}
protected ExecResult runAdbCommand(String[] cmd, Long timeout, int retries) {
ExecResult result = null;
StringBuilder sb=new StringBuilder();
int remainingAttempts = retries + 1;
while (remainingAttempts > 0) {
result = Exec.run(cmd, timeout);
if (result.timedOut()) {
sb.append("adb command timed out, killing the server.....\n");
killAdbServer();
} else if (result.getStderr() != null
&& (result.getStderr().contains("device not found") || result.getStderr()
.contains("device offline"))) {
sb.append("adb returned \"" + result.getStderr() + "\", killing the server.....\n");
killAdbServer();
} else if (result.getStderr() != null
&& result.getStderr().contains("waiting for device")) {
// fall thru to retry, need to check this before checking status
} else if (result.getStatus().equals(ExecStatus.OK)) {
break;
}
sb.append("adb returned status=" + result.getStatus() + " " + (retries - 1)
+ " retries remaining:" + " exitValue=" + result.getExitValue() + " message="
+ result.getMessage() + " stdout=" + result.getStdout() + " stderr="
+ result.getStderr() + " timedOut=" + result.timedOut() + "\n");
remainingAttempts--;
if (remainingAttempts>0) {
pause(ADB_RETRY_TIME);
}
}
if (retries == 0) {
sb.append("adb command did not succeed after " + (retries+1) + " attempts.\n");
}
return result;
}
private void killAdbServer() {
String[] nuke = null;
nuke = new String[] { getAdb().getAbsolutePath(), "kill-server" };
Exec.run(nuke, new Long(5000));
}
protected void pause(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException ex) {
// do nothing
}
}
}