OSDN Git Service

AI 144322: am: CL 144320 ADT: Fix debugger launch connection when debugging Android...
authorBrett Chabot <>
Thu, 2 Apr 2009 22:37:39 +0000 (15:37 -0700)
committerThe Android Open Source Project <initial-contribution@android.com>
Thu, 2 Apr 2009 22:37:39 +0000 (15:37 -0700)
  Original author: brettchabot
  Merged from: //branches/cupcake/...

Automated import of CL 144322

eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DelayedLaunchInfo.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchAction.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/common/project/AndroidManifestParserTest.java

index b6c7640..655c038 100644 (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$
index 7dae56d..f3bd28a 100644 (file)
@@ -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;
@@ -130,6 +135,17 @@ public final class DelayedLaunchInfo {
     }
 
     /**
+     * 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
      */
     public IFile getPackageFile() {
index d057ac7..9f12b16 100644 (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
index 9bcc63d..24ebe21 100644 (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; 
index 543daf0..1906792 100755 (executable)
@@ -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.
index 584d45e..34e64e3 100644 (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) {
index f22fc7c..7ebbb09 100644 (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) {
index 85ba968..f853ada 100644 (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$
@@ -77,6 +78,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/>
      * This serves both as an {@link XmlErrorHandler} to report errors and as a data repository
@@ -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;
index 7e8b0af..2f93e51 100644 (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() {
@@ -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());
     }