aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2010-07-15 17:10:32 -0700
committerAndroid Code Review <code-review@android.com>2010-07-15 17:10:32 -0700
commit3992e7f56fdb4a8ffded283c8589f0f505ae198d (patch)
tree30b8f2248c262d3a2b3a4d81142e600d3946632c
parent63442129aa2c3e4e5a3c83a79c66b00924957c20 (diff)
parenta6e573c897b84f21802a7bccad817552c32364e7 (diff)
downloadsdk-3992e7f56fdb4a8ffded283c8589f0f505ae198d.zip
sdk-3992e7f56fdb4a8ffded283c8589f0f505ae198d.tar.gz
sdk-3992e7f56fdb4a8ffded283c8589f0f505ae198d.tar.bz2
Merge "Add new exceptions to ddmlib."
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/AdbCommandRejectedException.java56
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/AdbHelper.java93
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/Device.java98
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/DeviceMonitor.java38
-rwxr-xr-xddms/libs/ddmlib/src/com/android/ddmlib/IDevice.java149
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/ShellCommandUnresponsiveException.java28
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/SyncService.java3
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/IRemoteAndroidTestRunner.java28
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunner.java18
-rw-r--r--ddms/libs/ddmlib/tests/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunnerTest.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/ActivityLaunchAction.java34
-rw-r--r--hierarchyviewer/src/com/android/hierarchyviewer/device/DeviceBridge.java34
12 files changed, 413 insertions, 170 deletions
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/AdbCommandRejectedException.java b/ddms/libs/ddmlib/src/com/android/ddmlib/AdbCommandRejectedException.java
new file mode 100644
index 0000000..673acb5
--- /dev/null
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/AdbCommandRejectedException.java
@@ -0,0 +1,56 @@
+/*
+ * 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.ddmlib;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown when adb refuses a command.
+ */
+public class AdbCommandRejectedException extends IOException {
+ private static final long serialVersionUID = 1L;
+ private final boolean mIsDeviceOffline;
+ private final boolean mErrorDuringDeviceSelection;
+
+ AdbCommandRejectedException(String message) {
+ super(message);
+ mIsDeviceOffline = "device offline".equals(message);
+ mErrorDuringDeviceSelection = false;
+ }
+
+ AdbCommandRejectedException(String message, boolean errorDuringDeviceSelection) {
+ super(message);
+ mErrorDuringDeviceSelection = errorDuringDeviceSelection;
+ mIsDeviceOffline = "device offline".equals(message);
+ }
+
+ /**
+ * Returns true if the error is due to the device being offline.
+ */
+ public boolean isDeviceOffline() {
+ return mIsDeviceOffline;
+ }
+
+ /**
+ * Returns whether adb refused to target a given device for the command.
+ * <p/>If false, adb refused the command itself, if true, it refused to target the given
+ * device.
+ */
+ public boolean wasErrorDuringDeviceSelection() {
+ return mErrorDuringDeviceSelection;
+ }
+}
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/AdbHelper.java b/ddms/libs/ddmlib/src/com/android/ddmlib/AdbHelper.java
index f31e27f..5b5a41f 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/AdbHelper.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/AdbHelper.java
@@ -68,9 +68,11 @@ final class AdbHelper {
* @param devicePort the port we're opening
* @throws TimeoutException in case of timeout on the connection.
* @throws IOException in case of I/O error on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
*/
public static SocketChannel open(InetSocketAddress adbSockAddr,
- Device device, int devicePort) throws IOException, TimeoutException {
+ Device device, int devicePort)
+ throws IOException, TimeoutException, AdbCommandRejectedException {
SocketChannel adbChan = SocketChannel.open(adbSockAddr);
try {
@@ -87,8 +89,8 @@ final class AdbHelper {
write(adbChan, req);
AdbResponse resp = readAdbResponse(adbChan, false);
- if (!resp.okay) {
- throw new IOException("connection request rejected"); //$NON-NLS-1$
+ if (resp.okay == false) {
+ throw new AdbCommandRejectedException(resp.message);
}
adbChan.configureBlocking(true);
@@ -112,10 +114,12 @@ final class AdbHelper {
* to the first available device.
* @param pid the process pid to connect to.
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException in case of I/O error on the connection.
*/
public static SocketChannel createPassThroughConnection(InetSocketAddress adbSockAddr,
- Device device, int pid) throws TimeoutException, IOException {
+ Device device, int pid)
+ throws TimeoutException, AdbCommandRejectedException, IOException {
SocketChannel adbChan = SocketChannel.open(adbSockAddr);
try {
@@ -132,8 +136,8 @@ final class AdbHelper {
write(adbChan, req);
AdbResponse resp = readAdbResponse(adbChan, false /* readDiagString */);
- if (!resp.okay) {
- throw new IOException("connection request rejected: " + resp.message); //$NON-NLS-1$
+ if (resp.okay == false) {
+ throw new AdbCommandRejectedException(resp.message);
}
adbChan.configureBlocking(true);
@@ -258,10 +262,11 @@ final class AdbHelper {
/**
* Retrieve the frame buffer from the device.
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException in case of I/O error on the connection.
*/
static RawImage getFrameBuffer(InetSocketAddress adbSockAddr, Device device)
- throws TimeoutException, IOException {
+ throws TimeoutException, AdbCommandRejectedException, IOException {
RawImage imageParams = new RawImage();
byte[] request = formAdbRequest("framebuffer:"); //$NON-NLS-1$
@@ -283,7 +288,7 @@ final class AdbHelper {
AdbResponse resp = readAdbResponse(adbChan, false /* readDiagString */);
if (resp.okay == false) {
- throw new IOException(resp.message);
+ throw new AdbCommandRejectedException(resp.message);
}
// first the protocol version.
@@ -333,21 +338,28 @@ final class AdbHelper {
/**
* Executes a shell command on the device and retrieve the output. The output is
* handed to <var>rcvr</var> as it arrives.
+ *
* @param adbSockAddr the {@link InetSocketAddress} to adb.
* @param command the shell command to execute
* @param device the {@link IDevice} on which to execute the command.
* @param rcvr the {@link IShellOutputReceiver} that will receives the output of the shell
- * command
- * @param timeout timeout value in ms for the connection. 0 means no timeout. This only affects
- * the timeout for reading the command output. Execution setup uses the normal timeout.
- * @throws TimeoutException in case of timeout on the connection.
+ * command
+ * @param maxTimeToOutputResponse max time between command output. If more time passes
+ * between command output, the method will throw
+ * {@link ShellCommandUnresponsiveException}. A value of 0 means the method will
+ * wait forever for command output and never throw.
+ * @throws TimeoutException in case of timeout on the connection when sending the command.
+ * @throws AdbCommandRejectedException if adb rejects the command
+ * @throws ShellCommandUnresponsiveException in case the shell command doesn't send any output
+ * for a period longer than <var>maxTimeToOutputResponse</var>.
* @throws IOException in case of I/O error on the connection.
*
* @see DdmPreferences#getTimeOut()
*/
static void executeRemoteCommand(InetSocketAddress adbSockAddr,
- String command, IDevice device, IShellOutputReceiver rcvr, int timeout)
- throws TimeoutException, IOException {
+ String command, IDevice device, IShellOutputReceiver rcvr, int maxTimeToOutputResponse)
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException {
Log.v("ddms", "execute: running " + command);
SocketChannel adbChan = null;
@@ -366,12 +378,12 @@ final class AdbHelper {
AdbResponse resp = readAdbResponse(adbChan, false /* readDiagString */);
if (resp.okay == false) {
Log.e("ddms", "ADB rejected shell command (" + command + "): " + resp.message);
- throw new IOException("sad result from adb: " + resp.message);
+ throw new AdbCommandRejectedException(resp.message);
}
byte[] data = new byte[16384];
ByteBuffer buf = ByteBuffer.wrap(data);
- int timeoutCount = 0;
+ int timeToResponseCount = 0;
while (true) {
int count;
@@ -390,16 +402,17 @@ final class AdbHelper {
} else if (count == 0) {
try {
int wait = WAIT_TIME * 5;
- timeoutCount += wait;
- if (timeout > 0 && timeoutCount > timeout) {
- throw new TimeoutException();
+ timeToResponseCount += wait;
+ if (maxTimeToOutputResponse > 0 &&
+ timeToResponseCount > maxTimeToOutputResponse) {
+ throw new ShellCommandUnresponsiveException();
}
Thread.sleep(wait);
} catch (InterruptedException ie) {
}
} else {
// reset timeout
- timeoutCount = 0;
+ timeToResponseCount = 0;
// send data to receiver if present
if (rcvr != null) {
@@ -424,10 +437,11 @@ final class AdbHelper {
* @param device the Device on which to run the service
* @param rcvr the {@link LogReceiver} to receive the log output
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException in case of I/O error on the connection.
*/
public static void runEventLogService(InetSocketAddress adbSockAddr, Device device,
- LogReceiver rcvr) throws TimeoutException, IOException {
+ LogReceiver rcvr) throws TimeoutException, AdbCommandRejectedException, IOException {
runLogService(adbSockAddr, device, "events", rcvr); //$NON-NLS-1$
}
@@ -439,10 +453,11 @@ final class AdbHelper {
* @param logName the name of the log file to output
* @param rcvr the {@link LogReceiver} to receive the log output
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException in case of I/O error on the connection.
*/
public static void runLogService(InetSocketAddress adbSockAddr, Device device, String logName,
- LogReceiver rcvr) throws TimeoutException, IOException {
+ LogReceiver rcvr) throws TimeoutException, AdbCommandRejectedException, IOException {
SocketChannel adbChan = null;
try {
@@ -458,7 +473,7 @@ final class AdbHelper {
AdbResponse resp = readAdbResponse(adbChan, false /* readDiagString */);
if (resp.okay == false) {
- throw new IOException("Device rejected log command: " + resp.message);
+ throw new AdbCommandRejectedException(resp.message);
}
byte[] data = new byte[16384];
@@ -498,12 +513,12 @@ final class AdbHelper {
* @param device the device on which to do the port fowarding
* @param localPort the local port to forward
* @param remotePort the remote port.
- * @return <code>true</code> if success.
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException in case of I/O error on the connection.
*/
- public static boolean createForward(InetSocketAddress adbSockAddr, Device device, int localPort,
- int remotePort) throws TimeoutException, IOException {
+ public static void createForward(InetSocketAddress adbSockAddr, Device device, int localPort,
+ int remotePort) throws TimeoutException, AdbCommandRejectedException, IOException {
SocketChannel adbChan = null;
try {
@@ -519,8 +534,8 @@ final class AdbHelper {
AdbResponse resp = readAdbResponse(adbChan, false /* readDiagString */);
if (resp.okay == false) {
Log.w("create-forward", "Error creating forward: " + resp.message);
+ throw new AdbCommandRejectedException(resp.message);
}
- return resp.okay;
} finally {
if (adbChan != null) {
adbChan.close();
@@ -534,12 +549,12 @@ final class AdbHelper {
* @param device the device on which to remove the port fowarding
* @param localPort the local port of the forward
* @param remotePort the remote port.
- * @return <code>true</code> if success.
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException in case of I/O error on the connection.
*/
- public static boolean removeForward(InetSocketAddress adbSockAddr, Device device, int localPort,
- int remotePort) throws TimeoutException, IOException {
+ public static void removeForward(InetSocketAddress adbSockAddr, Device device, int localPort,
+ int remotePort) throws TimeoutException, AdbCommandRejectedException, IOException {
SocketChannel adbChan = null;
try {
@@ -555,8 +570,8 @@ final class AdbHelper {
AdbResponse resp = readAdbResponse(adbChan, false /* readDiagString */);
if (resp.okay == false) {
Log.w("remove-forward", "Error creating forward: " + resp.message);
+ throw new AdbCommandRejectedException(resp.message);
}
- return resp.okay;
} finally {
if (adbChan != null) {
adbChan.close();
@@ -703,10 +718,11 @@ final class AdbHelper {
* @param adbChan the socket connection to adb
* @param device The device to talk to.
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException in case of I/O error on the connection.
*/
static void setDevice(SocketChannel adbChan, IDevice device)
- throws TimeoutException, IOException {
+ throws TimeoutException, AdbCommandRejectedException, IOException {
// if the device is not -1, then we first tell adb we're looking to talk
// to a specific device
if (device != null) {
@@ -716,20 +732,23 @@ final class AdbHelper {
write(adbChan, device_query);
AdbResponse resp = readAdbResponse(adbChan, false /* readDiagString */);
- if (!resp.okay)
- throw new IOException("device (" + device +
- ") request rejected: " + resp.message);
+ if (resp.okay == false) {
+ throw new AdbCommandRejectedException(resp.message,
+ true/*errorDuringDeviceSelection*/);
+ }
}
-
}
/**
* Reboot the device.
*
* @param into what to reboot into (recovery, bootloader). Or null to just reboot.
+ * @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
+ * @throws IOException in case of I/O error on the connection.
*/
public static void reboot(String into, InetSocketAddress adbSockAddr,
- Device device) throws TimeoutException, IOException {
+ Device device) throws TimeoutException, AdbCommandRejectedException, IOException {
byte[] request;
if (into == null) {
request = formAdbRequest("reboot:"); //$NON-NLS-1$
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/Device.java b/ddms/libs/ddmlib/src/com/android/ddmlib/Device.java
index 24c20b2..7eff98e 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/Device.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/Device.java
@@ -36,6 +36,8 @@ import java.util.regex.Pattern;
*/
final class Device implements IDevice {
+ private final static int INSTALL_TIMEOUT = 2*60*1000; //2min
+
/** Emulator Serial Number regexp. */
final static String RE_EMULATOR_SN = "emulator-(\\d+)"; //$NON-NLS-1$
@@ -246,7 +248,8 @@ final class Device implements IDevice {
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#getSyncService()
*/
- public SyncService getSyncService() throws TimeoutException, IOException {
+ public SyncService getSyncService()
+ throws TimeoutException, AdbCommandRejectedException, IOException {
SyncService syncService = new SyncService(AndroidDebugBridge.getSocketAddress(), this);
if (syncService.openSync()) {
return syncService;
@@ -263,67 +266,44 @@ final class Device implements IDevice {
return new FileListingService(this);
}
- /*
- * (non-Javadoc)
- * @see com.android.ddmlib.IDevice#getScreenshot()
- */
- public RawImage getScreenshot() throws TimeoutException, IOException {
+ public RawImage getScreenshot()
+ throws TimeoutException, AdbCommandRejectedException, IOException {
return AdbHelper.getFrameBuffer(AndroidDebugBridge.getSocketAddress(), this);
}
public void executeShellCommand(String command, IShellOutputReceiver receiver)
- throws TimeoutException, IOException {
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException {
AdbHelper.executeRemoteCommand(AndroidDebugBridge.getSocketAddress(), command, this,
receiver, DdmPreferences.getTimeOut());
}
- public void executeShellCommand(String command, IShellOutputReceiver receiver, int timeout)
- throws TimeoutException, IOException {
+ public void executeShellCommand(String command, IShellOutputReceiver receiver,
+ int maxTimeToOutputResponse)
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException {
AdbHelper.executeRemoteCommand(AndroidDebugBridge.getSocketAddress(), command, this,
- receiver, timeout);
+ receiver, maxTimeToOutputResponse);
}
- public void runEventLogService(LogReceiver receiver) throws TimeoutException, IOException {
+ public void runEventLogService(LogReceiver receiver)
+ throws TimeoutException, AdbCommandRejectedException, IOException {
AdbHelper.runEventLogService(AndroidDebugBridge.getSocketAddress(), this, receiver);
}
public void runLogService(String logname, LogReceiver receiver)
- throws TimeoutException, IOException {
+ throws TimeoutException, AdbCommandRejectedException, IOException {
AdbHelper.runLogService(AndroidDebugBridge.getSocketAddress(), this, logname, receiver);
}
- /*
- * (non-Javadoc)
- * @see com.android.ddmlib.IDevice#createForward(int, int)
- */
- public boolean createForward(int localPort, int remotePort) {
- try {
- return AdbHelper.createForward(AndroidDebugBridge.getSocketAddress(), this,
- localPort, remotePort);
- } catch (TimeoutException e) {
- Log.e("adb-forward", "timeout");
- return false;
- } catch (IOException e) {
- Log.e("adb-forward", e); //$NON-NLS-1$
- return false;
- }
+ public void createForward(int localPort, int remotePort)
+ throws TimeoutException, AdbCommandRejectedException, IOException {
+ AdbHelper.createForward(AndroidDebugBridge.getSocketAddress(), this, localPort, remotePort);
}
- /*
- * (non-Javadoc)
- * @see com.android.ddmlib.IDevice#removeForward(int, int)
- */
- public boolean removeForward(int localPort, int remotePort) {
- try {
- return AdbHelper.removeForward(AndroidDebugBridge.getSocketAddress(), this,
- localPort, remotePort);
- } catch (TimeoutException e) {
- Log.e("adb-remove-forward", "timeout");
- return false;
- } catch (IOException e) {
- Log.e("adb-remove-forward", e); //$NON-NLS-1$
- return false;
- }
+ public void removeForward(int localPort, int remotePort)
+ throws TimeoutException, AdbCommandRejectedException, IOException {
+ AdbHelper.removeForward(AndroidDebugBridge.getSocketAddress(), this, localPort, remotePort);
}
/*
@@ -427,22 +407,17 @@ final class Device implements IDevice {
mMountPoints.put(name, value);
}
- /**
- * {@inheritDoc}
- */
public String installPackage(String packageFilePath, boolean reinstall)
- throws TimeoutException, IOException {
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException {
String remoteFilePath = syncPackageToDevice(packageFilePath);
String result = installRemotePackage(remoteFilePath, reinstall);
removeRemotePackage(remoteFilePath);
return result;
}
- /**
- * {@inheritDoc}
- */
public String syncPackageToDevice(String localFilePath)
- throws IOException, TimeoutException {
+ throws IOException, AdbCommandRejectedException, TimeoutException {
try {
String packageFileName = getFileName(localFilePath);
String remoteFilePath = String.format("/data/local/tmp/%1$s", packageFileName); //$NON-NLS-1$
@@ -485,25 +460,25 @@ final class Device implements IDevice {
return new File(filePath).getName();
}
- /**
- * {@inheritDoc}
- */
public String installRemotePackage(String remoteFilePath, boolean reinstall)
- throws TimeoutException, IOException {
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException {
InstallReceiver receiver = new InstallReceiver();
String cmd = String.format(reinstall ? "pm install -r \"%1$s\"" : "pm install \"%1$s\"",
remoteFilePath);
- executeShellCommand(cmd, receiver);
+ executeShellCommand(cmd, receiver, INSTALL_TIMEOUT);
return receiver.getErrorMessage();
}
/**
* {@inheritDoc}
*/
- public void removeRemotePackage(String remoteFilePath) throws TimeoutException, IOException {
+ public void removeRemotePackage(String remoteFilePath)
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException {
// now we delete the app we sync'ed
try {
- executeShellCommand("rm " + remoteFilePath, new NullOutputReceiver());
+ executeShellCommand("rm " + remoteFilePath, new NullOutputReceiver(), INSTALL_TIMEOUT);
} catch (IOException e) {
Log.e(LOG_TAG, String.format("Failed to delete temporary package: %1$s",
e.getMessage()));
@@ -514,9 +489,11 @@ final class Device implements IDevice {
/**
* {@inheritDoc}
*/
- public String uninstallPackage(String packageName) throws TimeoutException, IOException {
+ public String uninstallPackage(String packageName)
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException {
InstallReceiver receiver = new InstallReceiver();
- executeShellCommand("pm uninstall " + packageName, receiver);
+ executeShellCommand("pm uninstall " + packageName, receiver, INSTALL_TIMEOUT);
return receiver.getErrorMessage();
}
@@ -524,7 +501,8 @@ final class Device implements IDevice {
* (non-Javadoc)
* @see com.android.ddmlib.IDevice#reboot()
*/
- public void reboot(String into) throws TimeoutException, IOException {
+ public void reboot(String into)
+ throws TimeoutException, AdbCommandRejectedException, IOException {
AdbHelper.reboot(into, AndroidDebugBridge.getSocketAddress(), this);
}
}
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/DeviceMonitor.java b/ddms/libs/ddmlib/src/com/android/ddmlib/DeviceMonitor.java
index 82b3bc1..21869af 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/DeviceMonitor.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/DeviceMonitor.java
@@ -447,15 +447,30 @@ final class DeviceMonitor {
}
}
} catch (TimeoutException e) {
- Log.w("DeviceMonitor", String.format("Timeout getting device %s info",
+ Log.w("DeviceMonitor", String.format("Connection timeout getting info for device %s",
device.getSerialNumber()));
+
+ } catch (AdbCommandRejectedException e) {
+ // This should never happen as we only do this once the device is online.
+ Log.w("DeviceMonitor", String.format(
+ "Adb rejected command to get device %1$s info: %2$s",
+ device.getSerialNumber(), e.getMessage()));
+
+ } catch (ShellCommandUnresponsiveException e) {
+ Log.w("DeviceMonitor", String.format(
+ "Adb shell command took too long returning info for device %s",
+ device.getSerialNumber()));
+
} catch (IOException e) {
- // if we can't get the build info, it doesn't matter too much
+ Log.w("DeviceMonitor", String.format(
+ "IO Error getting info for device %s",
+ device.getSerialNumber()));
}
}
private void queryNewDeviceForMountingPoint(final Device device, final String name)
- throws TimeoutException, IOException {
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException {
device.executeShellCommand("echo $" + name, new MultiLineReceiver() { //$NON-NLS-1$
public boolean isCancelled() {
return false;
@@ -514,6 +529,16 @@ final class DeviceMonitor {
Log.d("DeviceMonitor",
"Connection Failure when starting to monitor device '"
+ device + "' : timeout");
+ } catch (AdbCommandRejectedException e) {
+ try {
+ // attempt to close the socket if needed.
+ socketChannel.close();
+ } catch (IOException e1) {
+ // we can ignore that one. It may already have been closed.
+ }
+ Log.d("DeviceMonitor",
+ "Adb refused to start monitoring device '"
+ + device + "' : " + e.getMessage());
} catch (IOException e) {
try {
// attempt to close the socket if needed.
@@ -636,7 +661,7 @@ final class DeviceMonitor {
}
private boolean sendDeviceMonitoringRequest(SocketChannel socket, Device device)
- throws TimeoutException, IOException {
+ throws TimeoutException, AdbCommandRejectedException, IOException {
try {
AdbHelper.setDevice(socket, device);
@@ -769,6 +794,11 @@ final class DeviceMonitor {
Log.w("DeviceMonitor",
"Failed to connect to client '" + pid + "': timeout");
return;
+ } catch (AdbCommandRejectedException e) {
+ Log.w("DeviceMonitor",
+ "Adb rejected connection to client '" + pid + "': " + e.getMessage());
+ return;
+
} catch (IOException ioe) {
Log.w("DeviceMonitor",
"Failed to connect to client '" + pid + "': " + ioe.getMessage());
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/IDevice.java b/ddms/libs/ddmlib/src/com/android/ddmlib/IDevice.java
index 59ae910..01814ac 100755
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/IDevice.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/IDevice.java
@@ -21,7 +21,6 @@ import com.android.ddmlib.log.LogReceiver;
import java.io.IOException;
import java.util.Map;
-
/**
* A Device. It can be a physical device or an emulator.
*/
@@ -65,6 +64,7 @@ public interface IDevice {
/**
* Returns a {@link DeviceState} from the string returned by <code>adb devices</code>.
+ *
* @param state the device state.
* @return a {@link DeviceState} object or <code>null</code> if the state is unknown.
*/
@@ -88,6 +88,7 @@ public interface IDevice {
* <p/>This is only valid if {@link #isEmulator()} returns true.
* <p/>If the emulator is not running any AVD (for instance it's running from an Android source
* tree build), this method will return "<code>&lt;build&gt;</code>".
+ *
* @return the name of the AVD or <code>null</code> if there isn't any.
*/
public String getAvdName();
@@ -109,6 +110,7 @@ public interface IDevice {
/**
* Returns a property value.
+ *
* @param name the name of the value to return.
* @return the value or <code>null</code> if the property does not exist.
*/
@@ -116,6 +118,7 @@ public interface IDevice {
/**
* Returns a mount point.
+ *
* @param name the name of the mount point to return
*
* @see #MNT_EXTERNAL_STORAGE
@@ -126,6 +129,7 @@ public interface IDevice {
/**
* Returns if the device is ready.
+ *
* @return <code>true</code> if {@link #getState()} returns {@link DeviceState#ONLINE}.
*/
public boolean isOnline();
@@ -137,12 +141,14 @@ public interface IDevice {
/**
* Returns if the device is offline.
+ *
* @return <code>true</code> if {@link #getState()} returns {@link DeviceState#OFFLINE}.
*/
public boolean isOffline();
/**
* Returns if the device is in bootloader mode.
+ *
* @return <code>true</code> if {@link #getState()} returns {@link DeviceState#BOOTLOADER}.
*/
public boolean isBootLoader();
@@ -159,6 +165,7 @@ public interface IDevice {
/**
* Returns a {@link Client} by its application name.
+ *
* @param applicationName the name of the application
* @return the <code>Client</code> object or <code>null</code> if no match was found.
*/
@@ -166,12 +173,16 @@ public interface IDevice {
/**
* Returns a {@link SyncService} object to push / pull files to and from the device.
+ *
* @return <code>null</code> if the SyncService couldn't be created. This can happen if adb
- * refuse to open the connection because the {@link IDevice} is invalid (or got disconnected).
+ * refuse to open the connection because the {@link IDevice} is invalid
+ * (or got disconnected).
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException if the connection with adb failed.
*/
- public SyncService getSyncService() throws TimeoutException, IOException;
+ public SyncService getSyncService()
+ throws TimeoutException, AdbCommandRejectedException, IOException;
/**
* Returns a {@link FileListingService} for this device.
@@ -180,55 +191,68 @@ public interface IDevice {
/**
* Takes a screen shot of the device and returns it as a {@link RawImage}.
- * @return the screenshot as a <code>RawImage</code> or <code>null</code> if
- * something went wrong.
+ *
+ * @return the screenshot as a <code>RawImage</code> or <code>null</code> if something
+ * went wrong.
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException in case of I/O error on the connection.
*/
- public RawImage getScreenshot() throws TimeoutException, IOException;
+ public RawImage getScreenshot() throws TimeoutException, AdbCommandRejectedException,
+ IOException;
/**
* Executes a shell command on the device, and sends the result to a <var>receiver</var>
- * <p/>This use the default timeout value returned by {@link DdmPreferences#getTimeOut()}.
+ * <p/>This is similar to calling
+ * <code>executeShellCommand(command, receiver, DdmPreferences.getTimeOut())</code>.
+ *
* @param command the shell command to execute
* @param receiver the {@link IShellOutputReceiver} that will receives the output of the shell
- * command
+ * command
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
+ * @throws ShellCommandUnresponsiveException in case the shell command doesn't send output
+ * for a given time.
* @throws IOException in case of I/O error on the connection.
*
* @see #executeShellCommand(String, IShellOutputReceiver, int)
+ * @see DdmPreferences#getTimeOut()
*/
- public void executeShellCommand(String command,
- IShellOutputReceiver receiver) throws TimeoutException, IOException;
+ public void executeShellCommand(String command, IShellOutputReceiver receiver)
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException;
/**
* Executes a shell command on the device, and sends the result to a <var>receiver</var>.
- * <p/>The timeout value is used as a maximum waiting time when expecting the command
- * output from the device.<br>
- * If the shell command takes a long time to run before outputting anything, this may be
- * impacted by the timeout. For instance, if the command outputs one line every 10sec but the
- * timeout is set to 5sec (default value) then the method will timeout.
- * <p/>For commands like log output, a timeout value of 0 (no timeout, always blocking till the
- * receiver's {@link IShellOutputReceiver#isCancelled()} return <code>true</code> should be
+ * <p/><var>maxTimeToOutputResponse</var> is used as a maximum waiting time when expecting the
+ * command output from the device.<br>
+ * At any time, if the shell command does not output anything for a period longer than
+ * <var>maxTimeToOutputResponse</var>, then the method will throw
+ * {@link ShellCommandUnresponsiveException}.
+ * <p/>For commands like log output, a <var>maxTimeToOutputResponse</var> value of 0, meaning
+ * that the method will never throw and will block until the receiver's
+ * {@link IShellOutputReceiver#isCancelled()} returns <code>true</code>, should be
* used.
- * <p/>When setting up the shell command to run, the normal timeout value is used while
- * communicating with adb.
*
* @param command the shell command to execute
* @param receiver the {@link IShellOutputReceiver} that will receives the output of the shell
- * command
- * @param timeout timeout value in ms for the connection.
- * @param timeout the timeout. timeout value in ms for the connection.If 0, there is no timeout.
- * @throws TimeoutException in case of timeout on the connection. Even with a timeout parameter
- * of 0, timeout can happen during the setup of the shell command. Once command has launched,
- * no timeout will occur as it's not possible to detect a difference between no output and
- * no timeout.
+ * command
+ * @param maxTimeToOutputResponse the maximum amount of time during which the command is allowed
+ * to not output any response. A value of 0 means the method will wait forever
+ * (until the <var>receiver</var> cancels the execution) for command output and
+ * never throw.
+ * @throws TimeoutException in case of timeout on the connection when sending the command.
+ * @throws AdbCommandRejectedException if adb rejects the command.
+ * @throws ShellCommandUnresponsiveException in case the shell command doesn't send any output
+ * for a period longer than <var>maxTimeToOutputResponse</var>.
* @throws IOException in case of I/O error on the connection.
*
* @see DdmPreferences#getTimeOut()
*/
- public void executeShellCommand(String command,
- IShellOutputReceiver receiver, int timeout) throws TimeoutException, IOException;
+ public void executeShellCommand(String command, IShellOutputReceiver receiver,
+ int maxTimeToOutputResponse)
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException;
/**
* Runs the event log service and outputs the event log to the {@link LogReceiver}.
@@ -237,38 +261,52 @@ public interface IDevice {
* @throws TimeoutException in case of timeout on the connection. This can only be thrown if the
* timeout happens during setup. Once logs start being received, no timeout will occur as it's
* not possible to detect a difference between no log and timeout.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException in case of I/O error on the connection.
*/
- public void runEventLogService(LogReceiver receiver) throws TimeoutException, IOException;
+ public void runEventLogService(LogReceiver receiver)
+ throws TimeoutException, AdbCommandRejectedException, IOException;
/**
* Runs the log service for the given log and outputs the log to the {@link LogReceiver}.
* <p/>This call is blocking until {@link LogReceiver#isCancelled()} returns true.
+ *
* @param logname the logname of the log to read from.
* @param receiver the receiver to receive the event log entries.
* @throws TimeoutException in case of timeout on the connection. This can only be thrown if the
- * timeout happens during setup. Once logs start being received, no timeout will occur as it's
- * not possible to detect a difference between no log and timeout.
+ * timeout happens during setup. Once logs start being received, no timeout will
+ * occur as it's not possible to detect a difference between no log and timeout.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException in case of I/O error on the connection.
*/
public void runLogService(String logname, LogReceiver receiver)
- throws TimeoutException, IOException;
+ throws TimeoutException, AdbCommandRejectedException, IOException;
/**
* Creates a port forwarding between a local and a remote port.
+ *
* @param localPort the local port to forward
* @param remotePort the remote port.
* @return <code>true</code> if success.
+ * @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
+ * @throws IOException in case of I/O error on the connection.
*/
- public boolean createForward(int localPort, int remotePort);
+ public void createForward(int localPort, int remotePort)
+ throws TimeoutException, AdbCommandRejectedException, IOException;
/**
* Removes a port forwarding between a local and a remote port.
+ *
* @param localPort the local port to forward
* @param remotePort the remote port.
* @return <code>true</code> if success.
+ * @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
+ * @throws IOException in case of I/O error on the connection.
*/
- public boolean removeForward(int localPort, int remotePort);
+ public void removeForward(int localPort, int remotePort)
+ throws TimeoutException, AdbCommandRejectedException, IOException;
/**
* Returns the name of the client by pid or <code>null</code> if pid is unknown
@@ -280,57 +318,84 @@ public interface IDevice {
* Installs an Android application on device.
* This is a helper method that combines the syncPackageToDevice, installRemotePackage,
* and removePackage steps
+ *
* @param packageFilePath the absolute file system path to file on local host to install
* @param reinstall set to <code>true</code> if re-install of app should be performed
* @return a {@link String} with an error code, or <code>null</code> if success.
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
+ * @throws ShellCommandUnresponsiveException if the device didn't respond for long time when
+ * performing the action.
* @throws IOException in case of I/O error on the connection.
*/
public String installPackage(String packageFilePath, boolean reinstall)
- throws TimeoutException, IOException;
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException;
/**
* Pushes a file to device
+ *
* @param localFilePath the absolute path to file on local host
* @return {@link String} destination path on device for file
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException in case of I/O error on the connection.
*/
public String syncPackageToDevice(String localFilePath)
- throws TimeoutException, IOException;
+ throws TimeoutException, AdbCommandRejectedException, IOException;
/**
* Installs the application package that was pushed to a temporary location on the device.
+ *
* @param remoteFilePath absolute file path to package file on device
* @param reinstall set to <code>true</code> if re-install of app should be performed
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
+ * @throws ShellCommandUnresponsiveException if the device didn't respond for long time when
+ * performing the action.
* @throws IOException if installation failed
*/
public String installRemotePackage(String remoteFilePath, boolean reinstall)
- throws TimeoutException, IOException;
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException;
/**
- * Remove a file from device
+ * Removes a file from device.
+ *
* @param remoteFilePath path on device of file to remove
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
+ * @throws ShellCommandUnresponsiveException if the device didn't respond for long time when
+ * performing the action.
* @throws IOException if file removal failed
*/
- public void removeRemotePackage(String remoteFilePath) throws TimeoutException, IOException;
+ public void removeRemotePackage(String remoteFilePath)
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException;
/**
- * Uninstall an package from the device.
+ * Uninstalls an package from the device.
+ *
* @param packageName the Android application package name to uninstall
* @return a {@link String} with an error code, or <code>null</code> if success.
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
+ * @throws ShellCommandUnresponsiveException if the device didn't respond for long time when
+ * performing the action.
* @throws IOException
*/
- public String uninstallPackage(String packageName) throws TimeoutException, IOException;
+ public String uninstallPackage(String packageName)
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException;
/**
* Reboot the device.
*
* @param into the bootloader name to reboot into, or null to just reboot the device.
+ * @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException
*/
- public void reboot(String into) throws TimeoutException, IOException;
+ public void reboot(String into)
+ throws TimeoutException, AdbCommandRejectedException, IOException;
}
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/ShellCommandUnresponsiveException.java b/ddms/libs/ddmlib/src/com/android/ddmlib/ShellCommandUnresponsiveException.java
new file mode 100644
index 0000000..2dc5d3a
--- /dev/null
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/ShellCommandUnresponsiveException.java
@@ -0,0 +1,28 @@
+/*
+ * 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.ddmlib;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown when a shell command executed on a device takes too long to send its output.
+ * <p/>The command may not actually be unresponsive, it just has spent too much time not outputting
+ * any thing to the console.
+ */
+public class ShellCommandUnresponsiveException extends IOException {
+ private static final long serialVersionUID = 1L;
+}
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/SyncService.java b/ddms/libs/ddmlib/src/com/android/ddmlib/SyncService.java
index e4740d0..d2b8af3 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/SyncService.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/SyncService.java
@@ -214,9 +214,10 @@ public final class SyncService {
* @return true if the connection opened, false if adb refuse the connection. This can happen
* if the {@link Device} is invalid.
* @throws TimeoutException in case of timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
* @throws IOException If the connection to adb failed.
*/
- boolean openSync() throws TimeoutException, IOException {
+ boolean openSync() throws TimeoutException, AdbCommandRejectedException, IOException {
try {
mChannel = SocketChannel.open(mAddress);
mChannel.configureBlocking(false);
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/IRemoteAndroidTestRunner.java b/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/IRemoteAndroidTestRunner.java
index a478216..7cb6557 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/IRemoteAndroidTestRunner.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/IRemoteAndroidTestRunner.java
@@ -17,6 +17,8 @@
package com.android.ddmlib.testrunner;
import com.android.ddmlib.IDevice;
+import com.android.ddmlib.AdbCommandRejectedException;
+import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.TimeoutException;
import java.io.IOException;
@@ -171,13 +173,17 @@ public interface IRemoteAndroidTestRunner {
public void setCoverage(boolean coverage);
/**
- * Sets the timeout to use for the adb shell command issued.
+ * Sets the maximum time allowed between output of the shell command running the tests on
+ * the devices.
+ * <p/>
+ * This allows setting a timeout in case the tests can become stuck and never finish. This is
+ * different from the normal timeout on the connection.
* <p/>
* By default no timeout will be specified.
*
* @see {@link IDevice#executeShellCommand(String, com.android.ddmlib.IShellOutputReceiver, int)}
*/
- public void setTimeout(int timeout);
+ public void setMaxtimeToOutputResponse(int maxTimeToOutputResponse);
/**
* Execute this test run.
@@ -186,18 +192,32 @@ public interface IRemoteAndroidTestRunner {
*
* @param listeners listens for test results
* @throws TimeoutException in case of a timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
+ * @throws ShellCommandUnresponsiveException if the device did not output any test result for
+ * a period longer than the max time to output.
* @throws IOException if connection to device was lost.
+ *
+ * @see #setMaxtimeToOutputResponse(int)
*/
- public void run(ITestRunListener... listeners) throws TimeoutException, IOException;
+ public void run(ITestRunListener... listeners)
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException;
/**
* Execute this test run.
*
* @param listeners collection of listeners for test results
* @throws TimeoutException in case of a timeout on the connection.
+ * @throws AdbCommandRejectedException if adb rejects the command
+ * @throws ShellCommandUnresponsiveException if the device did not output any test result for
+ * a period longer than the max time to output.
* @throws IOException if connection to device was lost.
+ *
+ * @see #setMaxtimeToOutputResponse(int)
*/
- public void run(Collection<ITestRunListener> listeners) throws TimeoutException, IOException;
+ public void run(Collection<ITestRunListener> listeners)
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException;
/**
* Requests cancellation of this test run.
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunner.java b/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunner.java
index 9fd3fbf..681c214 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunner.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunner.java
@@ -19,6 +19,8 @@ package com.android.ddmlib.testrunner;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.Log;
+import com.android.ddmlib.AdbCommandRejectedException;
+import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.TimeoutException;
import java.io.IOException;
@@ -37,7 +39,7 @@ public class RemoteAndroidTestRunner implements IRemoteAndroidTestRunner {
private final String mRunnerName;
private IDevice mRemoteDevice;
// default to no timeout
- private int mAdbTimeout = 0;
+ private int mMaxTimeToOutputResponse = 0;
/** map of name-value instrumentation argument pairs */
private Map<String, String> mArgMap;
@@ -205,28 +207,32 @@ public class RemoteAndroidTestRunner implements IRemoteAndroidTestRunner {
/**
* {@inheritDoc}
*/
- public void setTimeout(int timeout) {
- mAdbTimeout = timeout;
+ public void setMaxtimeToOutputResponse(int maxTimeToOutputResponse) {
+ mMaxTimeToOutputResponse = maxTimeToOutputResponse;
}
/**
* {@inheritDoc}
*/
- public void run(ITestRunListener... listeners) throws IOException, TimeoutException {
+ public void run(ITestRunListener... listeners)
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException {
run(Arrays.asList(listeners));
}
/**
* {@inheritDoc}
*/
- public void run(Collection<ITestRunListener> listeners) throws TimeoutException, IOException {
+ public void run(Collection<ITestRunListener> listeners)
+ throws TimeoutException, AdbCommandRejectedException, ShellCommandUnresponsiveException,
+ IOException {
final String runCaseCommandStr = String.format("am instrument -w -r %s %s",
getArgsCommand(), getRunnerPath());
Log.i(LOG_TAG, String.format("Running %s on %s", runCaseCommandStr,
mRemoteDevice.getSerialNumber()));
mParser = new InstrumentationResultParser(listeners);
- mRemoteDevice.executeShellCommand(runCaseCommandStr, mParser, mAdbTimeout);
+ mRemoteDevice.executeShellCommand(runCaseCommandStr, mParser, mMaxTimeToOutputResponse);
}
/**
diff --git a/ddms/libs/ddmlib/tests/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunnerTest.java b/ddms/libs/ddmlib/tests/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunnerTest.java
index a884c3b..85b57aa 100644
--- a/ddms/libs/ddmlib/tests/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunnerTest.java
+++ b/ddms/libs/ddmlib/tests/src/com/android/ddmlib/testrunner/RemoteAndroidTestRunnerTest.java
@@ -144,7 +144,7 @@ public class RemoteAndroidTestRunnerTest extends TestCase {
return mLastShellCommand;
}
- public boolean createForward(int localPort, int remotePort) {
+ public void createForward(int localPort, int remotePort) {
throw new UnsupportedOperationException();
}
@@ -216,7 +216,7 @@ public class RemoteAndroidTestRunnerTest extends TestCase {
throw new UnsupportedOperationException();
}
- public boolean removeForward(int localPort, int remotePort) {
+ public void removeForward(int localPort, int remotePort) {
throw new UnsupportedOperationException();
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/ActivityLaunchAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/ActivityLaunchAction.java
index d1502d3..0a6257f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/ActivityLaunchAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/ActivityLaunchAction.java
@@ -16,7 +16,10 @@
package com.android.ide.eclipse.adt.internal.launch;
+import com.android.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.IDevice;
+import com.android.ddmlib.ShellCommandUnresponsiveException;
+import com.android.ddmlib.TimeoutException;
import com.android.ide.eclipse.adt.AdtPlugin;
import java.io.IOException;
@@ -49,8 +52,16 @@ public class ActivityLaunchAction implements IAndroidLaunchAction {
* @see IAndroidLaunchAction#doLaunchAction(DelayedLaunchInfo, IDevice)
*/
public boolean doLaunchAction(DelayedLaunchInfo info, IDevice device) {
+ String command = "am start" //$NON-NLS-1$
+ + (info.isDebugMode() ? " -D" //$NON-NLS-1$
+ : "") //$NON-NLS-1$
+ + " -n " //$NON-NLS-1$
+ + info.getPackageName() + "/" //$NON-NLS-1$
+ + mActivity.replaceAll("\\$", "\\\\\\$") //$NON-NLS-1$ //$NON-NLS-2$
+ + " -a android.intent.action.MAIN" //$NON-NLS-1$
+ + " -c android.intent.category.LAUNCHER";
try {
- String msg = String.format("Starting activity %1$s on device ", mActivity,
+ String msg = String.format("Starting activity %1$s on device %2$s", mActivity,
device);
AdtPlugin.printToConsole(info.getProject(), msg);
@@ -60,15 +71,7 @@ public class ActivityLaunchAction implements IAndroidLaunchAction {
info.incrementAttemptCount();
// now we actually launch the app.
- device.executeShellCommand("am start" //$NON-NLS-1$
- + (info.isDebugMode() ? " -D" //$NON-NLS-1$
- : "") //$NON-NLS-1$
- + " -n " //$NON-NLS-1$
- + info.getPackageName() + "/" //$NON-NLS-1$
- + mActivity.replaceAll("\\$", "\\\\\\$") //$NON-NLS-1$ //$NON-NLS-2$
- + " -a android.intent.action.MAIN" //$NON-NLS-1$
- + " -c android.intent.category.LAUNCHER", //$NON-NLS-1$
- new AMReceiver(info, device, mLaunchController));
+ device.executeShellCommand(command, new AMReceiver(info, device, mLaunchController));
// if the app is not a debug app, we need to do some clean up, as
// the process is done!
@@ -77,6 +80,17 @@ public class ActivityLaunchAction implements IAndroidLaunchAction {
// provide any control over the app
return false;
}
+ } catch (TimeoutException e) {
+ AdtPlugin.printErrorToConsole(info.getProject(), "Launch error: timeout");
+ return false;
+ } catch (AdbCommandRejectedException e) {
+ AdtPlugin.printErrorToConsole(info.getProject(), String.format(
+ "Launch error: adb rejected command: %1$s", e.getMessage()));
+ return false;
+ } catch (ShellCommandUnresponsiveException e) {
+ // we didn't get the output but that's ok, just log it
+ AdtPlugin.log(e, "No command output when running: '%1$s' on device %2$s", command,
+ device);
} catch (IOException e) {
// something went wrong trying to launch the app.
// lets stop the Launch
diff --git a/hierarchyviewer/src/com/android/hierarchyviewer/device/DeviceBridge.java b/hierarchyviewer/src/com/android/hierarchyviewer/device/DeviceBridge.java
index 0f60be6..209577d 100644
--- a/hierarchyviewer/src/com/android/hierarchyviewer/device/DeviceBridge.java
+++ b/hierarchyviewer/src/com/android/hierarchyviewer/device/DeviceBridge.java
@@ -16,10 +16,12 @@
package com.android.hierarchyviewer.device;
+import com.android.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.Log;
import com.android.ddmlib.MultiLineReceiver;
+import com.android.ddmlib.TimeoutException;
import java.io.IOException;
import java.io.File;
@@ -120,8 +122,20 @@ public class DeviceBridge {
synchronized (devicePortMap) {
if (device.getState() == IDevice.DeviceState.ONLINE) {
int localPort = nextLocalPort++;
- device.createForward(localPort, Configuration.DEFAULT_SERVER_PORT);
- devicePortMap.put(device, localPort);
+ try {
+ device.createForward(localPort, Configuration.DEFAULT_SERVER_PORT);
+ devicePortMap.put(device, localPort);
+ } catch (TimeoutException e) {
+ Log.e("hierarchy", "Timeout setting up port forwarding for " + device);
+ } catch (AdbCommandRejectedException e) {
+ Log.e("hierarchy", String.format(
+ "Adb rejected forward command for device %1$s: %2$s",
+ device, e.getMessage()));
+ } catch (IOException e) {
+ Log.e("hierarchy", String.format(
+ "Failed to create forward for device %1$s: %2$s",
+ device, e.getMessage()));
+ }
}
}
}
@@ -130,8 +144,20 @@ public class DeviceBridge {
synchronized (devicePortMap) {
final Integer localPort = devicePortMap.get(device);
if (localPort != null) {
- device.removeForward(localPort, Configuration.DEFAULT_SERVER_PORT);
- devicePortMap.remove(device);
+ try {
+ device.removeForward(localPort, Configuration.DEFAULT_SERVER_PORT);
+ devicePortMap.remove(device);
+ } catch (TimeoutException e) {
+ Log.e("hierarchy", "Timeout removing port forwarding for " + device);
+ } catch (AdbCommandRejectedException e) {
+ Log.e("hierarchy", String.format(
+ "Adb rejected remove-forward command for device %1$s: %2$s",
+ device, e.getMessage()));
+ } catch (IOException e) {
+ Log.e("hierarchy", String.format(
+ "Failed to remove forward for device %1$s: %2$s",
+ device, e.getMessage()));
+ }
}
}
}