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:
committed by
The Android Open Source Project
parent
d63db799ea
commit
6bc8491396
@@ -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$
|
||||
|
||||
@@ -44,6 +44,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;
|
||||
@@ -79,7 +82,8 @@ public final class DelayedLaunchInfo {
|
||||
* Basic constructor with activity and package info.
|
||||
*
|
||||
* @param project the eclipse project that corresponds to Android app
|
||||
* @param packageName package name of 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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
@@ -66,17 +69,12 @@ public class AndroidManifestParserTest extends TestCase {
|
||||
public void testGetLauncherActivity() {
|
||||
assertEquals(ACTIVITY_NAME, mManifestTestApp.getLauncherActivity());
|
||||
}
|
||||
|
||||
|
||||
public void testGetUsesLibraries() {
|
||||
assertEquals(1, mManifestTestApp.getUsesLibraries().length);
|
||||
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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user