diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch')
32 files changed, 0 insertions, 8645 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AMReceiver.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AMReceiver.java deleted file mode 100644 index ea61945a2..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AMReceiver.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import com.android.ddmlib.IDevice; -import com.android.ddmlib.MultiLineReceiver; -import com.android.ide.eclipse.adt.AdtPlugin; - -import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - - -/** - * Output receiver for am process (Activity Manager) - * - * Monitors adb output for am errors, and retries launch as appropriate. - */ -public class AMReceiver extends MultiLineReceiver { - - private static final int MAX_ATTEMPT_COUNT = 5; - private static final Pattern sAmErrorType = Pattern.compile("Error type (\\d+)"); //$NON-NLS-1$ - - private final DelayedLaunchInfo mLaunchInfo; - private final IDevice mDevice; - private final ILaunchController mLaunchController; - - /** - * Basic constructor. - * - * @param launchInfo the {@link DelayedLaunchInfo} associated with the am process. - * @param device the Android device on which the launch is done. - * @param launchController the {@link ILaunchController} that is managing the launch - */ - public AMReceiver(DelayedLaunchInfo launchInfo, IDevice device, - ILaunchController launchController) { - mLaunchInfo = launchInfo; - mDevice = device; - mLaunchController = launchController; - } - - /** - * Monitors the am process for error messages. If an error occurs, will reattempt launch up to - * <code>MAX_ATTEMPT_COUNT</code> times. - * - * @param lines a portion of the am output - * - * @see MultiLineReceiver#processNewLines(String[]) - */ - @Override - public void processNewLines(String[] lines) { - // first we check if one starts with error - ArrayList<String> array = new ArrayList<String>(); - boolean error = false; - boolean warning = false; - for (String s : lines) { - // ignore empty lines. - if (s.length() == 0) { - continue; - } - - // check for errors that output an error type, if the attempt count is still - // valid. If not the whole text will be output in the console - if (mLaunchInfo.getAttemptCount() < MAX_ATTEMPT_COUNT && - mLaunchInfo.isCancelled() == false) { - Matcher m = sAmErrorType.matcher(s); - if (m.matches()) { - // get the error type - int type = Integer.parseInt(m.group(1)); - - final int waitTime = 3; - String msg; - - switch (type) { - case 1: - /* Intended fall through */ - case 2: - msg = String.format( - "Device not ready. Waiting %1$d seconds before next attempt.", - waitTime); - break; - case 3: - msg = String.format( - "New package not yet registered with the system. Waiting %1$d seconds before next attempt.", - waitTime); - break; - default: - msg = String.format( - "Device not ready (%2$d). Waiting %1$d seconds before next attempt.", - waitTime, type); - break; - - } - - AdtPlugin.printToConsole(mLaunchInfo.getProject(), msg); - - // launch another thread, that waits a bit and attempts another launch - new Thread("Delayed Launch attempt") { - @Override - public void run() { - try { - sleep(waitTime * 1000); - } catch (InterruptedException e) { - // ignore - } - - mLaunchController.launchApp(mLaunchInfo, mDevice); - } - }.start(); - - // no need to parse the rest - return; - } - } - - // check for error if needed - if (error == false && s.startsWith("Error:")) { //$NON-NLS-1$ - error = true; - } - if (warning == false && s.startsWith("Warning:")) { //$NON-NLS-1$ - warning = true; - } - - // add the line to the list - array.add("ActivityManager: " + s); //$NON-NLS-1$ - } - - // then we display them in the console - if (warning || error) { - AdtPlugin.printErrorToConsole(mLaunchInfo.getProject(), array.toArray()); - } else { - AdtPlugin.printToConsole(mLaunchInfo.getProject(), array.toArray()); - } - - // if error then we cancel the launch, and remove the delayed info - if (error) { - mLaunchController.stopLaunch(mLaunchInfo); - } - } - - /** - * Returns true if launch has been cancelled - */ - @Override - public boolean isCancelled() { - return mLaunchInfo.isCancelled(); - } -} 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 deleted file mode 100644 index 311b19aa7..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/ActivityLaunchAction.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.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; -import java.util.Collection; - -/** - * Launches the given activity - */ -public class ActivityLaunchAction implements IAndroidLaunchAction { - - private final String mActivity; - private final ILaunchController mLaunchController; - - /** - * Creates a ActivityLaunchAction - * - * @param activity fully qualified activity name to launch - * @param controller the {@link ILaunchController} that performs launch - */ - public ActivityLaunchAction(String activity, ILaunchController controller) { - mActivity = activity; - mLaunchController = controller; - } - - 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 %2$s", mActivity, - device); - AdtPlugin.printToConsole(info.getProject(), msg); - - // In debug mode, we need to add the info to the list of application monitoring - // client changes. - // increment launch attempt count, to handle retries and timeouts - info.incrementAttemptCount(); - - // now we actually launch the app. - 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! - if (info.isDebugMode() == false) { - // stop the launch object, since there's no debug, and it can't - // 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 - AdtPlugin.printErrorToConsole(info.getProject(), - String.format("Launch error: %s", e.getMessage())); - return false; - } - return true; - } - - /** - * Launches the activity on targeted device - * - * @param info the {@link DelayedLaunchInfo} that contains launch details - * @param devices list of Android devices on which the activity will be launched - */ - @Override - public boolean doLaunchAction(DelayedLaunchInfo info, Collection<IDevice> devices) { - boolean result = true; - for (IDevice d : devices) { - // Note that this expression should not short circuit - even if an action fails - // on a device, it should still be performed on all other devices. - result = doLaunchAction(info, d) && result; - } - - return result; - } - - /** - * Returns a description of the activity being launched - * - * @see IAndroidLaunchAction#getLaunchDescription() - */ - @Override - public String getLaunchDescription() { - return String.format("%1$s activity launch", mActivity); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunch.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunch.java deleted file mode 100644 index 8e2c133be..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunch.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import org.eclipse.debug.core.DebugException; -import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.debug.core.ILaunchManager; -import org.eclipse.debug.core.Launch; -import org.eclipse.debug.core.model.ISourceLocator; - -/** - * Custom implementation of Launch to allow access to the LaunchManager - * - */ -public class AndroidLaunch extends Launch { - - /** - * Basic constructor does nothing special - * @param launchConfiguration - * @param mode - * @param locator - */ - public AndroidLaunch(ILaunchConfiguration launchConfiguration, String mode, - ISourceLocator locator) { - super(launchConfiguration, mode, locator); - } - - /** Stops the launch, and removes it from the launch manager */ - public void stopLaunch() { - ILaunchManager mgr = getLaunchManager(); - - if (canTerminate()) { - try { - terminate(); - } catch (DebugException e) { - // well looks like we couldn't stop it. nothing else to be - // done really - } - } - // remove the launch - mgr.removeLaunch(this); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchConfiguration.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchConfiguration.java deleted file mode 100644 index 580bbbee5..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchConfiguration.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import org.eclipse.core.runtime.CoreException; -import org.eclipse.debug.core.ILaunchConfiguration; - -/** - * Launch configuration data. This stores the result of querying the - * {@link ILaunchConfiguration} so that it's only done once. - */ -public class AndroidLaunchConfiguration { - - /** - * Launch action. See {@link LaunchConfigDelegate#ACTION_DEFAULT}, - * {@link LaunchConfigDelegate#ACTION_ACTIVITY}, - * {@link LaunchConfigDelegate#ACTION_DO_NOTHING} - */ - public int mLaunchAction = LaunchConfigDelegate.DEFAULT_LAUNCH_ACTION; - - /** Target selection mode for the configuration. */ - public enum TargetMode { - /** Automatic target selection mode. */ - AUTO, - /** Manual target selection mode. */ - MANUAL, - /** All active devices */ - ALL_DEVICES, - /** All active emulators */ - ALL_EMULATORS, - /** All active devices and emulators */ - ALL_DEVICES_AND_EMULATORS; - - public static TargetMode getMode(String s) { - for (TargetMode m: values()) { - if (m.toString().equals(s)) { - return m; - } - } - - throw new IllegalArgumentException(String.format( - "Invalid representation (%s) for TargetMode", s)); - } - - public boolean isMultiDevice() { - return this == ALL_DEVICES - || this == ALL_EMULATORS - || this == ALL_DEVICES_AND_EMULATORS; - } - } - - /** - * Target selection mode. - * @see TargetMode - */ - public TargetMode mTargetMode = LaunchConfigDelegate.DEFAULT_TARGET_MODE; - - /** - * Indicates whether the emulator should be called with -wipe-data - */ - public boolean mWipeData = LaunchConfigDelegate.DEFAULT_WIPE_DATA; - - /** - * Indicates whether the emulator should be called with -no-boot-anim - */ - public boolean mNoBootAnim = LaunchConfigDelegate.DEFAULT_NO_BOOT_ANIM; - - /** - * AVD Name. - */ - public String mAvdName = null; - - public String mNetworkSpeed = EmulatorConfigTab.getSpeed( - LaunchConfigDelegate.DEFAULT_SPEED); - public String mNetworkDelay = EmulatorConfigTab.getDelay( - LaunchConfigDelegate.DEFAULT_DELAY); - - /** - * Optional custom command line parameter to launch the emulator - */ - public String mEmulatorCommandLine; - - /** Flag indicating whether the same device should be used for future launches. */ - public boolean mReuseLastUsedDevice = false; - - /** Serial number of the device used in the last launch of this config. */ - public String mLastUsedDevice = null; - - /** - * Initialized the structure from an ILaunchConfiguration object. - * @param config - */ - public void set(ILaunchConfiguration config) { - try { - mLaunchAction = config.getAttribute(LaunchConfigDelegate.ATTR_LAUNCH_ACTION, - mLaunchAction); - } catch (CoreException e1) { - // nothing to be done here, we'll use the default value - } - - mTargetMode = parseTargetMode(config, mTargetMode); - - try { - mReuseLastUsedDevice = config.getAttribute( - LaunchConfigDelegate.ATTR_REUSE_LAST_USED_DEVICE, false); - mLastUsedDevice = config.getAttribute( - LaunchConfigDelegate.ATTR_LAST_USED_DEVICE, (String)null); - } catch (CoreException e) { - // nothing to be done here, we'll use the default value - } - - try { - mAvdName = config.getAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, mAvdName); - } catch (CoreException e) { - // ignore - } - - int index = LaunchConfigDelegate.DEFAULT_SPEED; - try { - index = config.getAttribute(LaunchConfigDelegate.ATTR_SPEED, index); - } catch (CoreException e) { - // nothing to be done here, we'll use the default value - } - mNetworkSpeed = EmulatorConfigTab.getSpeed(index); - - index = LaunchConfigDelegate.DEFAULT_DELAY; - try { - index = config.getAttribute(LaunchConfigDelegate.ATTR_DELAY, index); - } catch (CoreException e) { - // nothing to be done here, we'll use the default value - } - mNetworkDelay = EmulatorConfigTab.getDelay(index); - - try { - mEmulatorCommandLine = config.getAttribute( - LaunchConfigDelegate.ATTR_COMMANDLINE, ""); //$NON-NLS-1$ - } catch (CoreException e) { - // lets not do anything here, we'll use the default value - } - - try { - mWipeData = config.getAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, mWipeData); - } catch (CoreException e) { - // nothing to be done here, we'll use the default value - } - - try { - mNoBootAnim = config.getAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM, - mNoBootAnim); - } catch (CoreException e) { - // nothing to be done here, we'll use the default value - } - } - - /** - * Retrieve the {@link TargetMode} saved in the provided launch configuration. - * Returns defaultMode if there are any errors while retrieving or parsing the saved setting. - */ - public static TargetMode parseTargetMode(ILaunchConfiguration config, TargetMode defaultMode) { - try { - String value = config.getAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE, - defaultMode.toString()); - return TargetMode.getMode(value); - } catch (CoreException e) { - // ADT R20 changes the attribute type of ATTR_TARGET_MODE to be a string from a bool. - // So if parsing as a string fails, attempt parsing as a boolean. - try { - boolean value = config.getAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE, true); - return value ? TargetMode.AUTO : TargetMode.MANUAL; - } catch (CoreException e1) { - return defaultMode; - } - } catch (IllegalArgumentException e) { - return defaultMode; - } - } -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java deleted file mode 100644 index a95ed6882..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java +++ /dev/null @@ -1,1872 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ddmlib.AdbCommandRejectedException; -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener; -import com.android.ddmlib.AndroidDebugBridge.IDebugBridgeChangeListener; -import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener; -import com.android.ddmlib.CanceledException; -import com.android.ddmlib.Client; -import com.android.ddmlib.ClientData; -import com.android.ddmlib.ClientData.DebuggerStatus; -import com.android.ddmlib.IDevice; -import com.android.ddmlib.InstallException; -import com.android.ddmlib.Log; -import com.android.ddmlib.TimeoutException; -import com.android.ide.common.xml.ManifestData; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.actions.AvdManagerAction; -import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo; -import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchConfiguration.TargetMode; -import com.android.ide.eclipse.adt.internal.launch.DelayedLaunchInfo.InstallRetryMode; -import com.android.ide.eclipse.adt.internal.launch.DeviceChooserDialog.DeviceChooserResponse; -import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; -import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper; -import com.android.ide.eclipse.adt.internal.project.ApkInstallManager; -import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; -import com.android.ide.eclipse.adt.internal.project.ProjectHelper; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.ide.eclipse.ddms.DdmsPlugin; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.utils.NullLogger; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.debug.core.DebugPlugin; -import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.debug.core.ILaunchConfigurationType; -import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; -import org.eclipse.debug.core.ILaunchManager; -import org.eclipse.debug.core.model.IDebugTarget; -import org.eclipse.debug.ui.DebugUITools; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; -import org.eclipse.jdt.launching.IVMConnector; -import org.eclipse.jdt.launching.JavaRuntime; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map.Entry; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Controls the launch of Android application either on a device or on the - * emulator. If an emulator is already running, this class will attempt to reuse - * it. - */ -public final class AndroidLaunchController implements IDebugBridgeChangeListener, - IDeviceChangeListener, IClientChangeListener, ILaunchController { - - private static final String FLAG_AVD = "-avd"; //$NON-NLS-1$ - private static final String FLAG_NETDELAY = "-netdelay"; //$NON-NLS-1$ - private static final String FLAG_NETSPEED = "-netspeed"; //$NON-NLS-1$ - private static final String FLAG_WIPE_DATA = "-wipe-data"; //$NON-NLS-1$ - private static final String FLAG_NO_BOOT_ANIM = "-no-boot-anim"; //$NON-NLS-1$ - - /** - * Map to store {@link ILaunchConfiguration} objects that must be launched as simple connection - * to running application. The integer is the port on which to connect. - * <b>ALL ACCESS MUST BE INSIDE A <code>synchronized (sListLock)</code> block!</b> - */ - private static final HashMap<ILaunchConfiguration, Integer> sRunningAppMap = - new HashMap<ILaunchConfiguration, Integer>(); - - private static final Object sListLock = sRunningAppMap; - - /** - * List of {@link DelayedLaunchInfo} waiting for an emulator to connect. - * <p>Once an emulator has connected, {@link DelayedLaunchInfo#getDevice()} is set and the - * DelayedLaunchInfo object is moved to - * {@link AndroidLaunchController#mWaitingForReadyEmulatorList}. - * <b>ALL ACCESS MUST BE INSIDE A <code>synchronized (sListLock)</code> block!</b> - */ - private final ArrayList<DelayedLaunchInfo> mWaitingForEmulatorLaunches = - new ArrayList<DelayedLaunchInfo>(); - - /** - * List of application waiting to be launched on a device/emulator.<br> - * <b>ALL ACCESS MUST BE INSIDE A <code>synchronized (sListLock)</code> block!</b> - * */ - private final ArrayList<DelayedLaunchInfo> mWaitingForReadyEmulatorList = - new ArrayList<DelayedLaunchInfo>(); - - /** - * Application waiting to show up as waiting for debugger. - * <b>ALL ACCESS MUST BE INSIDE A <code>synchronized (sListLock)</code> block!</b> - */ - private final ArrayList<DelayedLaunchInfo> mWaitingForDebuggerApplications = - new ArrayList<DelayedLaunchInfo>(); - - /** - * List of clients that have appeared as waiting for debugger before their name was available. - * <b>ALL ACCESS MUST BE INSIDE A <code>synchronized (sListLock)</code> block!</b> - */ - private final ArrayList<Client> mUnknownClientsWaitingForDebugger = new ArrayList<Client>(); - - /** static instance for singleton */ - private static AndroidLaunchController sThis = new AndroidLaunchController(); - - /** private constructor to enforce singleton */ - private AndroidLaunchController() { - AndroidDebugBridge.addDebugBridgeChangeListener(this); - AndroidDebugBridge.addDeviceChangeListener(this); - AndroidDebugBridge.addClientChangeListener(this); - } - - /** - * Returns the singleton reference. - */ - public static AndroidLaunchController getInstance() { - return sThis; - } - - - /** - * Launches a remote java debugging session on an already running application - * @param project The project of the application to debug. - * @param debugPort The port to connect the debugger to. - */ - public static void debugRunningApp(IProject project, int debugPort) { - // get an existing or new launch configuration - ILaunchConfiguration config = AndroidLaunchController.getLaunchConfig(project, - LaunchConfigDelegate.ANDROID_LAUNCH_TYPE_ID); - - if (config != null) { - setPortLaunchConfigAssociation(config, debugPort); - - // and launch - DebugUITools.launch(config, ILaunchManager.DEBUG_MODE); - } - } - - /** - * Returns an {@link ILaunchConfiguration} for the specified {@link IProject}. - * @param project the project - * @param launchTypeId launch delegate type id - * @return a new or already existing <code>ILaunchConfiguration</code> or null if there was - * an error when creating a new one. - */ - public static ILaunchConfiguration getLaunchConfig(IProject project, String launchTypeId) { - // get the launch manager - ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); - - // now get the config type for our particular android type. - ILaunchConfigurationType configType = manager.getLaunchConfigurationType(launchTypeId); - - String name = project.getName(); - - // search for an existing launch configuration - ILaunchConfiguration config = findConfig(manager, configType, name); - - // test if we found one or not - if (config == null) { - // Didn't find a matching config, so we make one. - // It'll be made in the "working copy" object first. - ILaunchConfigurationWorkingCopy wc = null; - - try { - // make the working copy object - wc = configType.newInstance(null, - manager.generateLaunchConfigurationName(name)); - - // set the project name - wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, name); - - // set the launch mode to default. - wc.setAttribute(LaunchConfigDelegate.ATTR_LAUNCH_ACTION, - LaunchConfigDelegate.DEFAULT_LAUNCH_ACTION); - - // set default target mode - wc.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE, - LaunchConfigDelegate.DEFAULT_TARGET_MODE.toString()); - - // default AVD: None - wc.setAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, (String) null); - - // set the default network speed - wc.setAttribute(LaunchConfigDelegate.ATTR_SPEED, - LaunchConfigDelegate.DEFAULT_SPEED); - - // and delay - wc.setAttribute(LaunchConfigDelegate.ATTR_DELAY, - LaunchConfigDelegate.DEFAULT_DELAY); - - // default wipe data mode - wc.setAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, - LaunchConfigDelegate.DEFAULT_WIPE_DATA); - - // default disable boot animation option - wc.setAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM, - LaunchConfigDelegate.DEFAULT_NO_BOOT_ANIM); - - // set default emulator options - IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore(); - String emuOptions = store.getString(AdtPrefs.PREFS_EMU_OPTIONS); - wc.setAttribute(LaunchConfigDelegate.ATTR_COMMANDLINE, emuOptions); - - // map the config and the project - wc.setMappedResources(getResourcesToMap(project)); - - // save the working copy to get the launch config object which we return. - return wc.doSave(); - - } catch (CoreException e) { - String msg = String.format( - "Failed to create a Launch config for project '%1$s': %2$s", - project.getName(), e.getMessage()); - AdtPlugin.printErrorToConsole(project, msg); - - // no launch! - return null; - } - } - - return config; - } - - /** - * Returns the list of resources to map to a Launch Configuration. - * @param project the project associated to the launch configuration. - */ - public static IResource[] getResourcesToMap(IProject project) { - ArrayList<IResource> array = new ArrayList<IResource>(2); - array.add(project); - - IFile manifest = ProjectHelper.getManifest(project); - if (manifest != null) { - array.add(manifest); - } - - return array.toArray(new IResource[array.size()]); - } - - /** - * Launches an android app on the device or emulator - * - * @param project The project we're launching - * @param mode the mode in which to launch, one of the mode constants - * 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's manifest, or null if not set. - * @param requiredApiVersionNumber the api version required by the app, or null if none. - * @param launchAction the action to perform after app sync - * @param config the launch configuration - * @param launch the launch object - */ - public void launch(final IProject project, String mode, IFile apk, - String packageName, String debugPackageName, Boolean debuggable, - String requiredApiVersionNumber, final IAndroidLaunchAction launchAction, - final AndroidLaunchConfiguration config, final AndroidLaunch launch, - IProgressMonitor monitor) { - - String message = String.format("Performing %1$s", launchAction.getLaunchDescription()); - AdtPlugin.printToConsole(project, message); - - // create the launch info - final DelayedLaunchInfo launchInfo = new DelayedLaunchInfo(project, packageName, - debugPackageName, launchAction, apk, debuggable, requiredApiVersionNumber, launch, - monitor); - - // set the debug mode - launchInfo.setDebugMode(mode.equals(ILaunchManager.DEBUG_MODE)); - - // get the SDK - Sdk currentSdk = Sdk.getCurrent(); - AvdManager avdManager = currentSdk.getAvdManager(); - - // reload the AVDs to make sure we are up to date - try { - avdManager.reloadAvds(NullLogger.getLogger()); - } catch (AndroidLocationException e1) { - // this happens if the AVD Manager failed to find the folder in which the AVDs are - // stored. This is unlikely to happen, but if it does, we should force to go manual - // to allow using physical devices. - config.mTargetMode = TargetMode.MANUAL; - } - - // get the sdk against which the project is built - IAndroidTarget projectTarget = currentSdk.getTarget(project); - - // get the min required android version - ManifestInfo mi = ManifestInfo.get(project); - final int minApiLevel = mi.getMinSdkVersion(); - final String minApiCodeName = mi.getMinSdkCodeName(); - final AndroidVersion minApiVersion = new AndroidVersion(minApiLevel, minApiCodeName); - - // FIXME: check errors on missing sdk, AVD manager, or project target. - - // device chooser response object. - final DeviceChooserResponse response = new DeviceChooserResponse(); - - /* - * Launch logic: - * - Use Last Launched Device/AVD set. - * If user requested to use same device for future launches, and the last launched - * device/avd is still present, then simply launch on the same device/avd. - * - Manual Mode - * Always display a UI that lets a user see the current running emulators/devices. - * The UI must show which devices are compatibles, and allow launching new emulators - * with compatible (and not yet running) AVD. - * - Automatic Way - * * Preferred AVD set. - * If Preferred AVD is not running: launch it. - * Launch the application on the preferred AVD. - * * No preferred AVD. - * Count the number of compatible emulators/devices. - * If != 1, display a UI similar to manual mode. - * If == 1, launch the application on this AVD/device. - * - Launch on multiple devices: - * From the currently active devices & emulators, filter out those that cannot run - * the app (by api level), and launch on all the others. - */ - IDevice[] devices = AndroidDebugBridge.getBridge().getDevices(); - if (config.mReuseLastUsedDevice) { - // check to see if the last used device is still online - IDevice lastUsedDevice = getDeviceIfOnline(config.mLastUsedDevice, - devices); - if (lastUsedDevice != null) { - response.setDeviceToUse(lastUsedDevice); - continueLaunch(response, project, launch, launchInfo, config); - return; - } - } - - if (config.mTargetMode == TargetMode.AUTO) { - // first check if we have a preferred AVD name, and if it actually exists, and is valid - // (ie able to run the project). - // We need to check this in case the AVD was recreated with a different target that is - // not compatible. - AvdInfo preferredAvd = null; - if (config.mAvdName != null) { - preferredAvd = avdManager.getAvd(config.mAvdName, true /*validAvdOnly*/); - } - - if (preferredAvd != null) { - IAndroidTarget preferredAvdTarget = preferredAvd.getTarget(); - if (preferredAvdTarget != null - && !preferredAvdTarget.getVersion().canRun(minApiVersion)) { - preferredAvd = null; - - AdtPlugin.printErrorToConsole(project, String.format( - "Preferred AVD '%1$s' (API Level: %2$d) cannot run application with minApi %3$s. Looking for a compatible AVD...", - config.mAvdName, - preferredAvdTarget.getVersion().getApiLevel(), - minApiVersion)); - } - } - - if (preferredAvd != null) { - // We have a preferred avd that can actually run the application. - // Now see if the AVD is running, and if so use it, otherwise launch it. - - for (IDevice d : devices) { - String deviceAvd = d.getAvdName(); - if (deviceAvd != null && deviceAvd.equals(config.mAvdName)) { - response.setDeviceToUse(d); - - AdtPlugin.printToConsole(project, String.format( - "Automatic Target Mode: Preferred AVD '%1$s' is available on emulator '%2$s'", - config.mAvdName, d)); - - continueLaunch(response, project, launch, launchInfo, config); - return; - } - } - - // at this point we have a valid preferred AVD that is not running. - // We need to start it. - response.setAvdToLaunch(preferredAvd); - - AdtPlugin.printToConsole(project, String.format( - "Automatic Target Mode: Preferred AVD '%1$s' is not available. Launching new emulator.", - config.mAvdName)); - - continueLaunch(response, project, launch, launchInfo, config); - return; - } - - // no (valid) preferred AVD? look for one. - - // If the API level requested in the manifest is lower than the current project - // target, when we will iterate devices/avds later ideally we will want to find - // a device/avd which target is as close to the manifest as possible (instead of - // a device which target is the same as the project's target) and use it as the - // new default. - - if (minApiCodeName != null && minApiLevel < projectTarget.getVersion().getApiLevel()) { - int maxDist = projectTarget.getVersion().getApiLevel() - minApiLevel; - IAndroidTarget candidate = null; - - for (IAndroidTarget target : currentSdk.getTargets()) { - if (target.canRunOn(projectTarget)) { - int currDist = target.getVersion().getApiLevel() - minApiLevel; - if (currDist >= 0 && currDist < maxDist) { - maxDist = currDist; - candidate = target; - if (maxDist == 0) { - // Found a perfect match - break; - } - } - } - } - - if (candidate != null) { - // We found a better SDK target candidate, that is closer to the - // API level from minSdkVersion than the one currently used by the - // project. Below (in the for...devices loop) we'll try to find - // a device/AVD for it. - projectTarget = candidate; - } - } - - HashMap<IDevice, AvdInfo> compatibleRunningAvds = new HashMap<IDevice, AvdInfo>(); - boolean hasDevice = false; // if there's 1+ device running, we may force manual mode, - // as we cannot always detect proper compatibility with - // devices. This is the case if the project target is not - // a standard platform - for (IDevice d : devices) { - String deviceAvd = d.getAvdName(); - if (deviceAvd != null) { // physical devices return null. - AvdInfo info = avdManager.getAvd(deviceAvd, true /*validAvdOnly*/); - if (AvdCompatibility.canRun(info, projectTarget, minApiVersion) - == AvdCompatibility.Compatibility.YES) { - compatibleRunningAvds.put(d, info); - } - } else { - if (projectTarget.isPlatform()) { // means this can run on any device as long - // as api level is high enough - AndroidVersion deviceVersion = Sdk.getDeviceVersion(d); - // the deviceVersion may be null if it wasn't yet queried (device just - // plugged in or emulator just booting up. - if (deviceVersion != null && - deviceVersion.canRun(projectTarget.getVersion())) { - // device is compatible with project - compatibleRunningAvds.put(d, null); - continue; - } - } else { - // for non project platform, we can't be sure if a device can - // run an application or not, since we don't query the device - // for the list of optional libraries that it supports. - } - hasDevice = true; - } - } - - // depending on the number of devices, we'll simulate an automatic choice - // from the device chooser or simply show up the device chooser. - if (hasDevice == false && compatibleRunningAvds.size() == 0) { - // if zero emulators/devices, we launch an emulator. - // We need to figure out which AVD first. - - // we are going to take the closest AVD. ie a compatible AVD that has the API level - // closest to the project target. - AvdInfo defaultAvd = findMatchingAvd(avdManager, projectTarget, minApiVersion); - - if (defaultAvd != null) { - response.setAvdToLaunch(defaultAvd); - - AdtPlugin.printToConsole(project, String.format( - "Automatic Target Mode: launching new emulator with compatible AVD '%1$s'", - defaultAvd.getName())); - - continueLaunch(response, project, launch, launchInfo, config); - return; - } else { - AdtPlugin.printToConsole(project, String.format( - "Failed to find an AVD compatible with target '%1$s'.", - projectTarget.getName())); - - final Display display = AdtPlugin.getDisplay(); - final boolean[] searchAgain = new boolean[] { false }; - // ask the user to create a new one. - display.syncExec(new Runnable() { - @Override - public void run() { - Shell shell = display.getActiveShell(); - if (MessageDialog.openQuestion(shell, "Android AVD Error", - "No compatible targets were found. Do you wish to add a new Android Virtual Device?")) { - AvdManagerAction action = new AvdManagerAction(); - action.run(null /*action*/); - searchAgain[0] = true; - } - } - }); - if (searchAgain[0]) { - // attempt to reload the AVDs and find one compatible. - defaultAvd = findMatchingAvd(avdManager, projectTarget, minApiVersion); - - if (defaultAvd == null) { - AdtPlugin.printErrorToConsole(project, String.format( - "Still no compatible AVDs with target '%1$s': Aborting launch.", - projectTarget.getName())); - stopLaunch(launchInfo); - } else { - response.setAvdToLaunch(defaultAvd); - - AdtPlugin.printToConsole(project, String.format( - "Launching new emulator with compatible AVD '%1$s'", - defaultAvd.getName())); - - continueLaunch(response, project, launch, launchInfo, config); - return; - } - } - } - } else if (hasDevice == false && compatibleRunningAvds.size() == 1) { - Entry<IDevice, AvdInfo> e = compatibleRunningAvds.entrySet().iterator().next(); - response.setDeviceToUse(e.getKey()); - - // get the AvdInfo, if null, the device is a physical device. - AvdInfo avdInfo = e.getValue(); - if (avdInfo != null) { - message = String.format("Automatic Target Mode: using existing emulator '%1$s' running compatible AVD '%2$s'", - response.getDeviceToUse(), e.getValue().getName()); - } else { - message = String.format("Automatic Target Mode: using device '%1$s'", - response.getDeviceToUse()); - } - AdtPlugin.printToConsole(project, message); - - continueLaunch(response, project, launch, launchInfo, config); - return; - } - - // if more than one device, we'll bring up the DeviceChooser dialog below. - if (compatibleRunningAvds.size() >= 2) { - message = "Automatic Target Mode: Several compatible targets. Please select a target device."; - } else if (hasDevice) { - message = "Automatic Target Mode: Unable to detect device compatibility. Please select a target device."; - } - - AdtPlugin.printToConsole(project, message); - } else if ((config.mTargetMode == TargetMode.ALL_DEVICES_AND_EMULATORS - || config.mTargetMode == TargetMode.ALL_DEVICES - || config.mTargetMode == TargetMode.ALL_EMULATORS) - && ILaunchManager.RUN_MODE.equals(mode)) { - // if running on multiple devices, identify all compatible devices - boolean includeDevices = config.mTargetMode != TargetMode.ALL_EMULATORS; - boolean includeAvds = config.mTargetMode != TargetMode.ALL_DEVICES; - Collection<IDevice> compatibleDevices = findCompatibleDevices(devices, - minApiVersion, includeDevices, includeAvds); - if (compatibleDevices.size() == 0) { - AdtPlugin.printErrorToConsole(project, - "No active compatible AVD's or devices found. " - + "Relaunch this configuration after connecting a device or starting an AVD."); - stopLaunch(launchInfo); - } else { - multiLaunch(launchInfo, compatibleDevices); - } - return; - } - - // bring up the device chooser. - final IAndroidTarget desiredProjectTarget = projectTarget; - final AtomicBoolean continueLaunch = new AtomicBoolean(false); - AdtPlugin.getDisplay().syncExec(new Runnable() { - @Override - public void run() { - try { - // open the chooser dialog. It'll fill 'response' with the device to use - // or the AVD to launch. - DeviceChooserDialog dialog = new DeviceChooserDialog( - AdtPlugin.getShell(), - response, launchInfo.getPackageName(), - desiredProjectTarget, minApiVersion, - config.mReuseLastUsedDevice); - if (dialog.open() == Dialog.OK) { - updateLaunchConfigWithLastUsedDevice(launch.getLaunchConfiguration(), - response); - continueLaunch.set(true); - } else { - AdtPlugin.printErrorToConsole(project, "Launch canceled!"); - stopLaunch(launchInfo); - return; - } - } catch (Exception e) { - // there seems to be some case where the shell will be null. (might be - // an OS X bug). Because of this the creation of the dialog will throw - // and IllegalArg exception interrupting the launch with no user feedback. - // So we trap all the exception and display something. - String msg = e.getMessage(); - if (msg == null) { - msg = e.getClass().getCanonicalName(); - } - AdtPlugin.printErrorToConsole(project, - String.format("Error during launch: %s", msg)); - stopLaunch(launchInfo); - } - } - }); - - if (continueLaunch.get()) { - continueLaunch(response, project, launch, launchInfo, config); - } - } - - /** - * Returns devices that can run a app of provided API level. - * @param devices list of devices to filter from - * @param requiredVersion minimum required API that should be supported - * @param includeDevices include physical devices in the filtered list - * @param includeAvds include emulators in the filtered list - * @return set of compatible devices, may be an empty set - */ - private Collection<IDevice> findCompatibleDevices(IDevice[] devices, - AndroidVersion requiredVersion, boolean includeDevices, boolean includeAvds) { - Set<IDevice> compatibleDevices = new HashSet<IDevice>(devices.length); - AvdManager avdManager = Sdk.getCurrent().getAvdManager(); - for (IDevice d: devices) { - boolean isEmulator = d.isEmulator(); - boolean canRun = false; - - if (isEmulator) { - if (!includeAvds) { - continue; - } - - AvdInfo avdInfo = avdManager.getAvd(d.getAvdName(), true); - if (avdInfo != null && avdInfo.getTarget() != null) { - canRun = avdInfo.getTarget().getVersion().canRun(requiredVersion); - } - } else { - if (!includeDevices) { - continue; - } - - AndroidVersion deviceVersion = Sdk.getDeviceVersion(d); - if (deviceVersion != null) { - canRun = deviceVersion.canRun(requiredVersion); - } - } - - if (canRun) { - compatibleDevices.add(d); - } - } - - return compatibleDevices; - } - - /** - * Find a matching AVD. - * @param minApiVersion - */ - private AvdInfo findMatchingAvd(AvdManager avdManager, final IAndroidTarget projectTarget, - AndroidVersion minApiVersion) { - AvdInfo[] avds = avdManager.getValidAvds(); - AvdInfo bestAvd = null; - for (AvdInfo avd : avds) { - if (AvdCompatibility.canRun(avd, projectTarget, minApiVersion) - == AvdCompatibility.Compatibility.YES) { - // at this point we can ignore the code name issue since - // AvdCompatibility.canRun() will already have filtered out the non compatible AVDs. - if (bestAvd == null || - avd.getTarget().getVersion().getApiLevel() < - bestAvd.getTarget().getVersion().getApiLevel()) { - bestAvd = avd; - } - } - } - return bestAvd; - } - - /** - * Continues the launch based on the DeviceChooser response. - * @param response the device chooser response - * @param project The project being launched - * @param launch The eclipse launch info - * @param launchInfo The {@link DelayedLaunchInfo} - * @param config The config needed to start a new emulator. - */ - private void continueLaunch(final DeviceChooserResponse response, final IProject project, - final AndroidLaunch launch, final DelayedLaunchInfo launchInfo, - final AndroidLaunchConfiguration config) { - if (response.getAvdToLaunch() != null) { - // there was no selected device, we start a new emulator. - synchronized (sListLock) { - AvdInfo info = response.getAvdToLaunch(); - mWaitingForEmulatorLaunches.add(launchInfo); - AdtPlugin.printToConsole(project, String.format( - "Launching a new emulator with Virtual Device '%1$s'", - info.getName())); - boolean status = launchEmulator(config, info); - - if (status == false) { - // launching the emulator failed! - AdtPlugin.displayError("Emulator Launch", - "Couldn't launch the emulator! Make sure the SDK directory is properly setup and the emulator is not missing."); - - // stop the launch and return - mWaitingForEmulatorLaunches.remove(launchInfo); - AdtPlugin.printErrorToConsole(project, "Launch canceled!"); - stopLaunch(launchInfo); - return; - } - - return; - } - } else if (response.getDeviceToUse() != null) { - launchInfo.setDevice(response.getDeviceToUse()); - simpleLaunch(launchInfo, launchInfo.getDevice()); - } - } - - /** - * Queries for a debugger port for a specific {@link ILaunchConfiguration}. - * <p/> - * If the configuration and a debugger port where added through - * {@link #setPortLaunchConfigAssociation(ILaunchConfiguration, int)}, then this method - * will return the debugger port, and remove the configuration from the list. - * @param launchConfig the {@link ILaunchConfiguration} - * @return the debugger port or {@link LaunchConfigDelegate#INVALID_DEBUG_PORT} if the - * configuration was not setup. - */ - static int getPortForConfig(ILaunchConfiguration launchConfig) { - synchronized (sListLock) { - Integer port = sRunningAppMap.get(launchConfig); - if (port != null) { - sRunningAppMap.remove(launchConfig); - return port; - } - } - - return LaunchConfigDelegate.INVALID_DEBUG_PORT; - } - - /** - * Set a {@link ILaunchConfiguration} and its associated debug port, in the list of - * launch config to connect directly to a running app instead of doing full launch (sync, - * launch, and connect to). - * @param launchConfig the {@link ILaunchConfiguration} object. - * @param port The debugger port to connect to. - */ - private static void setPortLaunchConfigAssociation(ILaunchConfiguration launchConfig, - int port) { - synchronized (sListLock) { - sRunningAppMap.put(launchConfig, port); - } - } - - /** - * Checks the build information, and returns whether the launch should continue. - * <p/>The value tested are: - * <ul> - * <li>Minimum API version requested by the application. If the target device does not match, - * the launch is canceled.</li> - * <li>Debuggable attribute of the application and whether or not the device requires it. If - * the device requires it and it is not set in the manifest, the launch will be forced to - * "release" mode instead of "debug"</li> - * <ul> - */ - private boolean checkBuildInfo(DelayedLaunchInfo launchInfo, IDevice device) { - if (device != null) { - // check the app required API level versus the target device API level - - String deviceVersion = device.getProperty(IDevice.PROP_BUILD_VERSION); - String deviceApiLevelString = device.getProperty(IDevice.PROP_BUILD_API_LEVEL); - String deviceCodeName = device.getProperty(IDevice.PROP_BUILD_CODENAME); - - int deviceApiLevel = -1; - try { - deviceApiLevel = Integer.parseInt(deviceApiLevelString); - } catch (NumberFormatException e) { - // pass, we'll keep the apiLevel value at -1. - } - - String requiredApiString = launchInfo.getRequiredApiVersionNumber(); - if (requiredApiString != null) { - int requiredApi = -1; - try { - requiredApi = Integer.parseInt(requiredApiString); - } catch (NumberFormatException e) { - // pass, we'll keep requiredApi value at -1. - } - - if (requiredApi == -1) { - // this means the manifest uses a codename for minSdkVersion - // check that the device is using the same codename - if (requiredApiString.equals(deviceCodeName) == false) { - AdtPlugin.printErrorToConsole(launchInfo.getProject(), String.format( - "ERROR: Application requires a device running '%1$s'!", - requiredApiString)); - return false; - } - } else { - // app requires a specific API level - if (deviceApiLevel == -1) { - AdtPlugin.printToConsole(launchInfo.getProject(), - "WARNING: Unknown device API version!"); - } else if (deviceApiLevel < requiredApi) { - String msg = String.format( - "ERROR: Application requires API version %1$d. Device API version is %2$d (Android %3$s).", - requiredApi, deviceApiLevel, deviceVersion); - AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg); - - // abort the launch - return false; - } - } - } else { - // warn the application API level requirement is not set. - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - "WARNING: Application does not specify an API level requirement!"); - - // and display the target device API level (if known) - if (deviceApiLevel == -1) { - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - "WARNING: Unknown device API version!"); - } else { - AdtPlugin.printErrorToConsole(launchInfo.getProject(), String.format( - "Device API version is %1$d (Android %2$s)", deviceApiLevel, - deviceVersion)); - } - } - - // now checks that the device/app can be debugged (if needed) - if (device.isEmulator() == false && launchInfo.isDebugMode()) { - String debuggableDevice = device.getProperty(IDevice.PROP_DEBUGGABLE); - if (debuggableDevice != null && debuggableDevice.equals("0")) { //$NON-NLS-1$ - // the device is "secure" and requires apps to declare themselves as debuggable! - // launchInfo.getDebuggable() will return null if the manifest doesn't declare - // anything. In this case this is fine since the build system does insert - // debuggable=true. The only case to look for is if false is manually set - // in the manifest. - if (launchInfo.getDebuggable() == Boolean.FALSE) { - String message = String.format("Application '%1$s' has its 'debuggable' attribute set to FALSE and cannot be debugged.", - launchInfo.getPackageName()); - AdtPlugin.printErrorToConsole(launchInfo.getProject(), message); - - // because am -D does not check for ro.debuggable and the - // 'debuggable' attribute, it is important we do not use the -D option - // in this case or the app will wait for a debugger forever and never - // really launch. - launchInfo.setDebugMode(false); - } - } - } - } - - return true; - } - - /** - * Do a simple launch on the specified device, attempting to sync the new - * package, and then launching the application. Failed sync/launch will - * stop the current AndroidLaunch and return false; - * @param launchInfo - * @param device - * @return true if succeed - */ - private boolean simpleLaunch(DelayedLaunchInfo launchInfo, IDevice device) { - if (!doPreLaunchActions(launchInfo, device)) { - AdtPlugin.printErrorToConsole(launchInfo.getProject(), "Launch canceled!"); - stopLaunch(launchInfo); - return false; - } - - // launch the app - launchApp(launchInfo, device); - - return true; - } - - private boolean doPreLaunchActions(DelayedLaunchInfo launchInfo, IDevice device) { - // API level check - if (!checkBuildInfo(launchInfo, device)) { - return false; - } - - // sync app - if (!syncApp(launchInfo, device)) { - return false; - } - - return true; - } - - private void multiLaunch(DelayedLaunchInfo launchInfo, Collection<IDevice> devices) { - for (IDevice d: devices) { - boolean success = doPreLaunchActions(launchInfo, d); - if (!success) { - String deviceName = d.isEmulator() ? d.getAvdName() : d.getSerialNumber(); - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - "Launch failed on device: " + deviceName); - continue; - } - } - - doLaunchAction(launchInfo, devices); - - // multiple launches are only supported for run configuration, so we can terminate - // the launch itself - stopLaunch(launchInfo); - } - - /** - * If needed, syncs the application and all its dependencies on the device/emulator. - * - * @param launchInfo The Launch information object. - * @param device the device on which to sync the application - * @return true if the install succeeded. - */ - private boolean syncApp(DelayedLaunchInfo launchInfo, IDevice device) { - boolean alreadyInstalled = ApkInstallManager.getInstance().isApplicationInstalled( - launchInfo.getProject(), launchInfo.getPackageName(), device); - - if (alreadyInstalled) { - AdtPlugin.printToConsole(launchInfo.getProject(), - "Application already deployed. No need to reinstall."); - } else { - if (doSyncApp(launchInfo, device) == false) { - return false; - } - } - - // The app is now installed, now try the dependent projects - for (DelayedLaunchInfo dependentLaunchInfo : getDependenciesLaunchInfo(launchInfo)) { - String msg = String.format("Project dependency found, installing: %s", - dependentLaunchInfo.getProject().getName()); - AdtPlugin.printToConsole(launchInfo.getProject(), msg); - if (syncApp(dependentLaunchInfo, device) == false) { - return false; - } - } - - return true; - } - - /** - * Syncs the application on the device/emulator. - * - * @param launchInfo The Launch information object. - * @param device the device on which to sync the application - * @return true if the install succeeded. - */ - private boolean doSyncApp(DelayedLaunchInfo launchInfo, IDevice device) { - IPath path = launchInfo.getPackageFile().getLocation(); - String fileName = path.lastSegment(); - try { - String message = String.format("Uploading %1$s onto device '%2$s'", - fileName, device.getSerialNumber()); - AdtPlugin.printToConsole(launchInfo.getProject(), message); - - String remotePackagePath = device.syncPackageToDevice(path.toOSString()); - boolean installResult = installPackage(launchInfo, remotePackagePath, device); - device.removeRemotePackage(remotePackagePath); - - // if the installation succeeded, we register it. - if (installResult) { - ApkInstallManager.getInstance().registerInstallation( - launchInfo.getProject(), launchInfo.getPackageName(), device); - } - return installResult; - } - catch (IOException e) { - String msg = String.format("Failed to install %1$s on device '%2$s': %3$s", fileName, - device.getSerialNumber(), e.getMessage()); - AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg, e); - } catch (TimeoutException e) { - String msg = String.format("Failed to install %1$s on device '%2$s': timeout", fileName, - device.getSerialNumber()); - AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg); - } catch (AdbCommandRejectedException e) { - String msg = String.format( - "Failed to install %1$s on device '%2$s': adb rejected install command with: %3$s", - fileName, device.getSerialNumber(), e.getMessage()); - AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg, e); - } catch (CanceledException e) { - if (e.wasCanceled()) { - AdtPlugin.printToConsole(launchInfo.getProject(), - String.format("Install of %1$s canceled", fileName)); - } else { - String msg = String.format("Failed to install %1$s on device '%2$s': %3$s", - fileName, device.getSerialNumber(), e.getMessage()); - AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg, e); - } - } - - return false; - } - - /** - * For the current launchInfo, create additional DelayedLaunchInfo that should be used to - * sync APKs that we are dependent on to the device. - * - * @param launchInfo the original launch info that we want to find the - * @return a list of DelayedLaunchInfo (may be empty if no dependencies were found or error) - */ - public List<DelayedLaunchInfo> getDependenciesLaunchInfo(DelayedLaunchInfo launchInfo) { - List<DelayedLaunchInfo> dependencies = new ArrayList<DelayedLaunchInfo>(); - - // Convert to equivalent JavaProject - IJavaProject javaProject; - try { - //assuming this is an Android (and Java) project since it is attached to the launchInfo. - javaProject = BaseProjectHelper.getJavaProject(launchInfo.getProject()); - } catch (CoreException e) { - // return empty dependencies - AdtPlugin.printErrorToConsole(launchInfo.getProject(), e); - return dependencies; - } - - // Get all projects that this depends on - List<IJavaProject> androidProjectList; - try { - androidProjectList = ProjectHelper.getAndroidProjectDependencies(javaProject); - } catch (JavaModelException e) { - // return empty dependencies - AdtPlugin.printErrorToConsole(launchInfo.getProject(), e); - return dependencies; - } - - // for each project, parse manifest and create launch information - for (IJavaProject androidProject : androidProjectList) { - // Parse the Manifest to get various required information - // copied from LaunchConfigDelegate - ManifestData manifestData = AndroidManifestHelper.parseForData( - androidProject.getProject()); - - if (manifestData == null) { - continue; - } - - // Get the APK location (can return null) - IFile apk = ProjectHelper.getApplicationPackage(androidProject.getProject()); - if (apk == null) { - // getApplicationPackage will have logged an error message - continue; - } - - // Create new launchInfo as an hybrid between parent and dependency information - DelayedLaunchInfo delayedLaunchInfo = new DelayedLaunchInfo( - androidProject.getProject(), - manifestData.getPackage(), - manifestData.getPackage(), - launchInfo.getLaunchAction(), - apk, - manifestData.getDebuggable(), - manifestData.getMinSdkVersionString(), - launchInfo.getLaunch(), - launchInfo.getMonitor()); - - // Add to the list - dependencies.add(delayedLaunchInfo); - } - - return dependencies; - } - - /** - * Installs the application package on the device, and handles return result - * @param launchInfo The launch information - * @param remotePath The remote path of the package. - * @param device The device on which the launch is done. - */ - private boolean installPackage(DelayedLaunchInfo launchInfo, final String remotePath, - final IDevice device) { - String message = String.format("Installing %1$s...", launchInfo.getPackageFile().getName()); - AdtPlugin.printToConsole(launchInfo.getProject(), message); - try { - // try a reinstall first, because the most common case is the app is already installed - String result = doInstall(launchInfo, remotePath, device, true /* reinstall */); - - /* For now we force to retry the install (after uninstalling) because there's no - * other way around it: adb install does not want to update a package w/o uninstalling - * the old one first! - */ - return checkInstallResult(result, device, launchInfo, remotePath, - InstallRetryMode.ALWAYS); - } catch (Exception e) { - String msg = String.format( - "Failed to install %1$s on device '%2$s!", - launchInfo.getPackageFile().getName(), device.getSerialNumber()); - AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg, e.getMessage()); - } - - return false; - } - - /** - * Checks the result of an installation, and takes optional actions based on it. - * @param result the result string from the installation - * @param device the device on which the installation occured. - * @param launchInfo the {@link DelayedLaunchInfo} - * @param remotePath the temporary path of the package on the device - * @param retryMode indicates what to do in case, a package already exists. - * @return <code>true<code> if success, <code>false</code> otherwise. - * @throws InstallException - */ - private boolean checkInstallResult(String result, IDevice device, DelayedLaunchInfo launchInfo, - String remotePath, InstallRetryMode retryMode) throws InstallException { - if (result == null) { - AdtPlugin.printToConsole(launchInfo.getProject(), "Success!"); - return true; - } - else if (result.equals("INSTALL_FAILED_ALREADY_EXISTS")) { //$NON-NLS-1$ - // this should never happen, since reinstall mode is used on the first attempt - if (retryMode == InstallRetryMode.PROMPT) { - boolean prompt = AdtPlugin.displayPrompt("Application Install", - "A previous installation needs to be uninstalled before the new package can be installed.\nDo you want to uninstall?"); - if (prompt) { - retryMode = InstallRetryMode.ALWAYS; - } else { - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - "Installation error! The package already exists."); - return false; - } - } - - if (retryMode == InstallRetryMode.ALWAYS) { - /* - * TODO: create a UI that gives the dev the choice to: - * - clean uninstall on launch - * - full uninstall if application exists. - * - soft uninstall if application exists (keeps the app data around). - * - always ask (choice of soft-reinstall, full reinstall) - AdtPlugin.printErrorToConsole(launchInfo.mProject, - "Application already exists, uninstalling..."); - String res = doUninstall(device, launchInfo); - if (res == null) { - AdtPlugin.printToConsole(launchInfo.mProject, "Success!"); - } else { - AdtPlugin.printErrorToConsole(launchInfo.mProject, - String.format("Failed to uninstall: %1$s", res)); - return false; - } - */ - - AdtPlugin.printToConsole(launchInfo.getProject(), - "Application already exists. Attempting to re-install instead..."); - String res = doInstall(launchInfo, remotePath, device, true /* reinstall */ ); - return checkInstallResult(res, device, launchInfo, remotePath, - InstallRetryMode.NEVER); - } - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - "Installation error! The package already exists."); - } else if (result.equals("INSTALL_FAILED_INVALID_APK")) { //$NON-NLS-1$ - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - "Installation failed due to invalid APK file!", - "Please check logcat output for more details."); - } else if (result.equals("INSTALL_FAILED_INVALID_URI")) { //$NON-NLS-1$ - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - "Installation failed due to invalid URI!", - "Please check logcat output for more details."); - } else if (result.equals("INSTALL_FAILED_COULDNT_COPY")) { //$NON-NLS-1$ - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - String.format("Installation failed: Could not copy %1$s to its final location!", - launchInfo.getPackageFile().getName()), - "Please check logcat output for more details."); - } else if (result.equals("INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES")) { //$NON-NLS-1$ - if (retryMode != InstallRetryMode.NEVER) { - boolean prompt = AdtPlugin.displayPrompt("Application Install", - "Re-installation failed due to different application signatures. You must perform a full uninstall of the application. WARNING: This will remove the application data!\nDo you want to uninstall?"); - if (prompt) { - doUninstall(device, launchInfo); - String res = doInstall(launchInfo, remotePath, device, false); - return checkInstallResult(res, device, launchInfo, remotePath, - InstallRetryMode.NEVER); - } - } - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - "Re-installation failed due to different application signatures.", - "You must perform a full uninstall of the application. WARNING: This will remove the application data!", - String.format("Please execute 'adb uninstall %1$s' in a shell.", launchInfo.getPackageName())); - } else { - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - String.format("Installation error: %1$s", result), - "Please check logcat output for more details."); - } - - return false; - } - - /** - * Performs the uninstallation of an application. - * @param device the device on which to install the application. - * @param launchInfo the {@link DelayedLaunchInfo}. - * @return a {@link String} with an error code, or <code>null</code> if success. - * @throws InstallException if the installation failed. - */ - private String doUninstall(IDevice device, DelayedLaunchInfo launchInfo) - throws InstallException { - try { - return device.uninstallPackage(launchInfo.getPackageName()); - } catch (InstallException e) { - String msg = String.format( - "Failed to uninstall %1$s: %2$s", launchInfo.getPackageName(), e.getMessage()); - AdtPlugin.printErrorToConsole(launchInfo.getProject(), msg); - throw e; - } - } - - /** - * Performs the installation of an application whose package has been uploaded on the device. - * - * @param launchInfo the {@link DelayedLaunchInfo}. - * @param remotePath the path of the application package in the device tmp folder. - * @param device the device on which to install the application. - * @param reinstall - * @return a {@link String} with an error code, or <code>null</code> if success. - * @throws InstallException if the uninstallation failed. - */ - private String doInstall(DelayedLaunchInfo launchInfo, final String remotePath, - final IDevice device, boolean reinstall) throws InstallException { - return device.installRemotePackage(remotePath, reinstall); - } - - /** - * launches an application on a device or emulator - * - * @param info the {@link DelayedLaunchInfo} that indicates the launch action - * @param device the device or emulator to launch the application on - */ - @Override - public void launchApp(final DelayedLaunchInfo info, IDevice device) { - if (info.isDebugMode()) { - synchronized (sListLock) { - if (mWaitingForDebuggerApplications.contains(info) == false) { - mWaitingForDebuggerApplications.add(info); - } - } - } - if (doLaunchAction(info, device)) { - // if the app is not a debug app, we need to do some clean up, as - // the process is done! - if (info.isDebugMode() == false) { - // stop the launch object, since there's no debug, and it can't - // provide any control over the app - stopLaunch(info); - } - } else { - // something went wrong or no further launch action needed - // lets stop the Launch - stopLaunch(info); - } - } - - private boolean doLaunchAction(final DelayedLaunchInfo info, Collection<IDevice> devices) { - boolean result = info.getLaunchAction().doLaunchAction(info, devices); - - // Monitor the logcat output on the launched device to notify - // the user if any significant error occurs that is visible from logcat - for (IDevice d : devices) { - DdmsPlugin.getDefault().startLogCatMonitor(d); - } - - return result; - } - - private boolean doLaunchAction(final DelayedLaunchInfo info, IDevice device) { - return doLaunchAction(info, Collections.singletonList(device)); - } - - private boolean launchEmulator(AndroidLaunchConfiguration config, AvdInfo avdToLaunch) { - - // split the custom command line in segments - ArrayList<String> customArgs = new ArrayList<String>(); - boolean hasWipeData = false; - if (config.mEmulatorCommandLine != null && config.mEmulatorCommandLine.length() > 0) { - String[] segments = config.mEmulatorCommandLine.split("\\s+"); //$NON-NLS-1$ - - // we need to remove the empty strings - for (String s : segments) { - if (s.length() > 0) { - customArgs.add(s); - if (!hasWipeData && s.equals(FLAG_WIPE_DATA)) { - hasWipeData = true; - } - } - } - } - - boolean needsWipeData = config.mWipeData && !hasWipeData; - if (needsWipeData) { - if (!AdtPlugin.displayPrompt("Android Launch", "Are you sure you want to wipe all user data when starting this emulator?")) { - needsWipeData = false; - } - } - - // build the command line based on the available parameters. - ArrayList<String> list = new ArrayList<String>(); - - String path = AdtPlugin.getOsAbsoluteEmulator(); - - list.add(path); - - list.add(FLAG_AVD); - list.add(avdToLaunch.getName()); - - if (config.mNetworkSpeed != null) { - list.add(FLAG_NETSPEED); - list.add(config.mNetworkSpeed); - } - - if (config.mNetworkDelay != null) { - list.add(FLAG_NETDELAY); - list.add(config.mNetworkDelay); - } - - if (needsWipeData) { - list.add(FLAG_WIPE_DATA); - } - - if (config.mNoBootAnim) { - list.add(FLAG_NO_BOOT_ANIM); - } - - list.addAll(customArgs); - - // convert the list into an array for the call to exec. - String[] command = list.toArray(new String[list.size()]); - - // launch the emulator - try { - Process process = Runtime.getRuntime().exec(command); - grabEmulatorOutput(process); - } catch (IOException e) { - return false; - } - - return true; - } - - /** - * Looks for and returns an existing {@link ILaunchConfiguration} object for a - * specified project. - * @param manager The {@link ILaunchManager}. - * @param type The {@link ILaunchConfigurationType}. - * @param projectName The name of the project - * @return an existing <code>ILaunchConfiguration</code> object matching the project, or - * <code>null</code>. - */ - private static ILaunchConfiguration findConfig(ILaunchManager manager, - ILaunchConfigurationType type, String projectName) { - try { - ILaunchConfiguration[] configs = manager.getLaunchConfigurations(type); - - for (ILaunchConfiguration config : configs) { - if (config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, - "").equals(projectName)) { //$NON-NLS-1$ - return config; - } - } - } catch (CoreException e) { - MessageDialog.openError(AdtPlugin.getShell(), - "Launch Error", e.getStatus().getMessage()); - } - - // didn't find anything that matches. Return null - return null; - } - - - /** - * Connects a remote debugger on the specified port. - * @param debugPort The port to connect the debugger to - * @param launch The associated AndroidLaunch object. - * @param monitor A Progress monitor - * @return false if cancelled by the monitor - * @throws CoreException - */ - @SuppressWarnings("deprecation") - public static boolean connectRemoteDebugger(int debugPort, - AndroidLaunch launch, IProgressMonitor monitor) - throws CoreException { - // get some default parameters. - int connectTimeout = JavaRuntime.getPreferences().getInt(JavaRuntime.PREF_CONNECT_TIMEOUT); - - HashMap<String, String> newMap = new HashMap<String, String>(); - - newMap.put("hostname", "localhost"); //$NON-NLS-1$ //$NON-NLS-2$ - - newMap.put("port", Integer.toString(debugPort)); //$NON-NLS-1$ - - newMap.put("timeout", Integer.toString(connectTimeout)); - - // get the default VM connector - IVMConnector connector = JavaRuntime.getDefaultVMConnector(); - - // connect to remote VM - connector.connect(newMap, monitor, launch); - - // check for cancellation - if (monitor.isCanceled()) { - IDebugTarget[] debugTargets = launch.getDebugTargets(); - for (IDebugTarget target : debugTargets) { - if (target.canDisconnect()) { - target.disconnect(); - } - } - return false; - } - - return true; - } - - /** - * Launch a new thread that connects a remote debugger on the specified port. - * @param debugPort The port to connect the debugger to - * @param androidLaunch The associated AndroidLaunch object. - * @param monitor A Progress monitor - * @see #connectRemoteDebugger(int, AndroidLaunch, IProgressMonitor) - */ - public static void launchRemoteDebugger(final int debugPort, final AndroidLaunch androidLaunch, - final IProgressMonitor monitor) { - new Thread("Debugger connection") { //$NON-NLS-1$ - @Override - public void run() { - try { - connectRemoteDebugger(debugPort, androidLaunch, monitor); - } catch (CoreException e) { - androidLaunch.stopLaunch(); - } - monitor.done(); - } - }.start(); - } - - /** - * Sent when a new {@link AndroidDebugBridge} is started. - * <p/> - * This is sent from a non UI thread. - * @param bridge the new {@link AndroidDebugBridge} object. - * - * @see IDebugBridgeChangeListener#bridgeChanged(AndroidDebugBridge) - */ - @Override - public void bridgeChanged(AndroidDebugBridge bridge) { - // The adb server has changed. We cancel any pending launches. - String message = "adb server change: cancelling '%1$s'!"; - synchronized (sListLock) { - for (DelayedLaunchInfo launchInfo : mWaitingForReadyEmulatorList) { - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - String.format(message, launchInfo.getLaunchAction().getLaunchDescription())); - stopLaunch(launchInfo); - } - for (DelayedLaunchInfo launchInfo : mWaitingForDebuggerApplications) { - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - String.format(message, - launchInfo.getLaunchAction().getLaunchDescription())); - stopLaunch(launchInfo); - } - - mWaitingForReadyEmulatorList.clear(); - mWaitingForDebuggerApplications.clear(); - } - } - - /** - * Sent when the a device is connected to the {@link AndroidDebugBridge}. - * <p/> - * This is sent from a non UI thread. - * @param device the new device. - * - * @see IDeviceChangeListener#deviceConnected(IDevice) - */ - @Override - public void deviceConnected(IDevice device) { - synchronized (sListLock) { - // look if there's an app waiting for a device - if (mWaitingForEmulatorLaunches.size() > 0) { - // get/remove first launch item from the list - // FIXME: what if we have multiple launches waiting? - DelayedLaunchInfo launchInfo = mWaitingForEmulatorLaunches.get(0); - mWaitingForEmulatorLaunches.remove(0); - - // give the launch item its device for later use. - launchInfo.setDevice(device); - - // and move it to the other list - mWaitingForReadyEmulatorList.add(launchInfo); - - // and tell the user about it - AdtPlugin.printToConsole(launchInfo.getProject(), - String.format("New emulator found: %1$s", device.getSerialNumber())); - AdtPlugin.printToConsole(launchInfo.getProject(), - String.format("Waiting for HOME ('%1$s') to be launched...", - AdtPlugin.getDefault().getPreferenceStore().getString( - AdtPrefs.PREFS_HOME_PACKAGE))); - } - } - } - - /** - * Sent when the a device is connected to the {@link AndroidDebugBridge}. - * <p/> - * This is sent from a non UI thread. - * @param device the new device. - * - * @see IDeviceChangeListener#deviceDisconnected(IDevice) - */ - @Override - public void deviceDisconnected(IDevice device) { - // any pending launch on this device must be canceled. - String message = "%1$s disconnected! Cancelling '%2$s'!"; - synchronized (sListLock) { - ArrayList<DelayedLaunchInfo> copyList = - (ArrayList<DelayedLaunchInfo>) mWaitingForReadyEmulatorList.clone(); - for (DelayedLaunchInfo launchInfo : copyList) { - if (launchInfo.getDevice() == device) { - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - String.format(message, device.getSerialNumber(), - launchInfo.getLaunchAction().getLaunchDescription())); - stopLaunch(launchInfo); - } - } - copyList = (ArrayList<DelayedLaunchInfo>) mWaitingForDebuggerApplications.clone(); - for (DelayedLaunchInfo launchInfo : copyList) { - if (launchInfo.getDevice() == device) { - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - String.format(message, device.getSerialNumber(), - launchInfo.getLaunchAction().getLaunchDescription())); - stopLaunch(launchInfo); - } - } - } - } - - /** - * Sent when a device data changed, or when clients are started/terminated on the device. - * <p/> - * This is sent from a non UI thread. - * @param device the device that was updated. - * @param changeMask the mask indicating what changed. - * - * @see IDeviceChangeListener#deviceChanged(IDevice, int) - */ - @Override - public void deviceChanged(IDevice device, int changeMask) { - // We could check if any starting device we care about is now ready, but we can wait for - // its home app to show up, so... - } - - /** - * Sent when an existing client information changed. - * <p/> - * This is sent from a non UI thread. - * @param client the updated client. - * @param changeMask the bit mask describing the changed properties. It can contain - * any of the following values: {@link Client#CHANGE_INFO}, {@link Client#CHANGE_NAME} - * {@link Client#CHANGE_DEBUGGER_STATUS}, {@link Client#CHANGE_THREAD_MODE}, - * {@link Client#CHANGE_THREAD_DATA}, {@link Client#CHANGE_HEAP_MODE}, - * {@link Client#CHANGE_HEAP_DATA}, {@link Client#CHANGE_NATIVE_HEAP_DATA} - * - * @see IClientChangeListener#clientChanged(Client, int) - */ - @Override - public void clientChanged(final Client client, int changeMask) { - boolean connectDebugger = false; - if ((changeMask & Client.CHANGE_NAME) == Client.CHANGE_NAME) { - String applicationName = client.getClientData().getClientDescription(); - if (applicationName != null) { - IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore(); - String home = store.getString(AdtPrefs.PREFS_HOME_PACKAGE); - - if (home.equals(applicationName)) { - - // looks like home is up, get its device - IDevice device = client.getDevice(); - - // look for application waiting for home - synchronized (sListLock) { - for (int i = 0; i < mWaitingForReadyEmulatorList.size(); ) { - DelayedLaunchInfo launchInfo = mWaitingForReadyEmulatorList.get(i); - if (launchInfo.getDevice() == device) { - // it's match, remove from the list - mWaitingForReadyEmulatorList.remove(i); - - // We couldn't check earlier the API level of the device - // (it's asynchronous when the device boot, and usually - // deviceConnected is called before it's queried for its build info) - // so we check now - if (checkBuildInfo(launchInfo, device) == false) { - // device is not the proper API! - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - "Launch canceled!"); - stopLaunch(launchInfo); - return; - } - - AdtPlugin.printToConsole(launchInfo.getProject(), - String.format("HOME is up on device '%1$s'", - device.getSerialNumber())); - - // attempt to sync the new package onto the device. - if (syncApp(launchInfo, device)) { - // application package is sync'ed, lets attempt to launch it. - launchApp(launchInfo, device); - } else { - // failure! Cancel and return - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - "Launch canceled!"); - stopLaunch(launchInfo); - } - - break; - } else { - i++; - } - } - } - } - - // check if it's already waiting for a debugger, and if so we connect to it. - if (client.getClientData().getDebuggerConnectionStatus() == DebuggerStatus.WAITING) { - // search for this client in the list; - synchronized (sListLock) { - int index = mUnknownClientsWaitingForDebugger.indexOf(client); - if (index != -1) { - connectDebugger = true; - mUnknownClientsWaitingForDebugger.remove(client); - } - } - } - } - } - - // if it's not home, it could be an app that is now in debugger mode that we're waiting for - // lets check it - - if ((changeMask & Client.CHANGE_DEBUGGER_STATUS) == Client.CHANGE_DEBUGGER_STATUS) { - ClientData clientData = client.getClientData(); - String applicationName = client.getClientData().getClientDescription(); - if (clientData.getDebuggerConnectionStatus() == DebuggerStatus.WAITING) { - // Get the application name, and make sure its valid. - if (applicationName == null) { - // looks like we don't have the client yet, so we keep it around for when its - // name becomes available. - synchronized (sListLock) { - mUnknownClientsWaitingForDebugger.add(client); - } - return; - } else { - connectDebugger = true; - } - } - } - - if (connectDebugger) { - Log.d("adt", "Debugging " + client); - // now check it against the apps waiting for a debugger - String applicationName = client.getClientData().getClientDescription(); - Log.d("adt", "App Name: " + applicationName); - synchronized (sListLock) { - for (int i = 0; i < mWaitingForDebuggerApplications.size(); ) { - final DelayedLaunchInfo launchInfo = mWaitingForDebuggerApplications.get(i); - if (client.getDevice() == launchInfo.getDevice() && - 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.getDebugPackageName(), client.getDebuggerListenPort()); - AdtPlugin.printToConsole(launchInfo.getProject(), msg); - - new Thread("Debugger Connection") { //$NON-NLS-1$ - @Override - public void run() { - try { - if (connectRemoteDebugger( - client.getDebuggerListenPort(), - launchInfo.getLaunch(), - launchInfo.getMonitor()) == false) { - return; - } - } catch (CoreException e) { - // well something went wrong. - AdtPlugin.printErrorToConsole(launchInfo.getProject(), - String.format("Launch error: %s", e.getMessage())); - // stop the launch - stopLaunch(launchInfo); - } - - launchInfo.getMonitor().done(); - } - }.start(); - - // we're done processing this client. - return; - - } else { - i++; - } - } - } - - // if we get here, we haven't found an app that we were launching, so we look - // for opened android projects that contains the app asking for a debugger. - // If we find one, we automatically connect to it. - IProject project = ProjectHelper.findAndroidProjectByAppName(applicationName); - - if (project != null) { - debugRunningApp(project, client.getDebuggerListenPort()); - } - } - } - - /** - * Get the stderr/stdout outputs of a process and return when the process is done. - * Both <b>must</b> be read or the process will block on windows. - * @param process The process to get the output from - */ - private void grabEmulatorOutput(final Process process) { - // read the lines as they come. if null is returned, it's - // because the process finished - new Thread("") { //$NON-NLS-1$ - @Override - public void run() { - // create a buffer to read the stderr output - InputStreamReader is = new InputStreamReader(process.getErrorStream()); - BufferedReader errReader = new BufferedReader(is); - - try { - while (true) { - String line = errReader.readLine(); - if (line != null) { - AdtPlugin.printErrorToConsole("Emulator", line); - } else { - break; - } - } - } catch (IOException e) { - // do nothing. - } - } - }.start(); - - new Thread("") { //$NON-NLS-1$ - @Override - public void run() { - InputStreamReader is = new InputStreamReader(process.getInputStream()); - BufferedReader outReader = new BufferedReader(is); - - try { - while (true) { - String line = outReader.readLine(); - if (line != null) { - AdtPlugin.printToConsole("Emulator", line); - } else { - break; - } - } - } catch (IOException e) { - // do nothing. - } - } - }.start(); - } - - /* (non-Javadoc) - * @see com.android.ide.eclipse.adt.launch.ILaunchController#stopLaunch(com.android.ide.eclipse.adt.launch.AndroidLaunchController.DelayedLaunchInfo) - */ - @Override - public void stopLaunch(DelayedLaunchInfo launchInfo) { - launchInfo.getLaunch().stopLaunch(); - synchronized (sListLock) { - mWaitingForReadyEmulatorList.remove(launchInfo); - mWaitingForDebuggerApplications.remove(launchInfo); - } - } - - public static void updateLaunchConfigWithLastUsedDevice( - ILaunchConfiguration launchConfiguration, DeviceChooserResponse response) { - try { - boolean configModified = false; - boolean reuse = launchConfiguration.getAttribute( - LaunchConfigDelegate.ATTR_REUSE_LAST_USED_DEVICE, false); - String serial = launchConfiguration.getAttribute( - LaunchConfigDelegate.ATTR_LAST_USED_DEVICE, (String)null); - - ILaunchConfigurationWorkingCopy wc = launchConfiguration.getWorkingCopy(); - if (reuse != response.useDeviceForFutureLaunches()) { - reuse = response.useDeviceForFutureLaunches(); - wc.setAttribute(LaunchConfigDelegate.ATTR_REUSE_LAST_USED_DEVICE, reuse); - configModified = true; - } - - if (reuse) { - String selected = getSerial(response); - if (selected != null && !selected.equalsIgnoreCase(serial)) { - wc.setAttribute(LaunchConfigDelegate.ATTR_LAST_USED_DEVICE, selected); - configModified = true; - } - } - - if (configModified) { - wc.doSave(); - } - } catch (CoreException e) { - // in such a case, users just won't see this setting take effect - return; - } - } - - private static String getSerial(DeviceChooserResponse response) { - AvdInfo avd = response.getAvdToLaunch(); - return (avd != null) ? avd.getName() : response.getDeviceToUse().getSerialNumber(); - } - - @Nullable - public static IDevice getDeviceIfOnline(@Nullable String serial, - @NonNull IDevice[] onlineDevices) { - if (serial == null) { - return null; - } - - for (IDevice device : onlineDevices) { - if (serial.equals(device.getAvdName()) || - serial.equals(device.getSerialNumber())) { - return device; - } - } - - return null; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AvdCompatibility.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AvdCompatibility.java deleted file mode 100644 index 6133002bc..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AvdCompatibility.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2012 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.ide.eclipse.adt.internal.launch; - -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.internal.avd.AvdInfo; - -public class AvdCompatibility { - public enum Compatibility { - YES, - NO, - UNKNOWN, - }; - - /** - * Returns whether the specified AVD can run the given project that is built against - * a particular SDK and has the specified minApiLevel. - * @param avd AVD to check compatibility for - * @param projectTarget project build target - * @param minApiVersion project min api level - * @return whether the given AVD can run the given application - */ - public static Compatibility canRun(AvdInfo avd, IAndroidTarget projectTarget, - AndroidVersion minApiVersion) { - if (avd == null) { - return Compatibility.UNKNOWN; - } - - IAndroidTarget avdTarget = avd.getTarget(); - if (avdTarget == null) { - return Compatibility.UNKNOWN; - } - - // for platform targets, we only need to check the min api version - if (projectTarget.isPlatform()) { - return avdTarget.getVersion().canRun(minApiVersion) ? - Compatibility.YES : Compatibility.NO; - } - - // for add-on targets, delegate to the add on target to check for compatibility - return projectTarget.canRunOn(avdTarget) ? Compatibility.YES : Compatibility.NO; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DelayedLaunchInfo.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DelayedLaunchInfo.java deleted file mode 100644 index b0a6dda20..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DelayedLaunchInfo.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import com.android.ddmlib.IDevice; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.IProgressMonitor; - -/** - * A delayed launch waiting for a device to be present or ready before the - * application is launched. - */ -public final class DelayedLaunchInfo { - - /** - * Used to indicate behavior when Android app already exists - */ - enum InstallRetryMode { - NEVER, ALWAYS, PROMPT; - } - - /** The device on which to launch the app */ - private IDevice mDevice = null; - - /** The eclipse project */ - private final IProject mProject; - - /** Package name */ - private final String mPackageName; - - /** Debug package name */ - private final String mDebugPackageName; - - /** IFile to the package (.apk) file */ - private final IFile mPackageFile; - - /** debuggable attribute of the manifest file. */ - private final Boolean mDebuggable; - - /** Required Api level by the app. null means no requirements */ - private final String mRequiredApiVersionNumber; - - private InstallRetryMode mRetryMode = InstallRetryMode.NEVER; - - /** Launch action. */ - private final IAndroidLaunchAction mLaunchAction; - - /** the launch object */ - private final AndroidLaunch mLaunch; - - /** the monitor object */ - private final IProgressMonitor mMonitor; - - /** debug mode flag */ - private boolean mDebugMode; - - /** current number of launch attempts */ - private int mAttemptCount = 0; - - /** cancellation state of launch */ - private boolean mCancelled = false; - - /** - * 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 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 the debuggable value of the app's manifest, or null if not set. - * @param requiredApiVersionNumber required SDK version by the app. null means no requirements. - * @param launch the launch object - * @param monitor progress monitor for launch - */ - public DelayedLaunchInfo(IProject project, String packageName, String debugPackageName, - IAndroidLaunchAction launchAction, IFile pack, Boolean debuggable, - String requiredApiVersionNumber, AndroidLaunch launch, IProgressMonitor monitor) { - mProject = project; - mPackageName = packageName; - mDebugPackageName = debugPackageName; - mPackageFile = pack; - mLaunchAction = launchAction; - mLaunch = launch; - mMonitor = monitor; - mDebuggable = debuggable; - mRequiredApiVersionNumber = requiredApiVersionNumber; - } - - /** - * @return the device on which to launch the app - */ - public IDevice getDevice() { - return mDevice; - } - - /** - * Set the device on which to launch the app - */ - public void setDevice(IDevice device) { - mDevice = device; - } - - /** - * @return the eclipse project that corresponds to Android app - */ - public IProject getProject() { - return mProject; - } - - /** - * @return the package name of the Android app - */ - public String getPackageName() { - 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 - */ - public IFile getPackageFile() { - return mPackageFile; - } - - /** - * Returns the value of the manifest debuggable attribute. If the attribute was not set, - * then the method returns null. - * @return the manifest debuggable attribute. - */ - public Boolean getDebuggable() { - return mDebuggable; - } - - /** - * @return the required api version number for the Android app. - */ - public String getRequiredApiVersionNumber() { - return mRequiredApiVersionNumber; - } - - /** - * @param retryMode the install retry mode to set - */ - public void setRetryMode(InstallRetryMode retryMode) { - this.mRetryMode = retryMode; - } - - /** - * @return the installation retry mode - */ - public InstallRetryMode getRetryMode() { - return mRetryMode; - } - - /** - * @return the launch action - */ - public IAndroidLaunchAction getLaunchAction() { - return mLaunchAction; - } - - /** - * @return the launch - */ - public AndroidLaunch getLaunch() { - return mLaunch; - } - - /** - * @return the launch progress monitor - */ - public IProgressMonitor getMonitor() { - return mMonitor; - } - - /** - * @param debugMode the debug mode to set - */ - public void setDebugMode(boolean debugMode) { - this.mDebugMode = debugMode; - } - - /** - * @return true if this is a debug launch - */ - public boolean isDebugMode() { - return mDebugMode; - } - - /** - * Increases the number of launch attempts - */ - public void incrementAttemptCount() { - mAttemptCount++; - } - - /** - * @return the number of launch attempts made - */ - public int getAttemptCount() { - return mAttemptCount; - } - - /** - * Set if launch has been cancelled - */ - public void setCancelled(boolean cancelled) { - this.mCancelled = cancelled; - } - - /** - * @return true if launch has been cancelled - */ - public boolean isCancelled() { - return mCancelled; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java deleted file mode 100644 index 995ccdf46..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java +++ /dev/null @@ -1,824 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener; -import com.android.ddmlib.Client; -import com.android.ddmlib.IDevice; -import com.android.ddmlib.IDevice.DeviceState; -import com.android.ddmuilib.ImageLoader; -import com.android.ddmuilib.TableHelper; -import com.android.ide.eclipse.adt.internal.editors.IconFactory; -import com.android.ide.eclipse.adt.internal.sdk.AdtConsoleSdkLog; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.ide.eclipse.ddms.DdmsPlugin; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdkuilib.internal.widgets.AvdSelector; -import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode; -import com.android.sdkuilib.internal.widgets.AvdSelector.IAvdFilter; - -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.viewers.ILabelProviderListener; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.SWTException; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Table; - -import java.util.ArrayList; -import java.util.List; - -/** - * A dialog that lets the user choose a device to deploy an application. - * The user can either choose an exiting running device (including running emulators) - * or start a new emulator using an Android Virtual Device configuration that matches - * the current project. - */ -public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener { - - private final static int ICON_WIDTH = 16; - - private Table mDeviceTable; - private TableViewer mViewer; - private AvdSelector mPreferredAvdSelector; - - private Image mDeviceImage; - private Image mEmulatorImage; - private Image mMatchImage; - private Image mNoMatchImage; - private Image mWarningImage; - - private final DeviceChooserResponse mResponse; - private final String mPackageName; - private final IAndroidTarget mProjectTarget; - private final AndroidVersion mMinApiVersion; - private final Sdk mSdk; - - private Button mDeviceRadioButton; - private Button mUseDeviceForFutureLaunchesCheckbox; - private boolean mUseDeviceForFutureLaunches; - - private boolean mDisableAvdSelectionChange = false; - - /** - * Basic Content Provider for a table full of {@link IDevice} objects. The input is - * a {@link AndroidDebugBridge}. - */ - private class ContentProvider implements IStructuredContentProvider { - @Override - public Object[] getElements(Object inputElement) { - if (inputElement instanceof AndroidDebugBridge) { - return findCompatibleDevices(((AndroidDebugBridge)inputElement).getDevices()); - } - - return new Object[0]; - } - - private Object[] findCompatibleDevices(IDevice[] devices) { - if (devices == null) { - return null; - } - - List<IDevice> compatibleDevices = new ArrayList<IDevice>(devices.length); - for (IDevice device : devices) { - AndroidVersion deviceVersion = Sdk.getDeviceVersion(device); - if (deviceVersion == null || deviceVersion.canRun(mMinApiVersion)) { - compatibleDevices.add(device); - } - } - - return compatibleDevices.toArray(); - } - - @Override - public void dispose() { - // pass - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // pass - } - } - - /** - * A Label Provider for the {@link TableViewer} in {@link DeviceChooserDialog}. - * It provides labels and images for {@link IDevice} objects. - */ - private class LabelProvider implements ITableLabelProvider { - - @Override - public Image getColumnImage(Object element, int columnIndex) { - if (element instanceof IDevice) { - IDevice device = (IDevice)element; - switch (columnIndex) { - case 0: - return device.isEmulator() ? mEmulatorImage : mDeviceImage; - - case 2: - // check for compatibility. - if (device.isEmulator() == false) { // physical device - // get the version of the device - AndroidVersion deviceVersion = Sdk.getDeviceVersion(device); - if (deviceVersion == null) { - return mWarningImage; - } else { - if (!deviceVersion.canRun(mMinApiVersion)) { - return mNoMatchImage; - } - - // if the project is compiling against an add-on, - // the optional API may be missing from the device. - return mProjectTarget.isPlatform() ? - mMatchImage : mWarningImage; - } - } else { - // get the AvdInfo - AvdInfo info = mSdk.getAvdManager().getAvd(device.getAvdName(), - true /*validAvdOnly*/); - AvdCompatibility.Compatibility c = - AvdCompatibility.canRun(info, mProjectTarget, - mMinApiVersion); - switch (c) { - case YES: - return mMatchImage; - case NO: - return mNoMatchImage; - case UNKNOWN: - return mWarningImage; - } - } - } - } - - return null; - } - - @Override - public String getColumnText(Object element, int columnIndex) { - if (element instanceof IDevice) { - IDevice device = (IDevice)element; - switch (columnIndex) { - case 0: - return device.getName(); - case 1: - if (device.isEmulator()) { - return device.getAvdName(); - } else { - return "N/A"; // devices don't have AVD names. - } - case 2: - if (device.isEmulator()) { - AvdInfo info = mSdk.getAvdManager().getAvd(device.getAvdName(), - true /*validAvdOnly*/); - if (info == null) { - return "?"; - } - return info.getTarget().getFullName(); - } else { - String deviceBuild = device.getProperty(IDevice.PROP_BUILD_VERSION); - if (deviceBuild == null) { - return "unknown"; - } - return deviceBuild; - } - case 3: - String debuggable = device.getProperty(IDevice.PROP_DEBUGGABLE); - if (debuggable != null && debuggable.equals("1")) { //$NON-NLS-1$ - return "Yes"; - } else { - return ""; - } - case 4: - return getStateString(device); - } - } - - return null; - } - - @Override - public void addListener(ILabelProviderListener listener) { - // pass - } - - @Override - public void dispose() { - // pass - } - - @Override - public boolean isLabelProperty(Object element, String property) { - // pass - return false; - } - - @Override - public void removeListener(ILabelProviderListener listener) { - // pass - } - } - - public static class DeviceChooserResponse { - private AvdInfo mAvdToLaunch; - private IDevice mDeviceToUse; - private boolean mUseDeviceForFutureLaunches; - - public void setDeviceToUse(IDevice d) { - mDeviceToUse = d; - mAvdToLaunch = null; - } - - public void setAvdToLaunch(AvdInfo avd) { - mAvdToLaunch = avd; - mDeviceToUse = null; - } - - public IDevice getDeviceToUse() { - return mDeviceToUse; - } - - public AvdInfo getAvdToLaunch() { - return mAvdToLaunch; - } - - public void setUseDeviceForFutureLaunches(boolean en) { - mUseDeviceForFutureLaunches = en; - } - - public boolean useDeviceForFutureLaunches() { - return mUseDeviceForFutureLaunches; - } - } - - public DeviceChooserDialog(Shell parent, DeviceChooserResponse response, String packageName, - IAndroidTarget projectTarget, AndroidVersion minApiVersion, - boolean useDeviceForFutureLaunches) { - super(parent); - - mResponse = response; - mPackageName = packageName; - mProjectTarget = projectTarget; - mMinApiVersion = minApiVersion; - mSdk = Sdk.getCurrent(); - mUseDeviceForFutureLaunches = useDeviceForFutureLaunches; - - AndroidDebugBridge.addDeviceChangeListener(this); - loadImages(); - } - - private void cleanup() { - // done listening. - AndroidDebugBridge.removeDeviceChangeListener(this); - } - - @Override - protected void okPressed() { - cleanup(); - super.okPressed(); - } - - @Override - protected void cancelPressed() { - cleanup(); - super.cancelPressed(); - } - - @Override - protected Control createContents(Composite parent) { - Control content = super.createContents(parent); - - // this must be called after createContents() has happened so that the - // ok button has been created (it's created after the call to createDialogArea) - updateDefaultSelection(); - - return content; - } - - /** - * Create the button bar: We override the Dialog implementation of this method - * so that we can create the checkbox at the same level as the 'Cancel' and 'OK' buttons. - */ - @Override - protected Control createButtonBar(Composite parent) { - Composite composite = new Composite(parent, SWT.NONE); - - GridLayout layout = new GridLayout(1, false); - layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); - composite.setLayout(layout); - composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - mUseDeviceForFutureLaunchesCheckbox = new Button(composite, SWT.CHECK); - mUseDeviceForFutureLaunchesCheckbox.setSelection(mUseDeviceForFutureLaunches); - mResponse.setUseDeviceForFutureLaunches(mUseDeviceForFutureLaunches); - mUseDeviceForFutureLaunchesCheckbox.setText("Use same device for future launches"); - mUseDeviceForFutureLaunchesCheckbox.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - mUseDeviceForFutureLaunches = - mUseDeviceForFutureLaunchesCheckbox.getSelection(); - mResponse.setUseDeviceForFutureLaunches(mUseDeviceForFutureLaunches); - } - }); - mUseDeviceForFutureLaunchesCheckbox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - - createButton(composite, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); - createButton(composite, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); - - return composite; - } - - @Override - protected Control createDialogArea(Composite parent) { - // set dialog title - getShell().setText("Android Device Chooser"); - - Composite top = new Composite(parent, SWT.NONE); - top.setLayout(new GridLayout(1, true)); - - String msg; - if (mProjectTarget.isPlatform()) { - msg = String.format("Select a device with min API level %s.", - mMinApiVersion.getApiString()); - } else { - msg = String.format("Select a device compatible with target %s.", - mProjectTarget.getFullName()); - } - Label label = new Label(top, SWT.NONE); - label.setText(msg); - - mDeviceRadioButton = new Button(top, SWT.RADIO); - mDeviceRadioButton.setText("Choose a running Android device"); - mDeviceRadioButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - boolean deviceMode = mDeviceRadioButton.getSelection(); - - mDeviceTable.setEnabled(deviceMode); - mPreferredAvdSelector.setEnabled(!deviceMode); - - if (deviceMode) { - handleDeviceSelection(); - } else { - mResponse.setAvdToLaunch(mPreferredAvdSelector.getSelected()); - } - - enableOkButton(); - } - }); - mDeviceRadioButton.setSelection(true); - - - // offset the selector from the radio button - Composite offsetComp = new Composite(top, SWT.NONE); - offsetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - GridLayout layout = new GridLayout(1, false); - layout.marginRight = layout.marginHeight = 0; - layout.marginLeft = 30; - offsetComp.setLayout(layout); - - mDeviceTable = new Table(offsetComp, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER); - GridData gd; - mDeviceTable.setLayoutData(gd = new GridData(GridData.FILL_BOTH)); - gd.heightHint = 100; - - mDeviceTable.setHeaderVisible(true); - mDeviceTable.setLinesVisible(true); - - TableHelper.createTableColumn(mDeviceTable, "Serial Number", - SWT.LEFT, "AAA+AAAAAAAAAAAAAAAAAAA", //$NON-NLS-1$ - null /* prefs name */, null /* prefs store */); - - TableHelper.createTableColumn(mDeviceTable, "AVD Name", - SWT.LEFT, "AAAAAAAAAAAAAAAAAAA", //$NON-NLS-1$ - null /* prefs name */, null /* prefs store */); - - TableHelper.createTableColumn(mDeviceTable, "Target", - SWT.LEFT, "AAA+Android 9.9.9", //$NON-NLS-1$ - null /* prefs name */, null /* prefs store */); - - TableHelper.createTableColumn(mDeviceTable, "Debug", - SWT.LEFT, "Debug", //$NON-NLS-1$ - null /* prefs name */, null /* prefs store */); - - TableHelper.createTableColumn(mDeviceTable, "State", - SWT.LEFT, "bootloader", //$NON-NLS-1$ - null /* prefs name */, null /* prefs store */); - - // create the viewer for it - mViewer = new TableViewer(mDeviceTable); - mViewer.setContentProvider(new ContentProvider()); - mViewer.setLabelProvider(new LabelProvider()); - mViewer.setInput(AndroidDebugBridge.getBridge()); - - mDeviceTable.addSelectionListener(new SelectionAdapter() { - /** - * Handles single-click selection on the device selector. - * {@inheritDoc} - */ - @Override - public void widgetSelected(SelectionEvent e) { - handleDeviceSelection(); - } - - /** - * Handles double-click selection on the device selector. - * Note that the single-click handler will probably already have been called. - * {@inheritDoc} - */ - @Override - public void widgetDefaultSelected(SelectionEvent e) { - handleDeviceSelection(); - if (isOkButtonEnabled()) { - okPressed(); - } - } - }); - - Button radio2 = new Button(top, SWT.RADIO); - radio2.setText("Launch a new Android Virtual Device"); - - // offset the selector from the radio button - offsetComp = new Composite(top, SWT.NONE); - offsetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - layout = new GridLayout(1, false); - layout.marginRight = layout.marginHeight = 0; - layout.marginLeft = 30; - offsetComp.setLayout(layout); - - mPreferredAvdSelector = new AvdSelector(offsetComp, - mSdk.getSdkOsLocation(), - mSdk.getAvdManager(), - new NonRunningAvdFilter(), - DisplayMode.SIMPLE_SELECTION, - new AdtConsoleSdkLog()); - mPreferredAvdSelector.setTableHeightHint(100); - mPreferredAvdSelector.setEnabled(false); - mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() { - /** - * Handles single-click selection on the AVD selector. - * {@inheritDoc} - */ - @Override - public void widgetSelected(SelectionEvent e) { - if (mDisableAvdSelectionChange == false) { - mResponse.setAvdToLaunch(mPreferredAvdSelector.getSelected()); - enableOkButton(); - } - } - - /** - * Handles double-click selection on the AVD selector. - * - * Note that the single-click handler will probably already have been called - * but the selected item can have changed in between. - * - * {@inheritDoc} - */ - @Override - public void widgetDefaultSelected(SelectionEvent e) { - widgetSelected(e); - if (isOkButtonEnabled()) { - okPressed(); - } - } - }); - - return top; - } - - private void loadImages() { - ImageLoader ddmUiLibLoader = ImageLoader.getDdmUiLibLoader(); - Display display = DdmsPlugin.getDisplay(); - IconFactory factory = IconFactory.getInstance(); - - if (mDeviceImage == null) { - mDeviceImage = ddmUiLibLoader.loadImage(display, - "device.png", //$NON-NLS-1$ - ICON_WIDTH, ICON_WIDTH, - display.getSystemColor(SWT.COLOR_RED)); - } - if (mEmulatorImage == null) { - mEmulatorImage = ddmUiLibLoader.loadImage(display, - "emulator.png", ICON_WIDTH, ICON_WIDTH, //$NON-NLS-1$ - display.getSystemColor(SWT.COLOR_BLUE)); - } - - if (mMatchImage == null) { - mMatchImage = factory.getIcon("match", //$NON-NLS-1$ - IconFactory.COLOR_GREEN, - IconFactory.SHAPE_DEFAULT); - } - - if (mNoMatchImage == null) { - mNoMatchImage = factory.getIcon("error", //$NON-NLS-1$ - IconFactory.COLOR_RED, - IconFactory.SHAPE_DEFAULT); - } - - if (mWarningImage == null) { - mWarningImage = factory.getIcon("warning", //$NON-NLS-1$ - SWT.COLOR_YELLOW, - IconFactory.SHAPE_DEFAULT); - } - - } - - /** - * Returns a display string representing the state of the device. - * @param d the device - */ - private static String getStateString(IDevice d) { - DeviceState deviceState = d.getState(); - if (deviceState == DeviceState.ONLINE) { - return "Online"; - } else if (deviceState == DeviceState.OFFLINE) { - return "Offline"; - } else if (deviceState == DeviceState.BOOTLOADER) { - return "Bootloader"; - } - - return "??"; - } - - /** - * Sent when the a device is connected to the {@link AndroidDebugBridge}. - * <p/> - * This is sent from a non UI thread. - * @param device the new device. - * - * @see IDeviceChangeListener#deviceConnected(IDevice) - */ - @Override - public void deviceConnected(IDevice device) { - final DeviceChooserDialog dialog = this; - exec(new Runnable() { - @Override - public void run() { - if (mDeviceTable.isDisposed() == false) { - // refresh all - mViewer.refresh(); - - // update the selection - updateDefaultSelection(); - - // update the display of AvdInfo (since it's filtered to only display - // non running AVD.) - refillAvdList(false /*reloadAvds*/); - } else { - // table is disposed, we need to do something. - // lets remove ourselves from the listener. - AndroidDebugBridge.removeDeviceChangeListener(dialog); - } - - } - }); - } - - /** - * Sent when the a device is connected to the {@link AndroidDebugBridge}. - * <p/> - * This is sent from a non UI thread. - * @param device the new device. - * - * @see IDeviceChangeListener#deviceDisconnected(IDevice) - */ - @Override - public void deviceDisconnected(IDevice device) { - deviceConnected(device); - } - - /** - * Sent when a device data changed, or when clients are started/terminated on the device. - * <p/> - * This is sent from a non UI thread. - * @param device the device that was updated. - * @param changeMask the mask indicating what changed. - * - * @see IDeviceChangeListener#deviceChanged(IDevice, int) - */ - @Override - public void deviceChanged(final IDevice device, int changeMask) { - if ((changeMask & (IDevice.CHANGE_STATE | IDevice.CHANGE_BUILD_INFO)) != 0) { - final DeviceChooserDialog dialog = this; - exec(new Runnable() { - @Override - public void run() { - if (mDeviceTable.isDisposed() == false) { - // refresh the device - mViewer.refresh(device); - - // update the defaultSelection. - updateDefaultSelection(); - - // update the display of AvdInfo (since it's filtered to only display - // non running AVD). This is done on deviceChanged because the avd name - // of a (emulator) device may be updated as the emulator boots. - - refillAvdList(false /*reloadAvds*/); - - // if the changed device is the current selection, - // we update the OK button based on its state. - if (device == mResponse.getDeviceToUse()) { - enableOkButton(); - } - - } else { - // table is disposed, we need to do something. - // lets remove ourselves from the listener. - AndroidDebugBridge.removeDeviceChangeListener(dialog); - } - } - }); - } - } - - /** - * Returns whether the dialog is in "device" mode (true), or in "avd" mode (false). - */ - private boolean isDeviceMode() { - return mDeviceRadioButton.getSelection(); - } - - /** - * Enables or disables the OK button of the dialog based on various selections in the dialog. - */ - private void enableOkButton() { - Button okButton = getButton(IDialogConstants.OK_ID); - - if (isDeviceMode()) { - okButton.setEnabled(mResponse.getDeviceToUse() != null && - mResponse.getDeviceToUse().isOnline()); - } else { - okButton.setEnabled(mResponse.getAvdToLaunch() != null); - } - } - - /** - * Returns true if the ok button is enabled. - */ - private boolean isOkButtonEnabled() { - Button okButton = getButton(IDialogConstants.OK_ID); - return okButton.isEnabled(); - } - - /** - * Executes the {@link Runnable} in the UI thread. - * @param runnable the runnable to execute. - */ - private void exec(Runnable runnable) { - try { - Display display = mDeviceTable.getDisplay(); - display.asyncExec(runnable); - } catch (SWTException e) { - // tree is disposed, we need to do something. lets remove ourselves from the listener. - AndroidDebugBridge.removeDeviceChangeListener(this); - } - } - - private void handleDeviceSelection() { - int count = mDeviceTable.getSelectionCount(); - if (count != 1) { - handleSelection(null); - } else { - int index = mDeviceTable.getSelectionIndex(); - Object data = mViewer.getElementAt(index); - if (data instanceof IDevice) { - handleSelection((IDevice)data); - } else { - handleSelection(null); - } - } - } - - private void handleSelection(IDevice device) { - mResponse.setDeviceToUse(device); - enableOkButton(); - } - - /** - * Look for a default device to select. This is done by looking for the running - * clients on each device and finding one similar to the one being launched. - * <p/> - * This is done every time the device list changed unless there is a already selection. - */ - private void updateDefaultSelection() { - if (mDeviceTable.getSelectionCount() == 0) { - AndroidDebugBridge bridge = AndroidDebugBridge.getBridge(); - - IDevice[] devices = bridge.getDevices(); - - for (IDevice device : devices) { - Client[] clients = device.getClients(); - - for (Client client : clients) { - - if (mPackageName.equals(client.getClientData().getClientDescription())) { - // found a match! Select it. - mViewer.setSelection(new StructuredSelection(device)); - handleSelection(device); - - // and we're done. - return; - } - } - } - } - - handleDeviceSelection(); - } - - private final class NonRunningAvdFilter implements IAvdFilter { - - private IDevice[] mDevices; - - @Override - public void prepare() { - mDevices = AndroidDebugBridge.getBridge().getDevices(); - } - - @Override - public boolean accept(AvdInfo avd) { - if (mDevices != null) { - for (IDevice d : mDevices) { - // do not accept running avd's - if (avd.getName().equals(d.getAvdName())) { - return false; - } - - // only accept avd's that can actually run the project - AvdCompatibility.Compatibility c = - AvdCompatibility.canRun(avd, mProjectTarget, mMinApiVersion); - return (c == AvdCompatibility.Compatibility.NO) ? false : true; - } - } - - return true; - } - - @Override - public void cleanup() { - mDevices = null; - } - } - - /** - * Refills the AVD list keeping the current selection. - */ - private void refillAvdList(boolean reloadAvds) { - // save the current selection - AvdInfo selected = mPreferredAvdSelector.getSelected(); - - // disable selection change. - mDisableAvdSelectionChange = true; - - // refresh the list - mPreferredAvdSelector.refresh(false); - - // attempt to reselect the proper avd if needed - if (selected != null) { - if (mPreferredAvdSelector.setSelection(selected) == false) { - // looks like the selection is lost. this can happen if an emulator - // running the AVD that was selected was launched from outside of Eclipse). - mResponse.setAvdToLaunch(null); - enableOkButton(); - } - } - - // enable the selection change - mDisableAvdSelectionChange = false; - } -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmptyLaunchAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmptyLaunchAction.java deleted file mode 100644 index a8bb414e9..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmptyLaunchAction.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import com.android.ddmlib.IDevice; -import com.android.ide.eclipse.adt.AdtPlugin; - -import java.util.Collection; - -/** - * A launch action that does nothing after the application has been installed - */ -public class EmptyLaunchAction implements IAndroidLaunchAction { - @Override - public boolean doLaunchAction(DelayedLaunchInfo info, Collection<IDevice> devices) { - for (IDevice d : devices) { - doLaunchAction(info, d); - } - - return false; - } - - public boolean doLaunchAction(DelayedLaunchInfo info, IDevice device) { - // we're not supposed to do anything, just return; - String msg = String.format("%1$s installed on device", - info.getPackageFile().getFullPath().toOSString()); - AdtPlugin.printToConsole(info.getProject(), msg, "Done!"); - // return false so launch controller will not wait for debugger to attach - return false; - } - - @Override - public String getLaunchDescription() { - return "sync"; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmulatorConfigTab.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmulatorConfigTab.java deleted file mode 100644 index 779dfa111..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmulatorConfigTab.java +++ /dev/null @@ -1,596 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import com.android.ddmuilib.ImageLoader; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo; -import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchConfiguration.TargetMode; -import com.android.ide.eclipse.adt.internal.launch.AvdCompatibility.Compatibility; -import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; -import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; -import com.android.ide.eclipse.adt.internal.sdk.AdtConsoleSdkLog; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.prefs.AndroidLocation.AndroidLocationException; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.internal.avd.AvdInfo; -import com.android.sdklib.internal.avd.AvdManager; -import com.android.sdkuilib.internal.widgets.AvdSelector; -import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode; -import com.android.sdkuilib.internal.widgets.AvdSelector.IAvdFilter; -import com.android.utils.NullLogger; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; -import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -/** - * Launch configuration tab to control the parameters of the Emulator - */ -public class EmulatorConfigTab extends AbstractLaunchConfigurationTab { - - private final static String[][] NETWORK_SPEEDS = new String[][] { - { "Full", "full" }, //$NON-NLS-2$ - { "GSM", "gsm" }, //$NON-NLS-2$ - { "HSCSD", "hscsd" }, //$NON-NLS-2$ - { "GPRS", "gprs" }, //$NON-NLS-2$ - { "EDGE", "edge" }, //$NON-NLS-2$ - { "UMTS", "umts" }, //$NON-NLS-2$ - { "HSPDA", "hsdpa" }, //$NON-NLS-2$ - }; - - private final static String[][] NETWORK_LATENCIES = new String[][] { - { "None", "none" }, //$NON-NLS-2$ - { "GPRS", "gprs" }, //$NON-NLS-2$ - { "EDGE", "edge" }, //$NON-NLS-2$ - { "UMTS", "umts" }, //$NON-NLS-2$ - }; - - private Button mAutoTargetButton; - private Button mManualTargetButton; - private AvdSelector mPreferredAvdSelector; - private Combo mSpeedCombo; - private Combo mDelayCombo; - private Group mEmulatorOptionsGroup; - private Text mEmulatorCLOptions; - private Button mWipeDataButton; - private Button mNoBootAnimButton; - private Label mPreferredAvdLabel; - private IAndroidTarget mProjectTarget; - private AndroidVersion mProjectMinApiVersion; - private Button mFutureLaunchesOnSameDevice; - private boolean mSupportMultiDeviceLaunch; - private Button mAllDevicesTargetButton; - private Combo mDeviceTypeCombo; - - private static final String DEVICES_AND_EMULATORS = "Active devices and AVD's"; - private static final String EMULATORS_ONLY = "Active AVD's"; - private static final String DEVICES_ONLY = "Active devices"; - - /** - * Returns the emulator ready speed option value. - * @param value The index of the combo selection. - */ - public static String getSpeed(int value) { - try { - return NETWORK_SPEEDS[value][1]; - } catch (ArrayIndexOutOfBoundsException e) { - return NETWORK_SPEEDS[LaunchConfigDelegate.DEFAULT_SPEED][1]; - } - } - - /** - * Returns the emulator ready network latency value. - * @param value The index of the combo selection. - */ - public static String getDelay(int value) { - try { - return NETWORK_LATENCIES[value][1]; - } catch (ArrayIndexOutOfBoundsException e) { - return NETWORK_LATENCIES[LaunchConfigDelegate.DEFAULT_DELAY][1]; - } - } - - /** - * - */ - public EmulatorConfigTab(boolean supportMultiDeviceLaunch) { - mSupportMultiDeviceLaunch = supportMultiDeviceLaunch; - } - - /** - * @wbp.parser.entryPoint - */ - @Override - public void createControl(Composite parent) { - Font font = parent.getFont(); - - // Reload the AVDs to make sure we are up to date - try { - // SDK can be null if the user opens the dialog before ADT finished - // initializing the SDK itself. In this case just don't reload anything - // so there's nothing obsolete yet. - Sdk sdk = Sdk.getCurrent(); - if (sdk != null) { - AvdManager avdMan = sdk.getAvdManager(); - assert avdMan != null; - avdMan.reloadAvds(NullLogger.getLogger()); - } - } catch (AndroidLocationException e1) { - // this happens if the AVD Manager failed to find the folder in which the AVDs are - // stored. There isn't much we can do at this point. - } - - Composite topComp = new Composite(parent, SWT.NONE); - setControl(topComp); - GridLayout topLayout = new GridLayout(); - topLayout.numColumns = 1; - topLayout.verticalSpacing = 0; - topComp.setLayout(topLayout); - topComp.setFont(font); - - GridData gd; - GridLayout layout; - - // radio button for the target mode - Group targetModeGroup = new Group(topComp, SWT.NONE); - targetModeGroup.setText("Deployment Target Selection Mode"); - gd = new GridData(GridData.FILL_HORIZONTAL); - targetModeGroup.setLayoutData(gd); - layout = new GridLayout(); - layout.numColumns = 1; - targetModeGroup.setLayout(layout); - targetModeGroup.setFont(font); - - mManualTargetButton = new Button(targetModeGroup, SWT.RADIO); - mManualTargetButton.setText("Always prompt to pick device"); - - mAllDevicesTargetButton = new Button(targetModeGroup, SWT.RADIO); - mAllDevicesTargetButton.setText("Launch on all compatible devices/AVD's"); - mAllDevicesTargetButton.setEnabled(mSupportMultiDeviceLaunch); - - Composite deviceTypeOffsetComp = new Composite(targetModeGroup, SWT.NONE); - deviceTypeOffsetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - layout = new GridLayout(1, false); - layout.marginRight = layout.marginHeight = 0; - layout.marginLeft = 30; - deviceTypeOffsetComp.setLayout(layout); - - mDeviceTypeCombo = new Combo(deviceTypeOffsetComp, SWT.READ_ONLY); - mDeviceTypeCombo.setItems(new String[] { - DEVICES_AND_EMULATORS, - EMULATORS_ONLY, - DEVICES_ONLY, - }); - mDeviceTypeCombo.select(0); - mDeviceTypeCombo.setEnabled(false); - - // add the radio button - mAutoTargetButton = new Button(targetModeGroup, SWT.RADIO); - mAutoTargetButton.setText("Automatically pick compatible device: " - + "Always uses preferred AVD if set below, " - + "launches on compatible device/AVD otherwise."); - mAutoTargetButton.setSelection(true); - - SelectionListener targetModeChangeListener = new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - targetModeChanged(); - } - }; - - mAutoTargetButton.addSelectionListener(targetModeChangeListener); - mAllDevicesTargetButton.addSelectionListener(targetModeChangeListener); - mManualTargetButton.addSelectionListener(targetModeChangeListener); - - Composite avdOffsetComp = new Composite(targetModeGroup, SWT.NONE); - avdOffsetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - layout = new GridLayout(1, false); - layout.marginRight = layout.marginHeight = 0; - layout.marginLeft = 30; - avdOffsetComp.setLayout(layout); - - mPreferredAvdLabel = new Label(avdOffsetComp, SWT.NONE); - mPreferredAvdLabel.setText("Select a preferred Android Virtual Device for deployment:"); - - // create the selector with no manager, we'll reset the manager every time this is - // displayed to ensure we have the latest one (dialog is reused but SDK could have - // been changed in between. - mPreferredAvdSelector = new AvdSelector(avdOffsetComp, - Sdk.getCurrent().getSdkOsLocation(), - null /* avd manager */, - DisplayMode.SIMPLE_CHECK, - new AdtConsoleSdkLog()); - mPreferredAvdSelector.setTableHeightHint(100); - SelectionListener listener = new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - updateLaunchConfigurationDialog(); - } - }; - mPreferredAvdSelector.setSelectionListener(listener); - mDeviceTypeCombo.addSelectionListener(listener); - - mFutureLaunchesOnSameDevice = new Button(targetModeGroup, SWT.CHECK); - mFutureLaunchesOnSameDevice.setText("Use same device for future launches"); - mFutureLaunchesOnSameDevice.addSelectionListener(listener); - - // emulator size - mEmulatorOptionsGroup = new Group(topComp, SWT.NONE); - mEmulatorOptionsGroup.setText("Emulator launch parameters:"); - mEmulatorOptionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - layout = new GridLayout(); - layout.numColumns = 2; - mEmulatorOptionsGroup.setLayout(layout); - mEmulatorOptionsGroup.setFont(font); - - // Explanation - Label l = new Label(mEmulatorOptionsGroup, SWT.NONE); - l.setText("If no compatible and active devices or AVD's are found, then an AVD " - + "might be launched. Provide options for the AVD launch below."); - gd = new GridData(); - gd.horizontalSpan = 2; - l.setLayoutData(gd); - - // network options - new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Network Speed:"); - - mSpeedCombo = new Combo(mEmulatorOptionsGroup, SWT.READ_ONLY); - for (String[] speed : NETWORK_SPEEDS) { - mSpeedCombo.add(speed[0]); - } - mSpeedCombo.addSelectionListener(listener); - mSpeedCombo.pack(); - - new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Network Latency:"); - - mDelayCombo = new Combo(mEmulatorOptionsGroup, SWT.READ_ONLY); - - for (String[] delay : NETWORK_LATENCIES) { - mDelayCombo.add(delay[0]); - } - mDelayCombo.addSelectionListener(listener); - mDelayCombo.pack(); - - // wipe data option - mWipeDataButton = new Button(mEmulatorOptionsGroup, SWT.CHECK); - mWipeDataButton.setText("Wipe User Data"); - mWipeDataButton.setToolTipText("Check this if you want to wipe your user data each time you start the emulator. You will be prompted for confirmation when the emulator starts."); - gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalSpan = 2; - mWipeDataButton.setLayoutData(gd); - mWipeDataButton.addSelectionListener(listener); - - // no boot anim option - mNoBootAnimButton = new Button(mEmulatorOptionsGroup, SWT.CHECK); - mNoBootAnimButton.setText("Disable Boot Animation"); - mNoBootAnimButton.setToolTipText("Check this if you want to disable the boot animation. This can help the emulator start faster on slow machines."); - gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalSpan = 2; - mNoBootAnimButton.setLayoutData(gd); - mNoBootAnimButton.addSelectionListener(listener); - - // custom command line option for emulator - l = new Label(mEmulatorOptionsGroup, SWT.NONE); - l.setText("Additional Emulator Command Line Options"); - gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalSpan = 2; - l.setLayoutData(gd); - - mEmulatorCLOptions = new Text(mEmulatorOptionsGroup, SWT.BORDER); - gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalSpan = 2; - mEmulatorCLOptions.setLayoutData(gd); - mEmulatorCLOptions.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - updateLaunchConfigurationDialog(); - } - }); - } - - private void targetModeChanged() { - updateLaunchConfigurationDialog(); - - boolean auto = mAutoTargetButton.getSelection(); - mPreferredAvdSelector.setEnabled(auto); - mPreferredAvdLabel.setEnabled(auto); - - boolean all = mAllDevicesTargetButton.getSelection(); - mDeviceTypeCombo.setEnabled(all); - } - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName() - */ - @Override - public String getName() { - return "Target"; - } - - @Override - public Image getImage() { - return ImageLoader.getDdmUiLibLoader().loadImage("emulator.png", null); //$NON-NLS-1$ - } - - private void updateAvdList(AvdManager avdManager) { - if (avdManager == null) { - avdManager = Sdk.getCurrent().getAvdManager(); - } - - mPreferredAvdSelector.setManager(avdManager); - mPreferredAvdSelector.refresh(false); - - mPreferredAvdSelector.setFilter(new IAvdFilter() { - @Override - public void prepare() { - } - - @Override - public void cleanup() { - } - - @Override - public boolean accept(AvdInfo avd) { - AvdCompatibility.Compatibility c = - AvdCompatibility.canRun(avd, mProjectTarget, mProjectMinApiVersion); - return (c == Compatibility.NO) ? false : true; - } - }); - } - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration) - */ - @Override - public void initializeFrom(ILaunchConfiguration configuration) { - AvdManager avdManager = Sdk.getCurrent().getAvdManager(); - - TargetMode mode = AndroidLaunchConfiguration.parseTargetMode(configuration, - LaunchConfigDelegate.DEFAULT_TARGET_MODE); - - boolean multipleDevices = mode.isMultiDevice(); - if (multipleDevices && !mSupportMultiDeviceLaunch) { - // The launch config says to run on multiple devices, but this launch type does not - // suppport multiple devices. In such a case, switch back to default mode. - // This could happen if a launch config used for Run is then used for Debug. - multipleDevices = false; - mode = LaunchConfigDelegate.DEFAULT_TARGET_MODE; - } - - mAutoTargetButton.setSelection(mode == TargetMode.AUTO); - mManualTargetButton.setSelection(mode == TargetMode.MANUAL); - mAllDevicesTargetButton.setSelection(multipleDevices); - - targetModeChanged(); - - boolean reuseLastUsedDevice; - try { - reuseLastUsedDevice = configuration.getAttribute( - LaunchConfigDelegate.ATTR_REUSE_LAST_USED_DEVICE, false); - } catch (CoreException ex) { - reuseLastUsedDevice = false; - } - mFutureLaunchesOnSameDevice.setSelection(reuseLastUsedDevice); - - mDeviceTypeCombo.setEnabled(multipleDevices); - if (multipleDevices) { - int index = 0; - if (mode == TargetMode.ALL_EMULATORS) { - index = 1; - } else if (mode == TargetMode.ALL_DEVICES) { - index = 2; - } - mDeviceTypeCombo.select(index); - } - - // look for the project name to get its target. - String stringValue = ""; - try { - stringValue = configuration.getAttribute( - IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, stringValue); - } catch (CoreException ce) { - // let's not do anything here, we'll use the default value - } - - IProject project = null; - - // get the list of existing Android projects from the workspace. - IJavaProject[] projects = BaseProjectHelper.getAndroidProjects(null /*filter*/); - if (projects != null) { - // look for the project whose name we read from the configuration. - for (IJavaProject p : projects) { - if (p.getElementName().equals(stringValue)) { - project = p.getProject(); - break; - } - } - } - - // update the AVD list - if (project != null) { - mProjectTarget = Sdk.getCurrent().getTarget(project); - - ManifestInfo mi = ManifestInfo.get(project); - final int minApiLevel = mi.getMinSdkVersion(); - final String minApiCodeName = mi.getMinSdkCodeName(); - mProjectMinApiVersion = new AndroidVersion(minApiLevel, minApiCodeName); - } - - updateAvdList(avdManager); - - stringValue = ""; - try { - stringValue = configuration.getAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, - stringValue); - } catch (CoreException e) { - // let's not do anything here, we'll use the default value - } - - if (stringValue != null && stringValue.length() > 0 && avdManager != null) { - AvdInfo targetAvd = avdManager.getAvd(stringValue, true /*validAvdOnly*/); - mPreferredAvdSelector.setSelection(targetAvd); - } else { - mPreferredAvdSelector.setSelection(null); - } - - boolean value = LaunchConfigDelegate.DEFAULT_WIPE_DATA; - try { - value = configuration.getAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, value); - } catch (CoreException e) { - // let's not do anything here, we'll use the default value - } - mWipeDataButton.setSelection(value); - - value = LaunchConfigDelegate.DEFAULT_NO_BOOT_ANIM; - try { - value = configuration.getAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM, value); - } catch (CoreException e) { - // let's not do anything here, we'll use the default value - } - mNoBootAnimButton.setSelection(value); - - int index = -1; - - index = LaunchConfigDelegate.DEFAULT_SPEED; - try { - index = configuration.getAttribute(LaunchConfigDelegate.ATTR_SPEED, - index); - } catch (CoreException e) { - // let's not do anything here, we'll use the default value - } - if (index == -1) { - mSpeedCombo.clearSelection(); - } else { - mSpeedCombo.select(index); - } - - index = LaunchConfigDelegate.DEFAULT_DELAY; - try { - index = configuration.getAttribute(LaunchConfigDelegate.ATTR_DELAY, - index); - } catch (CoreException e) { - // let's not do anything here, we'll put a proper value in - // performApply anyway - } - if (index == -1) { - mDelayCombo.clearSelection(); - } else { - mDelayCombo.select(index); - } - - String commandLine = null; - try { - commandLine = configuration.getAttribute( - LaunchConfigDelegate.ATTR_COMMANDLINE, ""); //$NON-NLS-1$ - } catch (CoreException e) { - // let's not do anything here, we'll use the default value - } - if (commandLine != null) { - mEmulatorCLOptions.setText(commandLine); - } - } - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) - */ - @Override - public void performApply(ILaunchConfigurationWorkingCopy configuration) { - configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE, - getCurrentTargetMode().toString()); - configuration.setAttribute(LaunchConfigDelegate.ATTR_REUSE_LAST_USED_DEVICE, - mFutureLaunchesOnSameDevice.getSelection()); - AvdInfo avd = mPreferredAvdSelector.getSelected(); - if (avd != null) { - configuration.setAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, avd.getName()); - } else { - configuration.setAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, (String)null); - } - configuration.setAttribute(LaunchConfigDelegate.ATTR_SPEED, - mSpeedCombo.getSelectionIndex()); - configuration.setAttribute(LaunchConfigDelegate.ATTR_DELAY, - mDelayCombo.getSelectionIndex()); - configuration.setAttribute(LaunchConfigDelegate.ATTR_COMMANDLINE, - mEmulatorCLOptions.getText()); - configuration.setAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, - mWipeDataButton.getSelection()); - configuration.setAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM, - mNoBootAnimButton.getSelection()); - } - - private TargetMode getCurrentTargetMode() { - if (mAutoTargetButton.getSelection()) { - return TargetMode.AUTO; - } else if (mManualTargetButton.getSelection()) { - return TargetMode.MANUAL; - } else { - String selection = mDeviceTypeCombo.getText(); - if (DEVICES_AND_EMULATORS.equals(selection)) { - return TargetMode.ALL_DEVICES_AND_EMULATORS; - } else if (DEVICES_ONLY.equals(selection)) { - return TargetMode.ALL_DEVICES; - } else if (EMULATORS_ONLY.equals(selection)) { - return TargetMode.ALL_EMULATORS; - } - } - - return TargetMode.AUTO; - } - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) - */ - @Override - public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { - configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE, - LaunchConfigDelegate.DEFAULT_TARGET_MODE.toString()); - configuration.setAttribute(LaunchConfigDelegate.ATTR_SPEED, - LaunchConfigDelegate.DEFAULT_SPEED); - configuration.setAttribute(LaunchConfigDelegate.ATTR_DELAY, - LaunchConfigDelegate.DEFAULT_DELAY); - configuration.setAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, - LaunchConfigDelegate.DEFAULT_WIPE_DATA); - configuration.setAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM, - LaunchConfigDelegate.DEFAULT_NO_BOOT_ANIM); - - IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore(); - String emuOptions = store.getString(AdtPrefs.PREFS_EMU_OPTIONS); - configuration.setAttribute(LaunchConfigDelegate.ATTR_COMMANDLINE, emuOptions); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/IAndroidLaunchAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/IAndroidLaunchAction.java deleted file mode 100644 index 1ec46b603..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/IAndroidLaunchAction.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import com.android.ddmlib.IDevice; - -import java.util.Collection; - -/** - * An action to perform after performing a launch of an Android application - */ -public interface IAndroidLaunchAction { - - /** - * Do the launch - * - * @param info the {@link DelayedLaunchInfo} that contains launch details - * @param devices Android devices on which the action will be performed - * @returns true if launch was successfully, and controller should wait for debugger to attach - * (if applicable) - */ - boolean doLaunchAction(DelayedLaunchInfo info, Collection<IDevice> devices); - - /** - * Return a description of launch, to be used for logging and error messages - */ - String getLaunchDescription(); - -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/ILaunchController.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/ILaunchController.java deleted file mode 100644 index 6a5c00947..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/ILaunchController.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import com.android.ddmlib.IDevice; - -/** - * Interface for managing Android launches - */ -public interface ILaunchController { - - /** - * Launches an application on a device or emulator - * - * @param launchInfo the {@link DelayedLaunchInfo} that indicates the launch action - * @param device the device or emulator to launch the application on - */ - public void launchApp(DelayedLaunchInfo launchInfo, IDevice device); - - /** - * Cancels a launch - * - * @param launchInfo the {@link DelayedLaunchInfo} to cancel - */ - void stopLaunch(DelayedLaunchInfo launchInfo); -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/JUnitLaunchConfigDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/JUnitLaunchConfigDelegate.java deleted file mode 100644 index fdb1b305a..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/JUnitLaunchConfigDelegate.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import com.android.SdkConstants; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.AdtPlugin; - -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.FileLocator; -import org.eclipse.core.runtime.Platform; -import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate; -import org.osgi.framework.Bundle; - -import java.io.IOException; -import java.net.URL; - -/** - * <p> - * For Android projects, android.jar gets added to the launch configuration of - * JUnit tests as a bootstrap entry. This breaks JUnit tests as android.jar - * contains a skeleton version of JUnit classes and the JVM will stop with an error similar - * to: <blockquote> Error occurred during initialization of VM - * java/lang/NoClassDefFoundError: java/lang/ref/FinalReference </blockquote> - * <p> - * At compile time, Eclipse does not know that there is no valid junit.jar in - * the classpath since it can find a correct reference to all the necessary - * org.junit.* classes in the android.jar so it does not prompt the user to add - * the JUnit3 or JUnit4 jar. - * <p> - * This delegates removes the android.jar from the bootstrap path and if - * necessary also puts back the junit.jar in the user classpath. - * <p> - * This delegate will be present for both Java and Android projects (delegates - * setting instead of only the current project) but the behavior for Java - * projects should be neutral since: - * <ol> - * <li>Java tests can only compile (and then run) when a valid junit.jar is - * present - * <li>There is no android.jar in Java projects - * </ol> - */ -public class JUnitLaunchConfigDelegate extends JUnitLaunchConfigurationDelegate { - - private static final String JUNIT_JAR = "junit.jar"; //$NON-NLS-1$ - - @Override - public String[][] getBootpathExt(ILaunchConfiguration configuration) throws CoreException { - String[][] bootpath = super.getBootpathExt(configuration); - return fixBootpathExt(bootpath); - } - - @Override - public String[] getClasspath(ILaunchConfiguration configuration) throws CoreException { - String[] classpath = super.getClasspath(configuration); - return fixClasspath(classpath, getJavaProjectName(configuration)); - } - - /** - * Removes the android.jar from the bootstrap path if present. - * - * @param bootpath Array of Arrays of bootstrap class paths - * @return a new modified (if applicable) bootpath - */ - public static String[][] fixBootpathExt(String[][] bootpath) { - for (int i = 0; i < bootpath.length; i++) { - if (bootpath[i] != null && bootpath[i].length > 0) { - // we assume that the android.jar can only be present in the - // bootstrap path of android tests - if (bootpath[i][0].endsWith(SdkConstants.FN_FRAMEWORK_LIBRARY)) { - bootpath[i] = null; - } - } - } - return bootpath; - } - - /** - * Add the junit.jar to the user classpath; since Eclipse was relying on - * android.jar to provide the appropriate org.junit classes, it does not - * know it actually needs the junit.jar. - * - * @param classpath Array containing classpath - * @param projectName The name of the project (for logging purposes) - * - * @return a new modified (if applicable) classpath - */ - public static String[] fixClasspath(String[] classpath, String projectName) { - // search for junit.jar; if any are found return immediately - for (int i = 0; i < classpath.length; i++) { - if (classpath[i].endsWith(JUNIT_JAR)) { - return classpath; - } - } - - // This delegate being called without a junit.jar present is only - // possible for Android projects. In a non-Android project, the test - // would not compile and would be unable to run. - try { - // junit4 is backward compatible with junit3 and they uses the - // same junit.jar from bundle org.junit: - // When a project has mixed JUnit3 and JUnit4 tests, if JUnit3 jar - // is added first it is then replaced by the JUnit4 jar when user is - // prompted to fix the JUnit4 test failure - String jarLocation = getJunitJarLocation(); - // we extend the classpath by one element and append junit.jar - String[] newClasspath = new String[classpath.length + 1]; - System.arraycopy(classpath, 0, newClasspath, 0, classpath.length); - newClasspath[newClasspath.length - 1] = jarLocation; - classpath = newClasspath; - } catch (IOException e) { - // This should not happen as we depend on the org.junit - // plugin explicitly; the error is logged here so that the user can - // trace back the cause when the test fails to run - AdtPlugin.log(e, "Could not find a valid junit.jar"); - AdtPlugin.printErrorToConsole(projectName, - "Could not find a valid junit.jar"); - // Return the classpath as-is (with no junit.jar) anyway because we - // will let the actual launch config fails. - } - - return classpath; - } - - /** - * Returns the path of the junit jar in the highest version bundle. - * - * (This is public only so that the test can call it) - * - * @return the path as a string - * @throws IOException - */ - public static String getJunitJarLocation() throws IOException { - Bundle bundle = Platform.getBundle("org.junit"); //$NON-NLS-1$ - if (bundle == null) { - throw new IOException("Cannot find org.junit bundle"); - } - URL jarUrl = bundle.getEntry(AdtConstants.WS_SEP + JUNIT_JAR); - return FileLocator.resolve(jarUrl).getFile(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchConfigDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchConfigDelegate.java deleted file mode 100644 index 86fc2ffae..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchConfigDelegate.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ide.common.xml.ManifestData; -import com.android.ide.common.xml.ManifestData.Activity; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchConfiguration.TargetMode; -import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper; -import com.android.ide.eclipse.adt.internal.project.ProjectHelper; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IWorkspace; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.debug.core.ILaunch; -import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.debug.core.model.LaunchConfigurationDelegate; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; - -/** - * Implementation of an eclipse LauncConfigurationDelegate to launch android - * application in debug. - */ -public class LaunchConfigDelegate extends LaunchConfigurationDelegate { - final static int INVALID_DEBUG_PORT = -1; - - public final static String ANDROID_LAUNCH_TYPE_ID = - "com.android.ide.eclipse.adt.debug.LaunchConfigType"; //$NON-NLS-1$ - - /** Target mode parameters: true is automatic, false is manual */ - public static final String ATTR_TARGET_MODE = AdtPlugin.PLUGIN_ID + ".target"; //$NON-NLS-1$ - public static final TargetMode DEFAULT_TARGET_MODE = TargetMode.AUTO; - - /** Flag indicating whether the last used device should be used for future launches. */ - public static final String ATTR_REUSE_LAST_USED_DEVICE = - AdtPlugin.PLUGIN_ID + ".reuse.last.used.device"; //$NON-NLS-1$ - - /** Device on which the last launch happened. */ - public static final String ATTR_LAST_USED_DEVICE = - AdtPlugin.PLUGIN_ID + ".last.used.device"; //$NON-NLS-1$ - - /** - * Launch action: - * <ul> - * <li>0: launch default activity</li> - * <li>1: launch specified activity. See {@link #ATTR_ACTIVITY}</li> - * <li>2: Do Nothing</li> - * </ul> - */ - public final static String ATTR_LAUNCH_ACTION = AdtPlugin.PLUGIN_ID + ".action"; //$NON-NLS-1$ - - /** Default launch action. This launches the activity that is setup to be found in the HOME - * screen. - */ - public final static int ACTION_DEFAULT = 0; - /** Launch action starting a specific activity. */ - public final static int ACTION_ACTIVITY = 1; - /** Launch action that does nothing. */ - public final static int ACTION_DO_NOTHING = 2; - /** Default launch action value. */ - public final static int DEFAULT_LAUNCH_ACTION = ACTION_DEFAULT; - - /** - * Activity to be launched if {@link #ATTR_LAUNCH_ACTION} is 1 - */ - public static final String ATTR_ACTIVITY = AdtPlugin.PLUGIN_ID + ".activity"; //$NON-NLS-1$ - - public static final String ATTR_AVD_NAME = AdtPlugin.PLUGIN_ID + ".avd"; //$NON-NLS-1$ - - public static final String ATTR_SPEED = AdtPlugin.PLUGIN_ID + ".speed"; //$NON-NLS-1$ - - /** - * Index of the default network speed setting for the emulator.<br> - * Get the emulator option with <code>EmulatorConfigTab.getSpeed(index)</code> - */ - public static final int DEFAULT_SPEED = 0; - - public static final String ATTR_DELAY = AdtPlugin.PLUGIN_ID + ".delay"; //$NON-NLS-1$ - - /** - * Index of the default network latency setting for the emulator.<br> - * Get the emulator option with <code>EmulatorConfigTab.getDelay(index)</code> - */ - public static final int DEFAULT_DELAY = 0; - - public static final String ATTR_COMMANDLINE = AdtPlugin.PLUGIN_ID + ".commandline"; //$NON-NLS-1$ - - public static final String ATTR_WIPE_DATA = AdtPlugin.PLUGIN_ID + ".wipedata"; //$NON-NLS-1$ - public static final boolean DEFAULT_WIPE_DATA = false; - - public static final String ATTR_NO_BOOT_ANIM = AdtPlugin.PLUGIN_ID + ".nobootanim"; //$NON-NLS-1$ - public static final boolean DEFAULT_NO_BOOT_ANIM = false; - - public static final String ATTR_DEBUG_PORT = - AdtPlugin.PLUGIN_ID + ".debugPort"; //$NON-NLS-1$ - - @Override - public void launch(ILaunchConfiguration configuration, String mode, - ILaunch launch, IProgressMonitor monitor) throws CoreException { - // We need to check if it's a standard launch or if it's a launch - // to debug an application already running. - int debugPort = AndroidLaunchController.getPortForConfig(configuration); - - // get the project - IProject project = getProject(configuration); - - // first we make sure the launch is of the proper type - AndroidLaunch androidLaunch = null; - if (launch instanceof AndroidLaunch) { - androidLaunch = (AndroidLaunch)launch; - } else { - // wrong type, not sure how we got there, but we don't do - // anything else - AdtPlugin.printErrorToConsole(project, "Wrong Launch Type!"); - return; - } - - // if we have a valid debug port, this means we're debugging an app - // that's already launched. - if (debugPort != INVALID_DEBUG_PORT) { - AndroidLaunchController.launchRemoteDebugger(debugPort, androidLaunch, monitor); - return; - } - - if (project == null) { - AdtPlugin.printErrorToConsole("Couldn't get project object!"); - androidLaunch.stopLaunch(); - return; - } - - // make sure the project and its dependencies are built - // and PostCompilerBuilder runs. - // This is a synchronous call which returns when the - // build is done. - ProjectHelper.doFullIncrementalDebugBuild(project, monitor); - - // check if the project has errors, and abort in this case. - if (ProjectHelper.hasError(project, true)) { - AdtPlugin.displayError("Android Launch", - "Your project contains error(s), please fix them before running your application."); - return; - } - - AdtPlugin.printToConsole(project, "------------------------------"); //$NON-NLS-1$ - AdtPlugin.printToConsole(project, "Android Launch!"); - - // check if the project is using the proper sdk. - // if that throws an exception, we simply let it propagate to the caller. - if (checkAndroidProject(project) == false) { - AdtPlugin.printErrorToConsole(project, "Project is not an Android Project. Aborting!"); - androidLaunch.stopLaunch(); - return; - } - - // Check adb status and abort if needed. - AndroidDebugBridge bridge = AndroidDebugBridge.getBridge(); - if (bridge == null || bridge.isConnected() == false) { - try { - int connections = -1; - int restarts = -1; - if (bridge != null) { - connections = bridge.getConnectionAttemptCount(); - restarts = bridge.getRestartAttemptCount(); - } - - // if we get -1, the device monitor is not even setup (anymore?). - // We need to ask the user to restart eclipse. - // This shouldn't happen, but it's better to let the user know in case it does. - if (connections == -1 || restarts == -1) { - AdtPlugin.printErrorToConsole(project, - "The connection to adb is down, and a severe error has occured.", - "You must restart adb and Eclipse.", - String.format( - "Please ensure that adb is correctly located at '%1$s' and can be executed.", - AdtPlugin.getOsAbsoluteAdb())); - return; - } - - if (restarts == 0) { - AdtPlugin.printErrorToConsole(project, - "Connection with adb was interrupted.", - String.format("%1$s attempts have been made to reconnect.", connections), - "You may want to manually restart adb from the Devices view."); - } else { - AdtPlugin.printErrorToConsole(project, - "Connection with adb was interrupted, and attempts to reconnect have failed.", - String.format("%1$s attempts have been made to restart adb.", restarts), - "You may want to manually restart adb from the Devices view."); - - } - return; - } finally { - androidLaunch.stopLaunch(); - } - } - - // since adb is working, we let the user know - // TODO have a verbose mode for launch with more info (or some of the less useful info we now have). - AdtPlugin.printToConsole(project, "adb is running normally."); - - // make a config class - AndroidLaunchConfiguration config = new AndroidLaunchConfiguration(); - - // fill it with the config coming from the ILaunchConfiguration object - config.set(configuration); - - // get the launch controller singleton - AndroidLaunchController controller = AndroidLaunchController.getInstance(); - - // get the application package - IFile applicationPackage = ProjectHelper.getApplicationPackage(project); - if (applicationPackage == null) { - androidLaunch.stopLaunch(); - return; - } - - // we need some information from the manifest - ManifestData manifestData = AndroidManifestHelper.parseForData(project); - - if (manifestData == null) { - AdtPlugin.printErrorToConsole(project, "Failed to parse AndroidManifest: aborting!"); - androidLaunch.stopLaunch(); - return; - } - - doLaunch(configuration, mode, monitor, project, androidLaunch, config, controller, - applicationPackage, manifestData); - } - - protected void doLaunch(ILaunchConfiguration configuration, String mode, - IProgressMonitor monitor, IProject project, AndroidLaunch androidLaunch, - AndroidLaunchConfiguration config, AndroidLaunchController controller, - IFile applicationPackage, ManifestData manifestData) { - - String activityName = null; - - if (config.mLaunchAction == ACTION_ACTIVITY) { - // Get the activity name defined in the config - activityName = getActivityName(configuration); - - // Get the full activity list and make sure the one we got matches. - Activity[] activities = manifestData.getActivities(); - - // first we check that there are, in fact, activities. - if (activities.length == 0) { - // if the activities list is null, then the manifest is empty - // and we can't launch the app. We'll revert to a sync-only launch - AdtPlugin.printErrorToConsole(project, - "The Manifest defines no activity!", - "The launch will only sync the application package on the device!"); - config.mLaunchAction = ACTION_DO_NOTHING; - } else if (activityName == null) { - // if the activity we got is null, we look for the default one. - AdtPlugin.printErrorToConsole(project, - "No activity specified! Getting the launcher activity."); - Activity launcherActivity = manifestData.getLauncherActivity(); - if (launcherActivity != null) { - activityName = launcherActivity.getName(); - } - - // if there's no default activity. We revert to a sync-only launch. - if (activityName == null) { - revertToNoActionLaunch(project, config); - } - } else { - - // check the one we got from the config matches any from the list - boolean match = false; - for (Activity a : activities) { - if (a != null && a.getName().equals(activityName)) { - match = true; - break; - } - } - - // if we didn't find a match, we revert to the default activity if any. - if (match == false) { - AdtPlugin.printErrorToConsole(project, - "The specified activity does not exist! Getting the launcher activity."); - Activity launcherActivity = manifestData.getLauncherActivity(); - if (launcherActivity != null) { - activityName = launcherActivity.getName(); - } else { - // if there's no default activity. We revert to a sync-only launch. - revertToNoActionLaunch(project, config); - } - } - } - } else if (config.mLaunchAction == ACTION_DEFAULT) { - Activity launcherActivity = manifestData.getLauncherActivity(); - if (launcherActivity != null) { - activityName = launcherActivity.getName(); - } - - // if there's no default activity. We revert to a sync-only launch. - if (activityName == null) { - revertToNoActionLaunch(project, config); - } - } - - IAndroidLaunchAction launchAction = null; - if (config.mLaunchAction == ACTION_DO_NOTHING || activityName == null) { - launchAction = new EmptyLaunchAction(); - } else { - launchAction = new ActivityLaunchAction(activityName, controller); - } - - // everything seems fine, we ask the launch controller to handle - // the rest - controller.launch(project, mode, applicationPackage,manifestData.getPackage(), - manifestData.getPackage(), manifestData.getDebuggable(), - manifestData.getMinSdkVersionString(), launchAction, config, androidLaunch, - monitor); - } - - @Override - public boolean buildForLaunch(ILaunchConfiguration configuration, - String mode, IProgressMonitor monitor) throws CoreException { - // if this returns true, this forces a full workspace rebuild which is not - // what we want. - // Instead in the #launch method, we'll rebuild only the launching project. - return false; - } - - /** - * {@inheritDoc} - * @throws CoreException - */ - @Override - public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) - throws CoreException { - return new AndroidLaunch(configuration, mode, null); - } - - /** - * Returns the IProject object matching the name found in the configuration - * object under the name - * <code>IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME</code> - * @param configuration - * @return The IProject object or null - */ - private IProject getProject(ILaunchConfiguration configuration){ - // get the project name from the config - String projectName; - try { - projectName = configuration.getAttribute( - IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); - } catch (CoreException e) { - return null; - } - - // get the current workspace - IWorkspace workspace = ResourcesPlugin.getWorkspace(); - - // and return the project with the name from the config - return workspace.getRoot().getProject(projectName); - } - - /** - * Checks the project is an android project. - * @param project The project to check - * @return true if the project is an android SDK. - * @throws CoreException - */ - private boolean checkAndroidProject(IProject project) throws CoreException { - // check if the project is a java and an android project. - if (project.hasNature(JavaCore.NATURE_ID) == false) { - String msg = String.format("%1$s is not a Java project!", project.getName()); - AdtPlugin.displayError("Android Launch", msg); - return false; - } - - if (project.hasNature(AdtConstants.NATURE_DEFAULT) == false) { - String msg = String.format("%1$s is not an Android project!", project.getName()); - AdtPlugin.displayError("Android Launch", msg); - return false; - } - - return true; - } - - - /** - * Returns the name of the activity. - */ - private String getActivityName(ILaunchConfiguration configuration) { - String empty = ""; - String activityName; - try { - activityName = configuration.getAttribute(ATTR_ACTIVITY, empty); - } catch (CoreException e) { - return null; - } - - return (activityName != empty) ? activityName : null; - } - - private final void revertToNoActionLaunch(IProject project, AndroidLaunchConfiguration config) { - AdtPlugin.printErrorToConsole(project, - "No Launcher activity found!", - "The launch will only sync the application package on the device!"); - config.mLaunchAction = ACTION_DO_NOTHING; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchConfigTabGroup.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchConfigTabGroup.java deleted file mode 100644 index fbf17ce63..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchConfigTabGroup.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import org.eclipse.debug.core.ILaunchManager; -import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup; -import org.eclipse.debug.ui.CommonTab; -import org.eclipse.debug.ui.ILaunchConfigurationDialog; -import org.eclipse.debug.ui.ILaunchConfigurationTab; - -/** - * Tab group object for Android Launch Config type. - */ -public class LaunchConfigTabGroup extends AbstractLaunchConfigurationTabGroup { - - public LaunchConfigTabGroup() { - } - - @Override - public void createTabs(ILaunchConfigurationDialog dialog, String mode) { - ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] { - new MainLaunchConfigTab(), - new EmulatorConfigTab(ILaunchManager.RUN_MODE.equals(mode)), - new CommonTab() - }; - setTabs(tabs); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchMessages.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchMessages.java deleted file mode 100644 index 1fd2b5aa1..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchMessages.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import org.eclipse.osgi.util.NLS; - -public class LaunchMessages extends NLS { - private static final String BUNDLE_NAME = "com.android.ide.eclipse.adt.internal.launch.messages"; //$NON-NLS-1$ - - // generic messages that could be used by multiple classes - public static String LaunchDialogTitle; - public static String NonAndroidProjectError; - public static String ParseFileFailure_s; - - // specialized, class-specific messages - public static String AndroidJUnitLaunchAction_LaunchDesc_s; - public static String AndroidJUnitLaunchAction_LaunchFail; - public static String AndroidJUnitLaunchAction_LaunchInstr_2s; - public static String AndroidJUnitDelegate_NoRunnerConfigMsg_s; - public static String AndroidJUnitDelegate_NoRunnerConsoleMsg_4s; - public static String AndroidJUnitDelegate_NoRunnerMsg_s; - public static String AndroidJUnitDelegate_NoTargetMsg_3s; - public static String AndroidJUnitTab_LoaderLabel; - public static String AndroidJUnitTab_LoadInstrError_s; - public static String AndroidJUnitTab_NoRunnerError; - public static String AndroidJUnitTab_SizeLabel; - public static String AndroidJUnitTab_TestContainerText; - public static String InstrValidator_NoTestLibMsg_s; - public static String InstrValidator_WrongRunnerTypeMsg_s; - public static String RemoteAdtTestRunner_RunCompleteMsg; - public static String RemoteAdtTestRunner_RunFailedMsg_s; - - public static String RemoteAdtTestRunner_RunIOException_s; - public static String RemoteAdtTestRunner_RunTimeoutException; - public static String RemoteAdtTestRunner_RunAdbCommandRejectedException_s; - public static String RemoteAdtTestRunner_RunShellCommandUnresponsiveException; - public static String RemoteAdtTestRunner_RunStoppedMsg; - - static { - // initialize resource bundle - NLS.initializeMessages(BUNDLE_NAME, LaunchMessages.class); - } - - private LaunchMessages() { - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchShortcut.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchShortcut.java deleted file mode 100644 index bb02b29b6..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchShortcut.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import com.android.ide.eclipse.adt.internal.sdk.ProjectState; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.debug.ui.DebugUITools; -import org.eclipse.debug.ui.ILaunchShortcut; -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.PlatformUI; - -/** - * Launch shortcut to launch debug/run configuration directly. - */ -public class LaunchShortcut implements ILaunchShortcut { - - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.ILaunchShortcut#launch( - * org.eclipse.jface.viewers.ISelection, java.lang.String) - */ - @Override - public void launch(ISelection selection, String mode) { - if (selection instanceof IStructuredSelection) { - - // get the object and the project from it - IStructuredSelection structSelect = (IStructuredSelection)selection; - Object o = structSelect.getFirstElement(); - - // get the first (and normally only) element - if (o instanceof IAdaptable) { - IResource r = (IResource)((IAdaptable)o).getAdapter(IResource.class); - - // get the project from the resource - if (r != null) { - IProject project = r.getProject(); - - if (project != null) { - ProjectState state = Sdk.getProjectState(project); - if (state != null && state.isLibrary()) { - - MessageDialog.openError( - PlatformUI.getWorkbench().getDisplay().getActiveShell(), - "Android Launch", - "Android library projects cannot be launched."); - } else{ - // and launch - launch(project, mode); - } - } - } - } - } - } - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.ILaunchShortcut#launch( - * org.eclipse.ui.IEditorPart, java.lang.String) - */ - @Override - public void launch(IEditorPart editor, String mode) { - // since we force the shortcut to only work on selection in the - // package explorer, this will never be called. - } - - - /** - * Launch a config for the specified project. - * @param project The project to launch - * @param mode The launch mode ("debug", "run" or "profile") - */ - private void launch(IProject project, String mode) { - // get an existing or new launch configuration - ILaunchConfiguration config = AndroidLaunchController.getLaunchConfig(project, - LaunchConfigDelegate.ANDROID_LAUNCH_TYPE_ID); - - if (config != null) { - // and launch! - DebugUITools.launch(config, mode); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/MainLaunchConfigTab.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/MainLaunchConfigTab.java deleted file mode 100644 index c66458fc9..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/MainLaunchConfigTab.java +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch; - -import com.android.ide.common.xml.ManifestData; -import com.android.ide.common.xml.ManifestData.Activity; -import com.android.ide.eclipse.adt.internal.editors.IconFactory; -import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper; -import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper; -import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper.IProjectChooserFilter; -import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper.NonLibraryProjectOnlyFilter; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; -import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; -import org.eclipse.debug.ui.ILaunchConfigurationTab; -import org.eclipse.jdt.core.IJavaModel; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Group; -import org.eclipse.swt.widgets.Text; - -import java.util.ArrayList; - -/** - * Class for the main launch configuration tab. - */ -public class MainLaunchConfigTab extends AbstractLaunchConfigurationTab { - - /** - * - */ - public static final String LAUNCH_TAB_IMAGE = "mainLaunchTab"; //$NON-NLS-1$ - - protected static final String EMPTY_STRING = ""; //$NON-NLS-1$ - - protected Text mProjText; - private Button mProjButton; - - private Combo mActivityCombo; - private final ArrayList<Activity> mActivities = new ArrayList<Activity>(); - - private WidgetListener mListener = new WidgetListener(); - - private Button mDefaultActionButton; - private Button mActivityActionButton; - private Button mDoNothingActionButton; - private int mLaunchAction = LaunchConfigDelegate.DEFAULT_LAUNCH_ACTION; - - private ProjectChooserHelper mProjectChooserHelper; - - /** - * A listener which handles widget change events for the controls in this - * tab. - */ - private class WidgetListener implements ModifyListener, SelectionListener { - - @Override - public void modifyText(ModifyEvent e) { - IProject project = checkParameters(); - loadActivities(project); - setDirty(true); - } - - @Override - public void widgetDefaultSelected(SelectionEvent e) {/* do nothing */ - } - - @Override - public void widgetSelected(SelectionEvent e) { - Object source = e.getSource(); - if (source == mProjButton) { - handleProjectButtonSelected(); - } else { - checkParameters(); - } - } - } - - public MainLaunchConfigTab() { - } - - protected IProjectChooserFilter getProjectFilter() { - return new NonLibraryProjectOnlyFilter(); - } - - @Override - public void createControl(Composite parent) { - mProjectChooserHelper = new ProjectChooserHelper(parent.getShell(), getProjectFilter()); - - Font font = parent.getFont(); - Composite comp = new Composite(parent, SWT.NONE); - setControl(comp); - GridLayout topLayout = new GridLayout(); - topLayout.verticalSpacing = 0; - comp.setLayout(topLayout); - comp.setFont(font); - createProjectEditor(comp); - createVerticalSpacer(comp, 1); - - // create the combo for the activity chooser - Group group = new Group(comp, SWT.NONE); - group.setText("Launch Action:"); - GridData gd = new GridData(GridData.FILL_HORIZONTAL); - group.setLayoutData(gd); - GridLayout layout = new GridLayout(); - layout.numColumns = 2; - group.setLayout(layout); - group.setFont(font); - - mDefaultActionButton = new Button(group, SWT.RADIO); - gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalSpan = 2; - mDefaultActionButton.setLayoutData(gd); - mDefaultActionButton.setText("Launch Default Activity"); - mDefaultActionButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - // event are received for both selection and deselection, so we only process - // the selection event to avoid doing it twice. - if (mDefaultActionButton.getSelection() == true) { - mLaunchAction = LaunchConfigDelegate.ACTION_DEFAULT; - mActivityCombo.setEnabled(false); - checkParameters(); - } - } - }); - - mActivityActionButton = new Button(group, SWT.RADIO); - mActivityActionButton.setText("Launch:"); - mActivityActionButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - // event are received for both selection and deselection, so we only process - // the selection event to avoid doing it twice. - if (mActivityActionButton.getSelection() == true) { - mLaunchAction = LaunchConfigDelegate.ACTION_ACTIVITY; - mActivityCombo.setEnabled(true); - checkParameters(); - } - } - }); - - mActivityCombo = new Combo(group, SWT.DROP_DOWN | SWT.READ_ONLY); - gd = new GridData(GridData.FILL_HORIZONTAL); - mActivityCombo.setLayoutData(gd); - mActivityCombo.clearSelection(); - mActivityCombo.setEnabled(false); - mActivityCombo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - checkParameters(); - } - }); - - mDoNothingActionButton = new Button(group, SWT.RADIO); - gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalSpan = 2; - mDoNothingActionButton.setLayoutData(gd); - mDoNothingActionButton.setText("Do Nothing"); - mDoNothingActionButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - // event are received for both selection and deselection, so we only process - // the selection event to avoid doing it twice. - if (mDoNothingActionButton.getSelection() == true) { - mLaunchAction = LaunchConfigDelegate.ACTION_DO_NOTHING; - mActivityCombo.setEnabled(false); - checkParameters(); - } - } - }); - - } - - @Override - public String getName() { - return "Android"; - } - - @Override - public Image getImage() { - return IconFactory.getInstance().getIcon(LAUNCH_TAB_IMAGE); - } - - @Override - public void performApply(ILaunchConfigurationWorkingCopy configuration) { - configuration.setAttribute( - IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, mProjText.getText()); - configuration.setAttribute( - IJavaLaunchConfigurationConstants.ATTR_ALLOW_TERMINATE, true); - - // add the launch mode - configuration.setAttribute(LaunchConfigDelegate.ATTR_LAUNCH_ACTION, mLaunchAction); - - // add the activity - int selection = mActivityCombo.getSelectionIndex(); - if (mActivities != null && selection >=0 && selection < mActivities.size()) { - configuration.setAttribute(LaunchConfigDelegate.ATTR_ACTIVITY, - mActivities.get(selection).getName()); - } - - // link the project and the launch config. - mapResources(configuration); - } - - @Override - public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { - configuration.setAttribute(LaunchConfigDelegate.ATTR_LAUNCH_ACTION, - LaunchConfigDelegate.DEFAULT_LAUNCH_ACTION); - } - - /** - * Creates the widgets for specifying a main type. - * - * @param parent the parent composite - */ - protected void createProjectEditor(Composite parent) { - Font font = parent.getFont(); - Group group = new Group(parent, SWT.NONE); - group.setText("Project:"); - GridData gd = new GridData(GridData.FILL_HORIZONTAL); - group.setLayoutData(gd); - GridLayout layout = new GridLayout(); - layout.numColumns = 2; - group.setLayout(layout); - group.setFont(font); - mProjText = new Text(group, SWT.SINGLE | SWT.BORDER); - gd = new GridData(GridData.FILL_HORIZONTAL); - mProjText.setLayoutData(gd); - mProjText.setFont(font); - mProjText.addModifyListener(mListener); - mProjButton = createPushButton(group, "Browse...", null); - mProjButton.addSelectionListener(mListener); - } - - /** - * returns the default listener from this class. For all subclasses this - * listener will only provide the functi Jaonality of updating the current - * tab - * - * @return a widget listener - */ - protected WidgetListener getDefaultListener() { - return mListener; - } - - /** - * Return the {@link IJavaProject} corresponding to the project name in the project - * name text field, or null if the text does not match a project name. - * @param javaModel the Java Model object corresponding for the current workspace root. - * @return a IJavaProject object or null. - */ - protected IJavaProject getJavaProject(IJavaModel javaModel) { - String projectName = mProjText.getText().trim(); - if (projectName.length() < 1) { - return null; - } - return javaModel.getJavaProject(projectName); - } - - /** - * Show a dialog that lets the user select a project. This in turn provides - * context for the main type, allowing the user to key a main type name, or - * constraining the search for main types to the specified project. - */ - protected void handleProjectButtonSelected() { - IJavaProject javaProject = mProjectChooserHelper.chooseJavaProject( - mProjText.getText().trim(), - "Please select a project to launch"); - if (javaProject == null) { - return; - }// end if - String projectName = javaProject.getElementName(); - mProjText.setText(projectName); - - // get the list of activities and fill the combo - IProject project = javaProject.getProject(); - loadActivities(project); - }// end handle selected - - /** - * Initializes this tab's controls with values from the given - * launch configuration. This method is called when - * a configuration is selected to view or edit, after this - * tab's control has been created. - * - * @param config launch configuration - * - * @see ILaunchConfigurationTab - */ - @Override - public void initializeFrom(ILaunchConfiguration config) { - String projectName = EMPTY_STRING; - try { - projectName = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, - EMPTY_STRING); - }// end try - catch (CoreException ce) { - } - mProjText.setText(projectName); - - IProject proj = mProjectChooserHelper.getAndroidProject(projectName); - loadActivities(proj); - - // load the launch action. - mLaunchAction = LaunchConfigDelegate.DEFAULT_LAUNCH_ACTION; - try { - mLaunchAction = config.getAttribute(LaunchConfigDelegate.ATTR_LAUNCH_ACTION, - mLaunchAction); - } catch (CoreException e) { - // nothing to be done really. launchAction will keep its default value. - } - - mDefaultActionButton.setSelection(mLaunchAction == LaunchConfigDelegate.ACTION_DEFAULT); - mActivityActionButton.setSelection(mLaunchAction == LaunchConfigDelegate.ACTION_ACTIVITY); - mDoNothingActionButton.setSelection( - mLaunchAction == LaunchConfigDelegate.ACTION_DO_NOTHING); - - // now look for the activity and load it if present, otherwise, revert - // to the current one. - String activityName = EMPTY_STRING; - try { - activityName = config.getAttribute(LaunchConfigDelegate.ATTR_ACTIVITY, EMPTY_STRING); - }// end try - catch (CoreException ce) { - // nothing to be done really. activityName will stay empty - } - - if (mLaunchAction != LaunchConfigDelegate.ACTION_ACTIVITY) { - mActivityCombo.setEnabled(false); - mActivityCombo.clearSelection(); - } else { - mActivityCombo.setEnabled(true); - if (activityName == null || activityName.equals(EMPTY_STRING)) { - mActivityCombo.clearSelection(); - } else if (mActivities != null && mActivities.size() > 0) { - // look for the name of the activity in the combo. - boolean found = false; - for (int i = 0 ; i < mActivities.size() ; i++) { - if (activityName.equals(mActivities.get(i).getName())) { - found = true; - mActivityCombo.select(i); - break; - } - } - - // if we haven't found a matching activity we clear the combo selection - if (found == false) { - mActivityCombo.clearSelection(); - } - } - } - } - - /** - * Associates the launch config and the project. This allows Eclipse to delete the launch - * config when the project is deleted. - * - * @param config the launch config working copy. - */ - protected void mapResources(ILaunchConfigurationWorkingCopy config) { - // get the java model - IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); - IJavaModel javaModel = JavaCore.create(workspaceRoot); - - // get the IJavaProject described by the text field. - IJavaProject javaProject = getJavaProject(javaModel); - IResource[] resources = null; - if (javaProject != null) { - resources = AndroidLaunchController.getResourcesToMap(javaProject.getProject()); - } - config.setMappedResources(resources); - } - - /** - * Loads the ui with the activities of the specified project, and stores the - * activities in <code>mActivities</code>. - * <p/> - * First activity is selected by default if present. - * - * @param project The project to load the activities from. - */ - private void loadActivities(IProject project) { - if (project != null) { - // parse the manifest for the list of activities. - ManifestData manifestData = AndroidManifestHelper.parseForData(project); - if (manifestData != null) { - Activity[] activities = manifestData.getActivities(); - - mActivities.clear(); - mActivityCombo.removeAll(); - - for (Activity activity : activities) { - if (activity.isExported() && activity.hasAction()) { - mActivities.add(activity); - mActivityCombo.add(activity.getName()); - } - } - - if (mActivities.size() > 0) { - if (mLaunchAction == LaunchConfigDelegate.ACTION_ACTIVITY) { - mActivityCombo.setEnabled(true); - } - } else { - mActivityCombo.setEnabled(false); - } - - // the selection will be set when we update the ui from the current - // config object. - mActivityCombo.clearSelection(); - - return; - } - } - - // if we reach this point, either project is null, or we got an exception during - // the parsing. In either case, we empty the activity list. - mActivityCombo.removeAll(); - mActivities.clear(); - } - - /** - * Checks the parameters for correctness, and update the error message and buttons. - * @return the current IProject of this launch config. - */ - private IProject checkParameters() { - try { - //test the project name first! - String text = mProjText.getText(); - if (text.length() == 0) { - setErrorMessage("Project Name is required!"); - } else if (text.matches("[a-zA-Z0-9_ \\.-]+") == false) { - setErrorMessage("Project name contains unsupported characters!"); - } else { - IJavaProject[] projects = mProjectChooserHelper.getAndroidProjects(null); - IProject found = null; - for (IJavaProject javaProject : projects) { - if (javaProject.getProject().getName().equals(text)) { - found = javaProject.getProject(); - break; - } - - } - - if (found != null) { - setErrorMessage(null); - } else { - setErrorMessage(String.format("There is no android project named '%1$s'", - text)); - } - - return found; - } - } finally { - updateLaunchConfigurationDialog(); - } - - return null; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchAction.java deleted file mode 100644 index c773ab9ba..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchAction.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch.junit; - -import com.android.ddmlib.IDevice; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.launch.DelayedLaunchInfo; -import com.android.ide.eclipse.adt.internal.launch.IAndroidLaunchAction; -import com.android.ide.eclipse.adt.internal.launch.LaunchMessages; -import com.android.ide.eclipse.adt.internal.launch.junit.runtime.AndroidJUnitLaunchInfo; -import com.android.ide.eclipse.adt.internal.launch.junit.runtime.RemoteAdtTestRunner; -import com.google.common.base.Joiner; - -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.debug.core.ILaunch; -import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.debug.core.ILaunchManager; -import org.eclipse.debug.core.model.IProcess; -import org.eclipse.debug.core.model.IStreamsProxy; -import org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate; -import org.eclipse.jdt.launching.IVMRunner; -import org.eclipse.jdt.launching.VMRunnerConfiguration; -import org.eclipse.swt.widgets.Display; - -import java.util.Collection; - -/** - * A launch action that executes a instrumentation test run on an Android device. - */ -class AndroidJUnitLaunchAction implements IAndroidLaunchAction { - private static final Joiner JOINER = Joiner.on(',').skipNulls(); - private final AndroidJUnitLaunchInfo mLaunchInfo; - - /** - * Creates a AndroidJUnitLaunchAction. - * - * @param launchInfo the {@link AndroidJUnitLaunchInfo} for the JUnit run - */ - public AndroidJUnitLaunchAction(AndroidJUnitLaunchInfo launchInfo) { - mLaunchInfo = launchInfo; - } - - /** - * Launch a instrumentation test run on given Android devices. - * Reuses JDT JUnit launch delegate so results can be communicated back to JDT JUnit UI. - * <p/> - * Note: Must be executed on non-UI thread. - * - * @see IAndroidLaunchAction#doLaunchActions(DelayedLaunchInfo, IDevice) - */ - @Override - public boolean doLaunchAction(DelayedLaunchInfo info, Collection<IDevice> devices) { - String msg = String.format(LaunchMessages.AndroidJUnitLaunchAction_LaunchInstr_2s, - mLaunchInfo.getRunner(), JOINER.join(devices)); - AdtPlugin.printToConsole(info.getProject(), msg); - - try { - mLaunchInfo.setDebugMode(info.isDebugMode()); - mLaunchInfo.setDevices(devices); - JUnitLaunchDelegate junitDelegate = new JUnitLaunchDelegate(mLaunchInfo); - final String mode = info.isDebugMode() ? ILaunchManager.DEBUG_MODE : - ILaunchManager.RUN_MODE; - - junitDelegate.launch(info.getLaunch().getLaunchConfiguration(), mode, info.getLaunch(), - info.getMonitor()); - - // TODO: need to add AMReceiver-type functionality somewhere - } catch (CoreException e) { - AdtPlugin.printErrorToConsole(info.getProject(), - LaunchMessages.AndroidJUnitLaunchAction_LaunchFail); - } - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public String getLaunchDescription() { - return String.format(LaunchMessages.AndroidJUnitLaunchAction_LaunchDesc_s, - mLaunchInfo.getRunner()); - } - - /** - * Extends the JDT JUnit launch delegate to allow for JUnit UI reuse. - */ - private static class JUnitLaunchDelegate extends JUnitLaunchConfigurationDelegate { - - private AndroidJUnitLaunchInfo mLaunchInfo; - - public JUnitLaunchDelegate(AndroidJUnitLaunchInfo launchInfo) { - mLaunchInfo = launchInfo; - } - - /* (non-Javadoc) - * @see org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate#launch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.debug.core.ILaunch, org.eclipse.core.runtime.IProgressMonitor) - */ - @Override - public synchronized void launch(ILaunchConfiguration configuration, String mode, - ILaunch launch, IProgressMonitor monitor) throws CoreException { - // TODO: is progress monitor adjustment needed here? - super.launch(configuration, mode, launch, monitor); - } - - /** - * {@inheritDoc} - * @see org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate#verifyMainTypeName(org.eclipse.debug.core.ILaunchConfiguration) - */ - @Override - public String verifyMainTypeName(ILaunchConfiguration configuration) { - return "com.android.ide.eclipse.adt.junit.internal.runner.RemoteAndroidTestRunner"; //$NON-NLS-1$ - } - - /** - * Overrides parent to return a VM Runner implementation which launches a thread, rather - * than a separate VM process - */ - @Override - public IVMRunner getVMRunner(ILaunchConfiguration configuration, String mode) { - return new VMTestRunner(mLaunchInfo); - } - - /** - * {@inheritDoc} - * @see org.eclipse.debug.core.model.LaunchConfigurationDelegate#getLaunch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String) - */ - @Override - public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) { - return mLaunchInfo.getLaunch(); - } - } - - /** - * Provides a VM runner implementation which starts a inline implementation of a launch process - */ - private static class VMTestRunner implements IVMRunner { - - private final AndroidJUnitLaunchInfo mJUnitInfo; - - VMTestRunner(AndroidJUnitLaunchInfo info) { - mJUnitInfo = info; - } - - /** - * {@inheritDoc} - * @throws CoreException - */ - @Override - public void run(final VMRunnerConfiguration config, ILaunch launch, - IProgressMonitor monitor) throws CoreException { - - TestRunnerProcess runnerProcess = - new TestRunnerProcess(config, mJUnitInfo); - launch.addProcess(runnerProcess); - runnerProcess.run(); - } - } - - /** - * Launch process that executes the tests. - */ - private static class TestRunnerProcess implements IProcess { - - private final VMRunnerConfiguration mRunConfig; - private final AndroidJUnitLaunchInfo mJUnitInfo; - private RemoteAdtTestRunner mTestRunner = null; - private boolean mIsTerminated = false; - - TestRunnerProcess(VMRunnerConfiguration runConfig, AndroidJUnitLaunchInfo info) { - mRunConfig = runConfig; - mJUnitInfo = info; - } - - /* (non-Javadoc) - * @see org.eclipse.debug.core.model.IProcess#getAttribute(java.lang.String) - */ - @Override - public String getAttribute(String key) { - return null; - } - - /** - * {@inheritDoc} - * @see org.eclipse.debug.core.model.IProcess#getExitValue() - */ - @Override - public int getExitValue() { - return 0; - } - - /* (non-Javadoc) - * @see org.eclipse.debug.core.model.IProcess#getLabel() - */ - @Override - public String getLabel() { - return mJUnitInfo.getLaunch().getLaunchMode(); - } - - /* (non-Javadoc) - * @see org.eclipse.debug.core.model.IProcess#getLaunch() - */ - @Override - public ILaunch getLaunch() { - return mJUnitInfo.getLaunch(); - } - - /* (non-Javadoc) - * @see org.eclipse.debug.core.model.IProcess#getStreamsProxy() - */ - @Override - public IStreamsProxy getStreamsProxy() { - return null; - } - - /* (non-Javadoc) - * @see org.eclipse.debug.core.model.IProcess#setAttribute(java.lang.String, - * java.lang.String) - */ - @Override - public void setAttribute(String key, String value) { - // ignore - } - - /* (non-Javadoc) - * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) - */ - @Override - public Object getAdapter(Class adapter) { - return null; - } - - /* (non-Javadoc) - * @see org.eclipse.debug.core.model.ITerminate#canTerminate() - */ - @Override - public boolean canTerminate() { - return true; - } - - /* (non-Javadoc) - * @see org.eclipse.debug.core.model.ITerminate#isTerminated() - */ - @Override - public boolean isTerminated() { - return mIsTerminated; - } - - /** - * {@inheritDoc} - * @see org.eclipse.debug.core.model.ITerminate#terminate() - */ - @Override - public void terminate() { - if (mTestRunner != null) { - mTestRunner.terminate(); - } - mIsTerminated = true; - } - - /** - * Launches a test runner that will communicate results back to JDT JUnit UI. - * <p/> - * Must be executed on a non-UI thread. - */ - public void run() { - if (Display.getCurrent() != null) { - AdtPlugin.log(IStatus.ERROR, "Adt test runner executed on UI thread"); - AdtPlugin.printErrorToConsole(mJUnitInfo.getProject(), - "Test launch failed due to internal error: Running tests on UI thread"); - terminate(); - return; - } - mTestRunner = new RemoteAdtTestRunner(); - mTestRunner.runTests(mRunConfig.getProgramArguments(), mJUnitInfo); - } - } -} - diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchConfigDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchConfigDelegate.java deleted file mode 100755 index 6e47ce91c..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchConfigDelegate.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch.junit; - -import com.android.SdkConstants; -import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner.TestSize; -import com.android.ide.common.xml.ManifestData; -import com.android.ide.common.xml.ManifestData.Instrumentation; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.launch.AndroidLaunch; -import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchConfiguration; -import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchController; -import com.android.ide.eclipse.adt.internal.launch.IAndroidLaunchAction; -import com.android.ide.eclipse.adt.internal.launch.LaunchConfigDelegate; -import com.android.ide.eclipse.adt.internal.launch.LaunchMessages; -import com.android.ide.eclipse.adt.internal.launch.junit.runtime.AndroidJUnitLaunchInfo; -import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants; -import org.eclipse.jdt.internal.junit.launcher.TestKindRegistry; -import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; -import org.eclipse.swt.widgets.Display; - -/** - * Run configuration that can execute JUnit tests on an Android platform. - * <p/> - * Will deploy apps on target Android platform by reusing functionality from ADT - * LaunchConfigDelegate, and then run JUnits tests by reusing functionality from JDT - * JUnitLaunchConfigDelegate. - */ -@SuppressWarnings("restriction") -public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate { - - /** Launch config attribute that stores instrumentation runner. */ - static final String ATTR_INSTR_NAME = AdtPlugin.PLUGIN_ID + ".instrumentation"; //$NON-NLS-1$ - - /** Launch config attribute that stores the test size annotation to run. */ - static final String ATTR_TEST_SIZE = AdtPlugin.PLUGIN_ID + ".testSize"; //$NON-NLS-1$ - - private static final String EMPTY_STRING = ""; //$NON-NLS-1$ - - @Override - protected void doLaunch(final ILaunchConfiguration configuration, final String mode, - final IProgressMonitor monitor, final IProject project, - final AndroidLaunch androidLaunch, final AndroidLaunchConfiguration config, - final AndroidLaunchController controller, final IFile applicationPackage, - final ManifestData manifestData) { - - String runner = getRunner(project, configuration, manifestData); - if (runner == null) { - AdtPlugin.displayError(LaunchMessages.LaunchDialogTitle, - String.format(LaunchMessages.AndroidJUnitDelegate_NoRunnerMsg_s, - project.getName())); - androidLaunch.stopLaunch(); - return; - } - // get the target app's package - final String targetAppPackage = getTargetPackage(manifestData, runner); - if (targetAppPackage == null) { - AdtPlugin.displayError(LaunchMessages.LaunchDialogTitle, - String.format(LaunchMessages.AndroidJUnitDelegate_NoTargetMsg_3s, - project.getName(), runner, SdkConstants.FN_ANDROID_MANIFEST_XML)); - androidLaunch.stopLaunch(); - return; - } - final String testAppPackage = manifestData.getPackage(); - AndroidJUnitLaunchInfo junitLaunchInfo = new AndroidJUnitLaunchInfo(project, - testAppPackage, runner); - junitLaunchInfo.setTestClass(getTestClass(configuration)); - junitLaunchInfo.setTestPackage(getTestPackage(configuration)); - junitLaunchInfo.setTestMethod(getTestMethod(configuration)); - junitLaunchInfo.setLaunch(androidLaunch); - junitLaunchInfo.setTestSize(getTestSize(configuration)); - final IAndroidLaunchAction junitLaunch = new AndroidJUnitLaunchAction(junitLaunchInfo); - - // launch on a separate thread if currently on the display thread - if (Display.getCurrent() != null) { - Job job = new Job("Junit Launch") { //$NON-NLS-1$ - @Override - protected IStatus run(IProgressMonitor m) { - controller.launch(project, mode, applicationPackage, testAppPackage, - targetAppPackage, manifestData.getDebuggable(), - manifestData.getMinSdkVersionString(), - junitLaunch, config, androidLaunch, monitor); - return Status.OK_STATUS; - } - }; - job.setPriority(Job.INTERACTIVE); - job.schedule(); - } else { - controller.launch(project, mode, applicationPackage, testAppPackage, targetAppPackage, - manifestData.getDebuggable(), manifestData.getMinSdkVersionString(), - 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 ManifestData} for the test project - * @param runner the instrumentation runner class name - * @return the target package or <code>null</code> - */ - private String getTargetPackage(ManifestData 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. - * - * @param configuration the {@link ILaunchConfiguration} to retrieve the test package info from - * @return the test package or <code>null</code>. - */ - private String getTestPackage(ILaunchConfiguration configuration) { - // try to retrieve a package name from the JUnit container attribute - String containerHandle = getStringLaunchAttribute( - JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, configuration); - if (containerHandle != null && containerHandle.length() > 0) { - IJavaElement element = JavaCore.create(containerHandle); - // containerHandle could be a IProject, check if its a java package - if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT) { - return element.getElementName(); - } - } - return null; - } - - /** - * Returns the test class stored in the launch configuration. - * - * @param configuration the {@link ILaunchConfiguration} to retrieve the test class info from - * @return the test class. <code>null</code> if not specified. - */ - private String getTestClass(ILaunchConfiguration configuration) { - return getStringLaunchAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, - configuration); - } - - /** - * Returns the test method stored in the launch configuration. - * - * @param configuration the {@link ILaunchConfiguration} to retrieve the test method info from - * @return the test method. <code>null</code> if not specified. - */ - private String getTestMethod(ILaunchConfiguration configuration) { - return getStringLaunchAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_METHOD_NAME, - configuration); - } - - /** - * Returns the test sizes to run as saved in the launch configuration. - * @return {@link TestSize} if only tests of specific sizes should be run, - * null if all tests should be run - */ - private TestSize getTestSize(ILaunchConfiguration configuration) { - String testSizeAnnotation = getStringLaunchAttribute( - AndroidJUnitLaunchConfigDelegate.ATTR_TEST_SIZE, - configuration); - if (AndroidJUnitLaunchConfigurationTab.SMALL_TEST_ANNOTATION.equals( - testSizeAnnotation)){ - return TestSize.SMALL; - } else if (AndroidJUnitLaunchConfigurationTab.MEDIUM_TEST_ANNOTATION.equals( - testSizeAnnotation)) { - return TestSize.MEDIUM; - } else if (AndroidJUnitLaunchConfigurationTab.LARGE_TEST_ANNOTATION.equals( - testSizeAnnotation)) { - return TestSize.LARGE; - } else { - return null; - } - } - - /** - * Gets a instrumentation runner for the launch. - * <p/> - * If a runner is stored in the given <code>configuration</code>, will return that. - * Otherwise, will try to find the first valid runner for the project. - * If a runner can still not be found, will return <code>null</code>, and will log an error - * to the console. - * - * @param project the {@link IProject} for the app - * @param configuration the {@link ILaunchConfiguration} for the launch - * @param manifestData the {@link ManifestData} for the project - * - * @return <code>null</code> if no instrumentation runner can be found, otherwise return - * the fully qualified runner name. - */ - private String getRunner(IProject project, ILaunchConfiguration configuration, - ManifestData manifestData) { - try { - String runner = getRunnerFromConfig(configuration); - if (runner != null) { - return runner; - } - final InstrumentationRunnerValidator instrFinder = new InstrumentationRunnerValidator( - BaseProjectHelper.getJavaProject(project), manifestData); - runner = instrFinder.getValidInstrumentationTestRunner(); - if (runner != null) { - AdtPlugin.printErrorToConsole(project, String.format( - LaunchMessages.AndroidJUnitDelegate_NoRunnerConfigMsg_s, runner)); - return runner; - } - AdtPlugin.printErrorToConsole(project, String.format( - LaunchMessages.AndroidJUnitDelegate_NoRunnerConsoleMsg_4s, - project.getName(), - SdkConstants.CLASS_INSTRUMENTATION_RUNNER, - AdtConstants.LIBRARY_TEST_RUNNER, - SdkConstants.FN_ANDROID_MANIFEST_XML)); - return null; - } catch (CoreException e) { - AdtPlugin.log(e, "Error when retrieving instrumentation info"); //$NON-NLS-1$ - } - - return null; - } - - private String getRunnerFromConfig(ILaunchConfiguration configuration) { - return getStringLaunchAttribute(ATTR_INSTR_NAME, configuration); - } - - /** - * Helper method to retrieve a string attribute from the launch configuration - * - * @param attributeName name of the launch attribute - * @param configuration the {@link ILaunchConfiguration} to retrieve the attribute from - * @return the attribute's value. <code>null</code> if not found. - */ - private String getStringLaunchAttribute(String attributeName, - ILaunchConfiguration configuration) { - try { - String attrValue = configuration.getAttribute(attributeName, EMPTY_STRING); - if (attrValue.length() < 1) { - return null; - } - return attrValue; - } catch (CoreException e) { - AdtPlugin.log(e, String.format("Error when retrieving launch info %1$s", //$NON-NLS-1$ - attributeName)); - } - return null; - } - - /** - * Helper method to set JUnit-related attributes expected by JDT JUnit runner - * - * @param config the launch configuration to modify - */ - static void setJUnitDefaults(ILaunchConfigurationWorkingCopy config) { - // set the test runner to JUnit3 to placate JDT JUnit runner logic - config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_RUNNER_KIND, - TestKindRegistry.JUNIT3_TEST_KIND_ID); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchConfigurationTab.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchConfigurationTab.java deleted file mode 100644 index 038f0b91f..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchConfigurationTab.java +++ /dev/null @@ -1,1061 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch.junit; - -import com.android.SdkConstants; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.editors.IconFactory; -import com.android.ide.eclipse.adt.internal.launch.LaunchMessages; -import com.android.ide.eclipse.adt.internal.launch.MainLaunchConfigTab; -import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; -import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Path; -import org.eclipse.debug.core.ILaunchConfiguration; -import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; -import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IJavaModel; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IPackageFragment; -import org.eclipse.jdt.core.IPackageFragmentRoot; -import org.eclipse.jdt.core.ISourceReference; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.internal.junit.Messages; -import org.eclipse.jdt.internal.junit.launcher.ITestKind; -import org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants; -import org.eclipse.jdt.internal.junit.launcher.JUnitMigrationDelegate; -import org.eclipse.jdt.internal.junit.launcher.TestKindRegistry; -import org.eclipse.jdt.internal.junit.launcher.TestSelectionDialog; -import org.eclipse.jdt.internal.junit.ui.JUnitMessages; -import org.eclipse.jdt.internal.junit.util.LayoutUtil; -import org.eclipse.jdt.internal.junit.util.TestSearchEngine; -import org.eclipse.jdt.internal.ui.wizards.TypedElementSelectionValidator; -import org.eclipse.jdt.internal.ui.wizards.TypedViewerFilter; -import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; -import org.eclipse.jdt.ui.JavaElementComparator; -import org.eclipse.jdt.ui.JavaElementLabelProvider; -import org.eclipse.jdt.ui.StandardJavaElementContentProvider; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.layout.GridDataFactory; -import org.eclipse.jface.viewers.ILabelProvider; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerFilter; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; -import org.eclipse.ui.dialogs.SelectionDialog; - -import java.lang.reflect.InvocationTargetException; -import java.util.Arrays; -import java.util.List; - -/** - * The launch config UI tab for Android JUnit - * <p/> - * Based on org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationTab - */ -@SuppressWarnings("restriction") -public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurationTab { - - // Project UI widgets - private Label mProjLabel; - private Text mProjText; - private Button mProjButton; - - // Test class UI widgets - private Text mTestText; - private Button mSearchButton; - private String mOriginalTestMethodName; - private Label mTestMethodLabel; - private Text mContainerText; - private IJavaElement mContainerElement; - private final ILabelProvider mJavaElementLabelProvider = new JavaElementLabelProvider(); - - private Button mContainerSearchButton; - private Button mTestContainerRadioButton; - private Button mTestRadioButton; - private Label mTestLabel; - - // Android specific members - private Image mTabIcon = null; - private Combo mInstrumentationCombo; - private Combo mTestSizeCombo; - private static final String EMPTY_STRING = ""; //$NON-NLS-1$ - private static final String TAG = "AndroidJUnitLaunchConfigurationTab"; //$NON-NLS-1$ - private String[] mInstrumentations = null; - private InstrumentationRunnerValidator mInstrValidator = null; - private ProjectChooserHelper mProjectChooserHelper; - - public static final String SMALL_TEST_ANNOTATION = "@SmallTest"; //$NON-NLS-1$ - public static final String MEDIUM_TEST_ANNOTATION = "@MediumTest"; //$NON-NLS-1$ - public static final String LARGE_TEST_ANNOTATION = "@LargeTest"; //$NON-NLS-1$ - private static final List<String> TEST_SIZE_OPTIONS = Arrays.asList( - "All Tests", - SMALL_TEST_ANNOTATION, - MEDIUM_TEST_ANNOTATION, - LARGE_TEST_ANNOTATION - ); - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite) - */ - @Override - public void createControl(Composite parent) { - mProjectChooserHelper = new ProjectChooserHelper(parent.getShell(), null /*filter*/); - - Composite comp = new Composite(parent, SWT.NONE); - setControl(comp); - - GridLayout topLayout = new GridLayout(); - topLayout.numColumns = 3; - comp.setLayout(topLayout); - - createSingleTestSection(comp); - createTestContainerSelectionGroup(comp); - - createSpacer(comp); - - createInstrumentationGroup(comp); - createSizeSelector(comp); - - Dialog.applyDialogFont(comp); - // TODO: add help link here when available - //PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), - // IJUnitHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_JUNIT_MAIN_TAB); - validatePage(); - } - - - private void createSpacer(Composite comp) { - Label label = new Label(comp, SWT.NONE); - GridData gd = new GridData(); - gd.horizontalSpan = 3; - label.setLayoutData(gd); - } - - private void createSingleTestSection(Composite comp) { - mTestRadioButton = new Button(comp, SWT.RADIO); - mTestRadioButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_oneTest); - GridData gd = new GridData(); - gd.horizontalSpan = 3; - mTestRadioButton.setLayoutData(gd); - mTestRadioButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - if (mTestRadioButton.getSelection()) { - testModeChanged(); - } - } - }); - - mProjLabel = new Label(comp, SWT.NONE); - mProjLabel.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_project); - gd = new GridData(); - gd.horizontalIndent = 25; - mProjLabel.setLayoutData(gd); - - mProjText = new Text(comp, SWT.SINGLE | SWT.BORDER); - mProjText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mProjText.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent evt) { - validatePage(); - updateLaunchConfigurationDialog(); - mSearchButton.setEnabled(mTestRadioButton.getSelection() && - mProjText.getText().length() > 0); - } - }); - - mProjButton = new Button(comp, SWT.PUSH); - mProjButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_browse); - mProjButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent evt) { - handleProjectButtonSelected(); - } - }); - setButtonGridData(mProjButton); - - mTestLabel = new Label(comp, SWT.NONE); - gd = new GridData(); - gd.horizontalIndent = 25; - mTestLabel.setLayoutData(gd); - mTestLabel.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_test); - - - mTestText = new Text(comp, SWT.SINGLE | SWT.BORDER); - mTestText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mTestText.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent evt) { - validatePage(); - updateLaunchConfigurationDialog(); - } - }); - - mSearchButton = new Button(comp, SWT.PUSH); - mSearchButton.setEnabled(mProjText.getText().length() > 0); - mSearchButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_search); - mSearchButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent evt) { - handleSearchButtonSelected(); - } - }); - setButtonGridData(mSearchButton); - - new Label(comp, SWT.NONE); - - mTestMethodLabel = new Label(comp, SWT.NONE); - mTestMethodLabel.setText(""); //$NON-NLS-1$ - gd = new GridData(); - gd.horizontalSpan = 2; - mTestMethodLabel.setLayoutData(gd); - } - - private void createTestContainerSelectionGroup(Composite comp) { - mTestContainerRadioButton = new Button(comp, SWT.RADIO); - mTestContainerRadioButton.setText( - LaunchMessages.AndroidJUnitTab_TestContainerText); - GridData gd = new GridData(); - gd.horizontalSpan = 3; - mTestContainerRadioButton.setLayoutData(gd); - mTestContainerRadioButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - if (mTestContainerRadioButton.getSelection()) { - testModeChanged(); - } - } - }); - - mContainerText = new Text(comp, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY); - gd = new GridData(GridData.FILL_HORIZONTAL); - gd.horizontalIndent = 25; - gd.horizontalSpan = 2; - mContainerText.setLayoutData(gd); - mContainerText.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent evt) { - updateLaunchConfigurationDialog(); - } - }); - - mContainerSearchButton = new Button(comp, SWT.PUSH); - mContainerSearchButton.setText(JUnitMessages.JUnitLaunchConfigurationTab_label_search); - mContainerSearchButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent evt) { - handleContainerSearchButtonSelected(); - } - }); - setButtonGridData(mContainerSearchButton); - } - - private void createInstrumentationGroup(Composite comp) { - Label loaderLabel = new Label(comp, SWT.NONE); - loaderLabel.setText(LaunchMessages.AndroidJUnitTab_LoaderLabel); - GridData gd = new GridData(); - gd.horizontalIndent = 0; - loaderLabel.setLayoutData(gd); - - mInstrumentationCombo = new Combo(comp, SWT.DROP_DOWN | SWT.READ_ONLY); - GridDataFactory.defaultsFor(mInstrumentationCombo) - .span(2, 1) - .applyTo(mInstrumentationCombo); - mInstrumentationCombo.clearSelection(); - mInstrumentationCombo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - validatePage(); - updateLaunchConfigurationDialog(); - } - }); - } - - private void createSizeSelector(Composite comp) { - Label l = new Label(comp, SWT.NONE); - l.setText(LaunchMessages.AndroidJUnitTab_SizeLabel); - GridData gd = new GridData(); - gd.horizontalIndent = 0; - l.setLayoutData(gd); - - mTestSizeCombo = new Combo(comp, SWT.DROP_DOWN | SWT.READ_ONLY); - mTestSizeCombo.setItems(TEST_SIZE_OPTIONS.toArray(new String[TEST_SIZE_OPTIONS.size()])); - mTestSizeCombo.select(0); - mTestSizeCombo.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - updateLaunchConfigurationDialog(); - } - }); - } - - private void handleContainerSearchButtonSelected() { - IJavaElement javaElement = chooseContainer(mContainerElement); - if (javaElement != null) { - setContainerElement(javaElement); - } - } - - private void setContainerElement(IJavaElement javaElement) { - mContainerElement = javaElement; - mContainerText.setText(getPresentationName(javaElement)); - validatePage(); - updateLaunchConfigurationDialog(); - } - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration) - */ - @Override - public void initializeFrom(ILaunchConfiguration config) { - String projectName = updateProjectFromConfig(config); - String containerHandle = EMPTY_STRING; - try { - containerHandle = config.getAttribute( - JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, EMPTY_STRING); - } catch (CoreException ce) { - // ignore - } - - if (containerHandle.length() > 0) { - updateTestContainerFromConfig(config); - } else { - updateTestTypeFromConfig(config); - } - - IProject proj = mProjectChooserHelper.getAndroidProject(projectName); - loadInstrumentations(proj); - updateInstrumentationFromConfig(config); - updateTestSizeFromConfig(config); - - validatePage(); - } - - private void updateInstrumentationFromConfig(ILaunchConfiguration config) { - boolean found = false; - try { - String currentInstrumentation = config.getAttribute( - AndroidJUnitLaunchConfigDelegate.ATTR_INSTR_NAME, EMPTY_STRING); - if (mInstrumentations != null) { - // look for the name of the instrumentation in the combo. - for (int i = 0; i < mInstrumentations.length; i++) { - if (currentInstrumentation.equals(mInstrumentations[i])) { - found = true; - mInstrumentationCombo.select(i); - break; - } - } - } - } catch (CoreException ce) { - // ignore - } - if (!found) { - mInstrumentationCombo.clearSelection(); - } - } - - private void updateTestSizeFromConfig(ILaunchConfiguration config) { - try { - String testSize = config.getAttribute( - AndroidJUnitLaunchConfigDelegate.ATTR_TEST_SIZE, EMPTY_STRING); - int index = TEST_SIZE_OPTIONS.indexOf(testSize); - if (index >= 0 && mTestSizeCombo != null) { - mTestSizeCombo.select(index); - } - } catch (CoreException e) { - // ignore - } - } - - private String updateProjectFromConfig(ILaunchConfiguration config) { - String projectName = EMPTY_STRING; - try { - projectName = config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, - EMPTY_STRING); - } catch (CoreException ce) { - // ignore - } - mProjText.setText(projectName); - return projectName; - } - - private void updateTestTypeFromConfig(ILaunchConfiguration config) { - String testTypeName = EMPTY_STRING; - mOriginalTestMethodName = EMPTY_STRING; - try { - testTypeName = config.getAttribute( - IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, ""); //$NON-NLS-1$ - mOriginalTestMethodName = config.getAttribute( - JUnitLaunchConfigurationConstants.ATTR_TEST_METHOD_NAME, ""); //$NON-NLS-1$ - } catch (CoreException ce) { - // ignore - } - mTestRadioButton.setSelection(true); - setEnableSingleTestGroup(true); - setEnableContainerTestGroup(false); - mTestContainerRadioButton.setSelection(false); - mTestText.setText(testTypeName); - mContainerText.setText(EMPTY_STRING); - setTestMethodLabel(mOriginalTestMethodName); - } - - private void setTestMethodLabel(String testMethodName) { - if (!EMPTY_STRING.equals(testMethodName)) { - mTestMethodLabel.setText( - JUnitMessages.JUnitLaunchConfigurationTab_label_method + - mOriginalTestMethodName); - } else { - mTestMethodLabel.setText(EMPTY_STRING); - } - } - - private void updateTestContainerFromConfig(ILaunchConfiguration config) { - String containerHandle = EMPTY_STRING; - IJavaElement containerElement = null; - try { - containerHandle = config.getAttribute( - JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, EMPTY_STRING); - if (containerHandle.length() > 0) { - containerElement = JavaCore.create(containerHandle); - } - } catch (CoreException ce) { - // ignore - } - if (containerElement != null) { - mContainerElement = containerElement; - } - mTestContainerRadioButton.setSelection(true); - setEnableSingleTestGroup(false); - setEnableContainerTestGroup(true); - mTestRadioButton.setSelection(false); - if (mContainerElement != null) { - mContainerText.setText(getPresentationName(mContainerElement)); - } - mTestText.setText(EMPTY_STRING); - } - - /* - * (non-Javadoc) - * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) - */ - @Override - public void performApply(ILaunchConfigurationWorkingCopy config) { - if (mTestContainerRadioButton.getSelection() && mContainerElement != null) { - config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, - mContainerElement.getJavaProject().getElementName()); - config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, - mContainerElement.getHandleIdentifier()); - config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, - EMPTY_STRING); - //workaround for Eclipse bug 65399 - config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_METHOD_NAME, - EMPTY_STRING); - } else { - config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, - mProjText.getText()); - config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, - mTestText.getText()); - config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, - EMPTY_STRING); - config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_METHOD_NAME, - mOriginalTestMethodName); - } - try { - mapResources(config); - } catch (CoreException e) { - // TODO: does the real error need to be extracted out of CoreException - AdtPlugin.log(e, "Error occurred saving configuration"); //$NON-NLS-1$ - } - AndroidJUnitLaunchConfigDelegate.setJUnitDefaults(config); - - config.setAttribute(AndroidJUnitLaunchConfigDelegate.ATTR_INSTR_NAME, - getSelectedInstrumentation()); - config.setAttribute(AndroidJUnitLaunchConfigDelegate.ATTR_TEST_SIZE, - getSelectedTestSize()); - } - - private void mapResources(ILaunchConfigurationWorkingCopy config) throws CoreException { - JUnitMigrationDelegate.mapResources(config); - } - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#dispose() - */ - @Override - public void dispose() { - super.dispose(); - mTabIcon = null; - mJavaElementLabelProvider.dispose(); - } - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getImage() - */ - @Override - public Image getImage() { - // reuse icon from the Android App Launch config tab - if (mTabIcon == null) { - mTabIcon = IconFactory.getInstance().getIcon(MainLaunchConfigTab.LAUNCH_TAB_IMAGE); - } - return mTabIcon; - } - - /** - * Show a dialog that lists all main types - */ - private void handleSearchButtonSelected() { - Shell shell = getShell(); - - IJavaProject javaProject = getJavaProject(); - - IType[] types = new IType[0]; - boolean[] radioSetting = new boolean[2]; - try { - // fix for Eclipse bug 66922 Wrong radio behaviour when switching - // remember the selected radio button - radioSetting[0] = mTestRadioButton.getSelection(); - radioSetting[1] = mTestContainerRadioButton.getSelection(); - - types = TestSearchEngine.findTests(getLaunchConfigurationDialog(), javaProject, - getTestKind()); - } catch (InterruptedException e) { - setErrorMessage(e.getMessage()); - return; - } catch (InvocationTargetException e) { - AdtPlugin.log(e.getTargetException(), "Error finding test types"); //$NON-NLS-1$ - return; - } finally { - mTestRadioButton.setSelection(radioSetting[0]); - mTestContainerRadioButton.setSelection(radioSetting[1]); - } - - SelectionDialog dialog = new TestSelectionDialog(shell, types); - dialog.setTitle(JUnitMessages.JUnitLaunchConfigurationTab_testdialog_title); - dialog.setMessage(JUnitMessages.JUnitLaunchConfigurationTab_testdialog_message); - if (dialog.open() == Window.CANCEL) { - return; - } - - Object[] results = dialog.getResult(); - if ((results == null) || (results.length < 1)) { - return; - } - IType type = (IType) results[0]; - - if (type != null) { - mTestText.setText(type.getFullyQualifiedName('.')); - javaProject = type.getJavaProject(); - mProjText.setText(javaProject.getElementName()); - } - } - - private ITestKind getTestKind() { - // harddcode this to JUnit 3 - return TestKindRegistry.getDefault().getKind(TestKindRegistry.JUNIT3_TEST_KIND_ID); - } - - /** - * Show a dialog that lets the user select a Android project. This in turn provides - * context for the main type, allowing the user to key a main type name, or - * constraining the search for main types to the specified project. - */ - private void handleProjectButtonSelected() { - IJavaProject project = mProjectChooserHelper.chooseJavaProject(getProjectName(), - "Please select a project to launch"); - if (project == null) { - return; - } - - String projectName = project.getElementName(); - mProjText.setText(projectName); - loadInstrumentations(project.getProject()); - } - - /** - * Return the IJavaProject corresponding to the project name in the project name - * text field, or null if the text does not match a Android project name. - */ - private IJavaProject getJavaProject() { - String projectName = getProjectName(); - return getJavaModel().getJavaProject(projectName); - } - - /** - * Returns the name of the currently specified project. Null if no project is selected. - */ - private String getProjectName() { - String projectName = mProjText.getText().trim(); - if (projectName.length() < 1) { - return null; - } - return projectName; - } - - /** - * Convenience method to get the workspace root. - */ - private IWorkspaceRoot getWorkspaceRoot() { - return ResourcesPlugin.getWorkspace().getRoot(); - } - - /** - * Convenience method to get access to the java model. - */ - private IJavaModel getJavaModel() { - return JavaCore.create(getWorkspaceRoot()); - } - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration) - */ - @Override - public boolean isValid(ILaunchConfiguration config) { - validatePage(); - return getErrorMessage() == null; - } - - private void testModeChanged() { - boolean isSingleTestMode = mTestRadioButton.getSelection(); - setEnableSingleTestGroup(isSingleTestMode); - setEnableContainerTestGroup(!isSingleTestMode); - if (!isSingleTestMode && mContainerText.getText().length() == 0) { - String projText = mProjText.getText(); - if (Path.EMPTY.isValidSegment(projText)) { - IJavaProject javaProject = getJavaModel().getJavaProject(projText); - if (javaProject != null && javaProject.exists()) { - setContainerElement(javaProject); - } - } - } - validatePage(); - updateLaunchConfigurationDialog(); - } - - private void validatePage() { - setErrorMessage(null); - setMessage(null); - - if (mTestContainerRadioButton.getSelection()) { - if (mContainerElement == null) { - setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_noContainer); - return; - } - validateJavaProject(mContainerElement.getJavaProject()); - return; - } - - String projectName = mProjText.getText().trim(); - if (projectName.length() == 0) { - setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_projectnotdefined); - return; - } - - IStatus status = ResourcesPlugin.getWorkspace().validatePath(IPath.SEPARATOR + projectName, - IResource.PROJECT); - if (!status.isOK() || !Path.ROOT.isValidSegment(projectName)) { - setErrorMessage(Messages.format( - JUnitMessages.JUnitLaunchConfigurationTab_error_invalidProjectName, - projectName)); - return; - } - - IProject project = getWorkspaceRoot().getProject(projectName); - if (!project.exists()) { - setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_projectnotexists); - return; - } - IJavaProject javaProject = JavaCore.create(project); - validateJavaProject(javaProject); - - try { - if (!project.hasNature(AdtConstants.NATURE_DEFAULT)) { - setErrorMessage( - LaunchMessages.NonAndroidProjectError); - return; - } - String className = mTestText.getText().trim(); - if (className.length() == 0) { - setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_testnotdefined); - return; - } - if (javaProject.findType(className) == null) { - setErrorMessage(Messages.format( - JUnitMessages.JUnitLaunchConfigurationTab_error_test_class_not_found, - new String[] { className, projectName })); - return; - } - } catch (CoreException e) { - AdtPlugin.log(e, "validatePage failed"); //$NON-NLS-1$ - } - - validateInstrumentation(); - } - - private void validateJavaProject(IJavaProject javaProject) { - if (!TestSearchEngine.hasTestCaseType(javaProject)) { - setErrorMessage(JUnitMessages.JUnitLaunchConfigurationTab_error_testcasenotonpath); - return; - } - } - - private void validateInstrumentation() { - String instrumentation = getSelectedInstrumentation(); - if (instrumentation == null) { - setErrorMessage(LaunchMessages.AndroidJUnitTab_NoRunnerError); - return; - } - String result = mInstrValidator.validateInstrumentationRunner(instrumentation); - if (result != InstrumentationRunnerValidator.INSTRUMENTATION_OK) { - setErrorMessage(result); - return; - } - } - - private String getSelectedInstrumentation() { - int selectionIndex = mInstrumentationCombo.getSelectionIndex(); - if (mInstrumentations != null && selectionIndex >= 0 && - selectionIndex < mInstrumentations.length) { - return mInstrumentations[selectionIndex]; - } - return null; - } - - private String getSelectedTestSize() { - if (mTestSizeCombo != null) { - int index = mTestSizeCombo.getSelectionIndex(); - return TEST_SIZE_OPTIONS.get(index); - } else { - return null; - } - } - - private void setEnableContainerTestGroup(boolean enabled) { - mContainerSearchButton.setEnabled(enabled); - mContainerText.setEnabled(enabled); - } - - private void setEnableSingleTestGroup(boolean enabled) { - mProjLabel.setEnabled(enabled); - mProjText.setEnabled(enabled); - mProjButton.setEnabled(enabled); - mTestLabel.setEnabled(enabled); - mTestText.setEnabled(enabled); - mSearchButton.setEnabled(enabled && mProjText.getText().length() > 0); - mTestMethodLabel.setEnabled(enabled); - } - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) - */ - @Override - public void setDefaults(ILaunchConfigurationWorkingCopy config) { - IJavaElement javaElement = getContext(); - if (javaElement != null) { - initializeJavaProject(javaElement, config); - } else { - // We set empty attributes for project & main type so that when one config is - // compared to another, the existence of empty attributes doesn't cause an - // incorrect result (the performApply() method can result in empty values - // for these attributes being set on a config if there is nothing in the - // corresponding text boxes) - config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, EMPTY_STRING); - config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, - EMPTY_STRING); - } - initializeTestAttributes(javaElement, config); - } - - private void initializeTestAttributes(IJavaElement javaElement, - ILaunchConfigurationWorkingCopy config) { - if (javaElement != null && javaElement.getElementType() < IJavaElement.COMPILATION_UNIT) { - initializeTestContainer(javaElement, config); - } else { - initializeTestType(javaElement, config); - } - } - - private void initializeTestContainer(IJavaElement javaElement, - ILaunchConfigurationWorkingCopy config) { - config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_CONTAINER, - javaElement.getHandleIdentifier()); - initializeName(config, javaElement.getElementName()); - } - - private void initializeName(ILaunchConfigurationWorkingCopy config, String name) { - if (name == null) { - name = EMPTY_STRING; - } - if (name.length() > 0) { - int index = name.lastIndexOf('.'); - if (index > 0) { - name = name.substring(index + 1); - } - name = getLaunchConfigurationDialog().generateName(name); - config.rename(name); - } - } - - /** - * Sets the main type & name attributes on the working copy based on the IJavaElement - */ - private void initializeTestType(IJavaElement javaElement, - ILaunchConfigurationWorkingCopy config) { - String name = EMPTY_STRING; - String testKindId = null; - try { - // only do a search for compilation units or class files or source references - if (javaElement instanceof ISourceReference) { - ITestKind testKind = TestKindRegistry.getContainerTestKind(javaElement); - testKindId = testKind.getId(); - - IType[] types = TestSearchEngine.findTests(getLaunchConfigurationDialog(), - javaElement, testKind); - if ((types == null) || (types.length < 1)) { - return; - } - // Simply grab the first main type found in the searched element - name = types[0].getFullyQualifiedName('.'); - - } - } catch (InterruptedException ie) { - // ignore - } catch (InvocationTargetException ite) { - // ignore - } - config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, name); - if (testKindId != null) { - config.setAttribute(JUnitLaunchConfigurationConstants.ATTR_TEST_RUNNER_KIND, - testKindId); - } - initializeName(config, name); - } - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName() - */ - @Override - public String getName() { - return JUnitMessages.JUnitLaunchConfigurationTab_tab_label; - } - - private IJavaElement chooseContainer(IJavaElement initElement) { - @SuppressWarnings("rawtypes") - Class[] acceptedClasses = new Class[] { IJavaProject.class, - IPackageFragment.class }; - TypedElementSelectionValidator validator = new TypedElementSelectionValidator( - acceptedClasses, false) { - @Override - public boolean isSelectedValid(Object element) { - return true; - } - }; - - acceptedClasses = new Class[] { IJavaModel.class, IPackageFragmentRoot.class, - IJavaProject.class, IPackageFragment.class }; - ViewerFilter filter = new TypedViewerFilter(acceptedClasses) { - @Override - public boolean select(Viewer viewer, Object parent, Object element) { - if (element instanceof IPackageFragmentRoot && - ((IPackageFragmentRoot) element).isArchive()) { - return false; - } - try { - if (element instanceof IPackageFragment && - !((IPackageFragment) element).hasChildren()) { - return false; - } - } catch (JavaModelException e) { - return false; - } - return super.select(viewer, parent, element); - } - }; - - AndroidJavaElementContentProvider provider = new AndroidJavaElementContentProvider(); - ILabelProvider labelProvider = new JavaElementLabelProvider( - JavaElementLabelProvider.SHOW_DEFAULT); - ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), - labelProvider, provider); - dialog.setValidator(validator); - dialog.setComparator(new JavaElementComparator()); - dialog.setTitle(JUnitMessages.JUnitLaunchConfigurationTab_folderdialog_title); - dialog.setMessage(JUnitMessages.JUnitLaunchConfigurationTab_folderdialog_message); - dialog.addFilter(filter); - dialog.setInput(JavaCore.create(getWorkspaceRoot())); - dialog.setInitialSelection(initElement); - dialog.setAllowMultiple(false); - - if (dialog.open() == Window.OK) { - Object element = dialog.getFirstResult(); - return (IJavaElement) element; - } - return null; - } - - private String getPresentationName(IJavaElement element) { - return mJavaElementLabelProvider.getText(element); - } - - /** - * Returns the current Java element context from which to initialize - * default settings, or <code>null</code> if none. - * - * @return Java element context. - */ - private IJavaElement getContext() { - IWorkbenchWindow activeWorkbenchWindow = - PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - if (activeWorkbenchWindow == null) { - return null; - } - IWorkbenchPage page = activeWorkbenchWindow.getActivePage(); - if (page != null) { - ISelection selection = page.getSelection(); - if (selection instanceof IStructuredSelection) { - IStructuredSelection ss = (IStructuredSelection) selection; - if (!ss.isEmpty()) { - Object obj = ss.getFirstElement(); - if (obj instanceof IJavaElement) { - return (IJavaElement) obj; - } - if (obj instanceof IResource) { - IJavaElement je = JavaCore.create((IResource) obj); - if (je == null) { - IProject pro = ((IResource) obj).getProject(); - je = JavaCore.create(pro); - } - if (je != null) { - return je; - } - } - } - } - IEditorPart part = page.getActiveEditor(); - if (part != null) { - IEditorInput input = part.getEditorInput(); - return (IJavaElement) input.getAdapter(IJavaElement.class); - } - } - return null; - } - - private void initializeJavaProject(IJavaElement javaElement, - ILaunchConfigurationWorkingCopy config) { - IJavaProject javaProject = javaElement.getJavaProject(); - String name = null; - if (javaProject != null && javaProject.exists()) { - name = javaProject.getElementName(); - } - config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, name); - } - - private void setButtonGridData(Button button) { - GridData gridData = new GridData(); - button.setLayoutData(gridData); - LayoutUtil.setButtonDimensionHint(button); - } - - /* (non-Javadoc) - * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getId() - */ - @Override - public String getId() { - return "com.android.ide.eclipse.adt.launch.AndroidJUnitLaunchConfigurationTab"; //$NON-NLS-1$ - } - - /** - * Loads the UI with the instrumentations of the specified project, and stores the - * instrumentations in <code>mInstrumentations</code>. - * - * @param project the {@link IProject} to load the instrumentations from. - */ - private void loadInstrumentations(IProject project) { - try { - mInstrValidator = new InstrumentationRunnerValidator(project); - mInstrumentations = mInstrValidator.getInstrumentationNames(); - if (mInstrumentations.length > 0) { - mInstrumentationCombo.removeAll(); - for (String instrumentation : mInstrumentations) { - mInstrumentationCombo.add(instrumentation); - } - // the selection will be set when we update the ui from the current - // config object. - return; - } - } catch (CoreException e) { - AdtPlugin.logAndPrintError(e, project.getName(), - LaunchMessages.AndroidJUnitTab_LoadInstrError_s, - SdkConstants.FN_ANDROID_MANIFEST_XML); - } - // if we reach this point, either project is null, or we got an exception during - // the parsing. In either case, we empty the instrumentation list. - mInstrValidator = null; - mInstrumentations = null; - mInstrumentationCombo.removeAll(); - } - - /** - * Overrides the {@link StandardJavaElementContentProvider} to only display Android projects - */ - private static class AndroidJavaElementContentProvider - extends StandardJavaElementContentProvider { - - /** - * Override parent to return only Android projects if at the root. Otherwise, use parent - * functionality. - */ - @Override - public Object[] getChildren(Object element) { - if (element instanceof IJavaModel) { - return BaseProjectHelper.getAndroidProjects((IJavaModel) element, null /*filter*/); - } - return super.getChildren(element); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchShortcut.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchShortcut.java deleted file mode 100755 index b94ced891..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitLaunchShortcut.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch.junit; - -import org.eclipse.core.runtime.CoreException; -import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.junit.launcher.JUnitLaunchShortcut; - -/** - * Launch shortcut to launch debug/run Android JUnit configuration directly. - */ -public class AndroidJUnitLaunchShortcut extends JUnitLaunchShortcut { - - @Override - protected String getLaunchConfigurationTypeId() { - return "com.android.ide.eclipse.adt.junit.launchConfigurationType"; //$NON-NLS-1$ - } - - /** - * Creates a default Android JUnit launch configuration. Sets the instrumentation runner to the - * first instrumentation found in the AndroidManifest. - */ - @Override - protected ILaunchConfigurationWorkingCopy createLaunchConfiguration(IJavaElement element) - throws CoreException { - ILaunchConfigurationWorkingCopy config = super.createLaunchConfiguration(element); - // just get first valid instrumentation runner - String instrumentation = new InstrumentationRunnerValidator(element.getJavaProject()). - getValidInstrumentationTestRunner(); - if (instrumentation != null) { - config.setAttribute(AndroidJUnitLaunchConfigDelegate.ATTR_INSTR_NAME, - instrumentation); - } - // if a valid runner is not found, rely on launch delegate to log error. - // This method is called without explicit user action to launch Android JUnit, so avoid - // logging an error here. - - AndroidJUnitLaunchConfigDelegate.setJUnitDefaults(config); - return config; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitPropertyTester.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitPropertyTester.java deleted file mode 100644 index 5172e09a7..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitPropertyTester.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch.junit; - -import org.eclipse.core.expressions.PropertyTester; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.jdt.core.IClassFile; -import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.IJavaElement; -import org.eclipse.jdt.core.IMember; -import org.eclipse.jdt.core.IPackageFragment; -import org.eclipse.jdt.core.IType; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jdt.internal.junit.util.TestSearchEngine; - -/** - * A {@link PropertyTester} that checks if selected elements can be run as Android - * JUnit tests. - * <p/> - * Based on org.eclipse.jdt.internal.junit.JUnitPropertyTester. The only substantial difference in - * this implementation is source folders cannot be run as Android JUnit. - */ -@SuppressWarnings("restriction") -public class AndroidJUnitPropertyTester extends PropertyTester { - private static final String PROPERTY_IS_TEST = "isTest"; //$NON-NLS-1$ - - private static final String PROPERTY_CAN_LAUNCH_AS_JUNIT_TEST = "canLaunchAsJUnit"; //$NON-NLS-1$ - - /* (non-Javadoc) - * @see org.eclipse.jdt.internal.corext.refactoring.participants.properties.IPropertyEvaluator#test(java.lang.Object, java.lang.String, java.lang.String) - */ - @Override - public boolean test(Object receiver, String property, Object[] args, Object expectedValue) { - if (!(receiver instanceof IAdaptable)) { - final String elementName = (receiver == null ? "null" : //$NON-NLS-1$ - receiver.getClass().getName()); - throw new IllegalArgumentException( - String.format("Element must be of type IAdaptable, is %s", //$NON-NLS-1$ - elementName)); - } - - IJavaElement element; - if (receiver instanceof IJavaElement) { - element = (IJavaElement) receiver; - } else if (receiver instanceof IResource) { - element = JavaCore.create((IResource) receiver); - if (element == null) { - return false; - } - } else { // is IAdaptable - element= (IJavaElement) ((IAdaptable) receiver).getAdapter(IJavaElement.class); - if (element == null) { - IResource resource = (IResource) ((IAdaptable) receiver).getAdapter( - IResource.class); - element = JavaCore.create(resource); - if (element == null) { - return false; - } - } - } - if (PROPERTY_IS_TEST.equals(property)) { - return isJUnitTest(element); - } else if (PROPERTY_CAN_LAUNCH_AS_JUNIT_TEST.equals(property)) { - return canLaunchAsJUnitTest(element); - } - throw new IllegalArgumentException( - String.format("Unknown test property '%s'", property)); //$NON-NLS-1$ - } - - private boolean canLaunchAsJUnitTest(IJavaElement element) { - try { - switch (element.getElementType()) { - case IJavaElement.JAVA_PROJECT: - return true; // can run, let JDT detect if there are tests - case IJavaElement.PACKAGE_FRAGMENT_ROOT: - return false; // not supported by Android test runner - case IJavaElement.PACKAGE_FRAGMENT: - return ((IPackageFragment) element).hasChildren(); - case IJavaElement.COMPILATION_UNIT: - case IJavaElement.CLASS_FILE: - case IJavaElement.TYPE: - case IJavaElement.METHOD: - return isJUnitTest(element); - default: - return false; - } - } catch (JavaModelException e) { - return false; - } - } - - /** - * Return whether the target resource is a JUnit test. - */ - private boolean isJUnitTest(IJavaElement element) { - try { - IType testType = null; - if (element instanceof ICompilationUnit) { - testType = (((ICompilationUnit) element)).findPrimaryType(); - } else if (element instanceof IClassFile) { - testType = (((IClassFile) element)).getType(); - } else if (element instanceof IType) { - testType = (IType) element; - } else if (element instanceof IMember) { - testType = ((IMember) element).getDeclaringType(); - } - if (testType != null && testType.exists()) { - return TestSearchEngine.isTestOrTestSuite(testType); - } - } catch (CoreException e) { - // ignore, return false - } - return false; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitTabGroup.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitTabGroup.java deleted file mode 100644 index deb30de01..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/AndroidJUnitTabGroup.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch.junit; - -import com.android.ide.eclipse.adt.internal.launch.EmulatorConfigTab; - -import org.eclipse.debug.core.ILaunchManager; -import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup; -import org.eclipse.debug.ui.CommonTab; -import org.eclipse.debug.ui.ILaunchConfigurationDialog; -import org.eclipse.debug.ui.ILaunchConfigurationTab; - -/** - * Tab group object for Android JUnit launch configuration type. - */ -public class AndroidJUnitTabGroup extends AbstractLaunchConfigurationTabGroup { - - /** - * Creates the UI tabs for the Android JUnit configuration - */ - @Override - public void createTabs(ILaunchConfigurationDialog dialog, String mode) { - ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] { - new AndroidJUnitLaunchConfigurationTab(), - new EmulatorConfigTab(ILaunchManager.RUN_MODE.equals(mode)), - new CommonTab() - }; - setTabs(tabs); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/InstrumentationRunnerValidator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/InstrumentationRunnerValidator.java deleted file mode 100644 index 820fed7d3..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/InstrumentationRunnerValidator.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch.junit; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.common.xml.ManifestData; -import com.android.ide.common.xml.ManifestData.Instrumentation; -import com.android.ide.common.xml.ManifestData.UsesLibrary; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.internal.launch.LaunchMessages; -import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper; -import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.jdt.core.IJavaProject; - -/** - * Provides validation for Android instrumentation test runner - */ -class InstrumentationRunnerValidator { - private final IJavaProject mJavaProject; - private String[] mInstrumentationNames = null; - private boolean mHasRunnerLibrary = false; - - static final String INSTRUMENTATION_OK = null; - - /** - * Initializes the InstrumentationRunnerValidator. - * - * @param javaProject the {@link IJavaProject} for the Android project to validate - */ - InstrumentationRunnerValidator(IJavaProject javaProject) { - mJavaProject = javaProject; - ManifestData manifestData = AndroidManifestHelper.parseForData(javaProject.getProject()); - init(manifestData); - } - - /** - * Initializes the InstrumentationRunnerValidator. - * - * @param project the {@link IProject} for the Android project to validate - * @throws CoreException if a fatal error occurred in initialization - */ - InstrumentationRunnerValidator(IProject project) throws CoreException { - this(BaseProjectHelper.getJavaProject(project)); - } - - /** - * Initializes the InstrumentationRunnerValidator with an existing {@link AndroidManifestHelper} - * - * @param javaProject the {@link IJavaProject} for the Android project to validate - * @param manifestData the {@link ManifestData} for the Android project - */ - InstrumentationRunnerValidator(IJavaProject javaProject, ManifestData manifestData) { - mJavaProject = javaProject; - init(manifestData); - } - - private void init(ManifestData manifestData) { - if (manifestData == null) { - mInstrumentationNames = new String[0]; - mHasRunnerLibrary = false; - return; - } - - Instrumentation[] instrumentations = manifestData.getInstrumentations(); - mInstrumentationNames = new String[instrumentations.length]; - for (int i = 0; i < instrumentations.length; i++) { - mInstrumentationNames[i] = instrumentations[i].getName(); - } - mHasRunnerLibrary = hasTestRunnerLibrary(manifestData); - } - - /** - * Helper method to determine if given manifest has a <code>SdkConstants.LIBRARY_TEST_RUNNER - * </code> library reference - * - * @param manifestParser the {@link ManifestData} to search - * @return true if test runner library found, false otherwise - */ - private boolean hasTestRunnerLibrary(ManifestData manifestData) { - for (UsesLibrary lib : manifestData.getUsesLibraries()) { - if (AdtConstants.LIBRARY_TEST_RUNNER.equals(lib.getName())) { - return true; - } - } - return false; - } - - /** - * Return the set of instrumentation names for the Android project. - * - * @return array of instrumentation class names, possibly empty - */ - @NonNull - String[] getInstrumentationNames() { - return mInstrumentationNames; - } - - /** - * Helper method to get the first instrumentation that can be used as a test runner. - * - * @return fully qualified instrumentation class name. <code>null</code> if no valid - * instrumentation can be found. - */ - @Nullable - String getValidInstrumentationTestRunner() { - for (String instrumentation : getInstrumentationNames()) { - if (validateInstrumentationRunner(instrumentation) == INSTRUMENTATION_OK) { - return instrumentation; - } - } - return null; - } - - /** - * 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 #getInstrumentationNames()} - * @return <code>INSTRUMENTATION_OK</code> if valid, otherwise returns error message - */ - String validateInstrumentationRunner(String instrumentation) { - if (!mHasRunnerLibrary) { - return String.format(LaunchMessages.InstrValidator_NoTestLibMsg_s, - AdtConstants.LIBRARY_TEST_RUNNER); - } - // check if this instrumentation is the standard test runner - if (!instrumentation.equals(SdkConstants.CLASS_INSTRUMENTATION_RUNNER)) { - // Ideally, we'd check if the class extends instrumentation test runner. - // However, the Google Instrumentation Test Runner extends Google Instrumentation, and not a test runner, - // so we just check that the super class is Instrumentation. - String result = BaseProjectHelper.testClassForManifest(mJavaProject, - instrumentation, SdkConstants.CLASS_INSTRUMENTATION, true); - if (result != BaseProjectHelper.TEST_CLASS_OK) { - return String.format( - LaunchMessages.InstrValidator_WrongRunnerTypeMsg_s, - SdkConstants.CLASS_INSTRUMENTATION); - } - } - return INSTRUMENTATION_OK; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/AndroidJUnitLaunchInfo.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/AndroidJUnitLaunchInfo.java deleted file mode 100644 index 08702f4e2..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/AndroidJUnitLaunchInfo.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch.junit.runtime; - -import com.android.ddmlib.IDevice; -import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner.TestSize; - -import org.eclipse.core.resources.IProject; -import org.eclipse.debug.core.ILaunch; - -import java.util.Collection; -import java.util.Collections; - -/** - * Contains info about Android JUnit launch - */ -public class AndroidJUnitLaunchInfo { - private final IProject mProject; - private final String mAppPackage; - private final String mRunner; - - private boolean mDebugMode = false; - private Collection<IDevice> mDevices = Collections.EMPTY_LIST; - private String mTestPackage = null; - private String mTestClass = null; - private String mTestMethod = null; - private ILaunch mLaunch = null; - private TestSize mTestSize = null; - - public AndroidJUnitLaunchInfo(IProject project, String appPackage, String runner) { - mProject = project; - mAppPackage = appPackage; - mRunner = runner; - } - - public IProject getProject() { - return mProject; - } - - public String getAppPackage() { - return mAppPackage; - } - - public String getRunner() { - return mRunner; - } - - public boolean isDebugMode() { - return mDebugMode; - } - - public void setDebugMode(boolean debugMode) { - mDebugMode = debugMode; - } - - public TestSize getTestSize() { - return mTestSize; - } - - public void setTestSize(TestSize size) { - mTestSize = size; - } - - public Collection<IDevice> getDevices() { - return mDevices; - } - - public void setDevices(Collection<IDevice> devices) { - mDevices = devices; - } - - /** - * Specify to run all tests within given package. - * - * @param testPackage fully qualified java package - */ - public void setTestPackage(String testPackage) { - mTestPackage = testPackage; - } - - /** - * Return the package of tests to run. - * - * @return fully qualified java package. <code>null</code> if not specified. - */ - public String getTestPackage() { - return mTestPackage; - } - - /** - * Sets the test class to run. - * - * @param testClass fully qualfied test class to run - * Expected format: x.y.x.testclass - */ - public void setTestClass(String testClass) { - mTestClass = testClass; - } - - /** - * Returns the test class to run. - * - * @return fully qualfied test class to run. - * <code>null</code> if not specified. - */ - public String getTestClass() { - return mTestClass; - } - - /** - * Sets the test method to run. testClass must also be set. - * - * @param testMethod test method to run - */ - public void setTestMethod(String testMethod) { - mTestMethod = testMethod; - } - - /** - * Returns the test method to run. - * - * @return test method to run. <code>null</code> if not specified. - */ - public String getTestMethod() { - return mTestMethod; - } - - public ILaunch getLaunch() { - return mLaunch; - } - - public void setLaunch(ILaunch launch) { - mLaunch = launch; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/AndroidTestReference.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/AndroidTestReference.java deleted file mode 100644 index ec3104d91..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/AndroidTestReference.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch.junit.runtime; - -import org.eclipse.jdt.internal.junit.runner.ITestIdentifier; -import org.eclipse.jdt.internal.junit.runner.ITestReference; -import org.eclipse.jdt.internal.junit.runner.TestExecution; - -/** - * Base implementation of the Eclipse {@link ITestReference} and {@link ITestIdentifier} interfaces - * for Android tests. - * <p/> - * Provides generic equality/hashcode services - */ -@SuppressWarnings("restriction") -abstract class AndroidTestReference implements ITestReference, ITestIdentifier { - - /** - * Gets the {@link ITestIdentifier} for this test reference. - */ - @Override - public ITestIdentifier getIdentifier() { - // this class serves as its own test identifier - return this; - } - - /** - * Not supported. - */ - @Override - public void run(TestExecution execution) { - throw new UnsupportedOperationException(); - } - - /** - * Compares {@link ITestIdentifier} using names - */ - @Override - public boolean equals(Object obj) { - if (obj instanceof ITestIdentifier) { - ITestIdentifier testid = (ITestIdentifier) obj; - return getName().equals(testid.getName()); - } - return false; - } - - @Override - public int hashCode() { - return getName().hashCode(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/RemoteAdtTestRunner.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/RemoteAdtTestRunner.java deleted file mode 100755 index a48acd324..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/RemoteAdtTestRunner.java +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch.junit.runtime; - -import com.android.ddmlib.AdbCommandRejectedException; -import com.android.ddmlib.IDevice; -import com.android.ddmlib.ShellCommandUnresponsiveException; -import com.android.ddmlib.TimeoutException; -import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner.TestSize; -import com.android.ddmlib.testrunner.ITestRunListener; -import com.android.ddmlib.testrunner.RemoteAndroidTestRunner; -import com.android.ddmlib.testrunner.TestIdentifier; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.launch.LaunchMessages; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.jdt.internal.junit.runner.IListensToTestExecutions; -import org.eclipse.jdt.internal.junit.runner.ITestReference; -import org.eclipse.jdt.internal.junit.runner.MessageIds; -import org.eclipse.jdt.internal.junit.runner.RemoteTestRunner; -import org.eclipse.jdt.internal.junit.runner.TestExecution; -import org.eclipse.jdt.internal.junit.runner.TestReferenceFailure; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * Supports Eclipse JUnit execution of Android tests. - * <p/> - * Communicates back to a Eclipse JDT JUnit client via a socket connection. - * - * @see org.eclipse.jdt.internal.junit.runner.RemoteTestRunner for more details on the protocol - */ -@SuppressWarnings("restriction") -public class RemoteAdtTestRunner extends RemoteTestRunner { - - private static final String DELAY_MSEC_KEY = "delay_msec"; - /** the delay between each test execution when in collecting test info */ - private static final String COLLECT_TEST_DELAY_MS = "15"; - - private AndroidJUnitLaunchInfo mLaunchInfo; - private TestExecution mExecution; - - /** - * Initialize the JDT JUnit test runner parameters from the {@code args}. - * - * @param args name-value pair of arguments to pass to parent JUnit runner. - * @param launchInfo the Android specific test launch info - */ - protected void init(String[] args, AndroidJUnitLaunchInfo launchInfo) { - defaultInit(args); - mLaunchInfo = launchInfo; - } - - /** - * Runs a set of tests, and reports back results using parent class. - * <p/> - * JDT Unit expects to be sent data in the following sequence: - * <ol> - * <li>The total number of tests to be executed.</li> - * <li>The test 'tree' data about the tests to be executed, which is composed of the set of - * test class names, the number of tests in each class, and the names of each test in the - * class.</li> - * <li>The test execution result for each test method. Expects individual notifications of - * the test execution start, any failures, and the end of the test execution.</li> - * <li>The end of the test run, with its elapsed time.</li> - * </ol> - * <p/> - * In order to satisfy this, this method performs two actual Android instrumentation runs. - * The first is a 'log only' run that will collect the test tree data, without actually - * executing the tests, and send it back to JDT JUnit. The second is the actual test execution, - * whose results will be communicated back in real-time to JDT JUnit. - * - * The tests are run concurrently on all devices. The overall structure is as follows: - * <ol> - * <li> First, a separate job per device is run to collect test tree data. A per device - * {@link TestCollector} records information regarding the tests run on the device. - * </li> - * <li> Once all the devices have finished collecting the test tree data, the tree info is - * collected from all of them and passed to the Junit UI </li> - * <li> A job per device is again launched to do the actual test run. A per device - * {@link TestRunListener} notifies the shared {@link TestResultsNotifier} of test - * status. </li> - * <li> As tests complete, the test run listener updates the Junit UI </li> - * </ol> - * - * @param testClassNames ignored - the AndroidJUnitLaunchInfo will be used to determine which - * tests to run. - * @param testName ignored - * @param execution used to report test progress - */ - @Override - public void runTests(String[] testClassNames, String testName, TestExecution execution) { - // hold onto this execution reference so it can be used to report test progress - mExecution = execution; - - List<IDevice> devices = new ArrayList<IDevice>(mLaunchInfo.getDevices()); - List<RemoteAndroidTestRunner> runners = - new ArrayList<RemoteAndroidTestRunner>(devices.size()); - - for (IDevice device : devices) { - RemoteAndroidTestRunner runner = new RemoteAndroidTestRunner( - mLaunchInfo.getAppPackage(), mLaunchInfo.getRunner(), device); - - if (mLaunchInfo.getTestClass() != null) { - if (mLaunchInfo.getTestMethod() != null) { - runner.setMethodName(mLaunchInfo.getTestClass(), mLaunchInfo.getTestMethod()); - } else { - runner.setClassName(mLaunchInfo.getTestClass()); - } - } - - if (mLaunchInfo.getTestPackage() != null) { - runner.setTestPackageName(mLaunchInfo.getTestPackage()); - } - - TestSize size = mLaunchInfo.getTestSize(); - if (size != null) { - runner.setTestSize(size); - } - - runners.add(runner); - } - - // Launch all test info collector jobs - List<TestTreeCollectorJob> collectorJobs = - new ArrayList<TestTreeCollectorJob>(devices.size()); - List<TestCollector> perDeviceCollectors = new ArrayList<TestCollector>(devices.size()); - for (int i = 0; i < devices.size(); i++) { - RemoteAndroidTestRunner runner = runners.get(i); - String deviceName = devices.get(i).getName(); - TestCollector collector = new TestCollector(deviceName); - perDeviceCollectors.add(collector); - - TestTreeCollectorJob job = new TestTreeCollectorJob( - "Test Tree Collector for " + deviceName, - runner, mLaunchInfo.isDebugMode(), collector); - job.setPriority(Job.INTERACTIVE); - job.schedule(); - - collectorJobs.add(job); - } - - // wait for all test info collector jobs to complete - int totalTests = 0; - for (TestTreeCollectorJob job : collectorJobs) { - try { - job.join(); - } catch (InterruptedException e) { - endTestRunWithError(e.getMessage()); - return; - } - - if (!job.getResult().isOK()) { - endTestRunWithError(job.getResult().getMessage()); - return; - } - - TestCollector collector = job.getCollector(); - String err = collector.getErrorMessage(); - if (err != null) { - endTestRunWithError(err); - return; - } - - totalTests += collector.getTestCaseCount(); - } - - AdtPlugin.printToConsole(mLaunchInfo.getProject(), "Sending test information to Eclipse"); - notifyTestRunStarted(totalTests); - sendTestTrees(perDeviceCollectors); - - List<TestRunnerJob> instrumentationRunnerJobs = - new ArrayList<TestRunnerJob>(devices.size()); - - TestResultsNotifier notifier = new TestResultsNotifier(mExecution.getListener(), - devices.size()); - - // Spawn all instrumentation runner jobs - for (int i = 0; i < devices.size(); i++) { - RemoteAndroidTestRunner runner = runners.get(i); - String deviceName = devices.get(i).getName(); - TestRunListener testRunListener = new TestRunListener(deviceName, notifier); - InstrumentationRunJob job = new InstrumentationRunJob( - "Test Tree Collector for " + deviceName, - runner, mLaunchInfo.isDebugMode(), testRunListener); - job.setPriority(Job.INTERACTIVE); - job.schedule(); - - instrumentationRunnerJobs.add(job); - } - - // Wait for all jobs to complete - for (TestRunnerJob job : instrumentationRunnerJobs) { - try { - job.join(); - } catch (InterruptedException e) { - endTestRunWithError(e.getMessage()); - return; - } - - if (!job.getResult().isOK()) { - endTestRunWithError(job.getResult().getMessage()); - return; - } - } - } - - /** Sends info about the test tree to be executed (ie the suites and their enclosed tests) */ - private void sendTestTrees(List<TestCollector> perDeviceCollectors) { - for (TestCollector c : perDeviceCollectors) { - ITestReference ref = c.getDeviceSuite(); - ref.sendTree(this); - } - } - - private static abstract class TestRunnerJob extends Job { - private ITestRunListener mListener; - private RemoteAndroidTestRunner mRunner; - private boolean mIsDebug; - - public TestRunnerJob(String name, RemoteAndroidTestRunner runner, - boolean isDebug, ITestRunListener listener) { - super(name); - - mRunner = runner; - mIsDebug = isDebug; - mListener = listener; - } - - @Override - protected IStatus run(IProgressMonitor monitor) { - try { - setupRunner(); - mRunner.run(mListener); - } catch (TimeoutException e) { - return new Status(Status.ERROR, AdtPlugin.PLUGIN_ID, - LaunchMessages.RemoteAdtTestRunner_RunTimeoutException, - e); - } catch (IOException e) { - return new Status(Status.ERROR, AdtPlugin.PLUGIN_ID, - String.format(LaunchMessages.RemoteAdtTestRunner_RunIOException_s, - e.getMessage()), - e); - } catch (AdbCommandRejectedException e) { - return new Status(Status.ERROR, AdtPlugin.PLUGIN_ID, - String.format( - LaunchMessages.RemoteAdtTestRunner_RunAdbCommandRejectedException_s, - e.getMessage()), - e); - } catch (ShellCommandUnresponsiveException e) { - return new Status(Status.ERROR, AdtPlugin.PLUGIN_ID, - LaunchMessages.RemoteAdtTestRunner_RunTimeoutException, - e); - } - - return Status.OK_STATUS; - } - - public RemoteAndroidTestRunner getRunner() { - return mRunner; - } - - public boolean isDebug() { - return mIsDebug; - } - - public ITestRunListener getListener() { - return mListener; - } - - protected abstract void setupRunner(); - } - - private static class TestTreeCollectorJob extends TestRunnerJob { - public TestTreeCollectorJob(String name, RemoteAndroidTestRunner runner, boolean isDebug, - TestCollector listener) { - super(name, runner, isDebug, listener); - } - - @Override - protected void setupRunner() { - RemoteAndroidTestRunner runner = getRunner(); - - // set log only to just collect test case info, - // so Eclipse has correct test case count/tree info - runner.setLogOnly(true); - - // add a small delay between each test. Otherwise for large test suites framework may - // report Binder transaction failures - runner.addInstrumentationArg(DELAY_MSEC_KEY, COLLECT_TEST_DELAY_MS); - } - - public TestCollector getCollector() { - return (TestCollector) getListener(); - } - } - - private static class InstrumentationRunJob extends TestRunnerJob { - public InstrumentationRunJob(String name, RemoteAndroidTestRunner runner, boolean isDebug, - ITestRunListener listener) { - super(name, runner, isDebug, listener); - } - - @Override - protected void setupRunner() { - RemoteAndroidTestRunner runner = getRunner(); - runner.setLogOnly(false); - runner.removeInstrumentationArg(DELAY_MSEC_KEY); - if (isDebug()) { - runner.setDebug(true); - } - } - } - - /** - * Main entry method to run tests - * - * @param programArgs JDT JUnit program arguments to be processed by parent - * @param junitInfo the {@link AndroidJUnitLaunchInfo} containing info about this test ru - */ - public void runTests(String[] programArgs, AndroidJUnitLaunchInfo junitInfo) { - init(programArgs, junitInfo); - run(); - } - - /** - * Stop the current test run. - */ - public void terminate() { - stop(); - } - - @Override - protected void stop() { - if (mExecution != null) { - mExecution.stop(); - } - } - - private void notifyTestRunEnded(long elapsedTime) { - // copy from parent - not ideal, but method is private - sendMessage(MessageIds.TEST_RUN_END + elapsedTime); - flush(); - //shutDown(); - } - - /** - * @param errorMessage - */ - private void reportError(String errorMessage) { - AdtPlugin.printErrorToConsole(mLaunchInfo.getProject(), - String.format(LaunchMessages.RemoteAdtTestRunner_RunFailedMsg_s, errorMessage)); - // is this needed? - //notifyTestRunStopped(-1); - } - - private void endTestRunWithError(String message) { - reportError(message); - notifyTestRunEnded(0); - } - - /** - * This class provides the interface to notify the JDT UI regarding the status of tests. - * When running tests on multiple devices, there is a {@link TestRunListener} that listens - * to results from each device. Rather than all such listeners directly notifying JDT - * from different threads, they all notify this class which notifies JDT. In addition, - * the {@link #testRunEnded(String, long)} method make sure that JDT is notified that the - * test run has completed only when tests on all devices have completed. - * */ - private class TestResultsNotifier { - private final IListensToTestExecutions mListener; - private final int mDeviceCount; - - private int mCompletedRuns; - private long mMaxElapsedTime; - - public TestResultsNotifier(IListensToTestExecutions listener, int nDevices) { - mListener = listener; - mDeviceCount = nDevices; - } - - public synchronized void testEnded(TestCaseReference ref) { - mListener.notifyTestEnded(ref); - } - - public synchronized void testFailed(TestReferenceFailure ref) { - mListener.notifyTestFailed(ref); - } - - public synchronized void testRunEnded(String mDeviceName, long elapsedTime) { - mCompletedRuns++; - - if (elapsedTime > mMaxElapsedTime) { - mMaxElapsedTime = elapsedTime; - } - - if (mCompletedRuns == mDeviceCount) { - notifyTestRunEnded(mMaxElapsedTime); - } - } - - public synchronized void testStarted(TestCaseReference testId) { - mListener.notifyTestStarted(testId); - } - } - - /** - * TestRunListener that communicates results in real-time back to JDT JUnit via the - * {@link TestResultsNotifier}. - * */ - private class TestRunListener implements ITestRunListener { - private final String mDeviceName; - private TestResultsNotifier mNotifier; - - /** - * Constructs a {@link ITestRunListener} that listens for test results on given device. - * @param deviceName device on which the tests are being run - * @param notifier notifier to inform of test status - */ - public TestRunListener(String deviceName, TestResultsNotifier notifier) { - mDeviceName = deviceName; - mNotifier = notifier; - } - - @Override - public void testEnded(TestIdentifier test, Map<String, String> ignoredTestMetrics) { - mNotifier.testEnded(new TestCaseReference(mDeviceName, test)); - } - - @Override - public void testFailed(TestIdentifier test, String trace) { - TestReferenceFailure failure = - new TestReferenceFailure(new TestCaseReference(mDeviceName, test), - MessageIds.TEST_FAILED, trace, null); - mNotifier.testFailed(failure); - } - - @Override - public void testAssumptionFailure(TestIdentifier test, String trace) { - TestReferenceFailure failure = - new TestReferenceFailure(new TestCaseReference(mDeviceName, test), - MessageIds.TEST_FAILED, trace, null); - mNotifier.testFailed(failure); - } - - @Override - public void testIgnored(TestIdentifier test) { - // TODO: implement me? - } - - @Override - public synchronized void testRunEnded(long elapsedTime, Map<String, String> runMetrics) { - mNotifier.testRunEnded(mDeviceName, elapsedTime); - AdtPlugin.printToConsole(mLaunchInfo.getProject(), - LaunchMessages.RemoteAdtTestRunner_RunCompleteMsg); - } - - @Override - public synchronized void testRunFailed(String errorMessage) { - reportError(errorMessage); - } - - @Override - public synchronized void testRunStarted(String runName, int testCount) { - // ignore - } - - @Override - public synchronized void testRunStopped(long elapsedTime) { - notifyTestRunStopped(elapsedTime); - AdtPlugin.printToConsole(mLaunchInfo.getProject(), - LaunchMessages.RemoteAdtTestRunner_RunStoppedMsg); - } - - @Override - public synchronized void testStarted(TestIdentifier test) { - TestCaseReference testId = new TestCaseReference(mDeviceName, test); - mNotifier.testStarted(testId); - } - } - - /** Override parent to get extra logs. */ - @Override - protected boolean connect() { - boolean result = super.connect(); - if (!result) { - AdtPlugin.printErrorToConsole(mLaunchInfo.getProject(), - "Connect to Eclipse test result listener failed"); - } - return result; - } - - /** Override parent to dump error message to console. */ - @Override - public void runFailed(String message, Exception exception) { - if (exception != null) { - AdtPlugin.logAndPrintError(exception, mLaunchInfo.getProject().getName(), - "Test launch failed: %s", message); - } else { - AdtPlugin.printErrorToConsole(mLaunchInfo.getProject(), "Test launch failed: %s", - message); - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/TestCaseReference.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/TestCaseReference.java deleted file mode 100644 index e05e9b857..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/TestCaseReference.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch.junit.runtime; - -import com.android.ddmlib.testrunner.TestIdentifier; - -import org.eclipse.jdt.internal.junit.runner.IVisitsTestTrees; - -/** - * Reference for a single Android test method. - */ -@SuppressWarnings("restriction") -class TestCaseReference extends AndroidTestReference { - private final String mClassName; - private final String mTestName; - private final String mDeviceName; - - /** - * Creates a TestCaseReference from a {@link TestIdentifier} - * @param test - */ - TestCaseReference(String deviceName, TestIdentifier test) { - mDeviceName = deviceName; - mClassName = test.getClassName(); - mTestName = test.getTestName(); - } - - /** - * Returns a count of the number of test cases referenced. Is always one for this class. - */ - @Override - public int countTestCases() { - return 1; - } - - /** - * Sends test identifier and test count information for this test - * - * @param notified the {@link IVisitsTestTrees} to send test info to - */ - @Override - public void sendTree(IVisitsTestTrees notified) { - notified.visitTreeEntry(getIdentifier(), false, countTestCases()); - } - - /** - * Returns the identifier of this test, in a format expected by JDT JUnit - */ - @Override - public String getName() { - return String.format("%s (%s) [%s]", mTestName, mClassName, mDeviceName); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/TestCollector.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/TestCollector.java deleted file mode 100644 index 32c5ef81e..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/TestCollector.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch.junit.runtime; - -import com.android.ddmlib.testrunner.ITestRunListener; -import com.android.ddmlib.testrunner.TestIdentifier; - -import java.util.Map; - -/** - * Collects info about tests to be executed by listening to the results of an Android test run. - */ -class TestCollector implements ITestRunListener { - private final String mDeviceName; - private final TestSuiteReference mDeviceSuiteRef; - - private int mTotalTestCount; - /** test name to test suite reference map. */ - - private String mErrorMessage = null; - - TestCollector(String deviceName) { - mDeviceName = deviceName; - mDeviceSuiteRef = new TestSuiteReference(deviceName); - - mTotalTestCount = 0; - } - - @Override - public synchronized void testEnded(TestIdentifier test, Map<String, String> testMetrics) { - // ignore - } - - /* (non-Javadoc) - * @see com.android.ddmlib.testrunner.ITestRunListener#testFailed(com.android.ddmlib.testrunner.TestIdentifier, java.lang.String) - */ - @Override - public synchronized void testFailed(TestIdentifier test, String trace) { - // ignore - should be impossible since this is only collecting test information - } - - /* (non-Javadoc) - * @see com.android.ddmlib.testrunner.ITestRunListener#testIgnored(com.android.ddmlib.testrunner.TestIdentifier) - */ - @Override - public synchronized void testIgnored(TestIdentifier test) { - // ignore - should be impossible since this is only collecting test information - } - - /* (non-Javadoc) - * @see com.android.ddmlib.testrunner.ITestRunListener#testAssumptionFailure(com.android.ddmlib.testrunner.TestIdentifier, java.lang.String) - */ - @Override - public synchronized void testAssumptionFailure(TestIdentifier test, String trace) { - // ignore - should be impossible since this is only collecting test information - } - - /* (non-Javadoc) - * @see com.android.ddmlib.testrunner.ITestRunListener#testRunEnded(long, Map<String, String>) - */ - @Override - public synchronized void testRunEnded(long elapsedTime, Map<String, String> runMetrics) { - // ignore - } - - /* (non-Javadoc) - * @see com.android.ddmlib.testrunner.ITestRunListener#testRunFailed(java.lang.String) - */ - @Override - public synchronized void testRunFailed(String errorMessage) { - mErrorMessage = errorMessage; - } - - /* (non-Javadoc) - * @see com.android.ddmlib.testrunner.ITestRunListener#testRunStarted(int) - */ - @Override - public synchronized void testRunStarted(String ignoredRunName, int testCount) { - mTotalTestCount = testCount; - } - - /* (non-Javadoc) - * @see com.android.ddmlib.testrunner.ITestRunListener#testRunStopped(long) - */ - @Override - public synchronized void testRunStopped(long elapsedTime) { - // ignore - } - - /* (non-Javadoc) - * @see com.android.ddmlib.testrunner.ITestRunListener#testStarted(com.android.ddmlib.testrunner.TestIdentifier) - */ - @Override - public synchronized void testStarted(TestIdentifier test) { - TestSuiteReference suiteRef = mDeviceSuiteRef.getTestSuite(test.getClassName()); - if (suiteRef == null) { - suiteRef = new TestSuiteReference(test.getClassName()); - mDeviceSuiteRef.addTest(suiteRef); - } - - suiteRef.addTest(new TestCaseReference(mDeviceName, test)); - } - - /** - * Returns the total test count in the test run. - */ - public synchronized int getTestCaseCount() { - return mTotalTestCount; - } - - /** - * Returns the error message that was reported when collecting test info. - * Returns <code>null</code> if no error occurred. - */ - public synchronized String getErrorMessage() { - return mErrorMessage; - } - - public TestSuiteReference getDeviceSuite() { - return mDeviceSuiteRef; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/TestSuiteReference.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/TestSuiteReference.java deleted file mode 100644 index dcc9f10ec..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/junit/runtime/TestSuiteReference.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.ide.eclipse.adt.internal.launch.junit.runtime; - -import org.eclipse.jdt.internal.junit.runner.IVisitsTestTrees; - -import java.util.ArrayList; -import java.util.List; - -/** - * Reference for an Android test suite aka class. - */ -@SuppressWarnings("restriction") -class TestSuiteReference extends AndroidTestReference { - - private final String mClassName; - private List<AndroidTestReference> mTests; - - /** - * Creates a TestSuiteReference - * - * @param className the fully qualified name of the test class - */ - TestSuiteReference(String className) { - mClassName = className; - mTests = new ArrayList<AndroidTestReference>(); - } - - /** - * Returns a count of the number of test cases included in this suite. - */ - @Override - public int countTestCases() { - return mTests.size(); - } - - /** - * Sends test identifier and test count information for this test class, and all its included - * test methods. - * - * @param notified the {@link IVisitsTestTrees} to send test info too - */ - @Override - public void sendTree(IVisitsTestTrees notified) { - notified.visitTreeEntry(getIdentifier(), true, countTestCases()); - for (AndroidTestReference ref: mTests) { - ref.sendTree(notified); - } - } - - /** - * Return the name of this test class. - */ - @Override - public String getName() { - return mClassName; - } - - /** - * Adds a test method to this suite. - * - * @param testRef the {@link TestCaseReference} to add - */ - void addTest(AndroidTestReference testRef) { - mTests.add(testRef); - } - - /** Returns the test suite of given name, null if no such test suite exists */ - public TestSuiteReference getTestSuite(String name) { - for (AndroidTestReference ref: mTests) { - if (ref instanceof TestSuiteReference && ref.getName().equals(name)) { - return (TestSuiteReference) ref; - } - } - - return null; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/messages.properties b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/messages.properties deleted file mode 100644 index b27a3654e..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/messages.properties +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright (C) 2010 The Android Open Source Project -# -# Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php -# -# 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. -# - -# generic messages that could be used by multiple classes -LaunchDialogTitle=Android Launch -NonAndroidProjectError=Specified project is not an Android project -ParseFileFailure_s=Failed to parse %1$s file - -# specialized, class-specific messages -AndroidJUnitLaunchAction_LaunchDesc_s=%1$s JUnit launch -AndroidJUnitLaunchAction_LaunchFail=Failed to launch test -AndroidJUnitLaunchAction_LaunchInstr_2s=Launching instrumentation %1$s on %2$s -AndroidJUnitDelegate_NoRunnerConfigMsg_s=Warning: No instrumentation runner found for the launch, using %1$s -AndroidJUnitDelegate_NoRunnerConsoleMsg_4s=%1$s does not specify a %2$s instrumentation or does not declare uses-library %3$s in its %4$s -AndroidJUnitDelegate_NoRunnerMsg_s=%1$s is not configured correctly for running tests. See Console for details. -AndroidJUnitDelegate_NoTargetMsg_3s=%1$s is not configured correctly for running tests:\nA targetPackage attribute for instrumentation %2$s in its %3$s could not be found\! -AndroidJUnitTab_LoaderLabel=Instrumentation runner: -AndroidJUnitTab_LoadInstrError_s=Failed to load instrumentations from %1$s -AndroidJUnitTab_NoRunnerError=Instrumentation runner not specified -AndroidJUnitTab_SizeLabel=Only run test methods annotated with: -AndroidJUnitTab_TestContainerText=Run all tests in the selected project, or package -InstrValidator_NoTestLibMsg_s=The application does not declare uses-library %1$s -InstrValidator_WrongRunnerTypeMsg_s=The instrumentation runner must be of type %1$s -RemoteAdtTestRunner_RunCompleteMsg=Test run finished -RemoteAdtTestRunner_RunFailedMsg_s=Test run failed: %1$s -RemoteAdtTestRunner_RunTimeoutException=Connection with device timed out. -RemoteAdtTestRunner_RunIOException_s=Lost connection with device: %s -RemoteAdtTestRunner_RunStoppedMsg=Test run stopped -RemoteAdtTestRunner_RunAdbCommandRejectedException_s=Adb rejected command: %s -RemoteAdtTestRunner_RunShellCommandUnresponsiveException=Device stopped sending output |