AI 144322: am: CL 144320 ADT: Fix debugger launch connection when debugging Android JUnit

Original author: brettchabot
  Merged from: //branches/cupcake/...

Automated import of CL 144322
This commit is contained in:
Brett Chabot
2009-04-02 15:37:39 -07:00
committed by The Android Open Source Project
parent d63db799ea
commit 6bc8491396
9 changed files with 124 additions and 43 deletions

View File

@@ -314,6 +314,8 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* defined by <code>ILaunchManager</code> - <code>RUN_MODE</code> or
* <code>DEBUG_MODE</code>.
* @param apk the resource to the apk to launch.
* @param packageName the Android package name of the app
* @param debugPackageName the Android package name to debug
* @param debuggable the debuggable value of the app, or null if not set.
* @param requiredApiVersionNumber the api version required by the app, or
* {@link AndroidManifestParser#INVALID_MIN_SDK} if none.
@@ -322,7 +324,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @param launch the launch object
*/
public void launch(final IProject project, String mode, IFile apk,
String packageName, Boolean debuggable, int requiredApiVersionNumber,
String packageName, String debugPackageName, Boolean debuggable, int requiredApiVersionNumber,
final IAndroidLaunchAction launchAction, final AndroidLaunchConfiguration config,
final AndroidLaunch launch, IProgressMonitor monitor) {
@@ -331,7 +333,8 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
// create the launch info
final DelayedLaunchInfo launchInfo = new DelayedLaunchInfo(project, packageName,
launchAction, apk, debuggable, requiredApiVersionNumber, launch, monitor);
debugPackageName, launchAction, apk, debuggable, requiredApiVersionNumber, launch,
monitor);
// set the debug mode
launchInfo.setDebugMode(mode.equals(ILaunchManager.DEBUG_MODE));
@@ -922,6 +925,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
DelayedLaunchInfo delayedLaunchInfo = new DelayedLaunchInfo(
androidProject.getProject(),
manifestParser.getPackage(),
manifestParser.getPackage(),
launchInfo.getLaunchAction(),
apk,
manifestParser.getDebuggable(),
@@ -1524,14 +1528,14 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
for (int i = 0; i < mWaitingForDebuggerApplications.size(); ) {
final DelayedLaunchInfo launchInfo = mWaitingForDebuggerApplications.get(i);
if (client.getDevice() == launchInfo.getDevice() &&
applicationName.equals(launchInfo.getPackageName())) {
applicationName.equals(launchInfo.getDebugPackageName())) {
// this is a match. We remove the launch info from the list
mWaitingForDebuggerApplications.remove(i);
// and connect the debugger.
String msg = String.format(
"Attempting to connect debugger to '%1$s' on port %2$d",
launchInfo.getPackageName(), client.getDebuggerListenPort());
launchInfo.getDebugPackageName(), client.getDebuggerListenPort());
AdtPlugin.printToConsole(launchInfo.getProject(), msg);
new Thread("Debugger Connection") { //$NON-NLS-1$

View File

@@ -45,6 +45,9 @@ public final class DelayedLaunchInfo {
/** Package name */
private final String mPackageName;
/** Debug package name */
private final String mDebugPackageName;
/** IFile to the package (.apk) file */
private final IFile mPackageFile;
@@ -80,6 +83,7 @@ public final class DelayedLaunchInfo {
*
* @param project the eclipse project that corresponds to Android app
* @param packageName package name of Android app
* @param debugPackageName the package name of the Andriod app to debug
* @param launchAction action to perform after app install
* @param pack IFile to the package (.apk) file
* @param debuggable debuggable attribute of the app's manifest file.
@@ -88,11 +92,12 @@ public final class DelayedLaunchInfo {
* @param launch the launch object
* @param monitor progress monitor for launch
*/
public DelayedLaunchInfo(IProject project, String packageName,
public DelayedLaunchInfo(IProject project, String packageName, String debugPackageName,
IAndroidLaunchAction launchAction, IFile pack, Boolean debuggable,
int requiredApiVersionNumber, AndroidLaunch launch, IProgressMonitor monitor) {
mProject = project;
mPackageName = packageName;
mDebugPackageName = debugPackageName;
mPackageFile = pack;
mLaunchAction = launchAction;
mLaunch = launch;
@@ -129,6 +134,17 @@ public final class DelayedLaunchInfo {
return mPackageName;
}
/**
* Returns the Android app process name that the debugger should connect to. Typically this is
* the same value as {@link getPackageName}
*/
public String getDebugPackageName() {
if (mDebugPackageName == null) {
return getPackageName();
}
return mDebugPackageName;
}
/**
* @return the application package file
*/

View File

@@ -306,9 +306,10 @@ public class LaunchConfigDelegate extends LaunchConfigurationDelegate {
// everything seems fine, we ask the launch controller to handle
// the rest
controller.launch(project, mode, applicationPackage, manifestParser.getPackage(),
manifestParser.getDebuggable(), manifestParser.getApiLevelRequirement(),
launchAction, config, androidLaunch, monitor);
controller.launch(project, mode, applicationPackage,manifestParser.getPackage(),
manifestParser.getPackage(), manifestParser.getDebuggable(),
manifestParser.getApiLevelRequirement(), launchAction, config, androidLaunch,
monitor);
}
@Override

View File

@@ -63,7 +63,6 @@ class AndroidJUnitLaunchAction implements IAndroidLaunchAction {
try {
mLaunchInfo.setDebugMode(info.isDebugMode());
mLaunchInfo.setDevice(info.getDevice());
mLaunchInfo.setLaunch(info.getLaunch());
JUnitLaunchDelegate junitDelegate = new JUnitLaunchDelegate(mLaunchInfo);
final String mode = info.isDebugMode() ? ILaunchManager.DEBUG_MODE :
ILaunchManager.RUN_MODE;

View File

@@ -25,6 +25,7 @@ import com.android.ide.eclipse.adt.launch.LaunchConfigDelegate;
import com.android.ide.eclipse.adt.launch.junit.runtime.AndroidJUnitLaunchInfo;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
import com.android.ide.eclipse.common.project.AndroidManifestParser.Instrumentation;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import org.eclipse.core.resources.IFile;
@@ -60,7 +61,6 @@ public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate {
AndroidLaunchConfiguration config, AndroidLaunchController controller,
IFile applicationPackage, AndroidManifestParser manifestParser) {
String appPackage = manifestParser.getPackage();
String runner = getRunner(project, configuration, manifestParser);
if (runner == null) {
AdtPlugin.displayError("Android Launch",
@@ -68,19 +68,46 @@ public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate {
androidLaunch.stopLaunch();
return;
}
AndroidJUnitLaunchInfo junitLaunchInfo = new AndroidJUnitLaunchInfo(project, appPackage,
runner);
// get the target app's package
String targetAppPackage = getTargetPackage(manifestParser, runner);
if (targetAppPackage == null) {
AdtPlugin.displayError("Android Launch",
String.format("A target package for instrumention test runner %1$s could not be found!",
runner));
androidLaunch.stopLaunch();
return;
}
String testAppPackage = manifestParser.getPackage();
AndroidJUnitLaunchInfo junitLaunchInfo = new AndroidJUnitLaunchInfo(project,
testAppPackage, runner);
junitLaunchInfo.setTestClass(getTestClass(configuration));
junitLaunchInfo.setTestPackage(getTestPackage(configuration));
junitLaunchInfo.setTestMethod(getTestMethod(configuration));
junitLaunchInfo.setLaunch(androidLaunch);
IAndroidLaunchAction junitLaunch = new AndroidJUnitLaunchAction(junitLaunchInfo);
controller.launch(project, mode, applicationPackage, manifestParser.getPackage(),
controller.launch(project, mode, applicationPackage, testAppPackage, targetAppPackage,
manifestParser.getDebuggable(), manifestParser.getApiLevelRequirement(),
junitLaunch, config, androidLaunch, monitor);
}
/**
* Get the target Android application's package for the given instrumentation runner, or
* <code>null</code> if it could not be found.
*
* @param manifestParser the {@link AndroidManifestParser} for the test project
* @param runner the instrumentation runner class name
* @return the target package or <code>null</code>
*/
private String getTargetPackage(AndroidManifestParser manifestParser, String runner) {
for (Instrumentation instr : manifestParser.getInstrumentations()) {
if (instr.getName().equals(runner)) {
return instr.getTargetPackage();
}
}
return null;
}
/**
* Returns the test package stored in the launch configuration, or <code>null</code> if not
* specified.

View File

@@ -955,7 +955,7 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
try {
mInstrValidator = new InstrumentationRunnerValidator(project);
mInstrumentations = (mInstrValidator == null ? null :
mInstrValidator.getInstrumentations());
mInstrValidator.getInstrumentationNames());
if (mInstrumentations != null) {
mInstrumentationCombo.removeAll();
for (String instrumentation : mInstrumentations) {

View File

@@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.launch.junit;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
import com.android.ide.eclipse.common.project.AndroidManifestParser.Instrumentation;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import org.eclipse.core.resources.IProject;
@@ -29,7 +30,7 @@ import org.eclipse.jdt.core.IJavaProject;
*/
class InstrumentationRunnerValidator {
private final IJavaProject mJavaProject;
private String[] mInstrumentations = null;
private String[] mInstrumentationNames = null;
private boolean mHasRunnerLibrary = false;
static final String INSTRUMENTATION_OK = null;
@@ -73,7 +74,11 @@ class InstrumentationRunnerValidator {
}
private void init(AndroidManifestParser manifestParser) {
mInstrumentations = manifestParser.getInstrumentations();
Instrumentation[] instrumentations = manifestParser.getInstrumentations();
mInstrumentationNames = new String[instrumentations.length];
for (int i = 0; i < instrumentations.length; i++) {
mInstrumentationNames[i] = instrumentations[i].getName();
}
mHasRunnerLibrary = hasTestRunnerLibrary(manifestParser);
}
@@ -94,13 +99,13 @@ class InstrumentationRunnerValidator {
}
/**
* Return the set of instrumentations for the Android project.
* Return the set of instrumentation names for the Android project.
*
* @return <code>null</code if error occurred parsing instrumentations, otherwise returns array
* of instrumentation class names
*/
String[] getInstrumentations() {
return mInstrumentations;
String[] getInstrumentationNames() {
return mInstrumentationNames;
}
/**
@@ -110,7 +115,7 @@ class InstrumentationRunnerValidator {
* instrumentation can be found.
*/
String getValidInstrumentationTestRunner() {
for (String instrumentation : getInstrumentations()) {
for (String instrumentation : getInstrumentationNames()) {
if (validateInstrumentationRunner(instrumentation) == INSTRUMENTATION_OK) {
return instrumentation;
}
@@ -122,7 +127,7 @@ class InstrumentationRunnerValidator {
* Helper method to determine if specified instrumentation can be used as a test runner
*
* @param instrumentation the instrumentation class name to validate. Assumes this
* instrumentation is one of {@link #getInstrumentations()}
* instrumentation is one of {@link #getInstrumentationNames()}
* @return <code>INSTRUMENTATION_OK</code> if valid, otherwise returns error message
*/
String validateInstrumentationRunner(String instrumentation) {

View File

@@ -52,6 +52,7 @@ public class AndroidManifestParser {
private final static String ATTRIBUTE_PROCESS = "process"; //$NON-NLS-$
private final static String ATTRIBUTE_DEBUGGABLE = "debuggable"; //$NON-NLS-$
private final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; //$NON-NLS-$
private final static String ATTRIBUTE_TARGET_PACKAGE = "targetPackage"; //$NON-NLS-1$
private final static String NODE_MANIFEST = "manifest"; //$NON-NLS-1$
private final static String NODE_APPLICATION = "application"; //$NON-NLS-1$
private final static String NODE_ACTIVITY = "activity"; //$NON-NLS-1$
@@ -76,6 +77,33 @@ public class AndroidManifestParser {
public final static int INVALID_MIN_SDK = -1;
/**
* Instrumentation info obtained from manifest
*/
public static class Instrumentation {
private final String mName;
private final String mTargetPackage;
public Instrumentation(String name, String targetPackage) {
mName = name;
mTargetPackage = targetPackage;
}
/**
* Returns the fully qualified instrumentation class name
*/
public String getName() {
return mName;
}
/**
* Returns the Android app package that is the target of this instrumentation
*/
public String getTargetPackage() {
return mTargetPackage;
}
}
/**
* XML error & data handler used when parsing the AndroidManifest.xml file.
* <p/>
@@ -100,7 +128,8 @@ public class AndroidManifestParser {
* the attribute was not present. */
private int mApiLevelRequirement = INVALID_MIN_SDK;
/** List of all instrumentations declared by the manifest */
private final ArrayList<String> mInstrumentations = new ArrayList<String>();
private final ArrayList<Instrumentation> mInstrumentations =
new ArrayList<Instrumentation>();
/** List of all libraries in use declared by the manifest */
private final ArrayList<String> mLibraries = new ArrayList<String>();
@@ -185,11 +214,11 @@ public class AndroidManifestParser {
/**
* Returns the list of instrumentations found in the manifest.
* @return An array of instrumentation names, or empty if no instrumentations were
* @return An array of {@link Instrumentation}, or empty if no instrumentations were
* found.
*/
String[] getInstrumentations() {
return mInstrumentations.toArray(new String[mInstrumentations.size()]);
Instrumentation[] getInstrumentations() {
return mInstrumentations.toArray(new Instrumentation[mInstrumentations.size()]);
}
/**
@@ -459,7 +488,9 @@ public class AndroidManifestParser {
true /* hasNamespace */);
if (instrumentationName != null) {
String instrClassName = combinePackageAndClassName(mPackage, instrumentationName);
mInstrumentations.add(instrClassName);
String targetPackage = getAttributeValue(attributes, ATTRIBUTE_TARGET_PACKAGE,
true /* hasNamespace */);
mInstrumentations.add(new Instrumentation(instrClassName, targetPackage));
if (mMarkErrors) {
checkClass(instrClassName, AndroidConstants.CLASS_INSTRUMENTATION,
true /* testVisibility */);
@@ -544,7 +575,7 @@ public class AndroidManifestParser {
private final String[] mProcesses;
private final Boolean mDebuggable;
private final int mApiLevelRequirement;
private final String[] mInstrumentations;
private final Instrumentation[] mInstrumentations;
private final String[] mLibraries;
static {
@@ -819,9 +850,9 @@ public class AndroidManifestParser {
/**
* Returns the list of instrumentations found in the manifest.
* @return An array of fully qualified class names, or empty if no instrumentations were found.
* @return An array of {@link Instrumentation}, or empty if no instrumentations were found.
*/
public String[] getInstrumentations() {
public Instrumentation[] getInstrumentations() {
return mInstrumentations;
}
@@ -851,7 +882,7 @@ public class AndroidManifestParser {
*/
private AndroidManifestParser(String javaPackage, String[] activities,
String launcherActivity, String[] processes, Boolean debuggable,
int apiLevelRequirement, String[] instrumentations, String[] libraries) {
int apiLevelRequirement, Instrumentation[] instrumentations, String[] libraries) {
mJavaPackage = javaPackage;
mActivities = activities;
mLauncherActivity = launcherActivity;

View File

@@ -33,7 +33,7 @@ public class AndroidManifestParserTest extends TestCase {
private static final String ACTIVITY_NAME = "com.android.testapp.MainActivity"; //$NON-NLS-1$
private static final String LIBRARY_NAME = "android.test.runner"; //$NON-NLS-1$
private static final String INSTRUMENTATION_NAME = "android.test.InstrumentationTestRunner"; //$NON-NLS-1$
private static final String INSTRUMENTATION_TARGET = "com.android.AndroidProject"; //$NON-NLS-1$
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -51,7 +51,10 @@ public class AndroidManifestParserTest extends TestCase {
public void testGetInstrumentationInformation() {
assertEquals(1, mManifestInstrumentation.getInstrumentations().length);
assertEquals(INSTRUMENTATION_NAME, mManifestTestApp.getInstrumentations()[0]);
assertEquals(INSTRUMENTATION_NAME,
mManifestInstrumentation.getInstrumentations()[0].getName());
assertEquals(INSTRUMENTATION_TARGET,
mManifestInstrumentation.getInstrumentations()[0].getTargetPackage());
}
public void testGetPackage() {
@@ -72,11 +75,6 @@ public class AndroidManifestParserTest extends TestCase {
assertEquals(LIBRARY_NAME, mManifestTestApp.getUsesLibraries()[0]);
}
public void testGetInstrumentations() {
assertEquals(1, mManifestTestApp.getInstrumentations().length);
assertEquals(INSTRUMENTATION_NAME, mManifestTestApp.getInstrumentations()[0]);
}
public void testGetPackageName() {
assertEquals(PACKAGE_NAME, mManifestTestApp.getPackage());
}